> For the complete documentation index, see [llms.txt](/llms.txt).
> A full single-fetch corpus is available at [llms-full.txt](/llms-full.txt).
---
title: Model Context Protocol
description: Connect external MCP servers to AGNT5 agents, or publish your AGNT5 functions, workflows, and agents as an MCP server.
last_verified: 2026-10-20
---



**Model Context Protocol (MCP)** is an open standard for connecting AI systems to external tools and data sources. AGNT5 supports it in both directions:

- **`MCPClient`** pulls tools from any external MCP server into your agents.
- **`MCPServer`** publishes your AGNT5 functions, workflows, and agents so any MCP-compatible client can call them.

## Connect external MCP servers

`MCPClient` connects to one or more MCP servers, discovers their tools, and converts those tools into AGNT5 `Tool` objects.



**Python:**

```python
from agnt5 import Agent
from agnt5.mcp import MCPClient

mcp = MCPClient(id="deepwiki-client")
mcp.add_streamable_http_server("deepwiki", "https://mcp.deepwiki.com/mcp")
await mcp.connect()

agent = Agent(
    name="researcher",
    model="openai/gpt-6-luna",
    instructions="Use available tools to answer questions about code repositories.",
    tools=mcp.get_tools(),
)

result = await agent.run("What is CPython and what is it written in?")
print(result.output)

await mcp.disconnect()
```

Use `async with` when you want the client to connect and disconnect around one block:

```python
from agnt5 import Agent
from agnt5.mcp import MCPClient

mcp = MCPClient(id="deepwiki-client")
mcp.add_streamable_http_server("deepwiki", "https://mcp.deepwiki.com/mcp")

async with mcp:
    agent = Agent(
        name="researcher",
        model="openai/gpt-6-luna",
        instructions="Use available tools to answer questions about code repositories.",
        tools=mcp.get_tools(),
    )
    result = await agent.run("What is CPython and what is it written in?")
    print(result.output)
```





**TypeScript:**

```typescript
import { Agent, LM, MCPClient } from '@agnt5/sdk';

const mcp = new MCPClient('deepwiki-client');
mcp.addStreamableHttpServer('deepwiki', 'https://mcp.deepwiki.com/mcp');
await mcp.connect();

const agent = new Agent({
  name: 'researcher',
  model: LM.openai(),
  modelName: 'openai/gpt-6-luna',
  instructions: 'Use available tools to answer questions about code repositories.',
  tools: mcp.getTools(),
});

const result = await agent.run('What is CPython and what is it written in?');
console.log(result.output);

await mcp.disconnect();
```

Call `connect()` and `disconnect()` explicitly, and wrap the work in `try`/`finally` so the client always disconnects:

```typescript
const mcp = new MCPClient('deepwiki-client');
mcp.addStreamableHttpServer('deepwiki', 'https://mcp.deepwiki.com/mcp');

try {
  await mcp.connect();

  const agent = new Agent({
    name: 'researcher',
    model: LM.openai(),
    modelName: 'openai/gpt-6-luna',
    instructions: 'Use available tools to answer questions about code repositories.',
    tools: mcp.getTools(),
  });
  const result = await agent.run('What is CPython and what is it written in?');
  console.log(result.output);
} finally {
  await mcp.disconnect();
}
```





**Go:**

```go
import "github.com/agnt5dev/sdk-go/agnt5"

transport := agnt5.NewSSEMCPTransport("https://mcp.deepwiki.com/mcp", nil)
mcp, err := agnt5.NewMCPClient(transport)
defer mcp.Close()

mcpTools, err := mcp.ListTools(ctx)
tools := make([]agnt5.Tool, 0, len(mcpTools))
for _, t := range mcpTools {
    t := t
    wrapped, err := agnt5.NewTool(t.Name, func(c context.Context, args map[string]any) (any, error) {
        return mcp.CallTool(c, t.Name, args)
    }, agnt5.WithToolDescription(t.Description), agnt5.WithToolSchema(t.InputSchema))
    if err != nil {
        return err
    }
    tools = append(tools, wrapped)
}

agent, err := agnt5.NewAgent("researcher",
    agnt5.WithAgentModel(model),
    agnt5.WithAgentInstructions("Use available tools to answer questions about code repositories."),
    agnt5.WithAgentTools(tools...),
    agnt5.WithAgentMaxTurns(5),
)

result, err := agent.Run(ctx, agnt5.AgentInput{Message: "What is CPython and what is it written in?"})
fmt.Println(result.Response)
```

Each discovered `MCPTool` (name, description, input schema) is wrapped with `agnt5.NewTool` so it can go on `WithAgentTools`, as shown above.



## Client transports

A client transport defines how AGNT5 connects to an MCP server.



**Python:**

| Transport | Use it for | Helper |
|---|---|---|
| stdio | Local servers launched as a subprocess | `add_stdio_server` |
| Streamable HTTP | Remote MCP servers over HTTP | `add_streamable_http_server` |
| SSE | Remote servers over Server-Sent Events | `add_sse_server` |

