Start deploying
·4 min read·a2a cloud

Wire an MCP Server to Your Agent (With Zero Config)

The Model Context Protocol lets any client call your agent as a tool — but only if something hosts, authenticates, and keeps the MCP server in sync with your code. On a2a cloud that server is generated from your agent's skills on every deploy. Here's how it works.

mcpmodel context protocolai agentsagent toolstool callingcapabilitya2a cloudagent infrastructure

Wire an MCP Server to Your Agent (With Zero Config)

The Model Context Protocol has become the default way to hand tools and context to an agent. The appeal is obvious: write a tool once, expose it over MCP, and any MCP-speaking client — Claude, an IDE, another agent — can call it without a bespoke integration.

The part nobody puts on the slide is that an MCP *server* is a real service. Someone has to host it, authenticate callers, scope what each caller can reach, and — the tedious one — keep the tool schemas in lockstep with the code they wrap. Change a function signature, forget to update the server, and callers break in ways your type checker never sees.

On a2a cloud you don't stand up that server. Every agent's skills are exposed as MCP tools automatically, on every deploy, from the same source of truth as the code. This post is what that actually means and where the edges are.

The manual version, so the savings are concrete

Doing this by hand for one agent looks like:

  1. Pick or write an MCP server framework and mount it somewhere with a public, TLS-terminated URL.
  2. For each tool, hand-author an MCP tool definition — name, description, JSON Schema for inputs and outputs.
  3. Wire auth: decide who may connect, mint and rotate credentials, and enforce scopes so a caller can't invoke tools it shouldn't.
  4. Marshal every call from MCP into your function and the return value back out.
  5. Keep 1–4 in sync forever as the agent changes.

Step 5 is where it rots. The schema drifts from the implementation, and the failure is silent until a client sends what the *old* schema promised was valid.

What a2a does instead

Your agent is a class with @skill methods. The signature and docstring of each skill are the tool definition:

Python
from a2a_pack.agent import A2AAgent, skill
from a2a_pack.context import RunContext, NoAuth

class Researcher(A2AAgent[dict, NoAuth]):
    name = "researcher"
    description = "A research agent"

    @skill(description="Answer a research question and return sources")
    async def ask(self, ctx: RunContext[NoAuth], question: str) -> dict:
        # your logic — LLM calls, tools, a LangGraph graph, whatever
        return {"answer": "...", "sources": ["..."]}

When you run a2a deploy, the platform reads the skill signatures and generates the MCP tool schema from them: ask becomes an MCP tool, question: str becomes a required string input, the dict return becomes the output shape, and the description becomes the tool description an LLM sees when it decides whether to call it. There is no second file to maintain — the schema *is* the code, so it can't drift.

The generated server is mounted at a stable URL with the rest of the agent's surfaces (the HTTP/OpenAPI API, the agent card at /.well-known/agent-card, SSE streaming). You get all of it from the same three commands that deploy the agent:

Text
a2a init researcher
cd researcher
a2a deploy

Connecting a client

Once the agent is live, point any MCP client at the gateway. Locally the fastest path is the bundled gateway:

Text
npx -y a2amcp

That exposes your enabled agents as MCP tools to whatever client you've wired it into. For remote/programmatic use there's a hosted connector endpoint (https://api.a2acloud.io/connector-mcp) that speaks MCP over HTTP. Either way the client sees a tool per skill, named and typed from your code.

The two things this quietly gets right

Auth and scope aren't an afterthought. Because the MCP server is provisioned with the agent, it inherits the platform's grant model — a caller reaches the tools it's been granted and nothing across the boundary to another agent. You aren't bolting authentication onto a tool server you wrote at 2am. (The same isolation that keeps each agent's [database private](/blog/give-ai-agents-database-access-without-handing-over-production) applies to its tool surface.)

Every tool call still emits a signed receipt. An MCP tool call is a run like any other, so it produces an Ed25519-signed record of what was invoked, with what inputs, and what came back. When another agent calls yours over MCP, you don't have to trust its account of what happened — you have a cryptographic one. That's the difference between a [signed receipt and a trace log](/blog/signed-receipts-vs-trace-logs-agent-audit-trail): the receipt is verifiable by anyone, after the fact, without trusting the caller or the host.

Where this fits

If you're deploying a framework agent, the MCP server comes along for free — the [LangGraph](/blog/deploy-langgraph-agent-60-seconds), CrewAI, and OpenAI Agents SDK quickstarts all end with a live MCP surface without a line of server code. If you're starting from a bare Python class, [Build Your First A2A Agent](/blog/first-a2a-agent-python-to-url) walks the same path from class to live URL.

The throughline: MCP is a great protocol and a real amount of infrastructure. Generating the server from your skills on every deploy means you write the tool once — as a normal function — and the wire format, the hosting, the auth, and the audit trail are handled for you, and stay handled as the code changes.

Try it

Text
a2a init my-agent
cd my-agent   # add a @skill or two
a2a deploy
npx -y a2amcp   # your skills are now MCP tools

One function in, an authenticated, audited MCP tool out.

discussion

0 comments

Likes0Dislikes0
No comments yet.