@mcp-weave/nestjs 0.1.1 → 0.2.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/README.md CHANGED
@@ -27,6 +27,7 @@ pnpm add @mcp-weave/nestjs reflect-metadata
27
27
  - **Method Decorators** - `@McpTool`, `@McpResource`, `@McpPrompt`
28
28
  - **Parameter Decorators** - `@McpInput`, `@McpParam`, `@McpPromptArg`
29
29
  - **Runtime Server** - Start MCP servers from decorated classes
30
+ - **Multiple Transports** - Stdio (default) and SSE (Server-Sent Events)
30
31
 
31
32
  ## Quick Start
32
33
 
@@ -215,6 +216,46 @@ const server = new McpRuntimeServer(MyServer, {
215
216
  await server.start();
216
217
  ```
217
218
 
219
+ ### SSE Transport (Server-Sent Events)
220
+
221
+ For web-based integrations, use the SSE transport:
222
+
223
+ ```typescript
224
+ import { McpRuntimeServer } from '@mcp-weave/nestjs';
225
+
226
+ const server = new McpRuntimeServer(MyServer, {
227
+ transport: 'sse',
228
+ port: 3000,
229
+ endpoint: '/sse',
230
+ });
231
+
232
+ // Starts HTTP server with SSE endpoint
233
+ const httpServer = await server.start();
234
+
235
+ // Server available at:
236
+ // - SSE endpoint: http://localhost:3000/sse
237
+ // - Health check: http://localhost:3000/health
238
+ ```
239
+
240
+ Or use the `startSSE` method directly:
241
+
242
+ ```typescript
243
+ const server = new McpRuntimeServer(MyServer);
244
+
245
+ // Start with SSE transport
246
+ const httpServer = await server.startSSE({
247
+ port: 8080,
248
+ endpoint: '/mcp',
249
+ });
250
+ ```
251
+
252
+ **SSE Features:**
253
+
254
+ - CORS enabled by default
255
+ - Health check endpoint at `/health`
256
+ - Session management for multiple clients
257
+ - Automatic cleanup on connection close
258
+
218
259
  ## Metadata Extraction
219
260
 
220
261
  Extract metadata from decorated classes for code generation:
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ToolInputSchema, PromptArgument, McpParamMetadata, McpPromptMetadata, McpResourceMetadata, McpServerMetadata, McpToolMetadata } from '@mcp-weave/core';
2
2
  export { METADATA_KEYS, McpParamMetadata, McpPromptMetadata, McpResourceMetadata, McpServerMetadata, McpToolMetadata, ScannedMetadata, extractMetadata } from '@mcp-weave/core';
3
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { Server as Server$1 } from '@modelcontextprotocol/sdk/server/index.js';
4
+ import { Server } from 'http';
4
5
 
5
6
  /**
6
7
  * Options for @McpServer decorator
@@ -209,9 +210,17 @@ declare function getParamsMetadata(target: Function): McpParamMetadata[];
209
210
  */
210
211
  interface McpRuntimeOptions {
211
212
  /**
212
- * Transport type
213
+ * Transport type: 'stdio' (default), 'sse', or 'websocket'
213
214
  */
214
- transport?: 'stdio' | 'sse';
215
+ transport?: 'stdio' | 'sse' | 'websocket';
216
+ /**
217
+ * Port for SSE/WebSocket transport (default: 3000)
218
+ */
219
+ port?: number;
220
+ /**
221
+ * Endpoint path for SSE/WebSocket (default: '/sse' or '/ws')
222
+ */
223
+ endpoint?: string;
215
224
  }
216
225
  /**
217
226
  * Runtime MCP server that wraps a decorated class
@@ -230,16 +239,46 @@ declare class McpRuntimeServer {
230
239
  private resolvePromptArgs;
231
240
  private extractUriParams;
232
241
  /**
233
- * Start the MCP server
242
+ * Start the MCP server with stdio transport
234
243
  */
235
244
  start(): Promise<void>;
245
+ /**
246
+ * Start the MCP server with SSE transport
247
+ */
248
+ startSSE(options?: {
249
+ port?: number;
250
+ endpoint?: string;
251
+ }): Promise<Server>;
236
252
  /**
237
253
  * Get the underlying MCP server instance
238
254
  */
239
- getServer(): Server;
255
+ getServer(): Server$1;
256
+ /**
257
+ * Start the MCP server with WebSocket transport
258
+ */
259
+ startWebSocket(options?: {
260
+ port?: number;
261
+ endpoint?: string;
262
+ }): Promise<Server>;
263
+ /**
264
+ * Handle WebSocket JSON-RPC messages
265
+ */
266
+ private handleWebSocketMessage;
240
267
  }
241
268
  /**
242
269
  * Create and start an MCP server from a decorated class
270
+ *
271
+ * @example
272
+ * // Stdio transport (default)
273
+ * await createMcpServer(MyServer);
274
+ *
275
+ * @example
276
+ * // SSE transport
277
+ * await createMcpServer(MyServer, { transport: 'sse', port: 3000 });
278
+ *
279
+ * @example
280
+ * // WebSocket transport
281
+ * await createMcpServer(MyServer, { transport: 'websocket', port: 8080 });
243
282
  */
244
283
  declare function createMcpServer(target: Function, options?: McpRuntimeOptions): Promise<McpRuntimeServer>;
245
284
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ToolInputSchema, PromptArgument, McpParamMetadata, McpPromptMetadata, McpResourceMetadata, McpServerMetadata, McpToolMetadata } from '@mcp-weave/core';
2
2
  export { METADATA_KEYS, McpParamMetadata, McpPromptMetadata, McpResourceMetadata, McpServerMetadata, McpToolMetadata, ScannedMetadata, extractMetadata } from '@mcp-weave/core';
3
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { Server as Server$1 } from '@modelcontextprotocol/sdk/server/index.js';
4
+ import { Server } from 'http';
4
5
 
5
6
  /**
6
7
  * Options for @McpServer decorator
@@ -209,9 +210,17 @@ declare function getParamsMetadata(target: Function): McpParamMetadata[];
209
210
  */
210
211
  interface McpRuntimeOptions {
211
212
  /**
212
- * Transport type
213
+ * Transport type: 'stdio' (default), 'sse', or 'websocket'
213
214
  */
214
- transport?: 'stdio' | 'sse';
215
+ transport?: 'stdio' | 'sse' | 'websocket';
216
+ /**
217
+ * Port for SSE/WebSocket transport (default: 3000)
218
+ */
219
+ port?: number;
220
+ /**
221
+ * Endpoint path for SSE/WebSocket (default: '/sse' or '/ws')
222
+ */
223
+ endpoint?: string;
215
224
  }
216
225
  /**
217
226
  * Runtime MCP server that wraps a decorated class
@@ -230,16 +239,46 @@ declare class McpRuntimeServer {
230
239
  private resolvePromptArgs;
231
240
  private extractUriParams;
232
241
  /**
233
- * Start the MCP server
242
+ * Start the MCP server with stdio transport
234
243
  */
235
244
  start(): Promise<void>;
245
+ /**
246
+ * Start the MCP server with SSE transport
247
+ */
248
+ startSSE(options?: {
249
+ port?: number;
250
+ endpoint?: string;
251
+ }): Promise<Server>;
236
252
  /**
237
253
  * Get the underlying MCP server instance
238
254
  */
239
- getServer(): Server;
255
+ getServer(): Server$1;
256
+ /**
257
+ * Start the MCP server with WebSocket transport
258
+ */
259
+ startWebSocket(options?: {
260
+ port?: number;
261
+ endpoint?: string;
262
+ }): Promise<Server>;
263
+ /**
264
+ * Handle WebSocket JSON-RPC messages
265
+ */
266
+ private handleWebSocketMessage;
240
267
  }
241
268
  /**
242
269
  * Create and start an MCP server from a decorated class
270
+ *
271
+ * @example
272
+ * // Stdio transport (default)
273
+ * await createMcpServer(MyServer);
274
+ *
275
+ * @example
276
+ * // SSE transport
277
+ * await createMcpServer(MyServer, { transport: 'sse', port: 3000 });
278
+ *
279
+ * @example
280
+ * // WebSocket transport
281
+ * await createMcpServer(MyServer, { transport: 'websocket', port: 8080 });
243
282
  */
244
283
  declare function createMcpServer(target: Function, options?: McpRuntimeOptions): Promise<McpRuntimeServer>;
245
284
 
package/dist/index.js CHANGED
@@ -4,8 +4,15 @@ require('reflect-metadata');
4
4
  var core = require('@mcp-weave/core');
5
5
  var index_js = require('@modelcontextprotocol/sdk/server/index.js');
6
6
  var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
7
+ var sse_js = require('@modelcontextprotocol/sdk/server/sse.js');
8
+ var http = require('http');
7
9
 
8
- // src/index.ts
10
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
11
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
12
+ }) : x)(function(x) {
13
+ if (typeof require !== "undefined") return require.apply(this, arguments);
14
+ throw Error('Dynamic require of "' + x + '" is not supported');
15
+ });
9
16
  function McpServer(options) {
10
17
  return (target) => {
11
18
  const metadata = {
@@ -125,8 +132,6 @@ function getPromptsMetadata(target) {
125
132
  function getParamsMetadata(target) {
126
133
  return Reflect.getMetadata(core.METADATA_KEYS.PARAMS, target) ?? [];
127
134
  }
128
-
129
- // src/runtime/server.ts
130
135
  var McpRuntimeServer = class {
131
136
  server;
132
137
  instance;
@@ -326,23 +331,386 @@ var McpRuntimeServer = class {
326
331
  return params;
327
332
  }
328
333
  /**
329
- * Start the MCP server
334
+ * Start the MCP server with stdio transport
330
335
  */
331
336
  async start() {
332
337
  const transport = new stdio_js.StdioServerTransport();
333
338
  await this.server.connect(transport);
334
339
  console.error(`MCP server '${this.metadata.server?.name}' started on stdio`);
335
340
  }
341
+ /**
342
+ * Start the MCP server with SSE transport
343
+ */
344
+ async startSSE(options = {}) {
345
+ const port = options.port ?? 3e3;
346
+ const endpoint = options.endpoint ?? "/sse";
347
+ const httpServer = http.createServer(async (req, res) => {
348
+ res.setHeader("Access-Control-Allow-Origin", "*");
349
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
350
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
351
+ if (req.method === "OPTIONS") {
352
+ res.writeHead(200);
353
+ res.end();
354
+ return;
355
+ }
356
+ const url = new URL(req.url ?? "/", `http://localhost:${port}`);
357
+ if (url.pathname === endpoint && req.method === "GET") {
358
+ const transport = new sse_js.SSEServerTransport(endpoint, res);
359
+ await this.server.connect(transport);
360
+ return;
361
+ }
362
+ if (url.pathname === `${endpoint}/message` && req.method === "POST") {
363
+ let body = "";
364
+ req.on("data", (chunk) => {
365
+ body += chunk.toString();
366
+ });
367
+ req.on("end", () => {
368
+ res.writeHead(200, { "Content-Type": "application/json" });
369
+ res.end(JSON.stringify({ received: true }));
370
+ });
371
+ return;
372
+ }
373
+ if (url.pathname === "/health") {
374
+ res.writeHead(200, { "Content-Type": "application/json" });
375
+ res.end(
376
+ JSON.stringify({
377
+ status: "ok",
378
+ server: this.metadata.server?.name,
379
+ version: this.metadata.server?.version
380
+ })
381
+ );
382
+ return;
383
+ }
384
+ res.writeHead(404, { "Content-Type": "application/json" });
385
+ res.end(JSON.stringify({ error: "Not found" }));
386
+ });
387
+ return new Promise((resolve, reject) => {
388
+ httpServer.on("error", reject);
389
+ httpServer.listen(port, () => {
390
+ console.error(
391
+ `MCP server '${this.metadata.server?.name}' started on http://localhost:${port}${endpoint}`
392
+ );
393
+ resolve(httpServer);
394
+ });
395
+ });
396
+ }
336
397
  /**
337
398
  * Get the underlying MCP server instance
338
399
  */
