> ## 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.

# createSdkMcpServer() Function

> Create SDK-embedded MCP server instances

The `createSdkMcpServer()` function creates an MCP server instance that runs in the same process as your SDK application.

## Import

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

## Signature

```typescript theme={null}
function createSdkMcpServer(
  options: CreateSdkMcpServerOptions
): McpSdkServerConfigWithInstance
```

## Parameters

<ParamField path="options" type="CreateSdkMcpServerOptions" required>
  Configuration options for the MCP server.
</ParamField>

### CreateSdkMcpServerOptions

<ParamField path="name" type="string" required>
  Unique name for the MCP server. Used to identify the server in logs and error messages.

  ```typescript theme={null}
  createSdkMcpServer({
    name: 'calculator',
    // ...
  })
  ```
</ParamField>

<ParamField path="version" type="string" default="'1.0.0'">
  Server version string. Used for compatibility and debugging.

  ```typescript theme={null}
  createSdkMcpServer({
    name: 'my-server',
    version: '2.1.0',
    // ...
  })
  ```
</ParamField>

<ParamField path="tools" type="SdkMcpToolDefinition[]">
  Array of tools created with the `tool()` function.

  ```typescript theme={null}
  createSdkMcpServer({
    name: 'utilities',
    tools: [timeTool, weatherTool, calculatorTool],
  })
  ```
</ParamField>

## Return Value

<ResponseField name="McpSdkServerConfigWithInstance" type="object">
  A server configuration object that can be passed directly to the `mcpServers` option in `query()`.

  ```typescript theme={null}
  {
    type: 'sdk';
    name: string;
    instance: McpServer;
  }
  ```
</ResponseField>

## Examples

### Basic Server with One Tool

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

const addTool = tool(
  'add',
  'Add two numbers',
  { a: z.number(), b: z.number() },
  async (args) => ({
    content: [{ type: 'text', text: String(args.a + args.b) }],
  })
);

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

const result = query({
  prompt: 'What is 5 + 3?',
  options: {
    permissionMode: 'yolo',
    mcpServers: { calculator: server },
  },
});
```

### Server with Multiple Tools

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

const addTool = tool(
  'add',
  'Add two numbers',
  { a: z.number(), b: z.number() },
  async (args) => ({
    content: [{ type: 'text', text: String(args.a + args.b) }],
  })
);

const subtractTool = tool(
  'subtract',
  'Subtract two numbers',
  { a: z.number(), b: z.number() },
  async (args) => ({
    content: [{ type: 'text', text: String(args.a - args.b) }],
  })
);

const multiplyTool = tool(
  'multiply',
  'Multiply two numbers',
  { a: z.number(), b: z.number() },
  async (args) => ({
    content: [{ type: 'text', text: String(args.a * args.b) }],
  })
);

const server = createSdkMcpServer({
  name: 'calculator',
  version: '1.0.0',
  tools: [addTool, subtractTool, multiplyTool],
});

const result = query({
  prompt: 'Calculate (5 + 3) * 2',
  options: {
    permissionMode: 'yolo',
    mcpServers: { calculator: server },
  },
});
```

### Multiple Servers

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

// Calculator server
const calculatorServer = createSdkMcpServer({
  name: 'calculator',
  tools: [
    tool('add', 'Add numbers', {
      a: z.number(), b: z.number()
    }, async (args) => ({
      content: [{ type: 'text', text: String(args.a + args.b) }],
    })),
  ],
});

// Weather server
const weatherServer = createSdkMcpServer({
  name: 'weather',
  tools: [
    tool('get_weather', 'Get weather for a city', {
      city: z.string()
    }, async (args) => ({
      content: [{ type: 'text', text: `Weather in ${args.city}: Sunny` }],
    })),
  ],
});

// Time server
const timeServer = createSdkMcpServer({
  name: 'time',
  tools: [
    tool('get_time', 'Get current time', {}, async () => ({
      content: [{ type: 'text', text: new Date().toISOString() }],
    })),
  ],
});

