---
title: MCP tools | Letta Docs
description: Connect agents to external MCP servers for remote tool execution
---

If you’re using [Letta Code](/letta-code/index.md) or the [Letta Code SDK](/letta-code-sdk/quickstart/index.md), use [skills](/letta-code/skills/index.md) instead of MCP. For example, instead of connecting the GitHub MCP server, use a skill that explains how to download and use the `gh cli`.

Unlike MCP tools, skills can be dynamically loaded and unloaded at runtime (freeing up context space), and can be more easily modified by the agent (the agent can improve the skill if needed).

MCP tools execute on external MCP servers. Unlike server tools (where the tool code runs in Letta’s sandbox) or client tools (where the tool code runs in your app), MCP tools only require registering the server URL - the tool execution happens on the MCP server.

## Tool execution comparison

| Tool type        | Where code runs     | You provide                 | Use case                                        |
| ---------------- | ------------------- | --------------------------- | ----------------------------------------------- |
| **Server tools** | Letta sandbox       | Tool code                   | Custom logic, API calls                         |
| **Client tools** | Your application    | Tool schema + local handler | Local resources, HITL                           |
| **MCP tools**    | External MCP server | Server URL only             | You have an existing MCP server you want to use |

## Register an MCP server

- [Python](#tab-panel-253)
- [TypeScript](#tab-panel-254)

```
from letta_client import Letta


client = Letta()


# Register a remote MCP server
server = client.mcp_servers.create(
    server_name="github",
    config={
        "mcp_server_type": "streamable_http",
        "server_url": "https://mcp.example.com/github",
        "auth_header": "Authorization",
        "auth_token": "Bearer your-token",
    }
)


# List available tools from the server
tools = client.mcp_servers.list_tools(server.id)
for tool in tools:
    print(f"{tool.name}: {tool.description}")
```

```
import Letta from "@letta-ai/letta-client";


const client = new Letta();


// Register a remote MCP server
const server = await client.mcpServers.create({
  server_name: "github",
  config: {
    mcp_server_type: "streamable_http",
    server_url: "https://mcp.example.com/github",
    auth_header: "Authorization",
    auth_token: "Bearer your-token",
  },
});


// List available tools from the server
const tools = await client.mcpServers.listTools(server.id);
for (const tool of tools) {
  console.log(`${tool.name}: ${tool.description}`);
}
```

## Attach MCP tools to an agent

Once registered, attach MCP tools to agents like any other tool:

- [Python](#tab-panel-251)
- [TypeScript](#tab-panel-252)

```
# Create agent with MCP tools
agent = client.agents.create(
    name="github-assistant",
    tool_ids=[tool.id for tool in tools],  # MCP tools from server
)
```

```
// Create agent with MCP tools
const agent = await client.agents.create({
  name: "github-assistant",
  tool_ids: tools.map((t) => t.id), // MCP tools from server
});
```

## Transport types

| Transport           | Letta API | Docker | Notes                               |
| ------------------- | --------- | ------ | ----------------------------------- |
| **Streamable HTTP** | ✅         | ✅      | Recommended. Supports auth headers. |
| **SSE**             | ✅         | ✅      | Legacy, for compatibility only.     |
| **stdio**           | ❌         | ✅      | Local development only.             |

### Streamable HTTP (recommended)

```
client.mcp_servers.create(
    server_name="my-server",
    config={
        "mcp_server_type": "streamable_http",
        "server_url": "https://mcp.example.com/endpoint",
        "auth_header": "Authorization",
        "auth_token": "Bearer token",
        "custom_headers": {"X-API-Version": "v1"}
    }
)
```

### stdio (Docker only)

```
client.mcp_servers.create(
    server_name="local-server",
    config={
        "mcp_server_type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"]
    }
)
```

## Agent-scoped variables

Use templated variables in auth tokens for per-agent credentials:

```
client.mcp_servers.create(
    server_name="user-api",
    config={
        "mcp_server_type": "streamable_http",
        "server_url": "https://api.example.com/mcp",
        "auth_token": "Bearer {{USER_API_KEY | default_key}}",  # Falls back to default_key
    }
)
```

Set variables per-agent using [tool variables](/guides/core-concepts/tools/server-tools/index.md).

## Execution flow

```
sequenceDiagram
    participant Agent as Letta Agent
    participant Server as Letta Server
    participant MCP as MCP Server

    Agent->>Server: Tool call (create_issue)
    Server->>MCP: Forward request
    MCP->>MCP: Execute tool
    MCP-->>Server: Return result
    Server-->>Agent: Continue with result
```

The agent doesn’t need credentials or API details - the MCP server handles authentication and execution.