339
400
  getServer() {
340
401
  return this.server;
341
402
  }
403
+ /**
404
+ * Start the MCP server with WebSocket transport
405
+ */
406
+ async startWebSocket(options = {}) {
407
+ const port = options.port ?? 8080;
408
+ const endpoint = options.endpoint ?? "/ws";
409
+ const httpServer = http.createServer((req, res) => {
410
+ res.setHeader("Access-Control-Allow-Origin", "*");
411
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
412
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Upgrade, Connection");
413
+ if (req.method === "OPTIONS") {
414
+ res.writeHead(200);
415
+ res.end();
416
+ return;
417
+ }
418
+ if (req.url === "/health") {
419
+ res.writeHead(200, { "Content-Type": "application/json" });
420
+ res.end(
421
+ JSON.stringify({
422
+ status: "ok",
423
+ server: this.metadata.server?.name,
424
+ version: this.metadata.server?.version,
425
+ transport: "websocket"
426
+ })
427
+ );
428
+ return;
429
+ }
430
+ if (req.url === "/") {
431
+ res.writeHead(200, { "Content-Type": "application/json" });
432
+ res.end(
433
+ JSON.stringify({
434
+ name: this.metadata.server?.name,
435
+ version: this.metadata.server?.version,
436
+ websocket: `ws://localhost:${port}${endpoint}`,
437
+ tools: this.metadata.tools.length,
438
+ resources: this.metadata.resources.length,
439
+ prompts: this.metadata.prompts.length
440
+ })
441
+ );
442
+ return;
443
+ }
444
+ res.writeHead(426, { "Content-Type": "application/json" });
445
+ res.end(JSON.stringify({ error: "Upgrade Required", message: `Connect via WebSocket at ${endpoint}` }));
446
+ });
447
+ httpServer.on("upgrade", (req, socket, _head) => {
448
+ const url = new URL(req.url ?? "/", `http://localhost:${port}`);
449
+ if (url.pathname !== endpoint) {
450
+ socket.write("HTTP/1.1 404 Not Found\r\n\r\n");
451
+ socket.destroy();
452
+ return;
453
+ }
454
+ const key = req.headers["sec-websocket-key"];
455
+ if (!key) {
456
+ socket.write("HTTP/1.1 400 Bad Request\r\n\r\n");
457
+ socket.destroy();
458
+ return;
459
+ }
460
+ const crypto = __require("crypto");
461
+ const acceptKey = crypto.createHash("sha1").update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest("base64");
462
+ socket.write(
463
+ `HTTP/1.1 101 Switching Protocols\r
464
+ Upgrade: websocket\r
465
+ Connection: Upgrade\r
466
+ Sec-WebSocket-Accept: ${acceptKey}\r
467
+ \r
468
+ `
469
+ );
470
+ const sessions = /* @__PURE__ */ new Map();
471
+ const sessionId = crypto.randomUUID();
472
+ const encodeFrame = (data) => {
473
+ const payload = Buffer.from(data, "utf8");
474
+ const length = payload.length;
475
+ let frame;
476
+ if (length < 126) {
477
+ frame = Buffer.alloc(2 + length);
478
+ frame[0] = 129;
479
+ frame[1] = length;
480
+ payload.copy(frame, 2);
481
+ } else if (length < 65536) {
482
+ frame = Buffer.alloc(4 + length);
483
+ frame[0] = 129;
484
+ frame[1] = 126;
485
+ frame.writeUInt16BE(length, 2);
486
+ payload.copy(frame, 4);
487
+ } else {
488
+ frame = Buffer.alloc(10 + length);
489
+ frame[0] = 129;
490
+ frame[1] = 127;
491
+ frame.writeBigUInt64BE(BigInt(length), 2);
492
+ payload.copy(frame, 10);
493
+ }
494
+ return frame;
495
+ };
496
+ const decodeFrame = (buffer) => {
497
+ if (buffer.length < 2) return null;
498
+ const byte0 = buffer[0];
499
+ const byte1 = buffer[1];
500
+ const opcode = byte0 & 15;
501
+ const masked = (byte1 & 128) !== 0;
502
+ let payloadLength = byte1 & 127;
503
+ let offset = 2;
504
+ if (payloadLength === 126) {
505
+ if (buffer.length < 4) return null;
506
+ payloadLength = buffer.readUInt16BE(2);
507
+ offset = 4;
508
+ } else if (payloadLength === 127) {
509
+ if (buffer.length < 10) return null;
510
+ payloadLength = Number(buffer.readBigUInt64BE(2));
511
+ offset = 10;
512
+ }
513
+ if (masked) {
514
+ if (buffer.length < offset + 4 + payloadLength) return null;
515
+ const mask = buffer.slice(offset, offset + 4);
516
+ offset += 4;
517
+ const payload = buffer.slice(offset, offset + payloadLength);
518
+ for (let i = 0; i < payload.length; i++) {
519
+ const maskByte = mask[i % 4] ?? 0;
520
+ payload[i] = (payload[i] ?? 0) ^ maskByte;
521
+ }
522
+ return { opcode, payload: payload.toString("utf8") };
523
+ } else {
524
+ if (buffer.length < offset + payloadLength) return null;
525
+ return { opcode, payload: buffer.slice(offset, offset + payloadLength).toString("utf8") };
526
+ }
527
+ };
528
+ const send = (data) => {
529
+ try {
530
+ socket.write(encodeFrame(data));
531
+ } catch {
532
+ }
533
+ };
534
+ sessions.set(sessionId, { send });
535
+ send(JSON.stringify({
536
+ jsonrpc: "2.0",
537
+ method: "connection/established",
538
+ params: { sessionId, server: this.metadata.server?.name }
539
+ }));
540
+ let messageBuffer = Buffer.alloc(0);
541
+ socket.on("data", async (chunk) => {
542
+ messageBuffer = Buffer.concat([messageBuffer, chunk]);
543
+ while (messageBuffer.length > 0) {
544
+ const frame = decodeFrame(messageBuffer);
545
+ if (!frame) break;
546
+ let frameSize = 2;
547
+ const byte1 = messageBuffer[1] ?? 0;
548
+ const payloadLength = byte1 & 127;
549
+ if (payloadLength === 126) frameSize = 4;
550
+ else if (payloadLength === 127) frameSize = 10;
551
+ if ((byte1 & 128) !== 0) frameSize += 4;
552
+ frameSize += frame.payload.length;
553
+ messageBuffer = messageBuffer.slice(frameSize);
554
+ if (frame.opcode === 8) {
555
+ socket.end();
556
+ return;
557
+ }
558
+ if (frame.opcode === 9) {
559
+ socket.write(Buffer.from([138, 0]));
560
+ continue;
561
+ }
562
+ if (frame.opcode === 1) {
563
+ try {
564
+ const message = JSON.parse(frame.payload);
565
+ const response = await this.handleWebSocketMessage(message);
566
+ if (response) {
567
+ send(JSON.stringify(response));
568
+ }
569
+ } catch (error) {
570
+ send(JSON.stringify({
571
+ jsonrpc: "2.0",
572
+ error: { code: -32700, message: "Parse error" },
573
+ id: null
574
+ }));
575
+ }
576
+ }
577
+ }
578
+ });
579
+ socket.on("close", () => {
580
+ sessions.delete(sessionId);
581
+ });
582
+ socket.on("error", () => {
583
+ sessions.delete(sessionId);
584
+ });
585
+ });
586
+ return new Promise((resolve, reject) => {
587
+ httpServer.on("error", reject);
588
+ httpServer.listen(port, () => {
589
+ console.error(
590
+ `MCP server '${this.metadata.server?.name}' started on ws://localhost:${port}${endpoint}`
591
+ );
592
+ resolve(httpServer);
593
+ });
594
+ });
595
+ }
596
+ /**
597
+ * Handle WebSocket JSON-RPC messages
598
+ */
599
+ async handleWebSocketMessage(message) {
600
+ if (!message || typeof message !== "object") {
601
+ return { jsonrpc: "2.0", error: { code: -32600, message: "Invalid Request" }, id: null };
602
+ }
603
+ const req = message;
604
+ if (req.jsonrpc !== "2.0" || !req.method) {
605
+ return { jsonrpc: "2.0", error: { code: -32600, message: "Invalid Request" }, id: req.id ?? null };
606
+ }
607
+ try {
608
+ let result;
609
+ switch (req.method) {
610
+ case "initialize":
611
+ result = {
612
+ protocolVersion: "2024-11-05",
613
+ serverInfo: {
614
+ name: this.metadata.server?.name,
615
+ version: this.metadata.server?.version ?? "1.0.0"
616
+ },
617
+ capabilities: {
618
+ tools: this.metadata.tools.length > 0 ? {} : void 0,
619
+ resources: this.metadata.resources.length > 0 ? {} : void 0,
620
+ prompts: this.metadata.prompts.length > 0 ? {} : void 0
621
+ }
622
+ };
623
+ break;
624
+ case "tools/list":
625
+ result = {
626
+ tools: this.metadata.tools.map((t) => ({
627
+ name: t.name,
628
+ description: t.description,
629
+ inputSchema: t.inputSchema ?? { type: "object", properties: {} }
630
+ }))
631
+ };
632
+ break;
633
+ case "tools/call":
634
+ const toolParams = req.params;
635
+ const tool = this.metadata.tools.find((t) => t.name === toolParams.name);
636
+ if (!tool) {
637
+ return { jsonrpc: "2.0", error: { code: -32602, message: `Unknown tool: ${toolParams.name}` }, id: req.id };
638
+ }
639
+ const method = Reflect.get(this.instance, tool.propertyKey);
640
+ const toolResult = await method.apply(this.instance, [toolParams.arguments ?? {}]);
641
+ result = {
642
+ content: [{
643
+ type: "text",
644
+ text: typeof toolResult === "string" ? toolResult : JSON.stringify(toolResult)
645
+ }]
646
+ };
647
+ break;
648
+ case "resources/list":
649
+ result = {
650
+ resources: this.metadata.resources.map((r) => ({
651
+ uri: r.uri,
652
+ name: r.name,
653
+ description: r.description,
654
+ mimeType: r.mimeType
655
+ }))
656
+ };
657
+ break;
658
+ case "resources/read":
659
+ const resParams = req.params;
660
+ for (const resource of this.metadata.resources) {
661
+ const uriParams = this.extractUriParams(resource.uri, resParams.uri);
662
+ if (uriParams) {
663
+ const resMethod = Reflect.get(this.instance, resource.propertyKey);
664
+ const args = this.resolveResourceArgs(resource.propertyKey, uriParams);
665
+ result = await resMethod.apply(this.instance, args);
666
+ break;
667
+ }
668
+ }
669
+ if (!result) {
670
+ return { jsonrpc: "2.0", error: { code: -32602, message: `Resource not found: ${resParams.uri}` }, id: req.id };
671
+ }
672
+ break;
673
+ case "prompts/list":
674
+ result = {
675
+ prompts: this.metadata.prompts.map((p) => ({
676
+ name: p.name,
677
+ description: p.description,
678
+ arguments: p.arguments ?? []
679
+ }))
680
+ };
681
+ break;
682
+ case "prompts/get":
683
+ const promptParams = req.params;
684
+ const prompt = this.metadata.prompts.find((p) => p.name === promptParams.name);
685
+ if (!prompt) {
686
+ return { jsonrpc: "2.0", error: { code: -32602, message: `Unknown prompt: ${promptParams.name}` }, id: req.id };
687
+ }
688
+ const promptMethod = Reflect.get(this.instance, prompt.propertyKey);
689
+ const promptArgs = this.resolvePromptArgs(prompt.propertyKey, promptParams.arguments ?? {});
690
+ result = await promptMethod.apply(this.instance, promptArgs);
691
+ break;
692
+ default:
693
+ return { jsonrpc: "2.0", error: { code: -32601, message: `Method not found: ${req.method}` }, id: req.id };
694
+ }
695
+ return { jsonrpc: "2.0", result, id: req.id };
696
+ } catch (error) {
697
+ return {
698
+ jsonrpc: "2.0",
699
+ error: { code: -32e3, message: error instanceof Error ? error.message : "Internal error" },
700
+ id: req.id
701
+ };
702
+ }
703
+ }
342
704
  };
343
- async function createMcpServer(target, options) {
705
+ async function createMcpServer(target, options = {}) {
344
706
  const server = new McpRuntimeServer(target, options);
345
- await server.start();
707
+ if (options.transport === "sse") {
708
+ await server.startSSE({ port: options.port, endpoint: options.endpoint });
709
+ } else if (options.transport === "websocket") {
710
+ await server.startWebSocket({ port: options.port, endpoint: options.endpoint });
711
+ } else {
712
+ await server.start();
713
+ }
346
714
  return server;
347
715
  }
348
716