Configure servers with the typed helpers:

```python
from agnt5.mcp import MCPClient

mcp = MCPClient(id="tools")

mcp.add_streamable_http_server("deepwiki", "https://mcp.deepwiki.com/mcp")
mcp.add_sse_server("internal-tools", url="https://example.com/sse", api_key="...")
mcp.add_stdio_server("local", command="npx", args=["-y", "my-mcp-server"])
```





**TypeScript:**

| Transport | Use it for | Helper |
|---|---|---|
| stdio | Local servers launched as a subprocess | `addStdioServer` |
| Streamable HTTP | Remote MCP servers over HTTP | `addStreamableHttpServer` |
| SSE | Remote servers over Server-Sent Events | `addSseServer` |

Configure servers with the typed helpers:

```typescript
import { MCPClient } from "@agnt5/sdk";

const mcp = new MCPClient("tools");

mcp.addStreamableHttpServer("deepwiki", "https://mcp.deepwiki.com/mcp");
mcp.addSseServer("internal-tools", "https://example.com/sse", {
  Authorization: "Bearer ...",
});
mcp.addStdioServer("local", "npx", ["-y", "my-mcp-server"]);
```





**Go:**

| Transport | Use it for | Constructor |
|---|---|---|
| stdio | Local servers launched as a subprocess | `NewStdioMCPTransport` |
| Streamable HTTP and SSE | Remote MCP servers over HTTP | `NewSSEMCPTransport` |
| Stream | Newline-delimited JSON-RPC over any `io.ReadWriter` | `NewStreamMCPTransport` |

A Go `MCPClient` wraps one transport. Connect to several servers by creating one client per transport:

```go
stdioTransport, err := agnt5.NewStdioMCPTransport(ctx, "npx", "-y", "my-mcp-server")
localClient, err := agnt5.NewMCPClient(stdioTransport)

sseTransport := agnt5.NewSSEMCPTransport("https://example.com/sse", map[string]string{
    "Authorization": "Bearer ...",
})
remoteClient, err := agnt5.NewMCPClient(sseTransport)
```



## Work with MCP tools

After `connect()`, the client caches discovered tools. The DeepWiki server offers `ask_wiki_question`, `read_wiki_contents`, and `read_wiki_structure`.



**Python:**

Call a tool directly when you know the server name:

```python
result = await mcp.call_tool("deepwiki", "ask_wiki_question", {
    "repoName": "python/cpython",
    "question": "What is CPython?",
})

print(result.get_text())
```

Call by tool name when the server does not matter:

```python
result = await mcp.call_tool_auto("ask_wiki_question", {
    "repoName": "python/cpython",
    "question": "What language is CPython written in?",
})

print(result.get_text())
```

Common client methods:

| Method | What it does |
|---|---|
| `await connect()` / `await disconnect()` | Open and close connections to all configured servers |
| `get_tools()` | Return discovered MCP tools as AGNT5 `Tool` objects for `Agent(tools=...)` |
| `await list_tools()` | List every discovered tool. Each entry has the `server` name and the `tool` (with `name`, `description`, `input_schema`) |
| `await list_server_tools(server)` | List the tools from one server |
| `await call_tool(server, name, args)` | Call a tool on a specific server |
| `await call_tool_auto(name, args)` | Call the first matching tool name across connected servers |
| `is_connected(server)` | Check whether one server is connected |
| `connected_servers()` | Return connected server names |





**TypeScript:**

Call a tool directly when you know the server name:

```typescript
const result = await mcp.callTool('deepwiki', 'ask_wiki_question', {
  repoName: 'python/cpython',
  question: 'What is CPython?',
});

console.log(result.content.map((c) => c.text).join('\n'));
```

Call by tool name when the server does not matter:

```typescript
const result = await mcp.callToolAuto('ask_wiki_question', {
  repoName: 'python/cpython',
  question: 'What language is CPython written in?',
});

console.log(result.content.map((c) => c.text).join('\n'));
```

Read the text of a result from `result.content`.

Common client methods:

| Method | What it does |
|---|---|
| `connect()` / `disconnect()` | Open and close connections to all configured servers |
| `getTools()` | Return discovered MCP tools as AGNT5 `Tool` objects for `Agent({ tools: ... })` |
| `listTools()` | List every discovered tool with its source server |
| `listServerTools(server)` | List tools from one server |
| `callTool(server, name, args)` | Call a tool on a specific server |
| `callToolAuto(name, args)` | Call the first matching tool name across connected servers |
| `isConnected(server)` | Check whether one server is connected |
| `connectedServers()` | Return connected server names |





**Go:**

Call a tool by name. A Go client wraps one transport, so you call the tool directly on that client.

```go
result, err := mcp.CallTool(ctx, "ask_wiki_question", map[string]any{
    "repoName": "python/cpython",
    "question": "What is CPython?",
})

for _, block := range result.Content {
    fmt.Println(block["text"])
}
```

Client methods:

| Method | What it does |
|---|---|
| `ListTools(ctx) ([]MCPTool, error)` | List tools discovered from the wrapped transport |
| `CallTool(ctx, name, arguments) (MCPCallToolResult, error)` | Call a tool by name |
| `Close() error` | Close the underlying transport |

`MCPCallToolResult` has `Content` (a `[]map[string]any`), `IsError`, and `Raw`.




> Always call `connect()` first. The tool list is built from the cache populated during connection.


## Expose AGNT5 over MCP

`MCPServer` runs the protocol in reverse: it publishes AGNT5 primitives so MCP-compatible clients can call them. You can serve a server locally over stdio, or publish it with your deployment so AGNT5 hosts it.

### Serve locally over stdio

Use stdio for local developer workflows in Claude Desktop, Cursor, VS Code, and similar clients. Over stdio, a server publishes its tools and agents.



**Python:**

```python
from agnt5 import Agent
from agnt5.mcp import MCPServer
from agnt5.tool import tool

@tool
async def greet(ctx, name: str) -> str:
    """Greet someone by name."""
    return f"Hello, {name}!"

assistant = Agent(
    name="assistant",
    model="openai/gpt-6-luna",
    instructions="Help the user.",
)

server = MCPServer(
    id="my-server",
    name="My AGNT5 Server",
    version="1.0.0",
    tools={"greet": greet},
    agents={"assistant": assistant},
)

await server.run_stdio()
```

You can register primitives when constructing the server or add them later:

```python
server.add_tool("search", search_tool)
server.add_agent("analyst", analyst_agent)
```





**TypeScript:**

```typescript
import { Agent, LM, MCPServer, tool } from '@agnt5/sdk';
import type { Context } from '@agnt5/sdk';

const greet = tool(
  'greet',
  {
    description: 'Greet someone by name.',
    inputSchema: {
      type: 'object',
      properties: { name: { type: 'string' } },
      required: ['name'],
    },
  },
  async (ctx: Context, args: { name: string }) => `Hello, ${args.name}!`,
);

const assistant = new Agent({
  name: 'assistant',
  model: LM.openai(),
  modelName: 'openai/gpt-6-luna',
  instructions: 'Help the user.',
});

const server = new MCPServer({
  id: 'my-server',
  name: 'My AGNT5 Server',
  version: '1.0.0',
  tools: { greet: greet._tool },
  agents: { assistant },
});

await server.runStdio();
```

`tool()` returns a callable wrapper for use elsewhere in your code. `MCPServer` takes the underlying `Tool` instance, which the wrapper exposes as `._tool`.

You can register primitives when constructing the server or add them later:

```typescript
server.addTool('search', searchTool._tool);
server.addAgent('analyst', analystAgent);
```





**Go:**

Go connects agents to MCP servers with `agnt5.NewMCPClient` (see [Connect external MCP servers](#connect-external-mcp-servers)). Publishing an `MCPServer` is available in the Python and TypeScript SDKs.



### Publish with your deployment



**Python:**

Define the server in your worker project and add the functions, workflows, and agents you want to publish. A deploy then serves it at `https://api.agnt5.com/mcp/{project}/{environment}/{server}`, and `agnt5 dev` serves a dev session's servers at a dev URL only you can sign in to.

```python
from agnt5 import Agent
from agnt5.mcp import MCPServer

support = MCPServer("support", instructions="Order and ticket tools.")
support.add_function("lookup_order", lookup_order)
support.add_workflow("triage_ticket", triage_ticket)
support.add_agent("assistant", assistant)
```





**TypeScript:**

Define the server in your worker project and add the functions, workflows, and agents you want to publish. A deploy then serves it at `https://api.agnt5.com/mcp/{project}/{environment}/{server}`, and `agnt5 dev` serves a dev session's servers at a dev URL only you can sign in to.

```typescript
import { MCPServer } from '@agnt5/sdk';

const support = new MCPServer('support', { instructions: 'Order and ticket tools.' });
support.addFunction('lookup_order', lookupOrder);
support.addWorkflow('triage_ticket', triageTicket);
support.addAgent('assistant', assistant);
```





**Go:**

Publishing an `MCPServer` is available in the Python and TypeScript SDKs.



A hosted server publishes functions, workflows, and agents; a `@tool` is served only over stdio. Every call to a hosted server runs as a durable run you can inspect in Studio. For the full path (registering the server with your worker, trying it locally, deploying, and connecting Claude), see [Serve your project over MCP](/docs/run/mcp-servers.md).

## Next steps

- [Serve your project over MCP](/docs/run/mcp-servers.md): publish a server with your deployment and connect Claude to it.
- [Tools](/docs/build/tools.md): define AGNT5 tools that agents and MCP clients can call.
- [Agents](/docs/build/agents.md): attach imported MCP tools to an agent loop.
- [AI providers](/docs/integrations/ai-providers.md): configure model credentials for agents that use MCP tools.
- [Local development](/docs/build/local-development.md): run and test AGNT5 code from your laptop.
