docs/docker-mcp-sqlite.md裝完之後,任何連到 Docker MCP gateway 的 MCP 客戶端(Claude Code、Claude Desktop、Cursor、VS Code 等)會多出六個 SQLite 工具:
read_query · write_query · create_table · list_tables · describe_table · append_insight
SQLite(而不是 sqlite-mcp-server)目前 catalog 有兩個 SQLite MCP image,但只有一個能動:
| Catalog 名 | Image | 狀態 |
|---|---|---|
SQLite | mcp/sqlite | catalog metadata 標「Archived」,但能啟動且正確服務 |
sqlite-mcp-server | mcp/sqlite-mcp-server | 壞掉:entrypoint /app/.venv/bin/mcp-server-sqlite 在發布層不存在 |
用 SQLite(mcp/sqlite)直到上游修好新 image。
docker info 回傳 Server Version;public socket 在 /var/run/docker.sock(或連到 ~/.docker/run/docker.sock)。docker mcp):新 Docker Desktop 內建;docker mcp --version 應印出版本。# 把可用的 SQLite server 加進預設 MCP profile
docker mcp profile server add default \
--server catalog://mcp/docker-mcp-catalog/SQLite
# 預先拉 image,讓第一次工具呼叫變快
docker pull mcp/sqlite:latest
驗證 profile 現在同時有 fetch(內建)與 SQLite:
docker mcp profile show default | grep -E '^[[:space:]]+name:'
預期輸出:name: fetch、name: SQLite。gateway 應多暴露 6 個工具:docker mcp tools count → 15 個(加之前是 9 個)。
CLI 可以直接呼叫 MCP 工具(每次呼叫開新的 ephemeral gateway,約 5 秒開銷):
docker mcp tools call list_tables
docker mcp tools call create_table \
query='CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY AUTOINCREMENT, body TEXT NOT NULL, created_at TEXT DEFAULT CURRENT_TIMESTAMP)'
docker mcp tools call write_query \
query="INSERT INTO notes(body) VALUES ('first row'), ('second row')"
docker mcp tools call read_query \
query='SELECT * FROM notes ORDER BY id'
docker mcp tools call describe_table table_name=notes
docker mcp tools call append_insight insight='3 rows inserted; aggregates work.'
read_query 應回傳帶時間戳的插入列。
資料庫檔放在 Docker named volume mcp-sqlite,mount 在容器內 /mcp:
mcp-sqlite (named volume) → /mcp/db.sqlite
從 host 檢查:
docker volume inspect mcp-sqlite
docker run --rm -v mcp-sqlite:/mcp:ro alpine ls -la /mcp
docker run --rm -v mcp-sqlite:/mcp:ro keinos/sqlite3 \
sqlite3 /mcp/db.sqlite '.schema'
volume 在 docker run --rm 之間持續存在,所以一個 MCP 工具呼叫寫的資料,下一個呼叫看得到。
docker mcp client connect claude-code
docker mcp client connect cursor
docker mcp client connect vscode
docker mcp client connect claude-desktop
# 支援:claude-code, claude-desktop, cline, codex, continue, crush, cursor,
# gemini, goose, gordon, kiro, lmstudio, opencode, sema4, vscode, zed
每個客戶端連一次即可;gateway 會暴露 active profile 裡的所有 server。驗證:docker mcp client ls。
docker mcp profile server remove default SQLite
docker volume rm mcp-sqlite # 不可逆
docker rmi mcp/sqlite:latest
starting client: calling "initialize": EOF:要求的 server MCP handshake 失敗。直接跑 image 看錯誤:用 printf '{"jsonrpc":"2.0",…"initialize"…}' | docker run --rm -i -v mcp-sqlite:/mcp <image-ref> --db-path /mcp/db.sqlite。常見原因:image 缺 entrypoint binary(就是 sqlite-mcp-server 的掛法)或缺 env/secrets。cannot use --enable-all-servers with --servers flag:這兩個 gateway 參數互斥,選一個。docker mcp tools count 沒看到新工具:gateway 可能以 dynamic-tools 執行,直到 session 中啟動 profile 才暴露 meta-tools(mcp-add、mcp-find…)。執行 docker mcp tools(會以預設 profile 開 ephemeral gateway)或從 MCP session 內呼叫 mcp-activate-profile。這份 runbook 展示了「如何把一個 MCP server 裝進 Docker MCP Toolkit」。MCP(Model Context Protocol)是 AI 代理與外部工具溝通的協議,Docker MCP Toolkit 讓你用容器化方式管理多個 MCP server。
選型理由很重要:catalog 有兩個 SQLite MCP image,但只有一個能動。這反映了「開源工具的可靠性需要實測驗證」的現實。用 SQLite(mcp/sqlite)直到上游修好新 image。
儲存布局用 Docker named volume,確保資料在容器重啟後仍然存在。這是「無狀態容器 + 有狀態儲存」的標準模式。
docker info 確認 Docker Desktop 執行中。docker mcp profile server add default --server catalog://mcp/docker-mcp-catalog/SQLite。docker pull mcp/sqlite:latest。docker mcp profile show default,確認看到 SQLite。docker mcp tools call create_table query='CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT)'。docker mcp client connect claude-code。| 錯誤訊息 | 原因 | 解決方式 |
|---|---|---|
starting client: calling "initialize": EOF | MCP handshake 失敗 | 直接跑 image 看錯誤:printf '{"jsonrpc":"2.0",...}' | docker run --rm -i mcp/sqlite:latest --db-path /mcp/db.sqlite |
cannot use --enable-all-servers with --servers flag | 兩個 gateway 參數互斥 | 選一個參數使用 |
tools count not increasing | gateway 以 dynamic-tools 執行 | 執行 docker mcp tools 或從 MCP session 內呼叫 mcp-activate-profile |
entrypoint not found | 用了壞掉的 sqlite-mcp-server image | 改用 mcp/sqlite:latest |
前面的 runbook 把 SQLite 當獨立工作區;這次把兩者合起來:graph.json 建好後,用 SQLite MCP 對圖資料做 SQL 即席查詢——例如「哪個節點的 degree 最高」「某個社群有哪些節點」「哪些邊是 AMBIGUOUS 待人工檢視」。
graphify export 產出 graphify-out/graph.json(node-link 格式)。docker mcp tools call create_table 建立 nodes(id,label,file_type,community,degree)與 edges(source,target,relation,confidence)兩張表。docker mcp tools call write_query(或 sqlite3 CLI)批次插入。read_query 跑「SELECT … GROUP BY community ORDER BY COUNT(*) DESC」看社群大小分佈、或「SELECT * FROM edges WHERE confidence='AMBIGUOUS'」列待審邊。docker mcp client connect claude-code 後,你的 agent 就能用 SQL 語言查知識圖譜,而不只是 graphify query 的固定介面。這份 runbook 的技術核心其實是三個「生命周期」:
docker mcp tools call 每次開新的 ephemeral gateway(約 5 秒開銷),所以「沒看到新工具」多半是 session 用的 gateway 還停留在舊 profile——要 mcp-activate-profile 或開新 gateway。mcp-sqlite,mount 在 /mcp。docker run --rm 每次起新容器但 -v mcp-sqlite:/mcp 讓資料跨容器存活——這是「無狀態運算 + 有狀態儲存」的標準分隔。append_insight 這類「寫 meta」的工具要跟 write_query 共用同一顆 DB 才有意義。SQLite 的儲存(單檔、無 server、transactional)在這裡恰到好處——不像 MySQL/PG 要管理 daemon,也不像純 JSON 沒有聚合能力。
docker mcp tools call 是連到一個常駐 server」。其實每次呼叫都起一個新的 ephemeral gateway,而 SQLite server 容器每次也重新拉起來。如果你用 docker mcp tools call write_query 寫入,卻換一個終端機/換 profile 再 read_query,讀到的可能是不同 gateway 開的另一份 DB 檔(或連到不同 volume)。正確做法是把 DB 路徑固定在 /mcp/db.sqlite 與同一 named volume——否則「明明寫了卻讀不到」就是這個陷阱。| 症狀 | 可能原因 | 解決方案 |
|---|---|---|
| 寫入後立刻讀取讀不到資料 | 兩個呼叫用了不同 gateway / 不同 volume / 不同 DB 路徑 | 確認兩次呼叫都用 -v mcp-sqlite:/mcp 且 DB 路徑都是 /mcp/db.sqlite |
docker mcp tools count 沒增加 | gateway 以 dynamic-tools 模式執行,profile 尚未啟動 | 執行 docker mcp tools(用預設 profile 開 ephemeral gateway)或呼叫 mcp-activate-profile |
call: EOF 或 handshake 失敗 | server 容器缺 env、entrypoint binary 不存在(sqlite-mcp-server 的掛法) | 直接 docker run --rm -i -v mcp-sqlite:/mcp mcp/sqlite:latest --db-path /mcp/db.sqlite 看錯誤 |
| volume 裡有多顆 DB 檔,資料「散落」 | 不同工具/不同路徑各開了自己的 .db | docker run --rm -v mcp-sqlite:/mcp:ro alpine ls -la /mcp 檢查;統一 DB 路徑 |
| 解除安裝後重裝,舊資料還在 | docker mcp profile server remove 不會刪 volume | 手動 docker volume rm mcp-sqlite(不可逆,先確認不需要) |
-v $HOME/data:/mcp),持久化與備份的取捨會怎麼變?什麼場景下 bind mount 更好?graphify query 的「加權評分(IDF + trigram + 社群)」能在 SQL 裡重現嗎?如果可以,SQL 會多複雜;如果不可以,哪部分是 SQL 做不到的?DROP TABLE),你會在「MCP 工具層」還是「SQLite 層」做防護?設計一個最小防護方案。前面是把 SQLite MCP 當獨立工作區或即席分析後端。這次是完整的「圖→SQL→agent」管線:你的團隊要用 SQL 查知識圖譜,且 agent 要能自動化這個流程。
graphify extract corpus/——產出 graph.json(node-link 格式)。sqlite3 批次插入。把 DB 檔放進 Docker named volume mcp-sqlite。docker mcp profile server add default --server catalog://mcp/docker-mcp-catalog/SQLite——讓 agent 能用 SQL 查圖。docker mcp client connect claude-code 後,agent 可以用 read_query 跑「SELECT community, COUNT(*) FROM nodes GROUP BY community」看社群大小分佈,或「SELECT * FROM edges WHERE confidence='AMBIGUOUS'」列待審邊。graphify extract 更新圖後,自動跑匯出 script 更新 SQLite——用 cron 或 hook 確保圖與 SQL 同步。read_query 做跨維度分析(社群分佈、邊類型統計、god nodes 排名),而不只是 graphify query 的固定介面。Docker named volume 確保存續——重啟容器後分析成果還在。| 面向 | 考量 | 實務建議 |
|---|---|---|
| 效能 | Docker MCP 的 tools call 每次開新的 ephemeral gateway(~5 秒開銷) | 對高頻查詢改用常駐 MCP server 而非 tools call;SQLite 的 WAL 模式支持並發讀 |
| 品質 | 圖與 SQL 的同步延遲——graphify extract 更新圖後 SQL 還是舊的 | 用 hook 自動觸發匯出 script;在 SQL 查詢前驗證 graph.json 的 built_at_commit |
| 安全 | MCP 工具暴露給 agent 的是固定 6 個 SQLite 操作;agent 可能誤執行 DROP TABLE | 在 MCP 工具層做防護:只暴露 read_query(唯讀),或在 SQLite 層用 PRAGMA 限制寫入 |
| 面向 | 本文(Docker MCP + SQLite) | 相關文 | 差異說明 |
|---|---|---|---|
| MCP 部署 | Docker named volume + ephemeral gateway | 架構總覽 | 架構頁講 serve.py 的 MCP stdio server;Docker MCP 頁講容器化部署 |
| SQL 查詢 | read_query / write_query / create_table 等 6 個工具 | 運作原理 | 運作原理頁講圖的 query/path/explain 走訪;Docker MCP 頁講 SQL 即席查詢 |
| 儲存持久化 | Docker named volume mcp-sqlite → /mcp/db.sqlite | 增量更新 | 增量頁講 manifest.json 的持久化;Docker MCP 頁講 SQLite 的持久化 |
| 安全 | MCP transport 選擇 + 工具暴露範圍 | 安全模型 | 安全模型頁講 SSRF/XSS/prompt injection;Docker MCP 頁講 SQL 注入防護 |
docker mcp profile server add + docker pull),並用冒煙測試驗證docker mcp profile server remove + docker volume rm + docker rmi)