@hazeljs/mcp 0.7.8 → 0.8.0

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/dist/index.js ADDED
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ /**
3
+ * @hazeljs/mcp — Public API
4
+ *
5
+ * MCP Server: Expose HazelJS tools as MCP tools over STDIO/HTTP.
6
+ * MCP Client: Connect to external MCP servers and consume their tools.
7
+ *
8
+ * Quickstart (Server):
9
+ * import { createMcpServer } from '@hazeljs/mcp';
10
+ * const server = createMcpServer({ name: 'my-server', version: '1.0.0', toolRegistry });
11
+ * server.listenStdio();
12
+ *
13
+ * Quickstart (Client):
14
+ * import { McpClient } from '@hazeljs/mcp';
15
+ * const client = new McpClient({ name: 'my-app', version: '1.0.0' });
16
+ * await client.connect({ id: 'github', name: 'GitHub', transport: { type: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-github'] } });
17
+ * const tools = client.listTools();
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.McpClient = exports.internalError = exports.toolNotFoundError = exports.invalidParamsError = exports.methodNotFoundError = exports.invalidRequestError = exports.parseError = exports.makeErrorResponse = exports.makeError = exports.ErrorCode = exports.HazelToolAdapter = exports.createMcpServer = void 0;
21
+ // ---------------------------------------------------------------------------
22
+ // Server
23
+ // ---------------------------------------------------------------------------
24
+ // Factory function
25
+ var createMcpServer_1 = require("./server/createMcpServer");
26
+ Object.defineProperty(exports, "createMcpServer", { enumerable: true, get: function () { return createMcpServer_1.createMcpServer; } });
27
+ // Adapter — useful for testing or custom transports
28
+ var hazelToolAdapter_1 = require("./server/hazelToolAdapter");
29
+ Object.defineProperty(exports, "HazelToolAdapter", { enumerable: true, get: function () { return hazelToolAdapter_1.HazelToolAdapter; } });
30
+ // Error utilities — useful when building custom transports or middleware
31
+ var errors_1 = require("./server/errors");
32
+ Object.defineProperty(exports, "ErrorCode", { enumerable: true, get: function () { return errors_1.ErrorCode; } });
33
+ Object.defineProperty(exports, "makeError", { enumerable: true, get: function () { return errors_1.makeError; } });
34
+ Object.defineProperty(exports, "makeErrorResponse", { enumerable: true, get: function () { return errors_1.makeErrorResponse; } });
35
+ Object.defineProperty(exports, "parseError", { enumerable: true, get: function () { return errors_1.parseError; } });
36
+ Object.defineProperty(exports, "invalidRequestError", { enumerable: true, get: function () { return errors_1.invalidRequestError; } });
37
+ Object.defineProperty(exports, "methodNotFoundError", { enumerable: true, get: function () { return errors_1.methodNotFoundError; } });
38
+ Object.defineProperty(exports, "invalidParamsError", { enumerable: true, get: function () { return errors_1.invalidParamsError; } });
39
+ Object.defineProperty(exports, "toolNotFoundError", { enumerable: true, get: function () { return errors_1.toolNotFoundError; } });
40
+ Object.defineProperty(exports, "internalError", { enumerable: true, get: function () { return errors_1.internalError; } });
41
+ // ---------------------------------------------------------------------------
42
+ // Client
43
+ // ---------------------------------------------------------------------------
44
+ var mcp_client_1 = require("./client/mcp-client");
45
+ Object.defineProperty(exports, "McpClient", { enumerable: true, get: function () { return mcp_client_1.McpClient; } });
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;;;AAEH,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,mBAAmB;AACnB,4DAA2D;AAAlD,kHAAA,eAAe,OAAA;AAExB,oDAAoD;AACpD,8DAA6D;AAApD,oHAAA,gBAAgB,OAAA;AAEzB,yEAAyE;AACzE,0CAUyB;AATvB,mGAAA,SAAS,OAAA;AACT,mGAAA,SAAS,OAAA;AACT,2GAAA,iBAAiB,OAAA;AACjB,oGAAA,UAAU,OAAA;AACV,6GAAA,mBAAmB,OAAA;AACnB,6GAAA,mBAAmB,OAAA;AACnB,4GAAA,kBAAkB,OAAA;AAClB,2GAAA,iBAAiB,OAAA;AACjB,uGAAA,aAAa,OAAA;AAGf,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,kDAAgD;AAAvC,uGAAA,SAAS,OAAA"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * createMcpServer
3
+ *
4
+ * The main entry point of @hazeljs/mcp. Wires together:
5
+ * 1. HazelToolAdapter — converts Hazel tools to MCP definitions
6
+ * 2. Request router — dispatches JSON-RPC methods to handlers
7
+ * 3. STDIO transport — reads/writes newline-delimited JSON
8
+ *
9
+ * Supported JSON-RPC methods:
10
+ * initialize — MCP handshake; returns server name, version, capabilities
11
+ * ping — liveness probe; returns empty result
12
+ * tools/list — returns all registered MCP tool definitions
13
+ * tools/call — invokes a named tool with provided arguments
14
+ *
15
+ * Usage:
16
+ * const server = createMcpServer({ name, version, toolRegistry });
17
+ * server.listenStdio();
18
+ *
19
+ * Extension note:
20
+ * To expose the same tools over HTTP/SSE, call handleRequest() from an
21
+ * HTTP handler instead of wiring it to createStdioTransport(). The router
22
+ * logic and adapter are reusable across transports.
23
+ */
24
+ import type { McpServerOptions, McpServer } from './types';
25
+ export declare function createMcpServer(options: McpServerOptions): McpServer;
26
+ //# sourceMappingURL=createMcpServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createMcpServer.d.ts","sourceRoot":"","sources":["../../src/server/createMcpServer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,SAAS,EAMV,MAAM,SAAS,CAAC;AAUjB,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CA+GpE"}
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ /**
3
+ * createMcpServer
4
+ *
5
+ * The main entry point of @hazeljs/mcp. Wires together:
6
+ * 1. HazelToolAdapter — converts Hazel tools to MCP definitions
7
+ * 2. Request router — dispatches JSON-RPC methods to handlers
8
+ * 3. STDIO transport — reads/writes newline-delimited JSON
9
+ *
10
+ * Supported JSON-RPC methods:
11
+ * initialize — MCP handshake; returns server name, version, capabilities
12
+ * ping — liveness probe; returns empty result
13
+ * tools/list — returns all registered MCP tool definitions
14
+ * tools/call — invokes a named tool with provided arguments
15
+ *
16
+ * Usage:
17
+ * const server = createMcpServer({ name, version, toolRegistry });
18
+ * server.listenStdio();
19
+ *
20
+ * Extension note:
21
+ * To expose the same tools over HTTP/SSE, call handleRequest() from an
22
+ * HTTP handler instead of wiring it to createStdioTransport(). The router
23
+ * logic and adapter are reusable across transports.
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.createMcpServer = createMcpServer;
27
+ const hazelToolAdapter_1 = require("./hazelToolAdapter");
28
+ const stdioTransport_1 = require("./stdioTransport");
29
+ const errors_1 = require("./errors");
30
+ function createMcpServer(options) {
31
+ const { name, version, toolRegistry } = options;
32
+ // Snapshot the registry once at startup. Tools registered after this point
33
+ // won't be visible until the server is restarted or the adapter is rebuilt.
34
+ const adapter = hazelToolAdapter_1.HazelToolAdapter.fromRegistry(toolRegistry);
35
+ // ---------------------------------------------------------------------------
36
+ // Request router
37
+ // ---------------------------------------------------------------------------
38
+ async function handleRequest(req) {
39
+ const id = req.id ?? null;
40
+ switch (req.method) {
41
+ case 'initialize':
42
+ return handleInitialize(id);
43
+ case 'initialized':
44
+ // Notification — no response required by spec, but we send an ack
45
+ // to avoid clients hanging on a missing reply
46
+ return { jsonrpc: '2.0', id, result: {} };
47
+ case 'ping':
48
+ return { jsonrpc: '2.0', id, result: {} };
49
+ case 'tools/list':
50
+ return handleListTools(id);
51
+ case 'tools/call':
52
+ return handleCallTool(id, req);
53
+ default:
54
+ return (0, errors_1.methodNotFoundError)(id, req.method);
55
+ }
56
+ }
57
+ // ---------------------------------------------------------------------------
58
+ // Method handlers
59
+ // ---------------------------------------------------------------------------
60
+ function handleInitialize(id) {
61
+ return {
62
+ jsonrpc: '2.0',
63
+ id,
64
+ result: {
65
+ protocolVersion: '2024-11-05',
66
+ serverInfo: { name, version },
67
+ capabilities: {
68
+ // Advertise tool support; set listChanged: true if dynamic
69
+ // registration is added in a future version
70
+ tools: {},
71
+ },
72
+ },
73
+ };
74
+ }
75
+ function handleListTools(id) {
76
+ return {
77
+ jsonrpc: '2.0',
78
+ id,
79
+ result: {
80
+ tools: adapter.listTools(),
81
+ },
82
+ };
83
+ }
84
+ async function handleCallTool(id, req) {
85
+ const params = req.params;
86
+ if (!params?.name) {
87
+ return (0, errors_1.invalidParamsError)(id, 'Missing required field: name');
88
+ }
89
+ if (!adapter.hasTool(params.name)) {
90
+ return (0, errors_1.toolNotFoundError)(id, params.name);
91
+ }
92
+ try {
93
+ const result = await adapter.invoke(params.name, params.arguments ?? {});
94
+ return {
95
+ jsonrpc: '2.0',
96
+ id,
97
+ result: {
98
+ // MCP content block format — clients render type: 'text' as plain text
99
+ content: [{ type: 'text', text: JSON.stringify(result) }],
100
+ isError: false,
101
+ },
102
+ };
103
+ }
104
+ catch (err) {
105
+ return (0, errors_1.internalError)(id, err);
106
+ }
107
+ }
108
+ // ---------------------------------------------------------------------------
109
+ // Public API
110
+ // ---------------------------------------------------------------------------
111
+ return {
112
+ listenStdio() {
113
+ (0, stdioTransport_1.createStdioTransport)(handleRequest);
114
+ },
115
+ listTools() {
116
+ return adapter.listTools();
117
+ },
118
+ };
119
+ }
120
+ //# sourceMappingURL=createMcpServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createMcpServer.js","sourceRoot":"","sources":["../../src/server/createMcpServer.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;AAoBH,0CA+GC;AAxHD,yDAAsD;AACtD,qDAAwD;AACxD,qCAKkB;AAElB,SAAgB,eAAe,CAAC,OAAyB;IACvD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IAEhD,2EAA2E;IAC3E,4EAA4E;IAC5E,MAAM,OAAO,GAAG,mCAAgB,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;IAE5D,8EAA8E;IAC9E,iBAAiB;IACjB,8EAA8E;IAE9E,KAAK,UAAU,aAAa,CAAC,GAAe;QAC1C,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC;QAE1B,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;YACnB,KAAK,YAAY;gBACf,OAAO,gBAAgB,CAAC,EAAE,CAAC,CAAC;YAE9B,KAAK,aAAa;gBAChB,kEAAkE;gBAClE,8CAA8C;gBAC9C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YAE5C,KAAK,MAAM;gBACT,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YAE5C,KAAK,YAAY;gBACf,OAAO,eAAe,CAAC,EAAE,CAAC,CAAC;YAE7B,KAAK,YAAY;gBACf,OAAO,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAEjC;gBACE,OAAO,IAAA,4BAAmB,EAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E,SAAS,gBAAgB,CAAC,EAA0B;QAClD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,EAAE;YACF,MAAM,EAAE;gBACN,eAAe,EAAE,YAAY;gBAC7B,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;gBAC7B,YAAY,EAAE;oBACZ,2DAA2D;oBAC3D,4CAA4C;oBAC5C,KAAK,EAAE,EAAE;iBACV;aACF;SACF,CAAC;IACJ,CAAC;IAED,SAAS,eAAe,CAAC,EAA0B;QACjD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,EAAE;YACF,MAAM,EAAE;gBACN,KAAK,EAAE,OAAO,CAAC,SAAS,EAAE;aAC3B;SACF,CAAC;IACJ,CAAC;IAED,KAAK,UAAU,cAAc,CAC3B,EAA0B,EAC1B,GAAe;QAEf,MAAM,MAAM,GAAG,GAAG,CAAC,MAAoC,CAAC;QAExD,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;YAClB,OAAO,IAAA,2BAAkB,EAAC,EAAE,EAAE,8BAA8B,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,OAAO,IAAA,0BAAiB,EAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;YAEzE,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,EAAE;gBACF,MAAM,EAAE;oBACN,uEAAuE;oBACvE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;oBACzD,OAAO,EAAE,KAAK;iBACf;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,IAAA,sBAAa,EAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,aAAa;IACb,8EAA8E;IAE9E,OAAO;QACL,WAAW;YACT,IAAA,qCAAoB,EAAC,aAAa,CAAC,CAAC;QACtC,CAAC;QAED,SAAS;YACP,OAAO,OAAO,CAAC,SAAS,EAAE,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * JSON-RPC 2.0 Error Helpers
3
+ *
4
+ * Standard error codes: https://www.jsonrpc.org/specification#error_object
5
+ *
6
+ * MCP application-level codes occupy the -32000 to -32099 server-error range.
7
+ * The server never throws — every error path returns a typed response object
8
+ * so that the transport layer can safely serialize and send it.
9
+ */
10
+ import type { McpError, McpErrorResponse } from './types';
11
+ export declare const ErrorCode: {
12
+ readonly PARSE_ERROR: -32700;
13
+ readonly INVALID_REQUEST: -32600;
14
+ readonly METHOD_NOT_FOUND: -32601;
15
+ readonly INVALID_PARAMS: -32602;
16
+ readonly INTERNAL_ERROR: -32603;
17
+ readonly TOOL_NOT_FOUND: -32001;
18
+ readonly TOOL_EXECUTION_FAILED: -32002;
19
+ };
20
+ export declare function makeError(code: number, message: string, data?: unknown): McpError;
21
+ export declare function makeErrorResponse(id: string | number | null, code: number, message: string, data?: unknown): McpErrorResponse;
22
+ /** -32700 — Line received from stdin could not be parsed as JSON */
23
+ export declare function parseError(id?: string | number | null): McpErrorResponse;
24
+ /** -32600 — Message is not a valid JSON-RPC 2.0 request */
25
+ export declare function invalidRequestError(id?: string | number | null): McpErrorResponse;
26
+ /** -32601 — No handler registered for the given method */
27
+ export declare function methodNotFoundError(id: string | number | null, method: string): McpErrorResponse;
28
+ /** -32602 — Required parameter missing or malformed */
29
+ export declare function invalidParamsError(id: string | number | null, detail?: string): McpErrorResponse;
30
+ /** -32001 — Requested tool name is not registered in the adapter */
31
+ export declare function toolNotFoundError(id: string | number | null, toolName: string): McpErrorResponse;
32
+ /** -32603 — Unexpected exception inside a handler or tool execution */
33
+ export declare function internalError(id: string | number | null, detail?: unknown): McpErrorResponse;
34
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/server/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAM1D,eAAO,MAAM,SAAS;;;;;;;;CAWZ,CAAC;AAMX,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAEjF;AAED,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAC1B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,OAAO,GACb,gBAAgB,CAMlB;AAMD,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,EAAE,GAAE,MAAM,GAAG,MAAM,GAAG,IAAW,GAAG,gBAAgB,CAE9E;AAED,2DAA2D;AAC3D,wBAAgB,mBAAmB,CAAC,EAAE,GAAE,MAAM,GAAG,MAAM,GAAG,IAAW,GAAG,gBAAgB,CAEvF;AAED,0DAA0D;AAC1D,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAEhG;AAED,uDAAuD;AACvD,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAMhG;AAED,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAEhG;AAED,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAG5F"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /**
3
+ * JSON-RPC 2.0 Error Helpers
4
+ *
5
+ * Standard error codes: https://www.jsonrpc.org/specification#error_object
6
+ *
7
+ * MCP application-level codes occupy the -32000 to -32099 server-error range.
8
+ * The server never throws — every error path returns a typed response object
9
+ * so that the transport layer can safely serialize and send it.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ErrorCode = void 0;
13
+ exports.makeError = makeError;
14
+ exports.makeErrorResponse = makeErrorResponse;
15
+ exports.parseError = parseError;
16
+ exports.invalidRequestError = invalidRequestError;
17
+ exports.methodNotFoundError = methodNotFoundError;
18
+ exports.invalidParamsError = invalidParamsError;
19
+ exports.toolNotFoundError = toolNotFoundError;
20
+ exports.internalError = internalError;
21
+ // ---------------------------------------------------------------------------
22
+ // Error code constants
23
+ // ---------------------------------------------------------------------------
24
+ exports.ErrorCode = {
25
+ // Standard JSON-RPC 2.0 codes
26
+ PARSE_ERROR: -32700,
27
+ INVALID_REQUEST: -32600,
28
+ METHOD_NOT_FOUND: -32601,
29
+ INVALID_PARAMS: -32602,
30
+ INTERNAL_ERROR: -32603,
31
+ // MCP / application-level codes
32
+ TOOL_NOT_FOUND: -32001,
33
+ TOOL_EXECUTION_FAILED: -32002,
34
+ };
35
+ // ---------------------------------------------------------------------------
36
+ // Primitive builders
37
+ // ---------------------------------------------------------------------------
38
+ function makeError(code, message, data) {
39
+ return { code, message, ...(data !== undefined ? { data } : {}) };
40
+ }
41
+ function makeErrorResponse(id, code, message, data) {
42
+ return {
43
+ jsonrpc: '2.0',
44
+ id,
45
+ error: makeError(code, message, data),
46
+ };
47
+ }
48
+ // ---------------------------------------------------------------------------
49
+ // Named error constructors
50
+ // ---------------------------------------------------------------------------
51
+ /** -32700 — Line received from stdin could not be parsed as JSON */
52
+ function parseError(id = null) {
53
+ return makeErrorResponse(id, exports.ErrorCode.PARSE_ERROR, 'Parse error');
54
+ }
55
+ /** -32600 — Message is not a valid JSON-RPC 2.0 request */
56
+ function invalidRequestError(id = null) {
57
+ return makeErrorResponse(id, exports.ErrorCode.INVALID_REQUEST, 'Invalid Request');
58
+ }
59
+ /** -32601 — No handler registered for the given method */
60
+ function methodNotFoundError(id, method) {
61
+ return makeErrorResponse(id, exports.ErrorCode.METHOD_NOT_FOUND, `Method not found: ${method}`);
62
+ }
63
+ /** -32602 — Required parameter missing or malformed */
64
+ function invalidParamsError(id, detail) {
65
+ return makeErrorResponse(id, exports.ErrorCode.INVALID_PARAMS, detail ? `Invalid params: ${detail}` : 'Invalid params');
66
+ }
67
+ /** -32001 — Requested tool name is not registered in the adapter */
68
+ function toolNotFoundError(id, toolName) {
69
+ return makeErrorResponse(id, exports.ErrorCode.TOOL_NOT_FOUND, `Tool not found: ${toolName}`);
70
+ }
71
+ /** -32603 — Unexpected exception inside a handler or tool execution */
72
+ function internalError(id, detail) {
73
+ const data = detail instanceof Error ? { message: detail.message } : detail;
74
+ return makeErrorResponse(id, exports.ErrorCode.INTERNAL_ERROR, 'Internal error', data);
75
+ }
76
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/server/errors.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAyBH,8BAEC;AAED,8CAWC;AAOD,gCAEC;AAGD,kDAEC;AAGD,kDAEC;AAGD,gDAMC;AAGD,8CAEC;AAGD,sCAGC;AA3ED,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAEjE,QAAA,SAAS,GAAG;IACvB,8BAA8B;IAC9B,WAAW,EAAE,CAAC,KAAK;IACnB,eAAe,EAAE,CAAC,KAAK;IACvB,gBAAgB,EAAE,CAAC,KAAK;IACxB,cAAc,EAAE,CAAC,KAAK;IACtB,cAAc,EAAE,CAAC,KAAK;IAEtB,gCAAgC;IAChC,cAAc,EAAE,CAAC,KAAK;IACtB,qBAAqB,EAAE,CAAC,KAAK;CACrB,CAAC;AAEX,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,SAAgB,SAAS,CAAC,IAAY,EAAE,OAAe,EAAE,IAAc;IACrE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACpE,CAAC;AAED,SAAgB,iBAAiB,CAC/B,EAA0B,EAC1B,IAAY,EACZ,OAAe,EACf,IAAc;IAEd,OAAO;QACL,OAAO,EAAE,KAAK;QACd,EAAE;QACF,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E,oEAAoE;AACpE,SAAgB,UAAU,CAAC,KAA6B,IAAI;IAC1D,OAAO,iBAAiB,CAAC,EAAE,EAAE,iBAAS,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AACrE,CAAC;AAED,2DAA2D;AAC3D,SAAgB,mBAAmB,CAAC,KAA6B,IAAI;IACnE,OAAO,iBAAiB,CAAC,EAAE,EAAE,iBAAS,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC;AAC7E,CAAC;AAED,0DAA0D;AAC1D,SAAgB,mBAAmB,CAAC,EAA0B,EAAE,MAAc;IAC5E,OAAO,iBAAiB,CAAC,EAAE,EAAE,iBAAS,CAAC,gBAAgB,EAAE,qBAAqB,MAAM,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED,uDAAuD;AACvD,SAAgB,kBAAkB,CAAC,EAA0B,EAAE,MAAe;IAC5E,OAAO,iBAAiB,CACtB,EAAE,EACF,iBAAS,CAAC,cAAc,EACxB,MAAM,CAAC,CAAC,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC,CAAC,gBAAgB,CACxD,CAAC;AACJ,CAAC;AAED,oEAAoE;AACpE,SAAgB,iBAAiB,CAAC,EAA0B,EAAE,QAAgB;IAC5E,OAAO,iBAAiB,CAAC,EAAE,EAAE,iBAAS,CAAC,cAAc,EAAE,mBAAmB,QAAQ,EAAE,CAAC,CAAC;AACxF,CAAC;AAED,uEAAuE;AACvE,SAAgB,aAAa,CAAC,EAA0B,EAAE,MAAgB;IACxE,MAAM,IAAI,GAAG,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5E,OAAO,iBAAiB,CAAC,EAAE,EAAE,iBAAS,CAAC,cAAc,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAC;AACjF,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * HazelToolAdapter
3
+ *
4
+ * Converts a Hazel tool registry into MCP tool definitions and handles
5
+ * tool invocation on behalf of the MCP server.
6
+ *
7
+ * Hazel → MCP field mapping:
8
+ * ToolMetadata.name → McpToolDefinition.name
9
+ * ToolMetadata.description → McpToolDefinition.description
10
+ * ToolMetadata.parameters → McpToolDefinition.inputSchema (JSON Schema object)
11
+ *
12
+ * Invocation:
13
+ * The adapter calls method.call(target, input) to preserve the `this`
14
+ * context of the original decorated class instance. This means tools
15
+ * registered via @Tool() on an agent class work out of the box.
16
+ *
17
+ * Schema handling:
18
+ * - parameters[] present → converted to JSON Schema (type/description/enum)
19
+ * - parameters absent → empty schema, accepts any JSON object
20
+ *
21
+ * Extension note:
22
+ * To support input validation via Zod, replace the direct method.call with
23
+ * a validation step: parse input with the Zod schema, then call the method.
24
+ * The validation hook below is a placeholder for that upgrade path.
25
+ *
26
+ * The adapter is designed to be transport-agnostic. The same instance can be
27
+ * used by STDIO, HTTP, or SSE transports — only the transport glue changes.
28
+ */
29
+ import type { IToolRegistry, McpToolDefinition } from './types';
30
+ export declare class HazelToolAdapter {
31
+ private readonly tools;
32
+ private constructor();
33
+ /**
34
+ * Build an adapter from a Hazel tool registry.
35
+ *
36
+ * The registry is snapshotted at construction time. If tools are registered
37
+ * dynamically after server start, call fromRegistry() again and replace the
38
+ * server's adapter (or extend this class to hold a live registry reference).
39
+ */
40
+ static fromRegistry(registry: IToolRegistry): HazelToolAdapter;
41
+ /** Return all tools as MCP definitions for a tools/list response */
42
+ listTools(): McpToolDefinition[];
43
+ /**
44
+ * Invoke a named tool with the given input object.
45
+ *
46
+ * Throws if the tool is not found — callers should check hasTool() first
47
+ * or catch the error and convert it to a JSON-RPC error response.
48
+ */
49
+ invoke(toolName: string, input: Record<string, unknown>): Promise<unknown>;
50
+ hasTool(toolName: string): boolean;
51
+ /**
52
+ * Convert a Hazel tool's parameter list into an MCP JSON Schema inputSchema.
53
+ *
54
+ * If parameters is empty or undefined, an open schema is emitted
55
+ * ({ type: 'object', properties: {}, required: [] }) which accepts any input.
56
+ */
57
+ private toMcpDefinition;
58
+ }
59
+ //# sourceMappingURL=hazelToolAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hazelToolAdapter.d.ts","sourceRoot":"","sources":["../../src/server/hazelToolAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAa,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE3E,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;IAE3D,OAAO;IAEP;;;;;;OAMG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,gBAAgB;IAU9D,oEAAoE;IACpE,SAAS,IAAI,iBAAiB,EAAE;IAIhC;;;;;OAKG;IACG,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAWhF,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAQlC;;;;;OAKG;IACH,OAAO,CAAC,eAAe;CA0BxB"}
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ /**
3
+ * HazelToolAdapter
4
+ *
5
+ * Converts a Hazel tool registry into MCP tool definitions and handles
6
+ * tool invocation on behalf of the MCP server.
7
+ *
8
+ * Hazel → MCP field mapping:
9
+ * ToolMetadata.name → McpToolDefinition.name
10
+ * ToolMetadata.description → McpToolDefinition.description
11
+ * ToolMetadata.parameters → McpToolDefinition.inputSchema (JSON Schema object)
12
+ *
13
+ * Invocation:
14
+ * The adapter calls method.call(target, input) to preserve the `this`
15
+ * context of the original decorated class instance. This means tools
16
+ * registered via @Tool() on an agent class work out of the box.
17
+ *
18
+ * Schema handling:
19
+ * - parameters[] present → converted to JSON Schema (type/description/enum)
20
+ * - parameters absent → empty schema, accepts any JSON object
21
+ *
22
+ * Extension note:
23
+ * To support input validation via Zod, replace the direct method.call with
24
+ * a validation step: parse input with the Zod schema, then call the method.
25
+ * The validation hook below is a placeholder for that upgrade path.
26
+ *
27
+ * The adapter is designed to be transport-agnostic. The same instance can be
28
+ * used by STDIO, HTTP, or SSE transports — only the transport glue changes.
29
+ */
30
+ Object.defineProperty(exports, "__esModule", { value: true });
31
+ exports.HazelToolAdapter = void 0;
32
+ class HazelToolAdapter {
33
+ constructor() {
34
+ this.tools = new Map();
35
+ }
36
+ /**
37
+ * Build an adapter from a Hazel tool registry.
38
+ *
39
+ * The registry is snapshotted at construction time. If tools are registered
40
+ * dynamically after server start, call fromRegistry() again and replace the
41
+ * server's adapter (or extend this class to hold a live registry reference).
42
+ */
43
+ static fromRegistry(registry) {
44
+ const adapter = new HazelToolAdapter();
45
+ for (const tool of registry.getAllTools()) {
46
+ adapter.tools.set(tool.name, tool);
47
+ }
48
+ return adapter;
49
+ }
50
+ /** Return all tools as MCP definitions for a tools/list response */
51
+ listTools() {
52
+ return Array.from(this.tools.values()).map((tool) => this.toMcpDefinition(tool));
53
+ }
54
+ /**
55
+ * Invoke a named tool with the given input object.
56
+ *
57
+ * Throws if the tool is not found — callers should check hasTool() first
58
+ * or catch the error and convert it to a JSON-RPC error response.
59
+ */
60
+ async invoke(toolName, input) {
61
+ const tool = this.tools.get(toolName);
62
+ if (!tool) {
63
+ throw new Error(`Tool not found: ${toolName}`);
64
+ }
65
+ // Preserve the original `this` context from the registered class instance
66
+ return tool.method.call(tool.target, input);
67
+ }
68
+ hasTool(toolName) {
69
+ return this.tools.has(toolName);
70
+ }
71
+ // ---------------------------------------------------------------------------
72
+ // Private helpers
73
+ // ---------------------------------------------------------------------------
74
+ /**
75
+ * Convert a Hazel tool's parameter list into an MCP JSON Schema inputSchema.
76
+ *
77
+ * If parameters is empty or undefined, an open schema is emitted
78
+ * ({ type: 'object', properties: {}, required: [] }) which accepts any input.
79
+ */
80
+ toMcpDefinition(tool) {
81
+ const properties = {};
82
+ const required = [];
83
+ for (const param of tool.parameters ?? []) {
84
+ properties[param.name] = {
85
+ type: param.type,
86
+ description: param.description,
87
+ ...(param.enum !== undefined ? { enum: param.enum } : {}),
88
+ };
89
+ if (param.required) {
90
+ required.push(param.name);
91
+ }
92
+ }
93
+ return {
94
+ name: tool.name,
95
+ description: tool.description,
96
+ inputSchema: {
97
+ type: 'object',
98
+ properties,
99
+ required,
100
+ },
101
+ };
102
+ }
103
+ }
104
+ exports.HazelToolAdapter = HazelToolAdapter;
105
+ //# sourceMappingURL=hazelToolAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hazelToolAdapter.js","sourceRoot":"","sources":["../../src/server/hazelToolAdapter.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;;;AAIH,MAAa,gBAAgB;IAG3B;QAFiB,UAAK,GAA2B,IAAI,GAAG,EAAE,CAAC;IAEpC,CAAC;IAExB;;;;;;OAMG;IACH,MAAM,CAAC,YAAY,CAAC,QAAuB;QACzC,MAAM,OAAO,GAAG,IAAI,gBAAgB,EAAE,CAAC;QAEvC,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;YAC1C,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,oEAAoE;IACpE,SAAS;QACP,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;IACnF,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAM,CAAC,QAAgB,EAAE,KAA8B;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEtC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;QACjD,CAAC;QAED,0EAA0E;QAC1E,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAqB,CAAC;IAClE,CAAC;IAED,OAAO,CAAC,QAAgB;QACtB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAE9E;;;;;OAKG;IACK,eAAe,CAAC,IAAe;QACrC,MAAM,UAAU,GAAmD,EAAE,CAAC;QACtE,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;YAC1C,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG;gBACvB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC1D,CAAC;YAEF,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,UAAU;gBACV,QAAQ;aACT;SACF,CAAC;IACJ,CAAC;CACF;AApFD,4CAoFC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * STDIO Transport
3
+ *
4
+ * Reads newline-delimited JSON from process.stdin, passes each message to the
5
+ * supplied RequestHandler, and writes the JSON-RPC response back to
6
+ * process.stdout followed by a newline.
7
+ *
8
+ * Design decisions:
9
+ * - Each incoming line is handled in its own promise chain (no await in the
10
+ * readline handler) so slow tool calls don't block subsequent requests.
11
+ * - JSON parse errors are returned as -32700 responses instead of crashing.
12
+ * - Unexpected handler exceptions are caught and returned as -32603 so the
13
+ * server never exits due to user input.
14
+ * - process.stdin 'close' triggers a clean process.exit(0) — MCP clients
15
+ * that close stdin expect the server to terminate.
16
+ *
17
+ * Extension note:
18
+ * To add HTTP/SSE transport, implement the same RequestHandler signature
19
+ * and wire it to incoming HTTP requests (e.g. via Express or Fastify).
20
+ * The handler itself, the adapter, and all protocol types stay unchanged.
21
+ *
22
+ * Example HTTP skeleton:
23
+ * app.post('/rpc', async (req, res) => {
24
+ * const response = await handler(req.body as McpRequest);
25
+ * res.json(response);
26
+ * });
27
+ */
28
+ import type { McpRequest, McpResponse, McpErrorResponse } from './types';
29
+ export type RequestHandler = (req: McpRequest) => Promise<McpResponse | McpErrorResponse>;
30
+ /**
31
+ * Attach the STDIO transport to the current process.
32
+ *
33
+ * After this call, the process reads from stdin and writes to stdout until
34
+ * stdin is closed. Call this once at server startup.
35
+ */
36
+ export declare function createStdioTransport(handler: RequestHandler): void;
37
+ //# sourceMappingURL=stdioTransport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdioTransport.d.ts","sourceRoot":"","sources":["../../src/server/stdioTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGzE,MAAM,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC,WAAW,GAAG,gBAAgB,CAAC,CAAC;AAE1F;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAmBlE"}