const result = query({
  prompt: 'What time is it and what is the weather in Paris?',
  options: {
    permissionMode: 'yolo',
    mcpServers: {
      calculator: calculatorServer,
      weather: weatherServer,
      time: timeServer,
    },
  },
});
```

### Server with Stateful Tools

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

// State shared between tools
const storage = new Map<string, string>();

const setValueTool = tool(
  'set_value',
  'Store a key-value pair',
  { key: z.string(), value: z.string() },
  async (args) => {
    storage.set(args.key, args.value);
    return {
      content: [{ type: 'text', text: `Stored: ${args.key} = ${args.value}` }],
    };
  }
);

const getValueTool = tool(
  'get_value',
  'Retrieve a value by key',
  { key: z.string() },
  async (args) => {
    const value = storage.get(args.key);
    if (value === undefined) {
      return {
        content: [{ type: 'text', text: `Key not found: ${args.key}` }],
        isError: true,
      };
    }
    return {
      content: [{ type: 'text', text: value }],
    };
  }
);

const storageServer = createSdkMcpServer({
  name: 'storage',
  tools: [setValueTool, getValueTool],
});

const result = query({
  prompt: 'Store my name as John, then retrieve it',
  options: {
    permissionMode: 'yolo',
    mcpServers: { storage: storageServer },
  },
});
```

### Server with Async Operations

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

const fetchTool = tool(
  'fetch_url',
  'Fetch content from a URL',
  { url: z.string().url() },
  async (args) => {
    try {
      const response = await fetch(args.url);
      const content = await response.text();
      
      return {
        content: [{
          type: 'text',
          text: `Content from ${args.url}:\n${content.slice(0, 500)}...`,
        }],
      };
    } catch (error) {
      return {
        content: [{ type: 'text', text: `Failed to fetch: ${error.message}` }],
        isError: true,
      };
    }
  }
);

const httpServer = createSdkMcpServer({
  name: 'http',
  tools: [fetchTool],
});
```

### Server with Environment Access

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

const apiKeyTool = tool(
  'check_api_key',
  'Check if API key is configured',
  { service: z.string() },
  async (args) => {
    const envVar = `${args.service.toUpperCase()}_API_KEY`;
    const hasKey = !!process.env[envVar];
    
    return {
      content: [{
        type: 'text',
        text: hasKey
          ? `API key for ${args.service} is configured`
          : `API key for ${args.service} is NOT configured`,
      }],
    };
  }
);

const envServer = createSdkMcpServer({
  name: 'environment',
  tools: [apiKeyTool],
});
```

## Validation

### Tool Name Validation

The function validates that all tools have unique names:

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

const tool1 = tool('duplicate', 'First tool', {}, async () => ({
  content: [{ type: 'text', text: 'First' }],
}));

const tool2 = tool('duplicate', 'Second tool', {}, async () => ({
  content: [{ type: 'text', text: 'Second' }],
}));

// This will throw an error:
// "Duplicate tool name 'duplicate' in MCP server 'my-server'"
const server = createSdkMcpServer({
  name: 'my-server',
  tools: [tool1, tool2],
});
```

### Server Name Validation

Server name must be a non-empty string:

```typescript theme={null}
// ✅ Valid
createS dkMcpServer({ name: 'my-server', tools: [] })
createSdkMcpServer({ name: 'calculator-v2', tools: [] })

// ❌ Invalid - throws error
createS dkMcpServer({ name: '', tools: [] })
createSdkMcpServer({ name: null, tools: [] })
```

## Error Handling

### Creation Errors

```typescript theme={null}
try {
  const server = createSdkMcpServer({
    name: 'my-server',
    tools: [/* invalid tools */],
  });
} catch (error) {
  console.error('Failed to create server:', error.message);
}
```

### Runtime Tool Errors

Tool errors are caught and returned to the AI:

```typescript theme={null}
const errorTool = tool(
  'risky_operation',
  'Perform a risky operation',
  { input: z.string() },
  async (args) => {
    // If this throws, it's caught and returned as an error
    const result = await riskyOperation(args.input);
    return { content: [{ type: 'text', text: result }] };
  }
);

