0.1.0 • Published 4 months ago

mcp-toolkit v0.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

MCP Toolkit

npm version Node.js CI License: MIT

A TypeScript implementation of the Model Context Protocol (MCP) toolkit for connecting to and interacting with MCP-compliant servers.

Overview

The Model Context Protocol (MCP) is a standardized protocol that enables communication between LLM applications and external data sources or tools. The MCP Toolkit provides a robust, modular implementation for building MCP-compliant clients that can:

  • Connect to MCP servers using different transport mechanisms (stdio, SSE)
  • Discover and execute tools provided by servers
  • Discover, read, and subscribe to resources
  • Handle server lifecycle events and error conditions
  • Manage connections to multiple servers

Key Features

  • Simplified Client API: High-level client for quick integration
  • Transport Layer Options: Support for stdio (local processes) and SSE (remote servers)
  • Tool Execution: Discover and execute tools with proper error handling
  • Resource Management: List, read, and subscribe to resources
  • Error Handling: Comprehensive error handling with recovery strategies
  • TypeScript Support: Full TypeScript definitions for type safety

Installation

npm install @modelcontextprotocol/toolkit

Quick Start

Basic Usage

import { McpClient } from '@modelcontextprotocol/toolkit';
import { StdioClientTransport } from '@modelcontextprotocol/toolkit';

async function main() {
  // Create client
  const client = new McpClient(
    {
      name: 'my-client',
      version: '1.0.0'
    },
    {
      capabilities: {
        resources: {},
        tools: {},
        prompts: {}
      },
      requestTimeout: 10000
    }
  );

  try {
    // Create transport to a local server process
    const transport = new StdioClientTransport({
      command: 'node',
      args: ['path/to/server.js'],
      inherit: false
    });

    // Connect to server
    await client.connect(transport);
    console.log('Connected to server');

    // Get server info
    const serverInfo = await client.getServerInfo();
    console.log('Server info:', serverInfo);

    // List available tools
    const tools = await client.listTools();
    console.log('Available tools:', tools);

    // Call a tool
    if (tools.length > 0) {
      const result = await client.callTool(tools[0].name, { 
        // parameters matching the tool's schema
      });
      console.log('Tool result:', result);
    }

    // List available resources
    const resources = await client.listResources();
    console.log('Available resources:', resources);

    // Read a resource
    if (resources.length > 0) {
      const resourceContent = await client.readResource(resources[0].uri);
      console.log('Resource content:', resourceContent);
    }
  } catch (error) {
    console.error('Error:', error);
  } finally {
    // Close the connection
    await client.close();
    console.log('Connection closed');
  }
}

main();

Using SSE Transport (for remote servers)

import { McpClient, SseTransport } from '@modelcontextprotocol/toolkit';

// Create an SSE transport for a remote server
const transport = new SseTransport({
  baseUrl: 'https://your-mcp-server-url.com',
  headers: {
    'Authorization': 'Bearer your-auth-token'
  }
});

// Use the transport with your client
const client = new McpClient({ /* config */ });
await client.connect(transport);

Client Configuration

The McpClient constructor takes two optional configuration objects:

const client = new McpClient(
  // Client info (optional)
  {
    name: 'my-client',         // Client name
    version: '1.0.0'           // Client version
  },
  // Client config (optional)
  {
    capabilities: {            // Client capabilities
      resources: {},           // Resource-specific capabilities
      tools: {},               // Tool-specific capabilities
      prompts: {}              // Prompt-specific capabilities
    },
    requestTimeout: 10000,     // Request timeout in milliseconds
  }
);

Resource Management

Resources are data and content exposed by MCP servers that can be read by clients.

Listing Resources

// List all available resources
const resources = await client.listResources();
console.log('Available resources:', resources);

Reading Resources

// Read a resource by URI
const resourceContent = await client.readResource('mcp://server-name/path/to/resource');
console.log('Resource content:', resourceContent);

Subscribing to Resource Updates

// Subscribe to resource updates
await client.subscribeResource('mcp://server-name/path/to/resource');

// Listen for resource update events
client.onResourceUpdated((event) => {
  console.log('Resource updated:', event.uri);
  console.log('New content:', event.content);
});

Tool Execution

Tools are executable functions exposed by MCP servers that clients can call.

Listing Tools

// List all available tools
const tools = await client.listTools();
console.log('Available tools:', tools);

