Skip to content

Commit 586355b

Browse files
committed
feat(mcp): MCP Server Core + Adapter Framework
Implement the foundation of the MCP server with a robust, extensible adapter framework. This establishes the core protocol handler and plugin system for all future adapters. Implementation: - JSON-RPC 2.0 protocol handler with full spec compliance - Message routing and request/response handling - Structured error handling with proper error codes - Server lifecycle management (start, stop, health checks) - Stdio transport for process communication - Abstract Transport interface for future HTTP support - Base adapter interfaces (Adapter, ToolAdapter) - Adapter lifecycle hooks (initialize, shutdown, healthCheck) - Adapter Registry for management and execution routing - Message handler utilities and logger - Extracted pure functions following testability guidelines Features: ✅ JSON-RPC 2.0 protocol implementation ✅ Stdio transport with event-based communication ✅ Extensible adapter framework with plugin architecture ✅ Dynamic adapter registration/unregistration ✅ Structured error handling throughout ✅ Comprehensive README with architecture docs ✅ Kebab-case file naming for consistency Testing: - 80 tests, all passing - 67% statement coverage (utils at 94%+, integration at >60%) - Unit tests for JSON-RPC protocol (23 tests) - Unit tests for message handlers (25 tests) - Unit tests for adapter registry (23 tests) - Integration tests for full server stack (9 tests) - Mock adapter for testing framework Documentation: - Comprehensive README with examples - Architecture overview with diagrams - API reference for all public classes - Quick start guide with configuration examples Branch: feat/mcp-server-core Priority: High (blocks all other Epic #3 issues) Estimate: 3 days (actual: ~6 hours with AI assistance) Parent Epic: #26 (Epic: MCP Integration) Issue: #27
1 parent 50e6fcd commit 586355b

File tree

14 files changed

+1445
-17
lines changed

14 files changed

+1445
-17
lines changed

packages/mcp-server/README.md

Lines changed: 468 additions & 0 deletions
Large diffs are not rendered by default.

packages/mcp-server/src/adapters/AdapterRegistry.ts renamed to packages/mcp-server/src/adapters/adapter-registry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import { ErrorCode } from '../server/protocol/types';
7-
import type { ToolAdapter } from './ToolAdapter';
7+
import type { ToolAdapter } from './tool-adapter';
88
import type { AdapterContext, ToolDefinition, ToolExecutionContext, ToolResult } from './types';
99

1010
export interface RegistryConfig {
File renamed without changes.

packages/mcp-server/src/adapters/ToolAdapter.ts renamed to packages/mcp-server/src/adapters/tool-adapter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Extends Adapter to provide tool-specific functionality
44
*/
55

6-
import { Adapter } from './Adapter';
6+
import { Adapter } from './adapter';
77
import type { ToolDefinition, ToolExecutionContext, ToolResult, ValidationResult } from './types';
88

99
export abstract class ToolAdapter extends Adapter {

packages/mcp-server/src/index.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@
44
*/
55

66
// Adapter exports
7-
export { Adapter } from './adapters/Adapter';
8-
export { AdapterRegistry, type RegistryConfig } from './adapters/AdapterRegistry';
9-
export { ToolAdapter } from './adapters/ToolAdapter';
7+
export { Adapter } from './adapters/adapter';
8+
export { AdapterRegistry, type RegistryConfig } from './adapters/adapter-registry';
9+
export { ToolAdapter } from './adapters/tool-adapter';
1010
export * from './adapters/types';
1111
// Core exports
12-
export { MCPServer, type MCPServerConfig } from './server/MCPServer';
12+
export { MCPServer, type MCPServerConfig } from './server/mcp-server';
1313
// Protocol exports
1414
export { JSONRPCHandler } from './server/protocol/jsonrpc';
1515
export * from './server/protocol/types';
16-
export { StdioTransport } from './server/transport/StdioTransport';
16+
export { StdioTransport } from './server/transport/stdio-transport';
1717
// Transport exports
1818
export {
1919
Transport,
2020
type TransportConfig,
2121
type TransportMessage,
22-
} from './server/transport/Transport';
22+
} from './server/transport/transport';
2323

2424
// Utility exports
2525
export { ConsoleLogger } from './utils/logger';

packages/mcp-server/src/server/MCPServer.ts renamed to packages/mcp-server/src/server/mcp-server.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
* Handles protocol, routing, and adapter coordination
44
*/
55

6-
import { AdapterRegistry, type RegistryConfig } from '../adapters/AdapterRegistry';
7-
import type { ToolAdapter } from '../adapters/ToolAdapter';
6+
import { AdapterRegistry, type RegistryConfig } from '../adapters/adapter-registry';
7+
import type { ToolAdapter } from '../adapters/tool-adapter';
88
import type { AdapterContext, Config, ToolExecutionContext } from '../adapters/types';
99
import { ConsoleLogger } from '../utils/logger';
1010
import { JSONRPCHandler } from './protocol/jsonrpc';
@@ -18,8 +18,8 @@ import type {
1818
ServerInfo,
1919
ToolCall,
2020
} from './protocol/types';
21-
import { StdioTransport } from './transport/StdioTransport';
22-
import type { Transport, TransportMessage } from './transport/Transport';
21+
import { StdioTransport } from './transport/stdio-transport';
22+
import type { Transport, TransportMessage } from './transport/transport';
2323

2424
export interface MCPServerConfig {
2525
serverInfo: ServerInfo;
@@ -35,7 +35,6 @@ export class MCPServer {
3535
private logger = new ConsoleLogger('[MCP Server]');
3636
private config: Config;
3737
private serverInfo: ServerInfo;
38-
private initialized = false;
3938

4039
constructor(config: MCPServerConfig) {
4140
this.config = config.config;
@@ -163,8 +162,6 @@ export class MCPServer {
163162
* Handle initialize request
164163
*/
165164
private handleInitialize(): InitializeResult {
166-
this.initialized = true;
167-
168165
const capabilities: ServerCapabilities = {
169166
tools: { supported: true },
170167
resources: { supported: false }, // Not yet implemented

packages/mcp-server/src/server/transport/StdioTransport.ts renamed to packages/mcp-server/src/server/transport/stdio-transport.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import * as readline from 'readline';
77
import { JSONRPCHandler } from '../protocol/jsonrpc';
88
import type { JSONRPCNotification, JSONRPCResponse } from '../protocol/types';
9-
import { Transport, type TransportMessage } from './Transport';
9+
import { Transport, type TransportMessage } from './transport';
1010

1111
export class StdioTransport extends Transport {
1212
private messageHandler?: (message: TransportMessage) => void | Promise<void>;
File renamed without changes.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/**
2+
* Utilities for handling MCP protocol messages
3+
*/
4+
5+
import type { AdapterRegistry } from '../../adapters/adapter-registry';
6+
import type {
7+
InitializeResult,
8+
ServerCapabilities,
9+
ServerInfo,
10+
ToolDefinition,
11+
} from '../protocol/types';
12+
13+
/**
14+
* Create initialization result
15+
*/
16+
export function createInitializeResult(
17+
serverInfo: ServerInfo,
18+
capabilities: ServerCapabilities
19+
): InitializeResult {
20+
return {
21+
protocolVersion: '1.0.0',
22+
serverInfo,
23+
capabilities,
24+
};
25+
}
26+
27+
/**
28+
* Create tools list result
29+
*/
30+
export function createToolsListResult(registry: AdapterRegistry): { tools: ToolDefinition[] } {
31+
return {
32+
tools: registry.getToolDefinitions(),
33+
};
34+
}
35+
36+
/**
37+
* Extract tool call parameters from request
38+
*/
39+
export function extractToolCallParams(
40+
params: unknown
41+
): { name: string; arguments: Record<string, unknown> } | null {
42+
if (!params || typeof params !== 'object') {
43+
return null;
44+
}
45+
46+
const p = params as Record<string, unknown>;
47+
48+
if (typeof p.name !== 'string') {
49+
return null;
50+
}
51+
52+
if (typeof p.arguments !== 'object' || p.arguments === null) {
53+
return null;
54+
}
55+
56+
return {
57+
name: p.name,
58+
arguments: p.arguments as Record<string, unknown>,
59+
};
60+
}
61+
62+
/**
63+
* Validate JSON-RPC request structure
64+
*/
65+
export function validateRequest(request: unknown): boolean {
66+
if (!request || typeof request !== 'object') {
67+
return false;
68+
}
69+
70+
const req = request as Record<string, unknown>;
71+
72+
// Must have jsonrpc and method
73+
if (req.jsonrpc !== '2.0' || typeof req.method !== 'string') {
74+
return false;
75+
}
76+
77+
return true;
78+
}
79+
80+
/**
81+
* Check if method is supported
82+
*/
83+
export function isSupportedMethod(method: string): boolean {
84+
const supportedMethods = ['initialize', 'tools/list', 'tools/call'];
85+
return supportedMethods.includes(method);
86+
}

0 commit comments

Comments
 (0)