给你的 AI Agent 接上"菌丝网络":一个零依赖 MCP Server 的实战
给你的 AI Agent 接上"菌丝网络":一个零依赖 MCP Server 的实战
我们把自建 AI 平台上的智能体,通过一个 MCP Server 开放给了全世界的外部 Agent。外部 agent 现在可以"雇佣"我们平台上的智能体干活,按次扣积分结算。这篇文章记录完整的实现过程和三个真实的坑。
背景:协议层已经很热闹,接入层还是毛坯房
2026 年智能体协作协议层的进展很快:A2A(Agent2Agent)协议 3 月出 v1.0,4 月一周年时已有 150+ 组织支持,AWS Bedrock AgentCore、Azure AI Foundry、Google Cloud 全部原生集成,8 月又和 MCP 一起进了 Linux 基金会旗下的 Agentic AI Foundation。
但协议成熟不等于你能用起来。对个人开发者来说,真实的处境是:
- MCP 解决"agent 连接工具",生态已经起来;
- A2A 解决"agent 连接 agent",标准有了,但普通平台怎么把自己的 agent 变成外部 agent 可调用的节点,实践资料很少。
我们自建的 AI 平台 Mycel 上跑着几个发布状态的智能体(一个生活秘书、一个全栈搭档),内部通过 A2A v1.0 JSON-RPC 网关(message/send)互相调用,积分计费链路也是现成的。缺的是一根对外的"菌丝"——让任何 MCP 客户端(Claude Code、OpenClaw、Cursor、Codex CLI……)一句话挂载,就能发现并雇佣平台上的智能体。
于是我们写了 mycel-mcp。
方案:5 个工具,零新增依赖
MCP Streamable HTTP 传输的协议面其实很窄,我们直接在 FastAPI 主应用里加了一个 router(挂 /api/v1/mcp),没有引入任何新依赖,只用了主后端已有的 fastapi 和 httpx。
对外暴露 5 个工具:
| 工具 | 作用 | 鉴权 |
|---|---|---|
mycel_discover |
发现平台上可雇佣的智能体节点 | 免 Key |
mycel_models |
查平台 LLM 模型与积分单价 | 免 Key |
mycel_hire_agent |
雇佣智能体执行任务(扣积分) | API Key |
mycel_task_status |
查雇佣任务状态 | API Key |
mycel_balance |
查积分余额 | API Key |
设计上有两个取舍值得一提:
1. 免 Key 的只读发现。discover 和 models 不要求 API Key,外部 agent 挂载后不配置任何凭证也能"看到"网络里有什么——这符合菌丝的生长逻辑:先让孢子落到你门口,再谈合作。写操作类工具一律要 Key。
2. 雇佣走内部 A2A,不重写执行层。mycel_hire_agent 收到请求后,转发为平台自己的 A2A v1.0 message/send 调用。执行、扣费、权限校验全部复用现有链路,MCP 层只做协议翻译。一行伪代码:
MCP tools/call(mycel_hire_agent)
→ POST /api/v1/a2a (JSON-RPC message/send, 透传 X-API-Key)
→ agent runtime 执行 → 积分扣费 → 返回 artifacts
实现要点:Streamable HTTP 协议面
整个协议面 200 行左右。核心是正确处理这几件事:
initialize→ 返回protocolVersion、capabilities、serverInfo,并下发Mcp-Session-Id响应头;- 所有
notifications/*(无 id)→ 返回 202 空体; tools/list/tools/call/ping→ 正常 JSON-RPC 响应;- 响应格式按客户端
Accept头决定:包含application/json就直接回 JSON,否则用 SSE 单帧包裹(data: {...}\n\n,text/event-stream)。
很多教程一上来就推官方 SDK,但对于这种"薄翻译层",手写协议面反而更可控——毕竟 MCP 客户端实现参差不齐,你能精确控制每个响应的形态。
三个真实的坑
坑一:A2A v0.2 → v1.0 的方法名变更。
我们的 A2A 网关写着 protocolVersion 1.0,但 MCP 层第一次调用时用了 v0.2 时代的方法名 tasks/send,直接被拒绝:Method not found: tasks/send。v1.0 规范里任务创建统一叫 message/send,tasks/get、tasks/cancel 保留。协议版本号和实际支持的方法面要对齐,别只看版本号就以为兼容。
坑二:私有节点的隔离必须在"发现层"做,不是只在"调用层"。
我们有一个挂着敏感记忆工具集的内部专家智能体,在执行层有硬编码隔离(任何 API 侧调用一律拒绝)。但第一版 discover 把它也列出来了——名字、描述都暴露了。调用层拒绝只能防执行,防不了侦察。正确的做法是在发现层就过滤:私有节点应该像不存在一样。这条对所有做多租户 agent 平台的人都适用:可见性控制要在 listing 阶段生效,不能依赖调用阶段兜底。
坑三:nginx 的 SPA fallback 会安静地吞掉 /.well-known/ 发现端点。
这是最隐蔽的一个。我们的前端是 SPA,nginx 配了 location / { try_files $uri $uri/ /index.html; }。A2A 的 Agent Card 发现端点 /.well-known/agent.json 没有显式 location,于是被 try_files 兜底返回了 index.html——状态码 200,内容却是 HTML。外部 agent 拿到 200 还以为成功了,解析才发现不对。排查方法很简单但要刻意去做:
curl -s https://your-site/.well-known/agent.json | head -c 200
# 如果看到 <!DOCTYPE html>,你的发现端点已经被 fallback 吞了
修复就是加一条精确匹配:
location = /.well-known/agent.json { proxy_pass http://127.0.0.1:8006; }
实测实录
从外部网络(真实公网链路)挂载后跑完整流程:
# 1. 发现节点
→ mycel_discover
{"platform": "Mycel", "agents": [
{"agentId": 7, "name": "生活秘书", "description": "记账花销/日程提醒/吃穿住行查询/资料整理..."}]}
# 2. 雇佣它干活
→ mycel_hire_agent(agent_id=7, prompt="用一句话介绍你自己")
{"task_id": "aa7e5677-...", "output": "我是小禾,你的生活秘书,今天想帮你把这周的花销整理一下,省得月底乱糟糟。"}
# 3. 查余额确认计费
→ mycel_balance
{"balance": 812.0} # 调用前 813.0,一次雇佣扣 1 积分
余额 813 → 812,计费链路闭环。从"外部 agent 第一次听说 Mycel"到"真实雇佣并结算",全程无人工介入。
怎么接入
任何支持 MCP 的客户端,两行配置:
{
"mcpServers": {
"mycel": {
"url": "https://site.pianam.cn/api/v1/mcp",
"headers": { "X-API-Key": "qk_你的key" }
}
}
}
Claude Code 用户:
claude mcp add --transport http mycel https://site.pianam.cn/api/v1/mcp \
-H "X-API-Key: qk_你的key"
配好后你的 agent 就能直接说"帮我看看 Mycel 上有哪些智能体可以雇佣"。
下一步
这只是菌丝网络的第一根对外菌丝(外部 → 平台单向吸入)。往前的路:
- Agent Card 认证:用户把自己的能力包装成可雇佣节点,签名卡片跨边界互认;
- 用户 ↔ 用户雇佣:A 用户通过平台雇佣 B 用户发布的智能体,积分直接结算给 B(开发者分成体系已有,默认 80%);
- 常驻个人 agent:每个人都有自己的常驻 agent,代表自己参与协商——这是 Instinct、Pickle 那一层的事,等身份和结算基础设施再熟一点。
协议战争已经打完上半场(A2A 进基金会、云厂商原生支持),下半场是产品化。我们的判断是:个人规模跑生产的多智能体系统,现在还是稀缺品——而稀缺品的门槛不是技术,是动手把它跑起来。
Mycel 是一个个人运营的 AI 平台(site.pianam.cn),本文所有实测数据均为真实运行记录。

浙公网安备 33010602011771号