環境是寶塔面板加 Docker,已有 astrbot、n8n、tradingview-mcp 三個容器。目標是讓 LINE 上的 AstrBot 能查行情、做技術分析,並以 n8n 作為後續自動化的出口。實作後得到四個結論:三個容器必須在同一個自訂 Docker network;TradingView MCP 驗證 Host 標頭,用容器名稱連線會得到 421 錯誤;AstrBot 的 MCP 設定可加 headers 暫時繞過;Skill 負責流程、MCP 負責資料。本篇不是投資教學,金融只是試驗場景,用意是驗證「多角色依外部資料互相討論並產出結論」的工作流。
AstrBot AI 應用系列導覽
篇次主題性質狀態
0起源:從一場面試的需求討論到自建AI工作流實建主體與思路已完成
1AstrBot & Line BOT:檔案式知識庫試驗技術實作已實作,部分項目驗證中
2外部數據源獲取與多角色技能討論實驗(TradingView 案例)技術實作已實作,部分驗證部分待驗證
3通用產業情報Bot插件及商業化思路商業評估規劃評估,計畫尚未實作

承接第 1 篇的同一套環境。第 1 篇處理「靜態文件」,本篇處理「即時外部資料加多角色討論流程」,作為第 3 篇商業方案的技術前哨。

補充說明:為什麼用金融案例

本篇不是投資教學,金融只是試驗場景。實驗的用意是驗證這種工作流:

多個角色,各自根據外部取得的資料提出觀點,互相質疑,最後產出一個有依據的結論。

選用 TradingView,是因為 TradingView MCP 接入的外部資料屬於金融相關數據(行情、技術指標、情緒與新聞、回測),取得方式穩定、可程式呼叫、資料即時,剛好可以拿來驗證三件事:

  1. MCP 能否把外部資料穩定接進 AstrBot。
  2. Skill 能否約束多角色的討論流程與輸出格式。
  3. 結論能否附上資料依據,並在資料不足時誠實標示。

驗證完成後,同一套方法可以轉用到其他資料源,例如第 3 篇規劃的產業情報。

關於「多角色」的定位:三個角色是在單一 Skill、單一 Bot 內的角色扮演式討論,不是三個獨立運行的 Agent。這是起源篇所說「讓多個 AI 分工合作」的小規模試驗,並非完整的多 Agent 架構。MCP 工具清單中另有 multi_agent_analysis,是否與本 Skill 搭配使用,目前尚未測試。

先說結論:Docker 部署時,先解決網路與 Host 驗證,再談 Skill。順序反過來,很容易一直以為是模型或提示詞的問題。

實驗目標與範圍

希望 LINE 上的 AstrBot 做到三件事:

範圍只有「取得資料並整理分析」,不做下單或自動交易。資料正確性與流程可追蹤,比功能多寡更重要。

環境與整體架構

項目內容
主機VPS,寶塔面板管理,Docker 部署
AstrBotv4.28.2,容器名 astrbot,WebUI 埠 6185
n8n容器名 n8n,埠 5678
TradingView MCP容器名 tradingview-mcp,容器內 8000,映射到宿主機 8080
另一個容器openclaw-zh-gateway,目前反覆重啟,本文不使用
LINE 使用者
    ↓
AstrBot(Skill:多角色討論流程)
    ├─ MCP → tradingview-mcp:8000/mcp(行情、指標、新聞、回測)
    └─ MCP → n8n:5678/mcp/<path>(自動化工作流,待驗證)
         ※ 三個容器同在 mcp-network

把三個容器放進同一個網路

偵測腳本最初的結果:

astrbot          networks: bridge
n8n              networks: bridge, mcp-network
tradingview-mcp  networks: mcp-network

AstrBot 只在預設 bridge,用 http://n8n:5678 測試時出現 Could not resolve host: n8n。原因是預設 bridge 不提供容器名稱 DNS,使用者自訂 bridge 才有(Docker 官方文件說明自訂 bridge 提供容器間的自動 DNS 解析)。

處理方式

docker network connect --alias astrbot mcp-network astrbot
docker network inspect mcp-network

確認三個容器都在 mcp-network 後,從 AstrBot 容器內測試:

docker exec astrbot getent hosts n8n
docker exec astrbot getent hosts tradingview-mcp
docker exec astrbot curl -i --max-time 5 http://n8n:5678/healthz
docker exec astrbot curl -i --max-time 5 http://tradingview-mcp:8000/

這裡的 404 不是壞消息:它代表請求已到達 Uvicorn,只是根路徑沒有內容,網路層算是通過。

提醒:docker network connect 是執行期變更,容器重建後可能消失。要長期保留,必須把 mcp-network 寫進 AstrBot 的 Compose 設定。這一步目前尚未完成。

測試 MCP 端點與 421 排錯

Streamable HTTP 以 HTTP POST 傳送 JSON-RPC,所以直接送 initialize 測試:

docker exec astrbot curl -i --max-time 15 -X POST \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"astrbot-detect","version":"1.0"}}}' \
  http://tradingview-mcp:8000/mcp

