| 篇次 | 主題 | 性質 | 狀態 |
|---|---|---|---|
| 0 | 起源:從一場面試的需求討論到自建AI工作流實建 | 主體與思路 | 已完成 |
| 1 | AstrBot & Line BOT:檔案式知識庫試驗 | 技術實作 | 已實作,部分項目驗證中 |
| 2 | 外部數據源獲取與多角色技能討論實驗(TradingView 案例) | 技術實作 | 已實作,部分驗證部分待驗證 |
| 3 | 通用產業情報Bot插件及商業化思路 | 商業評估 | 規劃評估,計畫尚未實作 |
承接第 1 篇的同一套環境。第 1 篇處理「靜態文件」,本篇處理「即時外部資料加多角色討論流程」,作為第 3 篇商業方案的技術前哨。
補充說明:為什麼用金融案例
本篇不是投資教學,金融只是試驗場景。實驗的用意是驗證這種工作流:
多個角色,各自根據外部取得的資料提出觀點,互相質疑,最後產出一個有依據的結論。
選用 TradingView,是因為 TradingView MCP 接入的外部資料屬於金融相關數據(行情、技術指標、情緒與新聞、回測),取得方式穩定、可程式呼叫、資料即時,剛好可以拿來驗證三件事:
- MCP 能否把外部資料穩定接進 AstrBot。
- Skill 能否約束多角色的討論流程與輸出格式。
- 結論能否附上資料依據,並在資料不足時誠實標示。
驗證完成後,同一套方法可以轉用到其他資料源,例如第 3 篇規劃的產業情報。
關於「多角色」的定位:三個角色是在單一 Skill、單一 Bot 內的角色扮演式討論,不是三個獨立運行的 Agent。這是起源篇所說「讓多個 AI 分工合作」的小規模試驗,並非完整的多 Agent 架構。MCP 工具清單中另有 multi_agent_analysis,是否與本 Skill 搭配使用,目前尚未測試。
實驗目標與範圍
希望 LINE 上的 AstrBot 做到三件事:
- 查詢 KuCoin、Binance 等交易所的即時行情與技術指標。
- 不只丟一份指標清單,而是讓「看技術面」「看情緒」「看風險」三個角色互相質疑,再給出條件式結論。
- 保留 n8n 作為排程、通知與後續自動化的出口。
範圍只有「取得資料並整理分析」,不做下單或自動交易。資料正確性與流程可追蹤,比功能多寡更重要。
環境與整體架構
| 項目 | 內容 |
|---|---|
| 主機 | VPS,寶塔面板管理,Docker 部署 |
| AstrBot | v4.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/
- n8n 解析成功,
/healthz回200與{"status":"ok"}。 - tradingview-mcp 解析成功,根路徑
/回404,伺服器為uvicorn。
這裡的 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 與 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. 顯示目前設定與建議
設計重點:
- 所有測試都從AstrBot 容器內發出,因為宿主機連得到不代表容器連得到。
- 需要 token 時用環境變數傳入,不寫進腳本、不印在輸出。
- 所有輸出同時寫進
/tmp下的 log,方便事後比對。
多角色討論 Skill 設計
MCP 解決「資料從哪來」,Skill 解決「怎麼分析、怎麼回答」。分析拆成三個角色:
| 角色 | 看什麼 | 要回答的問題 |
|---|---|---|
| 技術派 | MACD、RSI、布林帶、MA、成交量 | 動能與趨勢是否一致? |
| 情緒派 | Reddit 情緒、金融新聞 | 是否出現 FOMO 或消息驅動? |
| 風控派 | MA 結構、波動率、歷史最大回撤 | 哪些條件會亮紅燈? |
流程:先取得共同的基礎資料,三個角色各自提出證據,進行兩輪交叉質詢,最後由主持人整合成偏多、偏空、觀望三種條件式情境。
Skill 內的限制
- 即時行情、指標、新聞一律先呼叫 MCP,不憑模型記憶回答。
- 缺少的欄位(例如 MCP 沒回傳歷史最大回撤)標示「未提供」,不自行估算。
- 工具沒有提供 Reuters RSS,就不能宣稱資料來源是 Reuters。
- 買賣只寫成條件情境,不寫成指令;不保證獲利,不執行下單。
- 資料不足時,信心最高只能標「中」。
打包與上傳
Skill 是一個含 SKILL.md 的資料夾,壓縮後上傳。ZIP 內結構必須是:
tradingview-debate-analyst/
└── SKILL.md
在 WebUI 的「插件 → 技能 → 上傳技能」拖入 ZIP,系統會自動校驗 SKILL.md。目前確認的只有 ZIP 結構與檔案完整性;在 LINE 上完整跑一輪多角色討論的結果,留待後續測試記錄。
Skill、知識庫與 MCP 的分工
- 知識庫解決「模型不知道什麼」,適合公司文件、手冊、歷史紀錄。
- Skill解決「應該怎麼做」,適合固定流程、輸出格式、禁止事項。
- MCP解決「能連到什麼」,適合即時資料與外部系統。
| 需求 | 選擇 |
|---|---|
| 即時價格與指標 | MCP(資料會過期,不能放知識庫) |
| 多角色討論流程與輸出格式 | Skill |
| 自己的風險上限與策略說明 | 知識庫(日後再加) |
第 1 篇已做過檔案式知識庫,本篇不重複。兩篇的分工是:第 1 篇處理「靜態文件」,本篇處理「即時資料加流程」。
電腦能力與權限邊界
AstrBot 文件指出,電腦能力決定 Agent 能否執行程式、讀寫檔案與呼叫 Shell。設定位置在「配置文件 → AI 配置 → 能力 → 使用電腦能力」,核心選項是 Computer Use Runtime。
| 選項 | 說明 |
|---|---|
| none | 不授予電腦能力 |
| Skill local | AstrBot 自身的 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 允許清單正式納入容器名稱,而非繼續依賴繞過。
- 缺點與代價:三個容器的網路排錯耗費大量時間,顯示容器化部署時「先解決網路,再談應用邏輯」這個順序的重要性,順序顛倒很容易誤判成模型或提示詞問題。
.md 原始檔(見 markdown/astrbot-02-mcp-multi-role-finance-experiment.md),供後續匯入 WordPress 或歸檔使用。