Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/content/docs/agents/guides/oauth-mcp-client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ When your Agent connects to an OAuth-protected MCP server, here's what happens:
3. **Your application presents** the `authUrl` to your user
4. **Your user authenticates** on the provider's site (Slack, etc.)
5. **The provider redirects** back to your Agent's callback URL with an authorization code
6. **Your Agent completes** the connection automatically
6. **Your Agent completes** the connection automatically and clears OAuth credentials for security

:::note[Security]

After successful OAuth completion, the Agent automatically clears the `auth_url` and `callback_url` from storage. This security measure prevents replay attacks and ensures completed authentications cannot be hijacked by malicious actors.

:::

## Connect and initiate OAuth

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class MyAgent extends Agent<Env, never> {

</TypeScriptExample>

Connections persist in the Agent's [SQL storage](/agents/api-reference/store-and-sync-state), and when an Agent connects to an MCP server, all tools from that server become available automatically.
Connections persist in the Agent's [SQL storage](/agents/api-reference/store-and-sync-state/) using a [storage adapter pattern](/agents/model-context-protocol/storage-adapter/), and when an Agent connects to an MCP server, all tools from that server become available automatically. The Agent automatically restores MCP connections after hibernation without requiring manual reconnection.

## Agent MCP Client Methods

Expand Down Expand Up @@ -115,10 +115,17 @@ export class MyAgent extends Agent<Env, never> {

If the MCP server requires OAuth authentication, `authUrl` will be returned for user authentication. Connections persist across requests and the Agent will automatically reconnect if the connection is lost.

:::note[Security]

After successful OAuth authentication, the Agent automatically clears sensitive OAuth credentials (`auth_url` and `callback_url`) from storage. This prevents replay attacks and ensures completed authentications cannot be hijacked. Learn more in [MCP storage architecture](/agents/model-context-protocol/mcp-storage/).

:::

**Related:**

- [OAuth handling guide](/agents/guides/oauth-mcp-client)
- [Transport options](/agents/model-context-protocol/transport)
- [MCP storage architecture](/agents/model-context-protocol/mcp-storage/)
- [removeMcpServer()](#removemcpserver)

### `removeMcpServer()`
Expand Down Expand Up @@ -272,7 +279,12 @@ export class MyAgent extends Agent<Env, never> {

</TypeScriptExample>

## Advanced Configuration

For advanced use cases, you can implement custom storage backends for MCP server configurations. Refer to the [Storage Adapter documentation](/agents/model-context-protocol/storage-adapter/) to learn about the storage adapter pattern and how to implement custom storage solutions.

## Next Steps

- [Connect your first MCP server](/agents/guides/connect-mcp-client) — Tutorial to get started
- [Handle OAuth flows](/agents/guides/oauth-mcp-client) — Complete OAuth integration guide
- [Connect your first MCP server](/agents/guides/connect-mcp-client/) — Tutorial to get started
- [Handle OAuth flows](/agents/guides/oauth-mcp-client/) — Complete OAuth integration guide
- [Storage Adapter](/agents/model-context-protocol/storage-adapter/) — Custom storage backends for MCP
179 changes: 179 additions & 0 deletions src/content/docs/agents/model-context-protocol/mcp-storage.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
---
title: MCP storage architecture
pcx_content_type: concept
tags:
- MCP
sidebar:
order: 9
---

import { TypeScriptExample } from "~/components";

The MCP client manager uses a storage adapter interface to persist server configurations and OAuth credentials. This architecture allows for flexible storage implementations while maintaining security best practices.

## Storage adapter interface

The `MCPStorageAdapter` interface defines how MCP server configurations are persisted:

<TypeScriptExample>

```ts
interface MCPStorageAdapter {
// Create storage schema
create(): void | Promise<void>;

// Destroy storage schema
destroy(): void | Promise<void>;

// Save or update server configuration
saveServer(server: MCPServerRow): void | Promise<void>;

// Remove server from storage
removeServer(serverId: string): void | Promise<void>;

// List all servers
listServers(): MCPServerRow[] | Promise<MCPServerRow[]>;

// Get server by callback URL (for OAuth)
getServerByCallbackUrl(callbackUrl: string): MCPServerRow | null | Promise<MCPServerRow | null>;

// Clear OAuth credentials after successful auth
clearOAuthCredentials(serverId: string): void | Promise<void>;
}
```

</TypeScriptExample>

### Server configuration structure

Each MCP server configuration includes:

```ts
type MCPServerRow = {
id: string; // Unique server identifier
name: string; // Display name
server_url: string; // MCP server endpoint
client_id: string | null; // OAuth client ID (if applicable)
auth_url: string | null; // OAuth authorization URL (cleared after auth)
callback_url: string; // OAuth callback endpoint
server_options: string | null; // JSON-stringified connection options
};
```

## Default SQL storage

Agents use the `AgentMCPStorageAdapter` by default, which stores MCP configurations in the Agent's SQL database:

- **Table**: `cf_agents_mcp_servers`
- **Persistence**: Configurations survive Agent hibernation
- **Security**: OAuth credentials automatically cleared after authentication

The storage adapter is automatically initialized when you create an Agent:

<TypeScriptExample>

```ts
import { Agent } from "agents";

export class MyAgent extends Agent<Env, never> {
// Storage adapter is automatically configured
// No setup required for default SQL storage
}
```

</TypeScriptExample>

## Security considerations

### Automatic credential cleanup

After successful OAuth authentication, the storage adapter automatically clears sensitive credentials:

- **`callback_url`**: Cleared to prevent malicious second callbacks
- **`auth_url`**: Cleared to prevent re-authentication loops

This ensures:
- OAuth tokens cannot be replayed
- Completed authentications cannot be hijacked
- Storage contains only necessary persistent data

### Callback URL validation

The MCP client manager validates OAuth callbacks by:

1. Checking callback URLs against the database
2. Matching the exact callback URL prefix
3. Rejecting callbacks after credentials are cleared

This prevents unauthorized callback requests from being processed.

## Connection restoration

When an Agent wakes from hibernation, the MCP client manager automatically:

1. Reads server configurations from storage
2. Recreates OAuth-protected connections in `authenticating` state
3. Reconnects to non-OAuth servers
4. Preserves connection state across Agent lifecycles

You don't need to manually restore connections - the Agent handles this automatically.

## Advanced: Custom storage adapters

For advanced use cases, you can implement a custom storage adapter. This is typically only needed for:

- Non-SQL storage backends
- Custom encryption requirements
- Multi-tenant isolation patterns
- External configuration management

:::note

Most users should use the default SQL storage adapter. Custom storage adapters are an advanced feature.

:::

To implement a custom adapter:

<TypeScriptExample>

```ts
import {
Agent,
type MCPStorageAdapter,
type MCPServerRow
} from "agents";

class CustomStorageAdapter implements MCPStorageAdapter {
async create(): Promise<void> {
// Initialize your storage
}

async saveServer(server: MCPServerRow): Promise<void> {
// Persist server configuration
}

async listServers(): Promise<MCPServerRow[]> {
// Retrieve all servers
}

// Implement remaining methods...
}

export class MyAgent extends Agent<Env, never> {
constructor(ctx: AgentContext, env: Env) {
super(ctx, env);

// Custom storage adapter must be configured in constructor
// This is an advanced pattern - most users should use default storage
}
}
```

</TypeScriptExample>

## Related

- [McpClient — API reference](/agents/model-context-protocol/mcp-client-api/) — MCP client methods
- [Handle OAuth with MCP servers](/agents/guides/oauth-mcp-client/) — OAuth integration guide
- [Store and sync state](/agents/api-reference/store-and-sync-state/) — Agent SQL storage
Loading
Loading