Documentation Index
Fetch the complete documentation index at: https://docs.ag-kit.dev/llms.txt
Use this file to discover all available pages before exploring further.
MCP Integration
The AG-Kit MCP integration provides seamless bidirectional conversion between AG-Kit’s tool system and the Model Context Protocol (MCP). This allows you to:
- Connect to standard MCP servers and use their tools as AG-Kit BaseTool instances
- Expose AG-Kit tools as MCP servers for external clients to consume
- Support multiple transport protocols including stdio, HTTP, SSE, in-memory etc.
Overview
The MCP integration consists of several key components:
- MCPClientTool: Wraps external MCP tools to work within AG-Kit
- MCPToolkit: High-level toolkit for managing MCP tools
- AGKitMCPServer: Exposes AG-Kit tools as a standard MCP server
- MCPClientManager: Manages connections to multiple MCP servers
Quick Start
import { MCPClientManager, MCPClientTool } from '@ag-kit/tools/mcp';
// Create a client manager
const clientManager = new MCPClientManager();
// Connect to an external MCP server
await clientManager.addServer('math-server', {
name: 'math-client',
version: '1.0.0',
transport: {
type: 'stdio',
command: 'python',
args: ['-m', 'math_mcp_server']
}
});
// Create AG-Kit tools from MCP tools
const clientTools = clientManager.createClientTools('math-server');
// Use the tools in your AG-Kit application
for (const tool of clientTools) {
const result = await tool.invoke({ a: 5, b: 3 });
console.log(result.data);
}
import { AGKitMCPServer } from '@ag-kit/tools/mcp';
import { MyCustomTool } from './my-tools';
// Create your AG-Kit tools
const calculatorTool = new MyCustomTool();
// Create MCP server
const server = new AGKitMCPServer({
name: 'ag-kit-mcp-server',
version: '1.0.0',
description: 'AG-Kit tools exposed via MCP'
});
// Register tools
server.registerTool(calculatorTool);
// Start server with stdio transport
await server.run({ type: 'stdio' });
Transport Protocols
Stdio Transport
The most common transport for MCP servers, using standard input/output.
Server Configuration
// Start server with stdio
await server.run({ type: 'stdio' });
Client Configuration
await clientManager.addServer('my-server', {
name: 'my-client',
version: '1.0.0',
transport: {
type: 'stdio',
command: 'python',
args: ['-m', 'my_mcp_server'],
timeout: 10000
}
});
HTTP Transport (StreamableHTTP)
For web-based MCP servers and clients.
Server Configuration
import express from 'express';
const app = express();
await server.run({
type: 'streamableHttp',
streamableHttpSetup: async (server, createTransport) => {
app.post('/mcp', async (req, res) => {
const transport = await createTransport({
enableJsonResponse: true,
sessionIdGenerator: () => crypto.randomUUID()
});
await transport.handleRequest(req, res, req.body);
});
}
});
app.listen(3000, () => {
console.log('MCP server running on http://localhost:3000/mcp');
});
Client Configuration
await clientManager.addServer('http-server', {
name: 'http-client',
version: '1.0.0',
transport: {
type: 'streamableHttp',
url: 'http://localhost:3000/mcp',
timeout: 15000
}
});
SSE Transport
Server-Sent Events transport for real-time communication.
Server Configuration
import express from 'express';
const app = express();
await server.run({
type: 'sse',
sseSetup: async (server, createTransport) => {
let transport
app.get('/mcp/sse', async (req, res) => {
transport = await createTransport('/mcp/sse', res, {
enableDnsRebindingProtection: false
});
});
// 处理认证的 POST 请求
app.post('/mcp/sse', async (req, res) => {
if (transport) {
await transport.handlePostMessage(req, res, req.body);
} else {
res.status(404).json({ error: 'No active SSE connection' });
}
});
app.listen(3000);
}
});
Client Configuration
await clientManager.addServer('sse-server', {
name: 'sse-client',
version: '1.0.0',
transport: {
type: 'sse',
url: 'http://localhost:3000/mcp/sse'
}
});
In-Memory Transport
For testing and same-process communication.
Server Configuration
const memoryId = 'my-memory-server';
await server.run({
type: 'memory',
memoryId
});
Client Configuration
await clientManager.addServer('memory-server', {
name: 'memory-client',
version: '1.0.0',
transport: {
type: 'memory',
memoryId: 'my-memory-server'
}
});
Core Examples
Example 1: Creating and Running an MCP Server
Expose AG-Kit tools as a standard MCP server:
import { AGKitMCPServer } from '@ag-kit/tools/mcp';
import { MyExistingTool } from './my-tools';
// Create MCP server instance
const server = new AGKitMCPServer({
name: 'my-agkit-server',
version: '1.0.0',
description: 'AG-Kit tools exposed via MCP'
});
// Register existing AG-Kit tools
const myTool = new MyExistingTool();
server.registerTool(myTool);
// Register multiple tools with shared configuration
server.registerTools([tool1, tool2, tool3], {
namePrefix: 'agkit_' // All tools will be prefixed with 'agkit_'
});
// Start server with different transports
// Option 1: Stdio (most common)
await server.run({ type: 'stdio' });
// Option 2: HTTP
await server.run({
type: 'streamableHttp',
streamableHttpSetup: async (server, createTransport) => {
app.post('/mcp', async (req, res) => {
const transport = await createTransport();
await transport.handleRequest(req, res, req.body);
});
}
});
// Option 3: Memory (for testing)
await server.run({
type: 'memory',
memoryId: 'test-server'
});
Example 2: Connecting to External MCP Servers
Use external MCP servers as AG-Kit tools:
import { MCPClientManager } from '@ag-kit/tools/mcp';
// Create client manager
const clientManager = new MCPClientManager();
// Connect to different types of MCP servers
// Stdio server
await clientManager.addServer('filesystem-server', {
name: 'fs-client',
version: '1.0.0',
transport: {
type: 'stdio',
command: 'npx',
args: ['@modelcontextprotocol/server-filesystem', './workspace']
}
});
// HTTP server
await clientManager.addServer('api-server', {
name: 'api-client',
version: '1.0.0',
transport: {
type: 'streamableHttp',
url: 'https://api.example.com/mcp'
}
});
// Create AG-Kit tools from MCP tools
const allClientTools = clientManager.createClientTools();
// Create specific tool with custom name
const specificTool = clientManager.createClientTool(
'filesystem-server',
'read_file',
'custom_file_reader'
);
// Use the tools in AG-Kit
const result = await specificTool.invoke({ path: 'README.md' });
console.log(result.data);
High-level toolkit approach for managing multiple MCP connections:
import { MCPToolkit, createMCPToolkit } from '@ag-kit/tools/mcp';
// Method 1: Create toolkit and add servers dynamically
const toolkit = new MCPToolkit('my-toolkit');
await toolkit.addServer('filesystem', {
name: 'filesystem',
version: '1.0.0',
transport: { type: 'stdio', command: 'fs-server' }
});
await toolkit.addServer('database', {
name: 'db-client',
version: '1.0.0',
transport: { type: 'streamableHttp', url: 'http://db-server/mcp' }
});
// Method 2: Create toolkit with object mapping (recommended)
// Matches standard MCP config format (e.g., Claude Desktop)
const toolkit2 = await createMCPToolkit({
filesystem: {
command: 'fs-server' // Direct transport config
},
database: {
url: 'http://db-server/mcp' // Direct transport config
}
}, 'multi-server-toolkit');
// Method 3: Create toolkit with array format (backward compatible)
const toolkit3 = await createMCPToolkit([
{
id: 'filesystem',
config: {
name: 'fs-client',
version: '1.0.0',
transport: { type: 'stdio', command: 'fs-server' }
}
},
{
id: 'database',
config: {
name: 'db-client',
version: '1.0.0',
transport: { type: 'streamableHttp', url: 'http://db-server/mcp' }
}
}
], 'multi-server-toolkit');
// Access tools by server
const fsTools = toolkit.getServerTools('filesystem');
const dbTools = toolkit.getServerTools('database');
// Access all tools
const allTools = toolkit.getTools();
// Refresh connections
await toolkit.refresh();
// Cleanup when done
await toolkit.cleanup();
Example 4: Memory Transport for Testing
Use memory transport for testing MCP integrations:
import { AGKitMCPServer, MCPClientManager } from '@ag-kit/tools/mcp';
// Test setup
const memoryId = 'test-memory-transport';
const serverInfo ={
name: 'test-server',
version: '1.0.0'
};
// Create server
const server = new AGKitMCPServer(serverInfo);
server.registerTool(new MyTestTool());
await server.run({ type: 'memory', memoryId });
// Create client
const clientManager = new MCPClientManager();
await clientManager.addServer(serverInfo.name, {
name: 'test-client',
version: '1.0.0',
transport: { type: 'memory', memoryId }
});
// Test tool execution
const tools = clientManager.createClientTools();
const testTool = tools[0];
const result = await testTool.invoke({ test: 'data' });
// Cleanup
await clientManager.disconnectAll();
await server.stop();
Example 5: Advanced Connection Management
Handle connection options and error scenarios:
import { MCPClientManager } from '@ag-kit/tools/mcp';
const clientManager = new MCPClientManager();
// Add server with connection options
await clientManager.addServer('reliable-server', {
name: 'reliable-client',
version: '1.0.0',
transport: {
type: 'stdio',
command: 'external-server',
timeout: 10000
}
}, {
autoReconnect: true,
reconnectDelay: 5000,
maxReconnectAttempts: 3,
heartbeatInterval: 30000
});
// Handle pre-connected clients
const preConnectedClient = new Client(/* ... */);
await preConnectedClient.connect(transport);
await clientManager.addServer('pre-connected', {
name: 'pre-connected-client',
version: '1.0.0',
client: preConnectedClient,
onReconnectNeeded: async (serverId, config) => {
// Custom reconnection logic
const newClient = new Client(/* ... */);
await newClient.connect(/* new transport */);
return newClient;
}
});
// Monitor connection status
setInterval(() => {
const isConnected = clientManager.isServerConnected('reliable-server');
console.log(`Server connected: ${isConnected}`);
}, 5000);
Example 6: Event Handling and Monitoring
Monitor MCP operations with event listeners:
import { AGKitMCPServer, MCPClientManager } from '@ag-kit/tools/mcp';
// Server event monitoring
const server = new AGKitMCPServer({
name: 'monitored-server',
version: '1.0.0'
});
server.addEventListener((event) => {
switch (event.type) {
case 'connected':
console.log(`Client connected: ${event.clientName}`);
break;
case 'tool_called':
console.log(`Tool ${event.toolName} called with:`, event.arguments);
break;
case 'tool_result':
console.log(`Tool ${event.toolName} returned:`, event.result);
break;
case 'error':
console.error(`Server error in ${event.context}:`, event.error);
break;
}
});
// Client event monitoring
const clientManager = new MCPClientManager();
clientManager.addEventListener((event) => {
switch (event.type) {
case 'connected':
console.log(`Connected to server: ${event.clientName}`);
break;
case 'tool_discovered':
console.log(`Discovered tool: ${event.tool.name}`);
break;
case 'disconnected':
console.log(`Disconnected from: ${event.clientName}`);
if (event.reason) {
console.log(`Reason: ${event.reason}`);
}
break;
case 'error':
console.error(`Client error:`, event.error);
break;
}
});
Advanced Configuration
Customize how AG-Kit tools are exposed via MCP:
// Register tool with custom configuration
server.registerTool(calculatorTool, {
namePrefix: 'math_', // Prefix tool name
description: 'Custom calculator' // Override description
});
// Register multiple tools with shared config
server.registerTools([tool1, tool2, tool3], {
namePrefix: 'utils_'
});
Customize MCP client tools:
const clientTool = new MCPClientTool(
mcpClient,
toolMetadata,
{
name: 'custom_tool_name', // Custom AG-Kit name
timeout: 30000, // Call timeout
retries: 3 // Retry attempts
},
{
includeMetadata: true, // Include execution metadata
transformInput: (input) => { // Transform input before MCP call
return { ...input, timestamp: Date.now() };
},
transformOutput: (output) => { // Transform output after MCP call
return { result: output, processed: true };
},
errorHandler: (error) => { // Custom error handling
return new ToolResult({
success: false,
error: `Custom error: ${error.message}`
});
}
}
);
Connection Management
Advanced connection options:
await clientManager.addServer('reliable-server', config, {
autoReconnect: true, // Auto-reconnect on failure
reconnectDelay: 5000, // Delay between reconnect attempts
maxReconnectAttempts: 5, // Maximum reconnect attempts
heartbeatInterval: 30000 // Heartbeat interval
});
// Handle pre-connected clients
const preConnectedClient = new Client(/* ... */);
await preConnectedClient.connect(transport);
await clientManager.addServer('pre-connected', {
name: 'pre-connected-client',
version: '1.0.0',
client: preConnectedClient,
onReconnectNeeded: async (serverId, config) => {
// Handle reconnection for pre-connected clients
const newClient = new Client(/* ... */);
await newClient.connect(/* new transport */);
return newClient;
}
});
Event Handling
Monitor MCP operations:
// Server events
server.addEventListener((event) => {
switch (event.type) {
case 'connected':
console.log(`Client connected: ${event.clientName}`);
break;
case 'tool_called':
console.log(`Tool called: ${event.toolName}`, event.arguments);
break;
case 'tool_result':
console.log(`Tool result: ${event.toolName}`, event.result);
break;
case 'error':
console.error(`Error in ${event.context}:`, event.error);
break;
}
});
// Client events
clientManager.addEventListener((event) => {
switch (event.type) {
case 'connected':
console.log(`Connected to server: ${event.clientName}`);
break;
case 'tool_discovered':
console.log(`Tool discovered: ${event.tool.name}`);
break;
case 'disconnected':
console.log(`Disconnected from server: ${event.clientName}`);
break;
}
});
Schema Conversion
AG-Kit automatically converts between Zod schemas and MCP JSON schemas:
Zod to MCP Schema
import { z } from 'zod';
import { zodSchemaToMCPSchema } from '@ag-kit/tools/mcp';
const zodSchema = z.object({
name: z.string().describe('User name'),
age: z.number().min(0).max(150),
email: z.string().email().optional(),
tags: z.array(z.string()),
preferences: z.record(z.string(), z.any())
});
const mcpSchema = zodSchemaToMCPSchema(zodSchema);
// Results in MCP-compatible JSON schema
MCP to Zod Schema
// MCPClientTool automatically converts MCP schemas to Zod
const mcpToolMetadata = {
name: 'user_tool',
inputSchema: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' }
},
required: ['name', 'age']
}
};
const clientTool = new MCPClientTool(client, mcpToolMetadata);
// Tool now has Zod schema for AG-Kit compatibility
Error Handling
Server Error Handling
const server = new AGKitMCPServer({
name: 'error-handling-server',
version: '1.0.0',
errorHandling: 'return_error', // or 'throw'
transformOutput: (output) => {
// Transform output before sending
return output;
}
});
// Handle tool errors gracefully
class SafeTool extends BaseTool {
protected async _invoke(input: any): Promise<ToolResult> {
try {
// Tool logic here
return new ToolResult({ success: true, data: result });
} catch (error) {
return new ToolResult({
success: false,
error: `Tool execution failed: ${error.message}`
});
}
}
}
Client Error Handling
const clientTool = new MCPClientTool(
client,
metadata,
{ retries: 3, timeout: 10000 },
{
errorHandler: (error) => {
// Custom error handling
if (error.message.includes('timeout')) {
return new ToolResult({
success: false,
error: 'Operation timed out, please try again'
});
}
return new ToolResult({
success: false,
error: `MCP tool error: ${error.message}`
});
}
}
);
API Reference
For complete API documentation including all interfaces, types, and detailed method signatures, see the MCP API Reference.
AGKitMCPServer - Exposes AG-Kit tools as a standard MCP server
registerTool(tool: BaseTool, config?: MCPToolConfig): MCPToolMetadata - Register a single tool
registerTools(tools: BaseTool[], config?: MCPToolConfig): MCPToolMetadata[] - Register multiple tools
unregisterTool(name: string): boolean - Remove a tool from the server
run(transportConfig: MCPTransportConfig): Promise<void> - Start the server with specified transport
stop(): Promise<void> - Stop the server and cleanup resources
callTool(name: string, args: Record<string, any>): Promise<CallToolResult> - Execute a tool directly
listTools() - Get list of all registered tools
isServerRunning(): boolean - Check if server is running
getStats(): object - Get server statistics
MCPClientManager - Manages connections to external MCP servers
addServer(serverId: string, config: MCPClientConfig, options?: MCPConnectionOptions): Promise<void> - Connect to an MCP server
disconnectServer(serverId: string): Promise<void> - Disconnect from a specific server
disconnectAll(): Promise<void> - Disconnect from all servers
createClientTools(serverId?: string): MCPClientTool[] - Create AG-Kit tool wrappers
createClientTool(serverId: string, toolName: string, agKitToolName?: string): MCPClientTool - Create specific tool wrapper
callTool(serverId: string, toolName: string, args: any): Promise<any> - Call an MCP tool directly
isServerConnected(serverId: string): boolean - Check connection status
getStats(): object - Get client manager statistics
MCPClientTool - Wraps external MCP tools for AG-Kit compatibility
invoke(input: any, context?: ToolExecutionContext): Promise<ToolResult> - Execute the MCP tool
getMCPMetadata(): MCPToolMetadata - Get original MCP tool metadata
isConnected(): boolean - Check if underlying client is connected
updateConfig(newConfig: Partial<MCPToolConfig>): void - Update tool configuration
MCPToolkit - High-level toolkit for managing MCP tools
addServer(serverId: string, config: MCPClientConfig): Promise<void> - Add an MCP server
removeServer(serverId: string): Promise<void> - Remove a server
getConnectedServers(): string[] - Get list of connected servers
getServerTools(serverId: string): MCPClientTool[] - Get tools from specific server
refresh(): Promise<void> - Refresh all connections
cleanup(): Promise<void> - Cleanup all resources
getClientManager(): MCPClientManager - Get underlying client manager
See the complete API documentation for detailed interface definitions, type information, utility functions, and advanced configuration options.
Best Practices
- Use appropriate transports: stdio for CLI tools, HTTP for web services, memory for testing
- Handle errors gracefully: Implement proper error handling and retry logic
- Monitor connections: Use event listeners to track connection status
- Clean up resources: Always call cleanup methods when done
- Test thoroughly: Use memory transport for comprehensive testing
- Schema validation: Ensure your schemas are compatible between Zod and MCP JSON Schema
- Connection management: Use connection options for reliable production deployments
Troubleshooting
Common Issues
- Connection timeouts: Increase timeout values in transport configuration
- Schema conversion errors: Ensure Zod schemas use supported types
- Tool not found: Check tool registration and naming
- Transport errors: Verify transport configuration and server availability
- Memory leaks: Always clean up connections and event listeners
Debug Mode
Enable logging for debugging:
const server = new AGKitMCPServer({
name: 'debug-server',
version: '1.0.0',
enableLogging: true // Enable debug logging
});
For more detailed examples and advanced usage patterns, see the MCP API Reference section.