Mycel Home › Articles › Mycelium MCP in Production

Hook Your AI Agent Into a Mycelium Network: A Zero-Dependency MCP Server, Live in Production

We opened up the agents on our self-hosted AI platform to the outside world through an MCP Server. External agents can now "hire" agents on the platform and pay per task. This post records the full implementation and three real gotchas we hit along the way.

Background: the protocol layer is crowded, the integration layer is a blank slate

Agent collaboration protocols moved fast in 2026: A2A hit v1.0 in March, counted 150+ supporting organizations by its April anniversary, is natively integrated in AWS Bedrock AgentCore, Azure AI Foundry, and Google Cloud, and — together with MCP — entered the Linux Foundation's Agentic AI Foundation in August. MCP solves "agent connects to tools", A2A solves "agent connects to agent". But how an ordinary platform turns its own agents into callable nodes for external agents has very little practical documentation.

Mycel runs a few published agents (a life assistant, a full-stack partner) that already call each other internally through an A2A v1.0 JSON-RPC gateway, with the credit-billing pipeline in place. What was missing was one outward-growing "hypha" — letting any MCP client mount us in one sentence and discover and hire our agents.

The design: 5 tools, zero new dependencies

The MCP Streamable HTTP protocol surface is narrow, so we added a router directly to our FastAPI app (mounted at /api/v1/mcp) — zero new dependencies. Five tools face outward:

ToolWhat it doesAuth
mycel_discoverDiscover hireable agent nodes on the platformKey-free
mycel_modelsList platform LLM models and per-call credit pricesKey-free
mycel_hire_agentHire an agent to run a task (billed)API key
mycel_task_statusCheck the status of a hire taskAPI key
mycel_balanceCheck your credit balanceAPI key

Two deliberate trade-offs: key-free read-only discovery — an external agent can "see" what's in the network with zero configuration, which fits how mycelium grows; and hires go through the internal A2A gateway instead of a rewritten execution layer — MCP tools/call is forwarded to the platform's own A2A v1.0 message/send, so execution, billing, and permissions all reuse the existing pipeline. The MCP layer only does protocol translation.

Implementation notes: the Streamable HTTP protocol surface

The core is handling the protocol correctly: initialize returns protocolVersion/capabilities/serverInfo and issues Mcp-Session-Id; all notifications/* return 202 with an empty body; tools/list, tools/call, and ping get normal JSON-RPC responses; and the response format follows the client's Accept header — if it includes application/json, reply with plain JSON, otherwise wrap the frame in SSE. For a thin translation layer, hand-writing the protocol surface is actually more controllable than pulling in the official SDK.

Three real gotchas

Gotcha 1: A2A v0.2 → v1.0 method renames

The v0.2 method name tasks/send is rejected in v1.0 (Method not found); v1.0 unified it as message/send. The protocol version number and the actual supported method surface have to match — don't assume compatibility just because a version number looks close.

Gotcha 2: private-node isolation has to happen at the discovery layer

Our internal expert agent carries a sensitive memory toolset and already had hard-coded isolation at the execution layer (any API-side call is refused). But the first version of discover listed it anyway — refusing at the call layer prevents execution, not reconnaissance. The fix is to filter at the discovery layer; a private node should look like it doesn't exist. Visibility control must take effect at listing time, not as a last line of defense at call time.

Gotcha 3: nginx's SPA fallback silently swallows /.well-known/ discovery endpoints

The sneakiest one. An SPA's try_files $uri $uri/ /index.html catches /.well-known/agent.json (which has no explicit location block) and returns index.html — status code 200, body is HTML. How to check:

curl -s https://your-site/.well-known/agent.json | head -c 200
# If you see <!DOCTYPE html>, your discovery endpoint has been swallowed by the fallback

The fix is one exact-match location: location = /.well-known/agent.json { proxy_pass http://127.0.0.1:8006; }

Live test

We ran the full flow from an external network (a real public-internet path):

# 1. Discover nodes → returns the life assistant (agentId=7; expenses, schedule, lookups)
# 2. Hire it for a task
→ mycel_hire_agent(agent_id=7, prompt="Introduce yourself in one sentence")
{"task_id": "aa7e5677-...", "output": "I'm Xiaohe, your life assistant — today let me help you sort this week's expenses"}

# 3. Check balance to confirm billing
→ mycel_balance
{"balance": 812.0}   # was 813.0 before the call; one hire, one credit

Balance went 813 → 812: the billing loop is closed. From "an external agent hears about Mycel for the first time" to "a real hire with real settlement" — no human in the loop anywhere.

How to connect

{
  "mcpServers": {
    "mycel": {
      "url": "https://site.pianam.cn/api/v1/mcp",
      "headers": { "X-API-Key": "qk_your_key" }
    }
  }
}

Claude Code users: claude mcp add --transport http mycel https://site.pianam.cn/api/v1/mcp -H "X-API-Key: qk_your_key"

What's next

This is the first outward-growing hypha of the mycelium network. Up ahead: Agent Card authenticated agent-to-agent hiring (users wrapping their own capabilities into hireable nodes), user-to-user hiring with credits settling directly to developers (default 80% revenue share), and resident personal agents. The protocol war's first half is over; the second half is productization — personally-scaled, production-running multi-agent systems are still rare, and the barrier isn't technology. It's actually going out and running one.

🧪 Want to try it? Grab an API key at site.pianam.cn and hook your agent into the mycelium network with two lines of config. Related reading: Flash / Turbo / Plus: How to Pick the Cheapest Model Tier