Bug:421 Invalid Host header

症狀:

HTTP/1.1 421 Misdirected Request
Invalid Host header

同時測 /mcp/ 得到 307 並導向 /mcp,證明端點路徑正確;/sse、/docs、/health 等路徑為 404。所以問題不在網路或路徑,而是服務拒絕 Host: tradingview-mcp:8000。
原因:MCP Python SDK 的 Host 驗證預設只接受 localhost 類主機名稱,目的是防範 DNS rebinding。

驗證是 Host 的問題

只把 Host 換成 127.0.0.1:8000,其餘請求不變:

docker exec astrbot curl -i --max-time 15 -X POST \
  -H 'Host: 127.0.0.1:8000' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"astrbot-test","version":"1.0"}}}' \
  http://tradingview-mcp:8000/mcp

這次回 200 OK、content-type: text/event-stream,並帶有 mcp-session-id,伺服器資訊為 TradingView Multi-Market Screener,版本 1.27.0。

容器環境變數中沒有 ALLOWED_HOSTS 之類的設定,因此選擇不猜變數名稱,先以改 Host 標頭的方式繞過。

在 AstrBot 新增 MCP 伺服器

AstrBot 的 MCP 伺服器在 WebUI 的「插件 → MCP」管理,新增視窗有 Stdio、Streamable HTTP、SSE 三種模板。選Streamable HTTP,貼入:

{
  "transport": "streamable_http",
  "url": "http://tradingview-mcp:8000/mcp",
  "headers": {
    "Host": "127.0.0.1:8000"
  }
}

名稱填 tradingview,先按「測試連接」,成功後才保存。測試訊息列出 27 個工具,包括:

top_gainers / top_losers / bollinger_scan / rating_filter / coin_analysis
consecutive_candles_scan / advanced_candle_pattern
volume_breakout_scanner / volume_confirmation_analysis / smart_volume_scanner
multi_agent_analysis / multi_timeframe_analysis / market_sentiment
financial_news / combined_analysis
backtest_strategy / compare_strategies / walk_forward_backtest_strategy
yahoo_price / market_snapshot / egx_* 系列

到這裡才算完成「AstrBot 取得 MCP 工具清單」。

這是繞過,不是最佳解:長期做法是讓 TradingView MCP 的 Host 允許清單正式包含 tradingview-mcp 與 tradingview-mcp:8000。不建議把允許清單設成萬用字元,因為那等於關掉 Host 驗證。

n8n 的接法與目前進度

n8n 要當 MCP 伺服器,工作流需放一個MCP Server Trigger 節點,並讓工作流處於 Active。節點提供 test 與 production 兩種 URL,AstrBot 要填 production。

已完成:AstrBot 到 n8n 的內網連線(/healthz 回 200)。

尚未完成:取得 production path,並以 initialize 與 tools/list 驗證 n8n MCP。這部分還沒實測,因此本文不宣稱 n8n MCP 已成功。預計的設定如下(<path> 為節點顯示的實際路徑):

{
  "transport": "streamable_http",
  "url": "http://n8n:5678/mcp/<path>"
}

若 n8n 設了 Bearer 認證,再加 headers.Authorization。另外要留意:WEBHOOK_URL 沒設定時,節點顯示的 URL 可能是 localhost:5678;經寶塔反向代理對外時需要補上,並關閉 proxy_buffering。

偵測流程腳本化

排錯過程適合腳本化,因此整理成一支選單式 Shell 腳本,只讀取與測試,不修改設定:

1. 盤點容器
2. 檢查 mcp-network 與容器 IP
3. 將容器加入 mcp-network(需手動確認)
4. 顯示單一容器詳細資訊
5. 測試 AstrBot → n8n / tradingview 基本通訊
6. 測試 tradingview-mcp 的 MCP initialize
7. 測試 n8n 的 MCP initialize
8. 測試兩個 MCP 的 tools/list
9. 查看容器 log
10. 顯示目前設定與建議

設計重點:

多角色討論 Skill 設計

MCP 解決「資料從哪來」,Skill 解決「怎麼分析、怎麼回答」。分析拆成三個角色:

角色看什麼要回答的問題
技術派MACD、RSI、布林帶、MA、成交量動能與趨勢是否一致?
情緒派Reddit 情緒、金融新聞是否出現 FOMO 或消息驅動?
風控派MA 結構、波動率、歷史最大回撤哪些條件會亮紅燈?

流程:先取得共同的基礎資料,三個角色各自提出證據,進行兩輪交叉質詢,最後由主持人整合成偏多、偏空、觀望三種條件式情境。

Skill 內的限制

打包與上傳

Skill 是一個含 SKILL.md 的資料夾,壓縮後上傳。ZIP 內結構必須是:

tradingview-debate-analyst/
└── SKILL.md

在 WebUI 的「插件 → 技能 → 上傳技能」拖入 ZIP,系統會自動校驗 SKILL.md。目前確認的只有 ZIP 結構與檔案完整性;在 LINE 上完整跑一輪多角色討論的結果,留待後續測試記錄。