Calling Tools

// Call a tool by name with parameters
const result = await client.callTool('tool-name', {
  param1: 'value1',
  param2: 'value2'
});
console.log('Tool result:', result);

Error Handling

The toolkit provides comprehensive error handling with specific error types for different scenarios.

import { ConnectionError, ToolError } from '@modelcontextprotocol/toolkit';

try {
  await client.callTool('non-existent-tool', {});
} catch (error) {
  if (error instanceof ToolError) {
    console.error('Tool execution error:', error.message);
    // Handle tool-specific errors
  } else if (error instanceof ConnectionError) {
    console.error('Connection error:', error.message);
    // Handle connection errors
  } else {
    console.error('Unexpected error:', error);
  }
}

Transport Options

StdioClientTransport

For connecting to local server processes using standard input/output.

import { StdioClientTransport } from '@modelcontextprotocol/toolkit';

const transport = new StdioClientTransport({
  command: 'node',             // Command to start the server
  args: ['server.js'],         // Command arguments
  inherit: false,              // Whether to inherit stdio from parent process
  env: {                       // Optional environment variables
    NODE_ENV: 'production'
  },
  cwd: '/path/to/working/dir'  // Optional working directory
});

SseTransport

For connecting to remote servers using Server-Sent Events (SSE).

import { SseTransport } from '@modelcontextprotocol/toolkit';

const transport = new SseTransport({
  baseUrl: 'https://your-mcp-server.com',  // Server URL
  headers: {                               // Optional HTTP headers
    'Authorization': 'Bearer token'
  },
  retryInterval: 3000                      // Retry interval in milliseconds
});

Advanced Usage

Event Handling

The client provides event handlers for various lifecycle events.

// Connection events
client.onConnect(() => {
  console.log('Connected to server');
});

client.onDisconnect(() => {
  console.log('Disconnected from server');
});

// Resource updates
client.onResourceUpdated((event) => {
  console.log('Resource updated:', event.uri);
});

// Server events
client.onServerEvent((event) => {
  console.log('Server event:', event.type, event.data);
});

Multi-Server Management

For applications that need to connect to multiple MCP servers, the toolkit provides a higher-level API:

import { container, registerServices } from '@modelcontextprotocol/toolkit';
import { IMCPToolkit } from '@modelcontextprotocol/toolkit';

// Register services with configuration
registerServices({
  servers: {
    'server1': {
      command: 'node',
      args: ['path/to/server1.js'],
      autoRestart: true
    },
    'server2': {
      command: 'node',
      args: ['path/to/server2.js'],
      autoRestart: true
    }
  },
  connections: {
    defaults: {
      transportType: 'stdio',
      requestTimeout: 5000
    }
  }
});

// Get the toolkit instance
const toolkit = container.resolve<IMCPToolkit>('IMCPToolkit');

// Start all servers and establish connections
await toolkit.start();

// Get tools from all servers
const allTools = await toolkit.getAvailableTools();

// Execute a tool call on any server
const result = await toolkit.executeToolCall({
  function_name: 'tool-name',
  parameters: { param1: 'value1' }
});

// Stop all servers and close connections
await toolkit.stop();

Parallel Tool Execution

// Execute multiple tool calls in parallel
const results = await toolkit.executeToolCalls([
  {
    function_name: 'tool1',
    parameters: { param1: 'value1' }
  },
  {
    function_name: 'tool2',
    parameters: { param2: 'value2' }
  }
]);

Examples

Check out the examples directory for more comprehensive examples:

Documentation

For more detailed documentation, see:

Development

Building from Source

# Clone the repository
git clone https://github.com/adamavenir/mcp-toolkit.git
cd mcp-toolkit

# Install dependencies
npm install

# Build the project
npm run build

# Run tests
npm test

Contributing

Contributions are welcome! Please read our Contributing Guide for details on how to submit pull requests, open issues, and more.

Development and Versioning

Versioning

We use semantic versioning. To bump the version and create a git tag, use one of the following npm scripts:

# Bump patch version (0.0.x)
npm run version:patch

# Bump minor version (0.x.0)
npm run version:minor

# Bump major version (x.0.0)
npm run version:major

After bumping the version, push the changes and tags:

git push && git push --tags

This will trigger the GitHub Action to automatically publish the new version to npm.

License

MIT