Docker MCP Toolkit + SQLite

一個可重現的 runbook:把 SQLite MCP server 裝進 Docker Desktop 的 MCP Toolkit
來源:docs/docker-mcp-sqlite.md
先聲明:這份文件不是使用 graphify 的必要條件——它住在 repo 裡,是一份「已知可用」的食譜,給想在同一個 MCP 環境旁放一個輕量 SQL 工作區的使用者。

能得到什麼

裝完之後,任何連到 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狀態
SQLitemcp/sqlitecatalog metadata 標「Archived」,但能啟動且正確服務
sqlite-mcp-servermcp/sqlite-mcp-server壞掉:entrypoint /app/.venv/bin/mcp-server-sqlite 在發布層不存在

SQLitemcp/sqlite)直到上游修好新 image。

前置需求

安裝

# 把可用的 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: fetchname: 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 工具呼叫寫的資料,下一個呼叫看得到。

接進 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

疑難排解

為什麼這份文件值得教:它是一份「小而完整的工具 runbook」範本——動機、選型理由(含壞 image 的陷阱)、前置、安裝、驗證、儲存、接線、解除、疑難排解。類似的可重現 step-by-step 寫法,也用在 實作案例 的重現步驟上。

教學解說

這份 runbook 展示了「如何把一個 MCP server 裝進 Docker MCP Toolkit」。MCP(Model Context Protocol)是 AI 代理與外部工具溝通的協議,Docker MCP Toolkit 讓你用容器化方式管理多個 MCP server。

選型理由很重要:catalog 有兩個 SQLite MCP image,但只有一個能動。這反映了「開源工具的可靠性需要實測驗證」的現實。用 SQLitemcp/sqlite)直到上游修好新 image。

儲存布局用 Docker named volume,確保資料在容器重啟後仍然存在。這是「無狀態容器 + 有狀態儲存」的標準模式。

Worked Example:從零安裝 SQLite MCP

  1. 確認 Docker:執行 docker info 確認 Docker Desktop 執行中。
  2. 安裝 server:執行 docker mcp profile server add default --server catalog://mcp/docker-mcp-catalog/SQLite
  3. 拉取 image:執行 docker pull mcp/sqlite:latest
  4. 驗證安裝:執行 docker mcp profile show default,確認看到 SQLite。
  5. 冒煙測試:執行 docker mcp tools call create_table query='CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, name TEXT)'
  6. 接進客戶端:執行 docker mcp client connect claude-code
預期結果:Claude Code 現在可以用 SQLite 工具讀取和寫入資料庫。

常見錯誤與診斷

錯誤訊息原因解決方式
starting client: calling "initialize": EOFMCP 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 increasinggateway 以 dynamic-tools 執行執行 docker mcp tools 或從 MCP session 內呼叫 mcp-activate-profile
entrypoint not found用了壞掉的 sqlite-mcp-server image改用 mcp/sqlite:latest

練習與驗收清單

① 進階真實情境 Worked Example:用 SQLite MCP 當 graphify-out 的「即席分析」後端

前面的 runbook 把 SQLite 當獨立工作區;這次把兩者合起來:graph.json 建好後,用 SQLite MCP 對圖資料做 SQL 即席查詢——例如「哪個節點的 degree 最高」「某個社群有哪些節點」「哪些邊是 AMBIGUOUS 待人工檢視」。

  1. 匯出圖資料graphify export 產出 graphify-out/graph.json(node-link 格式)。
  2. 建 SQLite schema:用 docker mcp tools call create_table 建立 nodes(id,label,file_type,community,degree)與 edges(source,target,relation,confidence)兩張表。
  3. 灌資料:寫個小 script 把 graph.json 攤平,用 docker mcp tools call write_query(或 sqlite3 CLI)批次插入。
  4. 即席分析read_query 跑「SELECT … GROUP BY community ORDER BY COUNT(*) DESC」看社群大小分佈、或「SELECT * FROM edges WHERE confidence='AMBIGUOUS'」列待審邊。
  5. 接進 agentdocker mcp client connect claude-code 後,你的 agent 就能用 SQL 語言查知識圖譜,而不只是 graphify query 的固定介面。
為什麼選這條路徑:graphify 的查詢(query/path/explain)是「設計好的走訪」,但跨維度的資料分析(分佈、聚合、Join)是 SQL 的主場。把圖倒進 SQLite 讓你拿到第二個查詢語言,且不影響 graphify 本體;而 Docker named volume 確保存續——重啟容器後分析成果還在。這是一條「工具拼裝」的路徑,示範 MCP 生態怎麼補足單一工具的盲點。

② 深入原理擴充:MCP 生命周期、named volume 持久化、與「無狀態 vs 有狀態」的界線

這份 runbook 的技術核心其實是三個「生命周期」:

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 檔,資料「散落」不同工具/不同路徑各開了自己的 .dbdocker run --rm -v mcp-sqlite:/mcp:ro alpine ls -la /mcp 檢查;統一 DB 路徑
解除安裝後重裝,舊資料還在docker mcp profile server remove 不會刪 volume手動 docker volume rm mcp-sqlite(不可逆,先確認不需要)

④ 進階挑戰題

  1. 這份 runbook 用 Docker named volume 存 SQLite。如果改用 bind mount(-v $HOME/data:/mcp),持久化與備份的取捨會怎麼變?什麼場景下 bind mount 更好?
  2. 把 graph.json 倒進 SQLite 後,graphify query 的「加權評分(IDF + trigram + 社群)」能在 SQL 裡重現嗎?如果可以,SQL 會多複雜;如果不可以,哪部分是 SQL 做不到的?
  3. MCP 工具暴露給 agent 的是固定 6 個 SQLite 操作。若要防止 agent 誤執行破壞性 SQL(如 DROP TABLE),你會在「MCP 工具層」還是「SQLite 層」做防護?設計一個最小防護方案。

① 專案級端到端 Worked Example:從 graph.json 到 SQLite 即席分析再到 agent 查詢

前面是把 SQLite MCP 當獨立工作區或即席分析後端。這次是完整的「圖→SQL→agent」管線:你的團隊要用 SQL 查知識圖譜,且 agent 要能自動化這個流程。

  1. 建圖graphify extract corpus/——產出 graph.json(node-link 格式)。
  2. 匯出到 SQLite:寫一個 Python script 把 graph.json 攤平成 nodes(id, label, file_type, community, degree)和 edges(source, target, relation, confidence)兩張表,用 sqlite3 批次插入。把 DB 檔放進 Docker named volume mcp-sqlite
  3. 建立 MCP 工具docker mcp profile server add default --server catalog://mcp/docker-mcp-catalog/SQLite——讓 agent 能用 SQL 查圖。
  4. Agent 查詢docker mcp client connect claude-code 後,agent 可以用 read_query 跑「SELECT community, COUNT(*) FROM nodes GROUP BY community」看社群大小分佈,或「SELECT * FROM edges WHERE confidence='AMBIGUOUS'」列待審邊。
  5. 持續同步:每次 graphify extract 更新圖後,自動跑匯出 script 更新 SQLite——用 cron 或 hook 確保圖與 SQL 同步。
預期產出:一份「SQL 可查」的知識圖譜,agent 能用 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.jsonbuilt_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 注入防護

④ 互動式檢核清單