createSdkMcpServer() function creates an MCP server instance that runs in the same process as your SDK application.
Import
import { createSdkMcpServer } from '@qwen-code/sdk';
import type { CreateSdkMcpServerOptions, McpSdkServerConfigWithInstance } from '@qwen-code/sdk';
Signature
function createSdkMcpServer(
options: CreateSdkMcpServerOptions
): McpSdkServerConfigWithInstance
Parameters
Configuration options for the MCP server.
CreateSdkMcpServerOptions
Unique name for the MCP server. Used to identify the server in logs and error messages.
createSdkMcpServer({
name: 'calculator',
// ...
})
Server version string. Used for compatibility and debugging.
createSdkMcpServer({
name: 'my-server',
version: '2.1.0',
// ...
})
Array of tools created with the
tool() function.createSdkMcpServer({
name: 'utilities',
tools: [timeTool, weatherTool, calculatorTool],
})
Return Value
A server configuration object that can be passed directly to the
mcpServers option in query().{
type: 'sdk';
name: string;
instance: McpServer;
}
Examples
Basic Server with One Tool
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
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
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
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
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
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: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:// ✅ 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
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: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],
});
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: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
const server = createSdkMcpServer({
name: 'utilities',
tools: [/* ... */],
});
const result = query({
prompt: 'Use the utility tools',
options: {
mcpServers: {
utilities: server, // Direct reference
},
},
});
Reuse Across Queries
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
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
// ✅ 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
// ✅ 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
const server = createSdkMcpServer({
name: 'my-api',
version: '2.1.0', // Track version changes
tools: [/* ... */],
});
4. Keep Servers Focused
// ✅ 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
// ✅ 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 - Create tools for your server
- MCP Overview - MCP integration guide
- MCP Examples - Complete working examples
- query() Function - Using servers in queries
