> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/QwenLM/qwen-code/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Integration Overview

> Extend Qwen Code with custom tools using the Model Context Protocol

The SDK provides built-in support for the Model Context Protocol (MCP), allowing you to create custom tools that extend the AI's capabilities.

## What is MCP?

The [Model Context Protocol](https://modelcontextprotocol.io/) is an open standard for connecting AI models to external tools and data sources. It enables:

* **Custom Tools**: Create application-specific functionality
* **External APIs**: Connect to third-party services
* **Data Sources**: Access databases, file systems, and more
* **Process Isolation**: Run tools in separate processes or in-process

## MCP Server Types

The SDK supports two types of MCP servers:

### SDK-Embedded Servers (Recommended)

Run in the same process as your application. No separate server process needed.

**Benefits:**

* Simple setup - no process management
* Direct access to your application's state
* Type-safe with Zod schema validation
* Lower latency - no IPC overhead

**Use cases:**

* Application-specific tools
* Tools that need access to app state
* Simple utility functions

```typescript theme={null}
import { z } from 'zod';
import { tool, createSdkMcpServer, query } from '@qwen-code/sdk';

const weatherTool = tool(
  'get_weather',
  'Get current weather for a city',
  { city: z.string() },
  async (args) => ({
    content: [{ type: 'text', text: `Weather in ${args.city}: Sunny, 72°F` }],
  })
);

const server = createSdkMcpServer({
  name: 'weather',
  tools: [weatherTool],
});

const result = query({
  prompt: 'What is the weather in San Francisco?',
  options: {
    mcpServers: { weather: server },
  },
});
```

### External Servers

Run as separate processes, connected via stdio, SSE, HTTP, or WebSocket.

**Benefits:**

* Process isolation and security
* Language agnostic - write servers in any language
* Share servers across multiple SDK instances
* Standard MCP protocol compliance

**Use cases:**

* Complex server implementations
* Shared services across applications
* Third-party MCP servers
* Security-sensitive operations

```typescript theme={null}
import { query } from '@qwen-code/sdk';

const result = query({
  prompt: 'Use the database tool',
  options: {
    mcpServers: {
      database: {
        command: 'node',
        args: ['./mcp-servers/database-server.js'],
        env: { DB_CONNECTION: 'postgresql://...' },
      },
    },
  },
});
```

## Quick Start

Create your first SDK-embedded MCP server in 3 steps:

### Step 1: Install Dependencies

```bash theme={null}
npm install @qwen-code/sdk zod
```

### Step 2: Create a Tool

```typescript example.ts theme={null}
import { z } from 'zod';
import { tool, createSdkMcpServer, query } from '@qwen-code/sdk';

// Define a calculator tool
const calculatorTool = tool(
  'calculate_sum',
  'Add two numbers together',
  {
    a: z.number().describe('First number'),
    b: z.number().describe('Second number'),
  },
  async (args) => {
    const result = args.a + args.b;
    return {
      content: [{
        type: 'text',
        text: `${args.a} + ${args.b} = ${result}`,
      }],
    };
  }
);

// Create MCP server
const server = createSdkMcpServer({
  name: 'calculator',
  version: '1.0.0',
  tools: [calculatorTool],
});

// Use in query
const result = query({
  prompt: 'What is 42 + 17?',
  options: {
    permissionMode: 'yolo',
    mcpServers: {
      calculator: server,
    },
  },
});

for await (const message of result) {
  if (message.type === 'assistant') {
    console.log(message.message.content);
  }
}
```

### Step 3: Run It

```bash theme={null}
npx tsx example.ts
```

## Architecture

### SDK-Embedded Servers

```
┌─────────────────────────────────┐
│         Your Application           │
│  ┌────────────────────────────┐  │
│  │  SDK Query Instance      │  │
│  │                            │  │
│  │  ┌─────────────────────┐  │  │
│  │  │ SDK MCP Server     │  │  │
│  │  │ (In-process)       │  │  │
│  │  │ - Tool handlers    │  │  │
│  │  │ - Zod validation   │  │  │
│  │  └─────────────────────┘  │  │
│  └────────────────────────────┘  │
└─────────────────────────────────┘
         │
         │ JSON Protocol
         ▼
┌─────────────────────────────────┐
│       Qwen CLI Process          │
└─────────────────────────────────┘
```

### External Servers

```
┌─────────────────────────────────┐
│         Your Application           │
│  ┌────────────────────────────┐  │
│  │  SDK Query Instance      │  │
│  └────────────────────────────┘  │
└─────────────────────────────────┘
         │
         │ JSON Protocol
         ▼
┌─────────────────────────────────┐
│       Qwen CLI Process          │
└─────────────────────────────────┘
         │
         │ MCP Protocol
         │ (stdio/SSE/HTTP)
         ▼
┌─────────────────────────────────┐
│   External MCP Server          │
│   (Separate Process)           │
└─────────────────────────────────┘
```

## Communication Flow

When the AI calls an MCP tool:

1. **CLI requests tool execution**: AI decides to use a tool and sends request to CLI
2. **CLI routes to SDK**: CLI identifies SDK-embedded server and sends control request
3. **SDK invokes handler**: SDK validates input and calls your tool handler
4. **Handler returns result**: Your function returns MCP-formatted result
5. **SDK sends response**: Result is sent back to CLI as control response
6. **CLI forwards to AI**: Tool result is included in the AI's context

## Tool Result Format

All tool handlers must return a `CallToolResult` object:

```typescript theme={null}
type CallToolResult = {
  content: Array<
    | { type: 'text'; text: string }
    | { type: 'image'; data: string; mimeType: string }
    | { type: 'resource'; uri: string; mimeType?: string; text?: string }
  >;
  isError?: boolean;
};
```

### Text Response

```typescript theme={null}
return {
  content: [{ type: 'text', text: 'Operation successful' }],
};
```

### Image Response

```typescript theme={null}
return {
  content: [{
    type: 'image',
    data: base64ImageData,
    mimeType: 'image/png',
  }],
};
```

### Multiple Content Blocks

```typescript theme={null}
return {
  content: [
    { type: 'text', text: 'Here is the chart:' },
    { type: 'image', data: chartData, mimeType: 'image/png' },
  ],
};
```

### Error Response

```typescript theme={null}
return {
  content: [{ type: 'text', text: 'Failed to process request' }],
  isError: true,
};
```

## Configuration Options

When connecting MCP servers to a query:

```typescript theme={null}
import { query, createSdkMcpServer } from '@qwen-code/sdk';

const result = query({
  prompt: 'Use my tools',
  options: {
    mcpServers: {
      // SDK-embedded server
      'my-server': createSdkMcpServer({
        name: 'my-server',
        tools: [/* ... */],
      }),
      
      // External server (stdio)
      'external-stdio': {
        command: 'node',
        args: ['server.js'],
        env: { API_KEY: 'xxx' },
      },
      
      // External server (SSE)
      'external-sse': {
        url: 'http://localhost:3000/sse',
      },
      
      // External server (HTTP)
      'external-http': {
        httpUrl: 'http://localhost:3000/mcp',
        headers: { 'Authorization': 'Bearer token' },
      },
    },
  },
});
```

## Timeout Configuration

Configure timeouts for MCP operations:

```typescript theme={null}
options: {
  mcpServers: { /* ... */ },
  timeout: {
    mcpRequest: 600000, // 10 minutes for long-running tools
  },
}
```

## Best Practices

### 1. Use SDK-Embedded Servers for Simple Tools

```typescript theme={null}
const simpleTool = tool(
  'get_time',
  'Get current time',
  {},
  async () => ({
    content: [{ type: 'text', text: new Date().toISOString() }],
  })
);
```

### 2. Use External Servers for Complex Operations

```typescript theme={null}
options: {
  mcpServers: {
    database: {
      command: 'node',
      args: ['database-server.js'],
    },
  },
}
```

### 3. Validate Input with Zod

```typescript theme={null}
const tool = tool(
  'create_user',
  'Create a new user',
  {
    email: z.string().email(),
    age: z.number().min(0).max(120),
  },
  async (args) => {
    // args.email is validated email
    // args.age is validated number
  }
);
```

### 4. Handle Errors Gracefully

```typescript theme={null}
const tool = tool(
  'risky_operation',
  'Perform a risky operation',
  { input: z.string() },
  async (args) => {
    try {
      const result = await performOperation(args.input);
      return {
        content: [{ type: 'text', text: result }],
      };
    } catch (error) {
      return {
        content: [{
          type: 'text',
          text: `Error: ${error.message}`,
        }],
        isError: true,
      };
    }
  }
);
```

### 5. Provide Clear Descriptions

```typescript theme={null}
const tool = tool(
  'search_docs',
  'Search technical documentation using semantic search. Returns relevant excerpts.',
  {
    query: z.string().describe('Search query (natural language)'),
    limit: z.number().default(5).describe('Maximum number of results'),
  },
  async (args) => { /* ... */ }
);
```

## Next Steps

<CardGroup cols={2}>
  <Card title="tool() Function" icon="wrench" href="/sdk/mcp/tool">
    Learn how to create tools
  </Card>

  <Card title="createSdkMcpServer()" icon="server" href="/sdk/mcp/create-server">
    Create MCP server instances
  </Card>

  <Card title="MCP Examples" icon="code" href="/sdk/mcp/examples">
    Complete working examples
  </Card>

  <Card title="External MCP Servers" icon="plug" href="/sdk/mcp/tool">
    Connect to external servers
  </Card>
</CardGroup>
