TypeScript SDK for implementing the Model Context Protocol, enabling developers to build MCP servers and clients with support for multiple transports, tools, resources, prompts, and authentication
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Tools enable LLMs to take actions through your MCP server. Tools are model-controlled - AI decides which tools to call and with what arguments.
server.registerTool<InputArgs extends ZodRawShape, OutputArgs extends ZodRawShape>(
name: string,
config: {
title?: string;
description?: string;
inputSchema?: InputArgs;
outputSchema?: OutputArgs;
annotations?: ToolAnnotations;
_meta?: Record<string, unknown>;
},
callback: (args: z.infer<ZodObject<InputArgs>>, extra: RequestHandlerExtra) => Promise<CallToolResult> | CallToolResult
): RegisteredTool;import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
const server = new McpServer({ name: 'tools-server', version: '1.0.0' });
// Simple tool
server.registerTool('add', {
title: 'Addition Tool',
description: 'Add two numbers together',
inputSchema: {
a: z.number().describe('First number'),
b: z.number().describe('Second number')
},
outputSchema: {
result: z.number().describe('Sum of the two numbers')
}
}, async ({ a, b }) => {
const output = { result: a + b };
return {
content: [{ type: 'text', text: JSON.stringify(output) }],
structuredContent: output
};
});
// Tool with annotations
server.registerTool('fetch-data', {
title: 'Fetch External Data',
description: 'Fetch data from an external API',
inputSchema: {
url: z.string().url(),
method: z.enum(['GET', 'POST']).optional()
},
outputSchema: {
data: z.unknown(),
status: z.number()
},
annotations: {
audience: ['user']
}
}, async ({ url, method = 'GET' }) => {
const response = await fetch(url, { method });
const data = await response.json();
const output = { data, status: response.status };
return {
content: [{ type: 'text', text: JSON.stringify(output) }],
structuredContent: output
};
});interface CallToolResult {
content: ContentBlock[]; // Required: Content to return
isError?: boolean; // Optional: Indicates error
structuredContent?: Record<string, unknown>; // Required if outputSchema defined
_meta?: Record<string, unknown>;
}interface TextContent {
type: 'text';
text: string;
annotations?: { audience?: ('user' | 'assistant')[]; priority?: number; };
}
interface ImageContent { type: 'image'; data: string; mimeType: string; }
interface AudioContent { type: 'audio'; data: string; mimeType: string; }
interface EmbeddedResource {
type: 'resource';
resource: { uri: string; mimeType?: string; text?: string; blob?: string; };
}
interface ResourceLink {
type: 'resource_link';
uri: string;
name?: string;
mimeType?: string;
description?: string;
}
type ContentBlock = TextContent | ImageContent | AudioContent | EmbeddedResource | ResourceLink;// Simple text
return {
content: [{ type: 'text', text: 'Operation completed successfully' }]
};
// With structured content (required if outputSchema defined)
return {
content: [{ type: 'text', text: JSON.stringify({ count: 42 }) }],
structuredContent: { count: 42 }
};
// Error result
return {
content: [{ type: 'text', text: 'Failed to process request' }],
isError: true
};
// Multiple content blocks with resource links
return {
content: [
{ type: 'text', text: 'Found 2 files' },
{ type: 'resource_link', uri: 'file:///project/README.md', name: 'README.md', mimeType: 'text/markdown' },
{ type: 'resource_link', uri: 'file:///project/index.ts', name: 'index.ts', mimeType: 'text/typescript' }
],
structuredContent: { count: 2, files: ['README.md', 'index.ts'] }
};type ToolCallback<Args extends ZodRawShape = undefined> = Args extends undefined
? (extra: RequestHandlerExtra) => Promise<CallToolResult> | CallToolResult
: (args: z.infer<ZodObject<Args>>, extra: RequestHandlerExtra) => Promise<CallToolResult> | CallToolResult;
interface RequestHandlerExtra {
signal: AbortSignal; // Cancellation signal
authInfo?: AuthInfo; // Validated access token info
sessionId?: string; // Session ID from transport
_meta?: RequestMeta; // Request metadata
requestId: RequestId; // JSON-RPC request ID
requestInfo?: RequestInfo; // HTTP request details
sendNotification: (notification: SendNotificationT) => Promise<void>;
sendRequest: <U extends ZodType<object>>(request: SendRequestT, resultSchema: U, options?: RequestOptions) => Promise<z.infer<U>>;
}interface RegisteredTool {
enable(): void; // Make visible in listTools
disable(): void; // Hide from listTools
update(updates: Partial<ToolConfig>): void; // Update configuration
remove(): void; // Remove entirely
}const tool = server.registerTool('admin-action', config, callback);
tool.disable(); // Initially disabled
// After authentication
tool.enable();
// Update description
tool.update({
description: 'Admin action (authenticated as user@example.com)'
});
// Remove when no longer needed
tool.remove();server.registerTool('risky-operation', {
title: 'Risky Operation',
description: 'An operation that might fail',
inputSchema: { id: z.string() }
}, async ({ id }) => {
try {
const result = await performRiskyOperation(id);
return {
content: [{ type: 'text', text: `Success: ${result}` }],
structuredContent: { success: true, result }
};
} catch (error) {
return {
content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
isError: true
};
}
});ErrorCode.InvalidParams errorstructuredContent is validated against outputSchema if providedstructuredContent when outputSchema is defined results in errorserver.sendToolListChanged(): void; // Notify clients of tool list changesTools are automatically notified when added, removed, enabled, or disabled (if client supports capability).
interface Tool {
name: string;
title?: string;
description?: string;
inputSchema: JSONSchema;
outputSchema?: JSONSchema;
annotations?: ToolAnnotations;
_meta?: Record<string, unknown>;
}
interface ToolAnnotations {
audience?: ('user' | 'assistant')[];
[key: string]: unknown;
}
interface ListToolsResult {
tools: Tool[];
nextCursor?: string;
}server.tool(name: string, callback: ToolCallback): RegisteredTool;
server.tool(name: string, description: string, callback: ToolCallback): RegisteredTool;
server.tool<Args extends ZodRawShape>(name: string, paramsSchema: Args, callback: ToolCallback<Args>): RegisteredTool;
server.tool<Args extends ZodRawShape>(name: string, description: string, paramsSchema: Args, callback: ToolCallback<Args>): RegisteredTool;Use registerTool for new code.