@agentdb/mcp-protocol
v1.1.1
Published
TypeScript framework for implementing MCP (Model Context Protocol) servers
Maintainers
Readme
MCP Protocol Framework
A reusable TypeScript framework for implementing MCP (Model Context Protocol) servers that can be used in any application with different tools and backends.
Overview
This framework extracts the core MCP protocol handling logic into a reusable, application-agnostic framework. It handles:
- JSON-RPC 2.0 protocol compliance
- MCP-specific methods (
initialize,ping,tools/list,tools/call,resources/list,resources/read,prompts/list,prompts/get, etc.) - HTTP transport with CORS support
- Tool execution delegation
- Resource management with list, read, templates, and subscriptions
- Prompt management with list and get operations
- Notification system for tools, resources, prompts, and cancellation events
- Error handling and response formatting
- Server-Sent Events (SSE) for notifications
Installation
npm install @agentdb/mcp-protocolArchitecture
The framework consists of several main components:
- MCPProtocolHandler - Core JSON-RPC protocol handling
- MCPHttpTransport - HTTP-specific transport layer
- ToolsProvider & ToolHandler - Interfaces for tool management and execution
- ResourcesProvider - Interface for resource management (optional)
- PromptsProvider - Interface for prompt management (optional)
- NotificationSubscriber - Interface for handling cancellation notifications (optional)
Quick Start
1. Define Your Tools
import { ToolsProvider, MCPTool } from '@agentdb/mcp-protocol';
class MyToolsProvider implements ToolsProvider {
getTools(): MCPTool[] {
return [
{
name: 'my_tool',
description: 'Description of what this tool does',
inputSchema: {
type: 'object',
properties: {
param1: { type: 'string', description: 'First parameter' }
},
required: ['param1']
}
}
];
}
}2. Implement Tool Handler
import { ToolHandler, ToolExecutionResult } from '@agentdb/mcp-protocol';
const myToolHandler: ToolHandler = async (name, args, context) => {
switch (name) {
case 'my_tool':
const result = await doSomething(args.param1);
return {
content: [{
type: 'text',
text: JSON.stringify({ success: true, result })
}]
};
default:
throw new Error(`Unknown tool: ${name}`);
}
};3. Create MCP Server
import { MCPProtocolHandler, MCPHttpTransport } from '@agentdb/mcp-protocol';
const config = {
serverInfo: {
name: 'My MCP Server',
version: '1.0.0'
}
};
const toolsProvider = new MyToolsProvider();
// Optional: Add resources and prompts providers
const resourcesProvider = new MyResourcesProvider(); // optional
const promptsProvider = new MyPromptsProvider(); // optional
const notificationSubscriber = new MyNotificationSubscriber(); // optional
const protocolHandler = new MCPProtocolHandler(
config,
toolsProvider,
myToolHandler,
resourcesProvider, // optional
promptsProvider, // optional
notificationSubscriber // optional
);
const httpTransport = new MCPHttpTransport(protocolHandler);4. Use in Your Application
AWS Lambda
export async function handler(event: any, context: any) {
const method = event.requestContext?.http?.method || event.httpMethod;
const body = event.body;
const headers = event.headers || {};
return await httpTransport.handleHttpRequest(method, body, headers);
}Express.js
app.post('/mcp', async (req, res) => {
const response = await httpTransport.handleHttpRequest(
req.method,
JSON.stringify(req.body),
req.headers
);
res.status(response.statusCode);
Object.entries(response.headers).forEach(([key, value]) => {
res.set(key, value);
});
res.send(response.body);
});Core Interfaces
MCPTool
Defines a tool that can be called by MCP clients:
interface MCPTool {
name: string;
description: string;
inputSchema: {
type: 'object';
properties: Record<string, any>;
required: string[];
};
}ToolsProvider
Interface for providing available tools:
interface ToolsProvider {
getTools(context?: any): Promise<MCPTool[]> | MCPTool[];
shouldNotifyToolsChanged?(toolName: string): boolean;
}ToolHandler
Function signature for handling tool execution:
interface ToolHandler {
(name: string, args: Record<string, any>, context: ToolExecutionContext): Promise<ToolExecutionResult>;
}ToolExecutionResult
Result format for tool execution:
interface ToolExecutionResult {
content: Array<{
type: 'text' | 'image' | 'resource';
text?: string;
data?: string;
mimeType?: string;
}>;
isError?: boolean;
}ResourcesProvider
Interface for providing resources (optional):
interface ResourcesProvider {
getResources(cursor?: string, context?: any): Promise<{ resources: MCPResource[]; nextCursor?: string }> | { resources: MCPResource[]; nextCursor?: string };
getResourceTemplates?(context?: any): Promise<MCPResourceTemplate[]> | MCPResourceTemplate[];
readResource(uri: string, context?: any): Promise<MCPResourceContent[]> | MCPResourceContent[];
subscribeToResource?(uri: string, context?: any): Promise<void> | void;
unsubscribeFromResource?(uri: string, context?: any): Promise<void> | void;
shouldNotifyResourcesChanged?(): boolean;
shouldNotifyResourceUpdated?(uri: string): boolean;
}PromptsProvider
Interface for providing prompts (optional):
interface PromptsProvider {
getPrompts(cursor?: string, context?: any): Promise<{ prompts: MCPPrompt[]; nextCursor?: string }> | { prompts: MCPPrompt[]; nextCursor?: string };
getPrompt(name: string, args?: Record<string, any>, context?: any): Promise<{ description?: string; messages: MCPPromptMessage[] }> | { description?: string; messages: MCPPromptMessage[] };
shouldNotifyPromptsChanged?(): boolean;
}NotificationSubscriber
Interface for handling notifications (optional):
interface NotificationSubscriber {
onCancelled?(requestId: string): void;
}Supported MCP Methods
The framework supports all standard MCP protocol methods:
Core Methods
initialize- Initialize the MCP sessionping- Health checknotifications/initialized- Initialization complete notification
Tools
tools/list- List available toolstools/call- Execute a tool
Resources (optional)
resources/list- List available resourcesresources/read- Read resource contentsresources/templates/list- List resource templatesresources/subscribe- Subscribe to resource updatesresources/unsubscribe- Unsubscribe from resource updates
Prompts (optional)
prompts/list- List available promptsprompts/get- Get a specific prompt with arguments
Notifications
notifications/tools/list_changed- Tools list changednotifications/resources/list_changed- Resources list changednotifications/resources/updated- Resource updatednotifications/prompts/list_changed- Prompts list changednotifications/cancelled- Request cancelled
Advanced Features
Dynamic Tools
Tools can be generated dynamically based on context:
class DynamicToolsProvider implements ToolsProvider {
async getTools(context?: any): Promise<MCPTool[]> {
// Generate tools based on context
const tools = await fetchAvailableTools(context);
return tools.map(tool => ({
name: tool.name,
description: tool.description,
inputSchema: tool.schema
}));
}
}Tool Change Notifications
Notify clients when tools change:
shouldNotifyToolsChanged(toolName: string): boolean {
// Return true for tools that modify the available tool set
return toolName === 'create_tool' || toolName === 'delete_tool';
}Resources Example
Implement a resources provider:
class MyResourcesProvider implements ResourcesProvider {
getResources(cursor?: string) {
return {
resources: [
{
uri: 'file:///project/README.md',
name: 'README.md',
title: 'Project Documentation',
description: 'Main project documentation',
mimeType: 'text/markdown'
}
]
};
}
readResource(uri: string) {
if (uri === 'file:///project/README.md') {
return [{
uri,
name: 'README.md',
mimeType: 'text/markdown',
text: '# My Project\n\nThis is the project documentation.'
}];
}
throw new Error('Resource not found');
}
}Prompts Example
Implement a prompts provider:
class MyPromptsProvider implements PromptsProvider {
getPrompts(cursor?: string) {
return {
prompts: [
{
name: 'code_review',
title: 'Code Review',
description: 'Review code for quality and improvements',
arguments: [
{
name: 'code',
description: 'The code to review',
required: true
}
]
}
]
};
}
getPrompt(name: string, args?: Record<string, any>) {
if (name === 'code_review') {
return {
description: 'Code review prompt',
messages: [
{
role: 'user',
content: {
type: 'text',
text: `Please review this code:\n\n${args?.code || 'No code provided'}`
}
}
]
};
}
throw new Error('Prompt not found');
}
}Custom Context
Pass custom context to tool handlers:
const executionContext = {
debug: true,
metadata: {
userId: 'user123',
sessionId: 'session456'
}
};
const response = await httpTransport.handleHttpRequest(
method, body, headers, executionContext
);Error Handling
The framework automatically handles:
- JSON-RPC protocol errors
- Tool execution errors
- HTTP transport errors
- Request validation errors
Errors are returned in standard JSON-RPC error format:
{
"jsonrpc": "2.0",
"id": "request-id",
"error": {
"code": -32603,
"message": "Tool execution failed: Error message"
}
}Examples
See the examples/ directory for complete examples including:
- File system tools
- Math calculation tools
- Combined tool providers
- AWS Lambda integration
- Express.js integration
License
MIT License - see LICENSE file for details.
Contributing
This package is part of the AgentDB project. Please see the main repository for contribution guidelines.