const server = createSdkMcpServer({
  name: 'risky',
  tools: [errorTool],
});
```

Better approach - handle errors explicitly:

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

## Server Capabilities

The MCP server automatically advertises its capabilities based on provided tools:

```typescript theme={null}
const server = createSdkMcpServer({
  name: 'my-server',
  tools: [tool1, tool2, tool3],
});

// Server instance has:
// - capabilities.tools = {} (indicates tool support)
// - Registered tool handlers for tool1, tool2, tool3
```

## Usage in Queries

### Direct Usage

```typescript theme={null}
const server = createSdkMcpServer({
  name: 'utilities',
  tools: [/* ... */],
});

const result = query({
  prompt: 'Use the utility tools',
  options: {
    mcpServers: {
      utilities: server,  // Direct reference
    },
  },
});
```

### Reuse Across Queries

```typescript theme={null}
const sharedServer = createSdkMcpServer({
  name: 'shared',
  tools: [/* ... */],
});

// Use in multiple queries
const query1 = query({
  prompt: 'First task',
  options: { mcpServers: { shared: sharedServer } },
});

const query2 = query({
  prompt: 'Second task',
  options: { mcpServers: { shared: sharedServer } },
});
```

### Mixed with External Servers

```typescript theme={null}
const sdkServer = createSdkMcpServer({
  name: 'sdk-tools',
  tools: [/* SDK tools */],
});

const result = query({
  prompt: 'Use both SDK and external tools',
  options: {
    mcpServers: {
      // SDK-embedded server
      'sdk-tools': sdkServer,
      
      // External server
      'external-db': {
        command: 'node',
        args: ['db-server.js'],
      },
    },
  },
});
```

## Best Practices

### 1. Group Related Tools

```typescript theme={null}
// ✅ Good - related tools in one server
const mathServer = createSdkMcpServer({
  name: 'math',
  tools: [addTool, subtractTool, multiplyTool, divideTool],
});

// ❌ Bad - unrelated tools mixed
const mixedServer = createSdkMcpServer({
  name: 'utilities',
  tools: [addTool, weatherTool, databaseTool, timeTool],
});
```

### 2. Use Descriptive Names

```typescript theme={null}
// ✅ Good
createS dkMcpServer({ name: 'weather-api', tools: [/* ... */] })
createS dkMcpServer({ name: 'database-queries', tools: [/* ... */] })

// ❌ Bad
createS dkMcpServer({ name: 'tools', tools: [/* ... */] })
createS dkMcpServer({ name: 'server1', tools: [/* ... */] })
```

### 3. Specify Versions

```typescript theme={null}
const server = createSdkMcpServer({
  name: 'my-api',
  version: '2.1.0',  // Track version changes
  tools: [/* ... */],
});
```

### 4. Keep Servers Focused

```typescript theme={null}
// ✅ Good - focused servers
const authServer = createSdkMcpServer({
  name: 'auth',
  tools: [loginTool, logoutTool, validateTokenTool],
});

const dataServer = createSdkMcpServer({
  name: 'data',
  tools: [queryTool, createTool, updateTool, deleteTool],
});

// ❌ Bad - monolithic server
const everythingServer = createSdkMcpServer({
  name: 'everything',
  tools: [
    loginTool, logoutTool, queryTool, createTool,
    weatherTool, calculatorTool, /* ... 20 more tools */
  ],
});
```

### 5. Initialize Once, Reuse

```typescript theme={null}
// ✅ Good - create once, use many times
const utilities = createSdkMcpServer({
  name: 'utilities',
  tools: [/* ... */],
});

function runQuery(prompt: string) {
  return query({
    prompt,
    options: { mcpServers: { utilities } },
  });
}

// ❌ Bad - recreate on every call
function runQuery(prompt: string) {
  const utilities = createSdkMcpServer({  // Wasteful
    name: 'utilities',
    tools: [/* ... */],
  });
  
  return query({
    prompt,
    options: { mcpServers: { utilities } },
  });
}
```

## See Also

* [tool() Function](/sdk/mcp/tool) - Create tools for your server
* [MCP Overview](/sdk/mcp/overview) - MCP integration guide
* [MCP Examples](/sdk/mcp/examples) - Complete working examples
* [query() Function](/sdk/api/query) - Using servers in queries
