🚀 MCP代碼執行服務器:超100種MCP工具的零上下文發現

別再每次查詢花費30000個令牌了。此橋樑採用無特權安全機制實現了Anthropic的發現模式,在代理任何標準輸入輸出服務器的同時,將MCP上下文從30000個令牌減少到200個。

本項目是一個MCP代碼執行服務器,其核心功能是實現“代碼執行與MCP”模式,通過暴露單一工具run_python,讓大語言模型(LLM)以編寫Python代碼的方式來發現、調用和組合其他工具,有效解決了MCP令牌消耗過大的問題,同時在數據科學、安全性和隔離性等方面具有顯著優勢。
🚀 快速開始
1. 前提條件(macOS或Linux)
- 檢查版本:
python3 --version
- 若有需要,通過包管理器或 python.org 安裝Python 3.14
- macOS:
brew install podman 或 brew install --cask docker
- Ubuntu/Debian:
sudo apt-get install -y podman 或 curl -fsSL https://get.docker.com | sh
curl -LsSf https://astral.sh/uv/install.sh | sh
podman pull python:3.14-slim
docker pull python:3.14-slim
⚠️ 重要提示
關於Pydantic兼容性(Python 3.14):如果你使用Python 3.14,請確保安裝了最新的Pydantic版本(例如,pydantic >= 2.12.0)。一些較舊的Pydantic版本或從PyPI安裝了單獨的typing包的環境可能會引發如下錯誤:
TypeError: _eval_type() got an unexpected keyword argument 'prefer_fwd_module'
如果你遇到此錯誤,請運行:
pip install -U pydantic
pip uninstall typing
並重新運行項目設置(例如,刪除 .venv/ 並執行 uv sync)。
2. 安裝依賴項
使用uv同步項目環境:
uv sync
3. 啟動橋樑
uvx --from git+https://github.com/elusznik/mcp-server-code-execution-mode mcp-server-code-execution-mode run
如果你更喜歡從本地檢出的代碼運行,等效命令如下:
uv run python mcp_server_code_execution_mode.py
4. 向你的代理註冊
將以下服務器配置添加到你的代理的MCP設置文件(例如,mcp_config.json、claude_desktop_config.json等)中:
{
"mcpServers": {
"mcp-server-code-execution-mode": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/elusznik/mcp-server-code-execution-mode",
"mcp-server-code-execution-mode",
"run"
],
"env": {
"MCP_BRIDGE_RUNTIME": "podman"
}
}
}
}
5. 執行代碼
result = await mcp_filesystem.read_file(path='/tmp/test.txt')
data = await mcp_search.search(query="TODO")
await mcp_github.create_issue(repo='owner/repo', title=data.title)
顯式加載服務器
run_python 僅加載你請求的MCP服務器。在調用該工具時,通過 servers 數組傳遞這些服務器,以便諸如 mcp_serena 或 mcp_filesystem 之類的代理在沙箱內可用:
{
"code": "print(await mcp_serena.search(query='latest AI papers'))",
"servers": ["serena", "filesystem"]
}
如果你省略該列表,發現助手仍會枚舉所有內容,但任何針對未加載服務器的RPC調用將返回 Server '<name>' is not available。
⚠️ 重要提示
servers 數組僅控制為沙箱調用生成哪些代理,它不會設置服務器配置字段(如 cwd)。cwd 屬性是主機/服務器配置的一部分,LLM應調用 runtime.describe_server(name) 或檢查 runtime.list_loaded_server_metadata() 以在假定服務器的工作目錄之前發現配置的 cwd。
✨ 主要特性
與JS “代碼模式”的比較
雖然有基於JavaScript的替代方案(如 universal-tool-calling-protocol/code-mode),但本項目是為 數據科學 和 安全性 而構建的:
| 特性 |
本項目(Python) |
JS代碼模式(Node.js) |
| 原生語言 |
Python(AI/ML領域的語言) |
TypeScript/JavaScript |
| 數據科學 |
原生支持(pandas、numpy、scikit-learn) |
無法實現/需使用技巧 |
| 隔離性 |
強隔離(Podman/Docker容器) |
弱隔離(Node.js虛擬機) |
| 安全性 |
企業級(無特權、無網絡、只讀) |
進程級 |
| 設計理念 |
基礎設施(獨立橋樑) |
庫(可嵌入) |
💡 使用建議
如果你希望你的代理分析數據、生成圖表、使用科學庫,或者需要嚴格的基於容器的隔離來運行不可信代碼,請選擇本項目。
解決的問題(其他方案無法解決的)
MCP令牌耗盡之痛
將Claude連接到11個MCP服務器,約100個工具,每個提示需要加載 30000個令牌 的工具模式。在你提出任何問題之前,每次查詢就需要花費 0.09美元。擴展到50個服務器時,上下文窗口就會 崩潰。
現有“解決方案”為何失敗
- Docker MCP網關:容器管理出色,但仍將 所有工具模式 流式傳輸到Claude的上下文中,沒有進行令牌優化。
- Cloudflare代碼模式:V8隔離速度快,但 無法代理現有的MCP服務器(Serena、Wolfram、自定義工具),存在平臺鎖定問題。
- 學術論文:描述了Anthropic的發現模式,但 沒有提供可靠的實現。
- 概念驗證:忽略了安全性(無特權)、持久性(冷啟動)和代理邊緣情況。
解決方案:以發現為優先的架構
- 恆定的200令牌開銷,無論服務器數量多少
- 代理任何標準輸入輸出MCP服務器 到無特權容器中
- 跨服務器模糊搜索,無需預加載模式
- 經過生產驗證,具備能力丟棄和安全隔離功能
架構差異
傳統MCP(上下文受限)
┌─────────────────────────────┐
│ LLM上下文(30000個令牌) │
│ - serverA.tool1: {...} │
│ - serverA.tool2: {...} │
│ - serverB.tool1: {...} │
│ - …(更多工具) │
└─────────────────────────────┘
↓
LLM選擇工具
↓
工具執行
本橋樑(以發現為優先)
┌─────────────────────────────┐
│ LLM上下文(約200個令牌) │
│ “使用discovered_servers(), │
│ query_tool_docs(), │
│ search_tool_docs()” │
└─────────────────────────────┘
↓
LLM發現服務器
↓
LLM加載模式
↓
LLM編寫Python代碼
↓
橋樑代理執行
結果:恆定的開銷。無論你管理10個還是1000個工具,系統提示始終保持合適的大小,模式僅在需要時加載。
功能對比
| 功能 |
Docker MCP網關 |
Cloudflare代碼模式 |
研究模式 |
本橋樑 |
| 解決令牌膨脹問題 |
❌ 手動預加載 |
❌ 固定目錄 |
❌ 僅停留在理論層面 |
✅ 運行時發現 |
| 通用MCP代理 |
✅ 容器 |
⚠️ 特定平臺 |
❌ 未提供 |
✅ 任何標準輸入輸出服務器 |
| 無特權安全機制 |
⚠️ 可選 |
✅ V8隔離 |
❌ 未解決 |
✅ 丟棄能力的沙箱 |
| 自動發現 |
⚠️ 受目錄限制 |
❌ 不適用 |
❌ 未實現 |
✅ 9種配置路徑 |
| 工具文檔搜索 |
❌ |
❌ |
⚠️ 概念性 |
✅ search_tool_docs() |
| 生產驗證 |
⚠️ 取決於你 |
✅ 託管服務 |
❌ 原型 |
✅ 經過測試的橋樑 |
與動態工具集(Speakeasy)的比較
Speakeasy的 動態工具集 使用三步流程:search_tools → describe_tools → execute_tool。雖然這節省了令牌,但會迫使代理進入“冗長”的循環:
- 搜索:“查找處理GitHub問題的工具”
- 描述:“獲取
create_issue 的模式”
- 執行:“調用
create_issue”
本橋樑(以代碼為優先)簡化了這個循環:
- 代碼:“導入
mcp_github,搜索‘issues’,如果不存在則創建一個。”
代理編寫 單個Python腳本,在一次往返中完成發現、邏輯和執行。它更快、更便宜(減少了中間LLM調用),並且能夠處理複雜邏輯(循環、重試),而簡單的“執行”工具無法做到。
與OneMCP(Gentoro)的比較
OneMCP 提供了一個“手冊”聊天界面,你可以在其中提問並計劃執行。這對於簡單查詢很有用,但會使執行過程變成一個 黑盒。
本橋樑 為代理提供 原始的、沙箱化的控制。代理不再要求黑盒“執行任務”,而是成為程序員,編寫與API交互的精確代碼。這允許精確處理邊緣情況和進行復雜的數據處理,而自然語言規劃器可能會遺漏這些。
獨特特性
-
兩階段發現 – discovered_servers() 揭示存在的服務器;query_tool_docs(name) 僅加載你需要的模式。
-
跨服務器模糊搜索 – 讓模型無需記憶目錄名稱即可找到工具:
from mcp import runtime
matches = await runtime.search_tool_docs("calendar events", limit=5)
for hit in matches:
print(hit["server"], hit["tool"], hit.get("description", ""))
-
零拷貝代理 – 每個工具調用都在沙箱內進行,通過標準輸入輸出嚴格超時鏡像。
-
默認無特權 – Podman/Docker容器以 --cap-drop=ALL 運行,根目錄只讀,無新特權,並具有顯式的內存/PID上限。
-
緊湊 + TOON輸出 – 大多數運行返回最小的純文本響應,可通過 MCP_BRIDGE_OUTPUT_MODE=toon 獲取確定性的TOON塊。
適用人群
- 管理兩位數MCP服務器且無法承受上下文膨脹的團隊。
- 編排循環、重試和條件語句而非單個工具調用的代理。
- 需要為LLM生成的代碼提供無特權隔離的安全意識較強的運維人員。
- 希望重用現有MCP目錄而無需手動策劃清單的從業者。
設計理念:“無MCP”方法
本服務器遵循 你可能根本不需要MCP 的理念,對於每個小工具都如此。與其為簡單任務構建剛性的MCP服務器,你可以使用本服務器為你的代理提供對Bash和Python的 原始、沙箱化訪問。
- 臨時工具:需要一個腳本來抓取網站或解析文件?只需編寫並運行它,無需部署新的MCP服務器。
- 可組合性:在命令之間管道輸出,將中間結果保存到文件中,並使用標準Unix工具。
- 安全性:與直接給代理訪問你的機器的原始shell不同,本服務器在安全的、無特權的容器中運行所有內容。你可以獲得“Bash/代碼”的強大功能而無需承擔風險。
關鍵特性
🛡️ 健壯性與可靠性
- 懶運行時檢測:即使Podman/Docker未準備好,也能立即啟動。僅在請求代碼執行時檢查運行時。
- 自引用預防:自動檢測並跳過會遞歸啟動橋樑的配置。
- 噪聲過濾:忽略來自健談的MCP客戶端的良性JSON解析錯誤(如空行)。
- 智能卷共享:探測Podman虛擬機以確保卷共享正常工作,即使在舊版本中也是如此。
🔒 安全至上
- 無特權容器 - 無需特權輔助程序
- 網絡隔離 - 無網絡訪問
- 只讀文件系統 - 不可變根目錄
- 丟棄能力 - 無系統訪問
- 無特權用戶 - 以UID 65534運行
- 資源限制 - 內存、PID、CPU、時間
- 自動清理 - 臨時IPC目錄
⚡ 性能
- 持久會話 - 跨調用保留變量和狀態
- 持久客戶端 - MCP服務器保持熱啟動
- 上下文效率 - 與傳統MCP相比,減少95%以上
- 異步執行 - 合理管理資源
- 單一工具 - Claude上下文中僅存在
run_python
🔧 開發者體驗
響應格式
- 默認(緊湊) – 響應以純文本呈現,外加一個最小的
structuredContent 有效負載,僅包含非空字段。stdout/stderr 行保持不變,因此提示保持簡潔,同時不犧牲內容。
- 可選TOON – 設置
MCP_BRIDGE_OUTPUT_MODE=toon 以發出 面向令牌的對象表示法 塊。我們仍然丟棄空字段,並在 structuredContent 中鏡像相同的結構;當你需要為下游提示進行確定性令牌化時,TOON很方便。
- 回退JSON – 如果TOON編碼器不可用,我們會自動回退到漂亮的JSON塊,同時保留修剪後的有效負載。
發現工作流
- 工具模式中的
SANDBOX_HELPERS_SUMMARY 僅宣傳發現助手(discovered_servers()、list_servers()、query_tool_docs()、search_tool_docs() 等)。它從不包含單個服務器或工具的文檔。
- 首次使用時,LLM通常調用
discovered_servers()(或 list_servers_sync() 獲取緩存列表)來枚舉MCP服務器,然後調用 query_tool_docs(server) / query_tool_docs_sync(server) 或 search_tool_docs("keyword") / search_tool_docs_sync("keyword") 來獲取相關的文檔子集。
- 工具元數據按需流式傳輸,無論安裝了多少服務器或工具,系統提示始終保持在大約200個令牌左右。
- 一旦LLM獲得所需的文檔,它就會編寫Python代碼,使用生成的
mcp_<alias> 代理或 mcp.runtime 助手來調用工具。
💡 使用建議
如果你需要簡短描述而不探查助手,請調用 runtime.capability_summary() 以打印一段適合回答諸如“代碼執行MCP可以做什麼?”之類問題的概述。
📦 安裝指南
環境變量
| 變量 |
默認值 |
描述 |
MCP_BRIDGE_RUNTIME |
auto |
容器運行時(podman/docker) |
MCP_BRIDGE_IMAGE |
python:3.14-slim |
容器鏡像 |
MCP_BRIDGE_TIMEOUT |
30s |
默認超時時間 |
MCP_BRIDGE_MAX_TIMEOUT |
120s |
最大超時時間 |
MCP_BRIDGE_MEMORY |
512m |
內存限制 |
MCP_BRIDGE_PIDS |
128 |
進程限制 |
MCP_BRIDGE_CPUS |
- |
CPU限制 |
MCP_BRIDGE_CONTAINER_USER |
65534:65534 |
以UID:GID運行 |
MCP_BRIDGE_RUNTIME_IDLE_TIMEOUT |
300s |
關閉延遲 |
MCP_BRIDGE_STATE_DIR |
~/MCPs |
主機目錄,用於IPC套接字和臨時狀態 |
MCP_BRIDGE_OUTPUT_MODE |
compact |
響應文本格式(compact 或 toon) |
MCP_BRIDGE_LOG_LEVEL |
INFO |
橋樑日誌詳細程度 |
服務器發現
主要位置
⚠️ 重要提示
目前 推遲 了對掃描單個代理配置文件(例如,.claude.json、.vscode/mcp.json)的支持。請將所有MCP服務器定義的 .json文件放在 ~/MCPs 目錄中,以確保它們被發現。
示例服務器(~/MCPs/filesystem.json)
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
}
}
}
⚠️ 重要提示
為防止遞歸啟動,橋樑會自動跳過任何似乎會再次啟動 mcp-server-code-execution-mode 的配置項(包括 uvx … mcp-server-code-execution-mode run)。如果你有意需要將橋樑作為嵌套MCP服務器暴露,請設置 MCP_BRIDGE_ALLOW_SELF_SERVER=1。
Docker MCP網關集成
當你依賴 docker mcp gateway run 來暴露第三方MCP服務器時,橋樑只需執行網關二進制文件。網關負責拉取工具鏡像並連接標準輸入輸出傳輸,因此請確保主機環境準備就緒:
- 為網關目錄中引用的每個註冊表運行
docker login(例如,Docker Hub mcp/* 鏡像、ghcr.io/github/github-mcp-server)。如果沒有緩存的憑證,拉取步驟將在任何工具上線之前失敗。
- 為這些服務器提供所需的機密信息 ——
github-official 需要 github.personal_access_token,其他服務器可能需要API密鑰或認證令牌。使用 docker mcp secret set <name>(或你的網關配置的任何機制),以便容器在啟動時看到這些值。
- 鏡像目錄所需的任何卷掛載或環境變量(文件系統路徑、存儲卷等)。缺少掛載或憑證通常會在標準輸入輸出握手期間顯示為
failed to connect: calling "initialize": EOF。
- 如果
list_tools 僅返回內部管理助手(mcp-add、code-mode 等),則網關從未完成初始化外部服務器 —— 檢查網關日誌以查找缺少的機密信息或註冊表訪問錯誤。
狀態目錄與卷共享
- 運行時工件(包括生成的
/ipc/entrypoint.py 和相關握手元數據)默認位於 ~/MCPs/ 下。設置 MCP_BRIDGE_STATE_DIR 以重新定位它們。
- 當選擇的運行時是Podman時,橋樑會自動執行
podman machine set --rootful --now --volume <state_dir>:<state_dir>,以便虛擬機可以掛載該目錄。在不支持 --volume 的舊版 podman machine 構建中,橋樑現在會使用 podman machine ssh test -d <state_dir> 探測虛擬機,如果共享已經可用則繼續執行。
- Docker Desktop不提供文件共享的CLI;在運行橋樑之前,請確保所選的狀態目錄在Docker Desktop → 設置 → 資源 → 文件共享中標記為共享。
- 要手動驗證共享,請運行
docker run --rm -v ~/MCPs:/ipc alpine ls /ipc(或Podman等效命令)並確認文件可見。
💻 使用示例
基礎用法
文件處理
files = await mcp_filesystem.read_file(path='/tmp/test.txt')
for file in files:
content = await mcp_filesystem.read_file(path=file)
if 'TODO' in content:
print(f"TODO in {file}")
高級用法
數據管道
transcript = await mcp_google_drive.get_document(documentId='abc123')
summary = transcript[:500] + "..."
await mcp_salesforce.update_record(
objectType='SalesMeeting',
recordId='00Q5f000001abcXYZ',
data={'Notes': summary}
)
多系統工作流
issues = await mcp_jira.search_issues(project='API', status='Open')
for issue in issues:
details = await mcp_jira.get_issue(id=issue.id)
if 'bug' in details.description.lower():
await mcp_github.create_issue(
repo='owner/repo',
title=f"Bug: {issue.title}",
body=details.description
)
檢查可用服務器
from mcp import runtime
print("Discovered:", runtime.discovered_servers())
print("Cached servers:", runtime.list_servers_sync())
print("Loaded metadata:", runtime.list_loaded_server_metadata())
print("Selectable via RPC:", await runtime.list_servers())
loaded = runtime.list_loaded_server_metadata()
if loaded:
first = runtime.describe_server(loaded[0]["name"])
for tool in first["tools"]:
print(tool["alias"], "→", tool.get("description", ""))
if loaded:
summaries = await runtime.query_tool_docs(loaded[0]["name"])
detailed = await runtime.query_tool_docs(
loaded[0]["name"],
tool=summaries[0]["toolAlias"],
detail="full",
)
print("Summaries:", summaries)
print("Cached tools:", runtime.list_tools_sync(loaded[0]["name"]))
print("Detailed doc:", detailed)
results = await runtime.search_tool_docs("calendar events", limit=3)
for result in results:
print(result["server"], result["tool"], result.get("description", ""))
print("Capability summary:", runtime.capability_summary())
print("Docs from cache:", runtime.query_tool_docs_sync(loaded[0]["name"]) if loaded else [])
print("Search from cache:", runtime.search_tool_docs_sync("calendar"))
運行上述代碼片段時,LLM看到的示例輸出如下:
Discovered: ('stub',)
Loaded metadata: ({'name': 'stub', 'alias': 'stub', 'tools': [{'name': 'echo', 'alias': 'echo', 'description': 'Echo the provided message', 'input_schema': {...}}]},)
Selectable via RPC: ('stub',)
更喜歡 listMcpResources 的客戶端可以跳過執行助手代碼片段,而是請求 resource://mcp-server-code-execution-mode/capabilities 資源。服務器通過 resources/list 宣傳該資源,讀取該資源將返回相同的助手摘要以及一個用於顯式加載服務器的簡短清單。
📚 詳細文檔
- README.md - 本文件,快速入門
- GUIDE.md - 全面的用戶指南
- ARCHITECTURE.md - 技術深度剖析
- HISTORY.md - 發展歷程與經驗教訓
- STATUS.md - 當前狀態與路線圖
🔧 技術細節
架構
┌─────────────┐
│ MCP客戶端 │ (你的代理)
└──────┬──────┘
│ 標準輸入輸出
▼
┌──────────────┐
│ MCP代碼執行 │ ← 發現、代理、管理
│ 橋樑 │
└──────┬──────┘
│ 容器
▼
┌─────────────┐
│ 容器 │ ← 以嚴格隔離方式執行
│ 沙箱 │
└─────────────┘
零上下文發現
與傳統的MCP服務器預加載每個工具定義(有時超過30000個令牌)不同,本橋樑將系統提示固定在大約200個令牌左右,並訓練LLM按需發現所需內容:
- LLM調用
discovered_servers() → 瞭解哪些橋樑可用,而無需加載模式。
- LLM調用
query_tool_docs("serena") → 僅加載該服務器的工具文檔,可根據工具進行過濾。
- LLM編寫編排代碼 → 調用助手,如
mcp_serena.search() 或 mcp.runtime.call_tool()。
結果:無論配置多少個MCP服務器,上下文使用量始終保持有效恆定。
過程:
- 客戶端調用
run_python(code, servers, timeout)
- 橋樑加載請求的MCP服務器
- 準備沙箱調用:收集MCP工具元數據,將入口點寫入共享的
/ipc 卷,並導出 MCP_AVAILABLE_SERVERS
- 生成的入口點將標準輸入輸出重新連接到JSON幀消息,並通過容器的標準輸入/標準輸出管道代理MCP調用
- 持久執行:容器啟動一次(如果未運行)並保持活動狀態。
- 狀態保留:一次調用中定義的變量、導入和函數在後續調用中可用。
- 主機流處理程序處理JSON幀,轉發MCP流量,強制執行超時,並使容器保持活動狀態以處理下一個請求。
📄 許可證
GPLv3許可證
支持
如有問題或疑問,請參閱文檔或提交問題。