@synth-coder/memhub 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/README.zh-CN.md +1 -1
- package/dist/src/contracts/mcp.d.ts +2 -112
- package/dist/src/contracts/mcp.d.ts.map +1 -1
- package/dist/src/contracts/mcp.js +8 -30
- package/dist/src/contracts/mcp.js.map +1 -1
- package/dist/src/server/mcp-server.d.ts +4 -74
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/src/server/mcp-server.js +55 -209
- package/dist/src/server/mcp-server.js.map +1 -1
- package/docs/proposals/mcp-typescript-sdk-refactor.md +568 -0
- package/package.json +4 -3
- package/src/contracts/mcp.ts +10 -145
- package/src/server/mcp-server.ts +66 -274
- package/test/server/mcp-server.test.ts +78 -8
- package/test/server/mcp-server-internals.test.ts +0 -257
package/src/contracts/mcp.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP (Model Context Protocol) specific types and constants
|
|
3
|
-
*
|
|
3
|
+
* Tool definitions and business-level types (protocol types provided by SDK)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { Memory } from './types.js';
|
|
@@ -19,86 +19,7 @@ export const SERVER_INFO = {
|
|
|
19
19
|
} as const;
|
|
20
20
|
|
|
21
21
|
// ============================================================================
|
|
22
|
-
// MCP
|
|
23
|
-
// ============================================================================
|
|
24
|
-
|
|
25
|
-
/** JSON-RPC request ID */
|
|
26
|
-
export type RequestId = string | number;
|
|
27
|
-
|
|
28
|
-
/** Base JSON-RPC request structure */
|
|
29
|
-
export interface JsonRpcRequest<T = unknown> {
|
|
30
|
-
jsonrpc: '2.0';
|
|
31
|
-
id?: RequestId;
|
|
32
|
-
method: string;
|
|
33
|
-
params?: T;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Base JSON-RPC response structure */
|
|
37
|
-
export interface JsonRpcResponse<T = unknown> {
|
|
38
|
-
jsonrpc: '2.0';
|
|
39
|
-
id: RequestId | null;
|
|
40
|
-
result?: T;
|
|
41
|
-
error?: JsonRpcError;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** JSON-RPC error structure */
|
|
45
|
-
export interface JsonRpcError {
|
|
46
|
-
code: number;
|
|
47
|
-
message: string;
|
|
48
|
-
data?: unknown;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** JSON-RPC notification (no response expected) */
|
|
52
|
-
export interface JsonRpcNotification<T = unknown> {
|
|
53
|
-
jsonrpc: '2.0';
|
|
54
|
-
method: string;
|
|
55
|
-
params?: T;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// ============================================================================
|
|
59
|
-
// MCP Lifecycle Messages
|
|
60
|
-
// ============================================================================
|
|
61
|
-
|
|
62
|
-
/** Initialize request parameters */
|
|
63
|
-
export interface InitializeParams {
|
|
64
|
-
protocolVersion: string;
|
|
65
|
-
capabilities: ClientCapabilities;
|
|
66
|
-
clientInfo: Implementation;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** Initialize result */
|
|
70
|
-
export interface InitializeResult {
|
|
71
|
-
protocolVersion: string;
|
|
72
|
-
capabilities: ServerCapabilities;
|
|
73
|
-
serverInfo: Implementation;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** Implementation information */
|
|
77
|
-
export interface Implementation {
|
|
78
|
-
name: string;
|
|
79
|
-
version: string;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/** Client capabilities */
|
|
83
|
-
export interface ClientCapabilities {
|
|
84
|
-
// Client can handle these features
|
|
85
|
-
readonly experimental?: Record<string, unknown>;
|
|
86
|
-
readonly roots?: { listChanged?: boolean };
|
|
87
|
-
readonly sampling?: Record<string, unknown>;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** Server capabilities */
|
|
91
|
-
export interface ServerCapabilities {
|
|
92
|
-
// Server provides these features
|
|
93
|
-
readonly experimental?: Record<string, unknown>;
|
|
94
|
-
readonly logging?: Record<string, unknown>;
|
|
95
|
-
readonly prompts?: { listChanged?: boolean };
|
|
96
|
-
readonly resources?: { subscribe?: boolean; listChanged?: boolean };
|
|
97
|
-
readonly tools?: { listChanged?: boolean };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// ============================================================================
|
|
101
|
-
// MCP Tool Definitions
|
|
22
|
+
// MCP Tool Definitions (kept for SDK use)
|
|
102
23
|
// ============================================================================
|
|
103
24
|
|
|
104
25
|
/** Tool definition for tool/list */
|
|
@@ -116,34 +37,6 @@ export interface ToolInputSchema {
|
|
|
116
37
|
additionalProperties?: boolean;
|
|
117
38
|
}
|
|
118
39
|
|
|
119
|
-
/** Tool call request */
|
|
120
|
-
export interface ToolCallRequest {
|
|
121
|
-
name: string;
|
|
122
|
-
arguments?: Record<string, unknown>;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/** Tool call result */
|
|
126
|
-
export interface ToolCallResult {
|
|
127
|
-
content: ToolContent[];
|
|
128
|
-
isError?: boolean;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/** Tool content types */
|
|
132
|
-
export type ToolContent = TextContent | ImageContent;
|
|
133
|
-
|
|
134
|
-
/** Text content */
|
|
135
|
-
export interface TextContent {
|
|
136
|
-
type: 'text';
|
|
137
|
-
text: string;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** Image content */
|
|
141
|
-
export interface ImageContent {
|
|
142
|
-
type: 'image';
|
|
143
|
-
data: string; // base64 encoded
|
|
144
|
-
mimeType: string;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
40
|
// ============================================================================
|
|
148
41
|
// MCP Tool List
|
|
149
42
|
// ============================================================================
|
|
@@ -209,41 +102,9 @@ export const TOOL_DEFINITIONS: readonly Tool[] = [
|
|
|
209
102
|
] as const;
|
|
210
103
|
|
|
211
104
|
// ============================================================================
|
|
212
|
-
//
|
|
213
|
-
// ============================================================================
|
|
214
|
-
|
|
215
|
-
/** All MCP method names */
|
|
216
|
-
export const MCP_METHODS = {
|
|
217
|
-
// Lifecycle
|
|
218
|
-
INITIALIZE: 'initialize',
|
|
219
|
-
INITIALIZED: 'notifications/initialized',
|
|
220
|
-
SHUTDOWN: 'shutdown',
|
|
221
|
-
EXIT: 'exit',
|
|
222
|
-
|
|
223
|
-
// Tools
|
|
224
|
-
TOOLS_LIST: 'tools/list',
|
|
225
|
-
TOOLS_CALL: 'tools/call',
|
|
226
|
-
|
|
227
|
-
// Logging
|
|
228
|
-
LOGGING_MESSAGE: 'notifications/message',
|
|
229
|
-
|
|
230
|
-
// Progress
|
|
231
|
-
PROGRESS: 'notifications/progress',
|
|
232
|
-
} as const;
|
|
233
|
-
|
|
234
|
-
// ============================================================================
|
|
235
|
-
// Error Codes (Standard MCP + Custom)
|
|
105
|
+
// Error Codes (MemHub Custom)
|
|
236
106
|
// ============================================================================
|
|
237
107
|
|
|
238
|
-
/** Standard JSON-RPC error codes */
|
|
239
|
-
export const JSONRPC_ERROR_CODES = {
|
|
240
|
-
PARSE_ERROR: -32700,
|
|
241
|
-
INVALID_REQUEST: -32600,
|
|
242
|
-
METHOD_NOT_FOUND: -32601,
|
|
243
|
-
INVALID_PARAMS: -32602,
|
|
244
|
-
INTERNAL_ERROR: -32603,
|
|
245
|
-
} as const;
|
|
246
|
-
|
|
247
108
|
/** MemHub custom error codes */
|
|
248
109
|
export const MEMHUB_ERROR_CODES = {
|
|
249
110
|
NOT_FOUND: -32001,
|
|
@@ -252,9 +113,13 @@ export const MEMHUB_ERROR_CODES = {
|
|
|
252
113
|
DUPLICATE_ERROR: -32004,
|
|
253
114
|
} as const;
|
|
254
115
|
|
|
255
|
-
/** Combined error codes */
|
|
116
|
+
/** Combined error codes (includes JSON-RPC standard codes) */
|
|
256
117
|
export const ERROR_CODES = {
|
|
257
|
-
|
|
118
|
+
PARSE_ERROR: -32700,
|
|
119
|
+
INVALID_REQUEST: -32600,
|
|
120
|
+
METHOD_NOT_FOUND: -32601,
|
|
121
|
+
INVALID_PARAMS: -32602,
|
|
122
|
+
INTERNAL_ERROR: -32603,
|
|
258
123
|
...MEMHUB_ERROR_CODES,
|
|
259
124
|
} as const;
|
|
260
125
|
|
|
@@ -300,4 +165,4 @@ export type ToolInput<T extends ToolName> = T extends 'memory_load'
|
|
|
300
165
|
category?: string;
|
|
301
166
|
importance?: number;
|
|
302
167
|
}
|
|
303
|
-
: never;
|
|
168
|
+
: never;
|
package/src/server/mcp-server.ts
CHANGED
|
@@ -1,36 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* MCP Server - Model Context Protocol server implementation
|
|
4
|
-
*
|
|
4
|
+
* Uses @modelcontextprotocol/sdk for protocol handling
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { readFileSync } from 'fs';
|
|
8
8
|
import { join, dirname } from 'path';
|
|
9
9
|
import { fileURLToPath } from 'url';
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
JsonRpcError,
|
|
14
|
-
RequestId,
|
|
15
|
-
InitializeParams,
|
|
16
|
-
InitializeResult,
|
|
17
|
-
ToolCallRequest,
|
|
18
|
-
ToolCallResult,
|
|
19
|
-
TextContent,
|
|
20
|
-
} from '../contracts/mcp.js';
|
|
10
|
+
import { homedir } from 'os';
|
|
11
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
12
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
21
13
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
MCP_METHODS,
|
|
26
|
-
ERROR_CODES,
|
|
27
|
-
} from '../contracts/mcp.js';
|
|
28
|
-
import { ErrorCode } from '../contracts/types.js';
|
|
14
|
+
CallToolRequestSchema,
|
|
15
|
+
ListToolsRequestSchema,
|
|
16
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
29
17
|
import { MemoryService, ServiceError } from '../services/memory-service.js';
|
|
30
18
|
import {
|
|
31
19
|
MemoryLoadInputSchema,
|
|
32
20
|
MemoryUpdateInputV2Schema,
|
|
33
21
|
} from '../contracts/schemas.js';
|
|
22
|
+
import { TOOL_DEFINITIONS, SERVER_INFO } from '../contracts/mcp.js';
|
|
23
|
+
import { ErrorCode } from '../contracts/types.js';
|
|
34
24
|
|
|
35
25
|
// Get package version
|
|
36
26
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -45,164 +35,35 @@ const packageJsonPath = join(__dirname, '../../../package.json');
|
|
|
45
35
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) as PackageJson;
|
|
46
36
|
|
|
47
37
|
/**
|
|
48
|
-
*
|
|
38
|
+
* Create McpServer instance using SDK
|
|
49
39
|
*/
|
|
50
|
-
export
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
this.log('info', 'MemHub MCP Server starting...');
|
|
63
|
-
|
|
64
|
-
process.stdin.setEncoding('utf-8');
|
|
65
|
-
|
|
66
|
-
let buffer = '';
|
|
67
|
-
|
|
68
|
-
process.stdin.on('data', (chunk: string) => {
|
|
69
|
-
buffer += chunk;
|
|
70
|
-
|
|
71
|
-
// Process complete lines (JSON-RPC messages)
|
|
72
|
-
const lines = buffer.split('\n');
|
|
73
|
-
buffer = lines.pop() || ''; // Keep incomplete line in buffer
|
|
74
|
-
|
|
75
|
-
for (const line of lines) {
|
|
76
|
-
if (line.trim()) {
|
|
77
|
-
void this.handleMessage(line.trim());
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
process.stdin.on('end', () => {
|
|
83
|
-
this.log('info', 'Stdin closed, shutting down...');
|
|
84
|
-
process.exit(0);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
process.on('SIGINT', () => {
|
|
88
|
-
this.log('info', 'Received SIGINT, shutting down...');
|
|
89
|
-
process.exit(0);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
process.on('SIGTERM', () => {
|
|
93
|
-
this.log('info', 'Received SIGTERM, shutting down...');
|
|
94
|
-
process.exit(0);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Handles an incoming JSON-RPC message
|
|
100
|
-
*
|
|
101
|
-
* @param message - The JSON-RPC message string
|
|
102
|
-
*/
|
|
103
|
-
private async handleMessage(message: string): Promise<void> {
|
|
104
|
-
let request: JsonRpcRequest | null = null;
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
request = JSON.parse(message) as JsonRpcRequest;
|
|
108
|
-
} catch {
|
|
109
|
-
this.sendError(null, ERROR_CODES.PARSE_ERROR, 'Parse error: Invalid JSON');
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Validate JSON-RPC request
|
|
114
|
-
if (request.jsonrpc !== '2.0' || !request.method) {
|
|
115
|
-
this.sendError(
|
|
116
|
-
request.id ?? null,
|
|
117
|
-
ERROR_CODES.INVALID_REQUEST,
|
|
118
|
-
'Invalid Request'
|
|
119
|
-
);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
const result = await this.handleMethod(request.method, request.params);
|
|
125
|
-
|
|
126
|
-
// Send response (only for requests with id, not notifications)
|
|
127
|
-
if (request.id !== undefined) {
|
|
128
|
-
this.sendResponse(request.id, result);
|
|
129
|
-
}
|
|
130
|
-
} catch (error) {
|
|
131
|
-
this.handleError(request.id ?? null, error);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Handles a specific method call
|
|
137
|
-
*
|
|
138
|
-
* @param method - The method name
|
|
139
|
-
* @param params - The method parameters
|
|
140
|
-
* @returns The method result
|
|
141
|
-
*/
|
|
142
|
-
private async handleMethod(
|
|
143
|
-
method: string,
|
|
144
|
-
params: unknown
|
|
145
|
-
): Promise<unknown> {
|
|
146
|
-
switch (method) {
|
|
147
|
-
case MCP_METHODS.INITIALIZE:
|
|
148
|
-
return this.handleInitialize(params as InitializeParams);
|
|
149
|
-
|
|
150
|
-
case MCP_METHODS.INITIALIZED:
|
|
151
|
-
// Notification, no response needed
|
|
152
|
-
this.log('info', 'Client initialized');
|
|
153
|
-
return null;
|
|
154
|
-
|
|
155
|
-
case MCP_METHODS.SHUTDOWN:
|
|
156
|
-
return null;
|
|
157
|
-
|
|
158
|
-
case MCP_METHODS.EXIT:
|
|
159
|
-
process.exit(0);
|
|
160
|
-
return null;
|
|
161
|
-
|
|
162
|
-
case MCP_METHODS.TOOLS_LIST:
|
|
163
|
-
return { tools: TOOL_DEFINITIONS };
|
|
164
|
-
|
|
165
|
-
case MCP_METHODS.TOOLS_CALL:
|
|
166
|
-
return this.handleToolCall(params as ToolCallRequest);
|
|
167
|
-
|
|
168
|
-
default:
|
|
169
|
-
throw new ServiceError(
|
|
170
|
-
`Method not found: ${method}`,
|
|
171
|
-
ErrorCode.METHOD_NOT_FOUND
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Handles the initialize method
|
|
178
|
-
*
|
|
179
|
-
* @param params - Initialize parameters
|
|
180
|
-
* @returns Initialize result
|
|
181
|
-
*/
|
|
182
|
-
private handleInitialize(params: InitializeParams): InitializeResult {
|
|
183
|
-
this.log('info', `Client initializing: ${params.clientInfo.name} v${params.clientInfo.version}`);
|
|
184
|
-
|
|
185
|
-
return {
|
|
186
|
-
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
40
|
+
export function createMcpServer(): Server {
|
|
41
|
+
const defaultStoragePath = join(homedir(), '.memhub');
|
|
42
|
+
const storagePath = process.env.MEMHUB_STORAGE_PATH || defaultStoragePath;
|
|
43
|
+
const memoryService = new MemoryService({ storagePath });
|
|
44
|
+
|
|
45
|
+
// Create server using SDK
|
|
46
|
+
const server = new Server(
|
|
47
|
+
{
|
|
48
|
+
name: SERVER_INFO.name,
|
|
49
|
+
version: packageJson.version || SERVER_INFO.version,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
187
52
|
capabilities: {
|
|
188
53
|
tools: { listChanged: false },
|
|
189
54
|
logging: {},
|
|
190
55
|
},
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// Handle tools/list request
|
|
60
|
+
server.setRequestHandler(ListToolsRequestSchema, () => {
|
|
61
|
+
return { tools: TOOL_DEFINITIONS };
|
|
62
|
+
});
|
|
197
63
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
* @param request - Tool call request
|
|
202
|
-
* @returns Tool call result
|
|
203
|
-
*/
|
|
204
|
-
private async handleToolCall(request: ToolCallRequest): Promise<ToolCallResult> {
|
|
205
|
-
const { name, arguments: args } = request;
|
|
64
|
+
// Handle tools/call request
|
|
65
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
66
|
+
const { name, arguments: args } = request.params;
|
|
206
67
|
|
|
207
68
|
try {
|
|
208
69
|
let result: unknown;
|
|
@@ -210,13 +71,13 @@ export class McpServer {
|
|
|
210
71
|
switch (name) {
|
|
211
72
|
case 'memory_load': {
|
|
212
73
|
const input = MemoryLoadInputSchema.parse(args ?? {});
|
|
213
|
-
result = await
|
|
74
|
+
result = await memoryService.memoryLoad(input);
|
|
214
75
|
break;
|
|
215
76
|
}
|
|
216
77
|
|
|
217
78
|
case 'memory_update': {
|
|
218
79
|
const input = MemoryUpdateInputV2Schema.parse(args ?? {});
|
|
219
|
-
result = await
|
|
80
|
+
result = await memoryService.memoryUpdate(input);
|
|
220
81
|
break;
|
|
221
82
|
}
|
|
222
83
|
|
|
@@ -230,9 +91,9 @@ export class McpServer {
|
|
|
230
91
|
return {
|
|
231
92
|
content: [
|
|
232
93
|
{
|
|
233
|
-
type: 'text',
|
|
94
|
+
type: 'text' as const,
|
|
234
95
|
text: JSON.stringify(result, null, 2),
|
|
235
|
-
}
|
|
96
|
+
},
|
|
236
97
|
],
|
|
237
98
|
};
|
|
238
99
|
} catch (error) {
|
|
@@ -240,115 +101,46 @@ export class McpServer {
|
|
|
240
101
|
return {
|
|
241
102
|
content: [
|
|
242
103
|
{
|
|
243
|
-
type: 'text',
|
|
104
|
+
type: 'text' as const,
|
|
244
105
|
text: JSON.stringify({ error: error.message }, null, 2),
|
|
245
|
-
}
|
|
106
|
+
},
|
|
246
107
|
],
|
|
247
108
|
isError: true,
|
|
248
109
|
};
|
|
249
110
|
}
|
|
250
111
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
112
|
+
if (error instanceof Error && error.name === 'ZodError') {
|
|
113
|
+
return {
|
|
114
|
+
content: [
|
|
115
|
+
{
|
|
116
|
+
type: 'text' as const,
|
|
117
|
+
text: JSON.stringify({ error: `Invalid parameters: ${error.message}` }, null, 2),
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
isError: true,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
255
123
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
*
|
|
259
|
-
* @param id - Request ID
|
|
260
|
-
* @param error - The error that occurred
|
|
261
|
-
*/
|
|
262
|
-
private handleError(id: RequestId | null, error: unknown): void {
|
|
263
|
-
if (error instanceof ServiceError) {
|
|
264
|
-
this.sendError(id, error.code, error.message, error.data);
|
|
265
|
-
} else if (error instanceof Error && error.name === 'ZodError') {
|
|
266
|
-
this.sendError(
|
|
267
|
-
id,
|
|
268
|
-
ERROR_CODES.INVALID_PARAMS,
|
|
269
|
-
`Invalid parameters: ${error.message}`
|
|
270
|
-
);
|
|
271
|
-
} else {
|
|
272
|
-
this.sendError(
|
|
273
|
-
id,
|
|
274
|
-
ERROR_CODES.INTERNAL_ERROR,
|
|
275
|
-
`Internal error: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
276
|
-
);
|
|
124
|
+
// Re-throw for SDK error handling
|
|
125
|
+
throw error;
|
|
277
126
|
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Sends a JSON-RPC response
|
|
282
|
-
*
|
|
283
|
-
* @param id - Request ID
|
|
284
|
-
* @param result - Response result
|
|
285
|
-
*/
|
|
286
|
-
private sendResponse(id: RequestId, result: unknown): void {
|
|
287
|
-
const response: JsonRpcResponse = {
|
|
288
|
-
jsonrpc: '2.0',
|
|
289
|
-
id,
|
|
290
|
-
result,
|
|
291
|
-
};
|
|
292
|
-
this.sendMessage(response);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Sends a JSON-RPC error
|
|
297
|
-
*
|
|
298
|
-
* @param id - Request ID
|
|
299
|
-
* @param code - Error code
|
|
300
|
-
* @param message - Error message
|
|
301
|
-
* @param data - Additional error data
|
|
302
|
-
*/
|
|
303
|
-
private sendError(
|
|
304
|
-
id: RequestId | null,
|
|
305
|
-
code: number,
|
|
306
|
-
message: string,
|
|
307
|
-
data?: Record<string, unknown>
|
|
308
|
-
): void {
|
|
309
|
-
const error: JsonRpcError = {
|
|
310
|
-
code,
|
|
311
|
-
message,
|
|
312
|
-
data,
|
|
313
|
-
};
|
|
127
|
+
});
|
|
314
128
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
id: id ?? null,
|
|
318
|
-
error,
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
this.sendMessage(response);
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* Sends a message to stdout
|
|
326
|
-
*
|
|
327
|
-
* @param message - The message to send
|
|
328
|
-
*/
|
|
329
|
-
private sendMessage(message: JsonRpcResponse | JsonRpcRequest): void {
|
|
330
|
-
const json = JSON.stringify(message);
|
|
331
|
-
process.stdout.write(json + '\n');
|
|
332
|
-
}
|
|
129
|
+
return server;
|
|
130
|
+
}
|
|
333
131
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
private log(level: 'debug' | 'info' | 'warn' | 'error', message: string): void {
|
|
341
|
-
const logLevel = process.env.MEMHUB_LOG_LEVEL || 'info';
|
|
342
|
-
const levels = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
132
|
+
/**
|
|
133
|
+
* Start the MCP server
|
|
134
|
+
*/
|
|
135
|
+
async function main(): Promise<void> {
|
|
136
|
+
const server = createMcpServer();
|
|
137
|
+
const transport = new StdioServerTransport();
|
|
343
138
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
}
|
|
347
|
-
}
|
|
139
|
+
await server.connect(transport);
|
|
140
|
+
console.error('MemHub MCP Server running on stdio');
|
|
348
141
|
}
|
|
349
142
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
143
|
+
main().catch((error) => {
|
|
144
|
+
console.error('Fatal error:', error);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
});
|