Skill、知識庫與 MCP 的分工

需求選擇
即時價格與指標MCP(資料會過期,不能放知識庫)
多角色討論流程與輸出格式Skill
自己的風險上限與策略說明知識庫(日後再加)

第 1 篇已做過檔案式知識庫,本篇不重複。兩篇的分工是:第 1 篇處理「靜態文件」,本篇處理「即時資料加流程」。

電腦能力與權限邊界

AstrBot 文件指出,電腦能力決定 Agent 能否執行程式、讀寫檔案與呼叫 Shell。設定位置在「配置文件 → AI 配置 → 能力 → 使用電腦能力」,核心選項是 Computer Use Runtime。

選項說明
none不授予電腦能力
Skill localAstrBot 自身的 Shell/Python sandbox
Shipyard/Neo/CUA外部沙箱服務,隔離度較高

這次實驗維持 none 或 Skill local,不授予完整電腦能力——即時行情透過 MCP 取得,不需要讓模型自己執行程式。

LINE 管理員權限排錯

管理指令(如 /kb approve)需要管理員身分,設定位置在 cmd_config.json 的 admins_id:

docker exec astrbot sh -c "grep -rn -A4 'admins_id' /data --include=*.json"

找到設定檔後,修改前先備份:

docker stop astrbot
cp /DATA/cmd_config.json /DATA/cmd_config.json.bak
# 編輯 admins_id,加入 LINE UID
python3 -c "import json;print(json.load(open('/DATA/cmd_config.json'))['admins_id'])"
docker start astrbot

AstrBot 與 OpenClaw 的取捨

WebUI、Gateway 用 Python/TypeScript,MCP/Skills/MCP/n8n/TradingView 整合在 AstrBot 這條路線相對成熟;OpenClaw 作為另一套 AI Gateway,目前容器(openclaw-zh-gateway)反覆重啟,本文暫不使用。

FAQ

常見問題

Q:為什麼 AstrBot 連不到 TradingView MCP,但 curl 用 Host 繞過卻能連?
A:MCP 服務驗證 Host 標頭以防 DNS rebinding,AstrBot 的 MCP 設定支援 headers.Host,加上後即可正常連線。

Q:為什麼會出現 421 Invalid Host header?
A:MCP Python SDK 的 Host 驗證預設只接受 localhost 類主機名稱,容器名稱連線會被拒絕,這是防範 DNS rebinding 的安全機制,不是網路或路徑錯誤。

Q:為什麼 AstrBot 連不到 n8n?
A:三個容器要在同一個自訂 bridge network,預設 bridge 不提供容器名稱 DNS 解析,需用 docker network connect 加入。

Q:為什麼測試根路徑回 404?
A:404 代表請求已到達 Uvicorn 伺服器,只是根路徑沒有內容,網路層是通的,不是連線失敗。

Q:LINE 的使用者 ID 跟 UMO 是什麼關係?
A:UMO(Unified Message Origin)包含平台、聊天類型與 ID;UID 是純粹的使用者識別碼,管理員設定需要用 UID,不是 UMO 全字串。

Q:多角色討論要用 MCP 的 Skill,還是用 local Skill?
A:目前驗證的是 local Skill 搭配 MCP 取得即時資料,MCP 工具清單裡的 multi_agent_analysis 是否能跟本 Skill 搭配使用,目前尚未測試。

風險聲明與目前狀態

  • 本篇不是投資教學,實驗目的在驗證「MCP 取得外部資料加多角色討論流程」的工作流可行性,不涉及下單或自動交易。
  • docker network connect 是執行期變更,容器重建後會消失,長期解法是寫進 Compose 設定,這部分尚未完成。
  • n8n MCP 尚未完成 initialize 與 tools/list 的實測驗證,本文不宣稱 n8n MCP 已成功串接。
  • Host 標頭繞過是臨時解法,長期應讓 TradingView MCP 的 Host 允許清單正式納入容器名稱,而非繼續依賴繞過。
  • 缺點與代價:三個容器的網路排錯耗費大量時間,顯示容器化部署時「先解決網路,再談應用邏輯」這個順序的重要性,順序顛倒很容易誤判成模型或提示詞問題。
心得:Docker 部署時,先解決網路與 Host 驗證,再談 Skill。順序反過來,很容易一直以為是模型或提示詞的問題。Skill 負責流程、MCP 負責資料,這個分工讓多角色討論的規則清楚寫在 SKILL.md,即時行情一律由 MCP 工具取得,不讓模型憑記憶回答。
延伸閱讀:承接自《AI 應用系列 1|實作:AstrBot & Line BOT:檔案式知識庫試驗》;下一篇《AI 應用系列 3|商業:產業情報 Bot 與合規 B2B 推薦方案評估》。
本篇文章同時提供 .md 原始檔(見 markdown/astrbot-02-mcp-multi-role-finance-experiment.md),供後續匯入 WordPress 或歸檔使用。