@mcp-ts/sdk 1.0.1 → 1.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.
Files changed (83) hide show
  1. package/README.md +42 -19
  2. package/dist/adapters/agui-adapter.d.mts +6 -6
  3. package/dist/adapters/agui-adapter.d.ts +6 -6
  4. package/dist/adapters/agui-adapter.js +50 -25
  5. package/dist/adapters/agui-adapter.js.map +1 -1
  6. package/dist/adapters/agui-adapter.mjs +50 -25
  7. package/dist/adapters/agui-adapter.mjs.map +1 -1
  8. package/dist/adapters/agui-middleware.d.mts +23 -8
  9. package/dist/adapters/agui-middleware.d.ts +23 -8
  10. package/dist/adapters/agui-middleware.js +71 -43
  11. package/dist/adapters/agui-middleware.js.map +1 -1
  12. package/dist/adapters/agui-middleware.mjs +71 -44
  13. package/dist/adapters/agui-middleware.mjs.map +1 -1
  14. package/dist/adapters/ai-adapter.d.mts +2 -2
  15. package/dist/adapters/ai-adapter.d.ts +2 -2
  16. package/dist/adapters/langchain-adapter.d.mts +2 -2
  17. package/dist/adapters/langchain-adapter.d.ts +2 -2
  18. package/dist/adapters/mastra-adapter.d.mts +2 -2
  19. package/dist/adapters/mastra-adapter.d.ts +2 -2
  20. package/dist/client/index.d.mts +182 -55
  21. package/dist/client/index.d.ts +182 -55
  22. package/dist/client/index.js +535 -130
  23. package/dist/client/index.js.map +1 -1
  24. package/dist/client/index.mjs +535 -131
  25. package/dist/client/index.mjs.map +1 -1
  26. package/dist/client/react.d.mts +386 -4
  27. package/dist/client/react.d.ts +386 -4
  28. package/dist/client/react.js +890 -143
  29. package/dist/client/react.js.map +1 -1
  30. package/dist/client/react.mjs +883 -145
  31. package/dist/client/react.mjs.map +1 -1
  32. package/dist/client/vue.d.mts +3 -3
  33. package/dist/client/vue.d.ts +3 -3
  34. package/dist/client/vue.js +546 -141
  35. package/dist/client/vue.js.map +1 -1
  36. package/dist/client/vue.mjs +546 -142
  37. package/dist/client/vue.mjs.map +1 -1
  38. package/dist/{events-BP6WyRNh.d.mts → events-BgeztGYZ.d.mts} +12 -1
  39. package/dist/{events-BP6WyRNh.d.ts → events-BgeztGYZ.d.ts} +12 -1
  40. package/dist/index.d.mts +4 -4
  41. package/dist/index.d.ts +4 -4
  42. package/dist/index.js +797 -248
  43. package/dist/index.js.map +1 -1
  44. package/dist/index.mjs +791 -245
  45. package/dist/index.mjs.map +1 -1
  46. package/dist/{multi-session-client-DMF3ED2O.d.mts → multi-session-client-CxogNckF.d.mts} +1 -1
  47. package/dist/{multi-session-client-BOFgPypS.d.ts → multi-session-client-cox_WXUj.d.ts} +1 -1
  48. package/dist/server/index.d.mts +41 -37
  49. package/dist/server/index.d.ts +41 -37
  50. package/dist/server/index.js +241 -116
  51. package/dist/server/index.js.map +1 -1
  52. package/dist/server/index.mjs +237 -112
  53. package/dist/server/index.mjs.map +1 -1
  54. package/dist/shared/index.d.mts +39 -3
  55. package/dist/shared/index.d.ts +39 -3
  56. package/dist/shared/index.js +19 -0
  57. package/dist/shared/index.js.map +1 -1
  58. package/dist/shared/index.mjs +18 -1
  59. package/dist/shared/index.mjs.map +1 -1
  60. package/package.json +9 -2
  61. package/src/adapters/agui-adapter.ts +58 -35
  62. package/src/adapters/agui-middleware.ts +83 -45
  63. package/src/client/core/app-host.ts +417 -0
  64. package/src/client/core/sse-client.ts +365 -212
  65. package/src/client/core/types.ts +31 -0
  66. package/src/client/index.ts +1 -0
  67. package/src/client/react/agui-subscriber.ts +275 -0
  68. package/src/client/react/index.ts +23 -3
  69. package/src/client/react/use-agui-subscriber.ts +270 -0
  70. package/src/client/react/use-app-host.ts +73 -0
  71. package/src/client/react/use-mcp-app-iframe.ts +164 -0
  72. package/src/client/react/{useMcp.ts → use-mcp.ts} +18 -0
  73. package/src/client/vue/index.ts +1 -1
  74. package/src/server/handlers/nextjs-handler.ts +8 -7
  75. package/src/server/handlers/sse-handler.ts +129 -165
  76. package/src/server/mcp/oauth-client.ts +32 -2
  77. package/src/server/storage/index.ts +17 -1
  78. package/src/server/storage/sqlite-backend.ts +185 -0
  79. package/src/shared/events.ts +12 -0
  80. package/src/shared/index.ts +6 -1
  81. package/src/shared/tool-utils.ts +61 -0
  82. package/src/shared/types.ts +3 -1
  83. /package/src/client/vue/{useMcp.ts → use-mcp.ts} +0 -0
@@ -6,7 +6,7 @@ var streamableHttp_js = require('@modelcontextprotocol/sdk/client/streamableHttp
6
6
  var sse_js = require('@modelcontextprotocol/sdk/client/sse.js');
7
7
  var auth_js = require('@modelcontextprotocol/sdk/client/auth.js');
8
8
  var types_js = require('@modelcontextprotocol/sdk/types.js');
9
- var fs = require('fs');
9
+ var fs2 = require('fs');
10
10
  var path = require('path');
11
11
 
12
12
  function _interopNamespace(e) {
@@ -27,6 +27,7 @@ function _interopNamespace(e) {
27
27
  return Object.freeze(n);
28
28
  }
29
29
 
30
+ var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2);
30
31
  var path__namespace = /*#__PURE__*/_interopNamespace(path);
31
32
 
32
33
  var __defProp = Object.defineProperty;
@@ -424,8 +425,8 @@ var FileStorageBackend = class {
424
425
  if (this.initialized) return;
425
426
  try {
426
427
  const dir = path__namespace.dirname(this.filePath);
427
- await fs.promises.mkdir(dir, { recursive: true });
428
- const data = await fs.promises.readFile(this.filePath, "utf-8");
428
+ await fs2.promises.mkdir(dir, { recursive: true });
429
+ const data = await fs2.promises.readFile(this.filePath, "utf-8");
429
430
  const json = JSON.parse(data);
430
431
  this.memoryCache = /* @__PURE__ */ new Map();
431
432
  if (Array.isArray(json)) {
@@ -450,7 +451,7 @@ var FileStorageBackend = class {
450
451
  async flush() {
451
452
  if (!this.memoryCache) return;
452
453
  const sessions = Array.from(this.memoryCache.values());
453
- await fs.promises.writeFile(this.filePath, JSON.stringify(sessions, null, 2), "utf-8");
454
+ await fs2.promises.writeFile(this.filePath, JSON.stringify(sessions, null, 2), "utf-8");
454
455
  }
455
456
  getSessionKey(identity, sessionId) {
456
457
  return `${identity}:${sessionId}`;
@@ -519,6 +520,148 @@ var FileStorageBackend = class {
519
520
  async disconnect() {
520
521
  }
521
522
  };
523
+ var SqliteStorage = class {
524
+ constructor(options = {}) {
525
+ __publicField(this, "db", null);
526
+ __publicField(this, "table");
527
+ __publicField(this, "initialized", false);
528
+ __publicField(this, "dbPath");
529
+ this.dbPath = options.path || "./sessions.db";
530
+ this.table = options.table || "mcp_sessions";
531
+ }
532
+ async init() {
533
+ if (this.initialized) return;
534
+ try {
535
+ const DatabaseConstructor = (await import('better-sqlite3')).default;
536
+ const dir = path__namespace.dirname(this.dbPath);
537
+ if (!fs2__namespace.existsSync(dir)) {
538
+ fs2__namespace.mkdirSync(dir, { recursive: true });
539
+ }
540
+ this.db = new DatabaseConstructor(this.dbPath);
541
+ this.db.exec(`
542
+ CREATE TABLE IF NOT EXISTS ${this.table} (
543
+ sessionId TEXT PRIMARY KEY,
544
+ identity TEXT NOT NULL,
545
+ data TEXT NOT NULL,
546
+ expiresAt INTEGER
547
+ );
548
+ CREATE INDEX IF NOT EXISTS idx_${this.table}_identity ON ${this.table}(identity);
549
+ `);
550
+ this.initialized = true;
551
+ } catch (error) {
552
+ if (error.code === "MODULE_NOT_FOUND" || error.message?.includes("better-sqlite3")) {
553
+ throw new Error(
554
+ "better-sqlite3 is not installed. Please install it with: npm install better-sqlite3"
555
+ );
556
+ }
557
+ throw error;
558
+ }
559
+ }
560
+ ensureInitialized() {
561
+ if (!this.initialized) {
562
+ throw new Error("SqliteStorage not initialized. Call init() first.");
563
+ }
564
+ }
565
+ generateSessionId() {
566
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
567
+ let result = "";
568
+ for (let i = 0; i < 32; i++) {
569
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
570
+ }
571
+ return result;
572
+ }
573
+ async createSession(session, ttl) {
574
+ this.ensureInitialized();
575
+ const { sessionId, identity } = session;
576
+ if (!sessionId || !identity) {
577
+ throw new Error("identity and sessionId required");
578
+ }
579
+ const expiresAt = ttl ? Date.now() + ttl * 1e3 : null;
580
+ try {
581
+ const stmt = this.db.prepare(
582
+ `INSERT INTO ${this.table} (sessionId, identity, data, expiresAt) VALUES (?, ?, ?, ?)`
583
+ );
584
+ stmt.run(sessionId, identity, JSON.stringify(session), expiresAt);
585
+ } catch (error) {
586
+ if (error.code === "SQLITE_CONSTRAINT_PRIMARYKEY") {
587
+ throw new Error(`Session ${sessionId} already exists`);
588
+ }
589
+ throw error;
590
+ }
591
+ }
592
+ async updateSession(identity, sessionId, data, ttl) {
593
+ this.ensureInitialized();
594
+ if (!sessionId || !identity) {
595
+ throw new Error("identity and sessionId required");
596
+ }
597
+ const currentSession = await this.getSession(identity, sessionId);
598
+ if (!currentSession) {
599
+ throw new Error(`Session ${sessionId} not found for identity ${identity}`);
600
+ }
601
+ const updatedSession = { ...currentSession, ...data };
602
+ const expiresAt = ttl ? Date.now() + ttl * 1e3 : null;
603
+ const stmt = this.db.prepare(
604
+ `UPDATE ${this.table} SET data = ?, expiresAt = ? WHERE sessionId = ? AND identity = ?`
605
+ );
606
+ stmt.run(JSON.stringify(updatedSession), expiresAt, sessionId, identity);
607
+ }
608
+ async getSession(identity, sessionId) {
609
+ this.ensureInitialized();
610
+ const stmt = this.db.prepare(
611
+ `SELECT data FROM ${this.table} WHERE sessionId = ? AND identity = ?`
612
+ );
613
+ const row = stmt.get(sessionId, identity);
614
+ if (!row) return null;
615
+ return JSON.parse(row.data);
616
+ }
617
+ async getIdentitySessionsData(identity) {
618
+ this.ensureInitialized();
619
+ const stmt = this.db.prepare(
620
+ `SELECT data FROM ${this.table} WHERE identity = ?`
621
+ );
622
+ const rows = stmt.all(identity);
623
+ return rows.map((row) => JSON.parse(row.data));
624
+ }
625
+ async getIdentityMcpSessions(identity) {
626
+ this.ensureInitialized();
627
+ const stmt = this.db.prepare(
628
+ `SELECT sessionId FROM ${this.table} WHERE identity = ?`
629
+ );
630
+ const rows = stmt.all(identity);
631
+ return rows.map((row) => row.sessionId);
632
+ }
633
+ async removeSession(identity, sessionId) {
634
+ this.ensureInitialized();
635
+ const stmt = this.db.prepare(
636
+ `DELETE FROM ${this.table} WHERE sessionId = ? AND identity = ?`
637
+ );
638
+ stmt.run(sessionId, identity);
639
+ }
640
+ async getAllSessionIds() {
641
+ this.ensureInitialized();
642
+ const stmt = this.db.prepare(`SELECT sessionId FROM ${this.table}`);
643
+ const rows = stmt.all();
644
+ return rows.map((row) => row.sessionId);
645
+ }
646
+ async clearAll() {
647
+ this.ensureInitialized();
648
+ const stmt = this.db.prepare(`DELETE FROM ${this.table}`);
649
+ stmt.run();
650
+ }
651
+ async cleanupExpiredSessions() {
652
+ this.ensureInitialized();
653
+ const now = Date.now();
654
+ const stmt = this.db.prepare(
655
+ `DELETE FROM ${this.table} WHERE expiresAt IS NOT NULL AND expiresAt < ?`
656
+ );
657
+ stmt.run(now);
658
+ }
659
+ async disconnect() {
660
+ if (this.db) {
661
+ this.db.close();
662
+ }
663
+ }
664
+ };
522
665
 
523
666
  // src/server/storage/index.ts
524
667
  var storageInstance = null;
@@ -550,6 +693,13 @@ async function createStorage() {
550
693
  store.init().catch((err) => console.error("[Storage] Failed to initialize file storage:", err));
551
694
  return store;
552
695
  }
696
+ if (type === "sqlite") {
697
+ const dbPath = process.env.MCP_TS_STORAGE_SQLITE_PATH;
698
+ console.log(`[Storage] Using SQLite storage (${dbPath || "default"}) (Explicit)`);
699
+ const store = new SqliteStorage({ path: dbPath });
700
+ store.init().catch((err) => console.error("[Storage] Failed to initialize SQLite storage:", err));
701
+ return store;
702
+ }
553
703
  if (type === "memory") {
554
704
  console.log("[Storage] Using In-Memory storage (Explicit)");
555
705
  return new MemoryStorageBackend();
@@ -572,6 +722,12 @@ async function createStorage() {
572
722
  store.init().catch((err) => console.error("[Storage] Failed to initialize file storage:", err));
573
723
  return store;
574
724
  }
725
+ if (process.env.MCP_TS_STORAGE_SQLITE_PATH) {
726
+ console.log(`[Storage] Auto-detected MCP_TS_STORAGE_SQLITE_PATH. Using SQLite storage (${process.env.MCP_TS_STORAGE_SQLITE_PATH}).`);
727
+ const store = new SqliteStorage({ path: process.env.MCP_TS_STORAGE_SQLITE_PATH });
728
+ store.init().catch((err) => console.error("[Storage] Failed to initialize SQLite storage:", err));
729
+ return store;
730
+ }
575
731
  console.log("[Storage] No storage configured. Using In-Memory storage (Default).");
576
732
  return new MemoryStorageBackend();
577
733
  }
@@ -1079,7 +1235,15 @@ var MCPClient = class _MCPClient {
1079
1235
  name: "mcp-ts-oauth-client",
1080
1236
  version: "2.0"
1081
1237
  },
1082
- { capabilities: {} }
1238
+ {
1239
+ capabilities: {
1240
+ extensions: {
1241
+ "io.modelcontextprotocol/ui": {
1242
+ mimeTypes: ["text/html+mcp"]
1243
+ }
1244
+ }
1245
+ }
1246
+ }
1083
1247
  );
1084
1248
  }
1085
1249
  const existingSession = await storage.getSession(this.identity, this.sessionId);
@@ -1261,7 +1425,15 @@ var MCPClient = class _MCPClient {
1261
1425
  name: "mcp-ts-oauth-client",
1262
1426
  version: "2.0"
1263
1427
  },
1264
- { capabilities: {} }
1428
+ {
1429
+ capabilities: {
1430
+ extensions: {
1431
+ "io.modelcontextprotocol/ui": {
1432
+ mimeTypes: ["text/html+mcp"]
1433
+ }
1434
+ }
1435
+ }
1436
+ }
1265
1437
  );
1266
1438
  this.emitStateChange("CONNECTING");
1267
1439
  await this.client.connect(this.transport);
@@ -1817,6 +1989,7 @@ var MultiSessionClient = class {
1817
1989
  };
1818
1990
 
1819
1991
  // src/server/handlers/sse-handler.ts
1992
+ var DEFAULT_HEARTBEAT_INTERVAL = 3e4;
1820
1993
  var SSEConnectionManager = class {
1821
1994
  constructor(options, sendEvent) {
1822
1995
  this.options = options;
@@ -1846,7 +2019,7 @@ var SSEConnectionManager = class {
1846
2019
  * Start heartbeat to keep connection alive
1847
2020
  */
1848
2021
  startHeartbeat() {
1849
- const interval = this.options.heartbeatInterval || 3e4;
2022
+ const interval = this.options.heartbeatInterval ?? DEFAULT_HEARTBEAT_INTERVAL;
1850
2023
  this.heartbeatTimer = setInterval(() => {
1851
2024
  if (this.isActive) {
1852
2025
  this.sendEvent({
@@ -1859,6 +2032,7 @@ var SSEConnectionManager = class {
1859
2032
  }
1860
2033
  /**
1861
2034
  * Handle incoming RPC requests
2035
+ * Returns the RPC response directly for immediate HTTP response (bypassing SSE latency)
1862
2036
  */
1863
2037
  async handleRequest(request) {
1864
2038
  try {
@@ -1900,39 +2074,29 @@ var SSEConnectionManager = class {
1900
2074
  default:
1901
2075
  throw new Error(`Unknown method: ${request.method}`);
1902
2076
  }
1903
- this.sendEvent({
2077
+ const response = {
1904
2078
  id: request.id,
1905
2079
  result
1906
- });
2080
+ };
2081
+ this.sendEvent(response);
2082
+ return response;
1907
2083
  } catch (error) {
1908
- this.sendEvent({
2084
+ const errorResponse = {
1909
2085
  id: request.id,
1910
2086
  error: {
1911
2087
  code: RpcErrorCodes.EXECUTION_ERROR,
1912
2088
  message: error instanceof Error ? error.message : "Unknown error"
1913
2089
  }
1914
- });
2090
+ };
2091
+ this.sendEvent(errorResponse);
2092
+ return errorResponse;
1915
2093
  }
1916
2094
  }
1917
2095
  /**
1918
- * Get all user sessions
2096
+ * Get all sessions for the current identity
1919
2097
  */
1920
2098
  async getSessions() {
1921
2099
  const sessions = await storage.getIdentitySessionsData(this.identity);
1922
- this.sendEvent({
1923
- level: "debug",
1924
- message: `Retrieved ${sessions.length} sessions for identity ${this.identity}`,
1925
- timestamp: Date.now(),
1926
- metadata: {
1927
- identity: this.identity,
1928
- sessionCount: sessions.length,
1929
- sessions: sessions.map((s) => ({
1930
- sessionId: s.sessionId,
1931
- serverId: s.serverId,
1932
- serverName: s.serverName
1933
- }))
1934
- }
1935
- });
1936
2100
  return {
1937
2101
  sessions: sessions.map((s) => ({
1938
2102
  sessionId: s.sessionId,
@@ -1948,7 +2112,7 @@ var SSEConnectionManager = class {
1948
2112
  */
1949
2113
  async connect(params) {
1950
2114
  const { serverName, serverUrl, callbackUrl, transportType } = params;
1951
- const serverId = params.serverId || await storage.generateSessionId();
2115
+ const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : await storage.generateSessionId();
1952
2116
  const existingSessions = await storage.getIdentitySessionsData(this.identity);
1953
2117
  const duplicate = existingSessions.find(
1954
2118
  (s) => s.serverId === serverId || s.serverUrl === serverUrl
@@ -1997,10 +2161,6 @@ var SSEConnectionManager = class {
1997
2161
  });
1998
2162
  await client.connect();
1999
2163
  const tools = await client.listTools();
2000
- const sessionAfterConnect = await storage.getSession(this.identity, sessionId);
2001
- console.log(`[SSE Handler] After connect() - Session ${sessionId}:`, {
2002
- serverId: sessionAfterConnect?.serverId
2003
- });
2004
2164
  this.emitConnectionEvent({
2005
2165
  type: "tools_discovered",
2006
2166
  sessionId,
@@ -2042,24 +2202,21 @@ var SSEConnectionManager = class {
2042
2202
  return { success: true };
2043
2203
  }
2044
2204
  /**
2045
- * Helper to get or restore a client
2205
+ * Get an existing client or create and connect a new one for the session.
2046
2206
  */
2047
2207
  async getOrCreateClient(sessionId) {
2048
- let client = this.clients.get(sessionId);
2049
- if (!client) {
2050
- client = new MCPClient({
2051
- identity: this.identity,
2052
- sessionId
2053
- });
2054
- client.onConnectionEvent((event) => {
2055
- this.emitConnectionEvent(event);
2056
- });
2057
- client.onObservabilityEvent((event) => {
2058
- this.sendEvent(event);
2059
- });
2060
- await client.connect();
2061
- this.clients.set(sessionId, client);
2208
+ const existing = this.clients.get(sessionId);
2209
+ if (existing) {
2210
+ return existing;
2062
2211
  }
2212
+ const client = new MCPClient({
2213
+ identity: this.identity,
2214
+ sessionId
2215
+ });
2216
+ client.onConnectionEvent((event) => this.emitConnectionEvent(event));
2217
+ client.onObservabilityEvent((event) => this.sendEvent(event));
2218
+ await client.connect();
2219
+ this.clients.set(sessionId, client);
2063
2220
  return client;
2064
2221
  }
2065
2222
  /**
@@ -2072,51 +2229,35 @@ var SSEConnectionManager = class {
2072
2229
  return { tools: result.tools };
2073
2230
  }
2074
2231
  /**
2075
- * Call a tool
2232
+ * Call a tool on the MCP server
2076
2233
  */
2077
2234
  async callTool(params) {
2078
2235
  const { sessionId, toolName, toolArgs } = params;
2079
2236
  const client = await this.getOrCreateClient(sessionId);
2080
- return await client.callTool(toolName, toolArgs);
2237
+ const result = await client.callTool(toolName, toolArgs);
2238
+ const meta = result._meta || {};
2239
+ return {
2240
+ ...result,
2241
+ _meta: {
2242
+ ...meta,
2243
+ sessionId
2244
+ }
2245
+ };
2081
2246
  }
2082
2247
  /**
2083
- * Refresh/validate a session
2248
+ * Restore and validate an existing session
2084
2249
  */
2085
2250
  async restoreSession(params) {
2086
2251
  const { sessionId } = params;
2087
- this.sendEvent({
2088
- level: "debug",
2089
- message: `Starting session refresh for ${sessionId}`,
2090
- timestamp: Date.now(),
2091
- metadata: { sessionId, identity: this.identity }
2092
- });
2093
2252
  const session = await storage.getSession(this.identity, sessionId);
2094
2253
  if (!session) {
2095
- this.sendEvent({
2096
- level: "error",
2097
- message: `Session not found: ${sessionId}`,
2098
- timestamp: Date.now(),
2099
- metadata: { sessionId, identity: this.identity }
2100
- });
2101
2254
  throw new Error("Session not found");
2102
2255
  }
2103
- this.sendEvent({
2104
- level: "debug",
2105
- message: `Session found in Redis`,
2106
- timestamp: Date.now(),
2107
- metadata: {
2108
- sessionId,
2109
- serverId: session.serverId,
2110
- serverName: session.serverName,
2111
- serverUrl: session.serverUrl,
2112
- transportType: session.transportType
2113
- }
2114
- });
2115
2256
  this.emitConnectionEvent({
2116
2257
  type: "state_changed",
2117
2258
  sessionId,
2118
- serverId: session.serverId || "unknown",
2119
- serverName: session.serverName || "Unknown",
2259
+ serverId: session.serverId ?? "unknown",
2260
+ serverName: session.serverName ?? "Unknown",
2120
2261
  state: "VALIDATING",
2121
2262
  previousState: "DISCONNECTED",
2122
2263
  timestamp: Date.now()
@@ -2127,21 +2268,16 @@ var SSEConnectionManager = class {
2127
2268
  identity: this.identity,
2128
2269
  sessionId,
2129
2270
  ...clientMetadata
2130
- // Include metadata for consistency
2131
- });
2132
- client.onConnectionEvent((event) => {
2133
- this.emitConnectionEvent(event);
2134
- });
2135
- client.onObservabilityEvent((event) => {
2136
- this.sendEvent(event);
2137
2271
  });
2272
+ client.onConnectionEvent((event) => this.emitConnectionEvent(event));
2273
+ client.onObservabilityEvent((event) => this.sendEvent(event));
2138
2274
  await client.connect();
2139
2275
  this.clients.set(sessionId, client);
2140
2276
  const tools = await client.listTools();
2141
2277
  this.emitConnectionEvent({
2142
2278
  type: "tools_discovered",
2143
2279
  sessionId,
2144
- serverId: session.serverId || "unknown",
2280
+ serverId: session.serverId ?? "unknown",
2145
2281
  toolCount: tools.tools.length,
2146
2282
  tools: tools.tools,
2147
2283
  timestamp: Date.now()
@@ -2151,7 +2287,7 @@ var SSEConnectionManager = class {
2151
2287
  this.emitConnectionEvent({
2152
2288
  type: "error",
2153
2289
  sessionId,
2154
- serverId: session.serverId || "unknown",
2290
+ serverId: session.serverId ?? "unknown",
2155
2291
  error: error instanceof Error ? error.message : "Validation failed",
2156
2292
  errorType: "validation",
2157
2293
  timestamp: Date.now()
@@ -2160,16 +2296,10 @@ var SSEConnectionManager = class {
2160
2296
  }
2161
2297
  }
2162
2298
  /**
2163
- * Complete OAuth authorization
2299
+ * Complete OAuth authorization flow
2164
2300
  */
2165
2301
  async finishAuth(params) {
2166
2302
  const { sessionId, code } = params;
2167
- this.sendEvent({
2168
- level: "debug",
2169
- message: `Completing OAuth for session ${sessionId}`,
2170
- timestamp: Date.now(),
2171
- metadata: { sessionId, identity: this.identity }
2172
- });
2173
2303
  const session = await storage.getSession(this.identity, sessionId);
2174
2304
  if (!session) {
2175
2305
  throw new Error("Session not found");
@@ -2177,8 +2307,8 @@ var SSEConnectionManager = class {
2177
2307
  this.emitConnectionEvent({
2178
2308
  type: "state_changed",
2179
2309
  sessionId,
2180
- serverId: session.serverId || "unknown",
2181
- serverName: session.serverName || "Unknown",
2310
+ serverId: session.serverId ?? "unknown",
2311
+ serverName: session.serverName ?? "Unknown",
2182
2312
  state: "AUTHENTICATING",
2183
2313
  previousState: "DISCONNECTED",
2184
2314
  timestamp: Date.now()
@@ -2188,16 +2318,14 @@ var SSEConnectionManager = class {
2188
2318
  identity: this.identity,
2189
2319
  sessionId
2190
2320
  });
2191
- client.onConnectionEvent((event) => {
2192
- this.emitConnectionEvent(event);
2193
- });
2321
+ client.onConnectionEvent((event) => this.emitConnectionEvent(event));
2194
2322
  await client.finishAuth(code);
2195
2323
  this.clients.set(sessionId, client);
2196
2324
  const tools = await client.listTools();
2197
2325
  this.emitConnectionEvent({
2198
2326
  type: "tools_discovered",
2199
2327
  sessionId,
2200
- serverId: session.serverId || "unknown",
2328
+ serverId: session.serverId ?? "unknown",
2201
2329
  toolCount: tools.tools.length,
2202
2330
  tools: tools.tools,
2203
2331
  timestamp: Date.now()
@@ -2207,7 +2335,7 @@ var SSEConnectionManager = class {
2207
2335
  this.emitConnectionEvent({
2208
2336
  type: "error",
2209
2337
  sessionId,
2210
- serverId: session.serverId || "unknown",
2338
+ serverId: session.serverId ?? "unknown",
2211
2339
  error: error instanceof Error ? error.message : "OAuth completion failed",
2212
2340
  errorType: "auth",
2213
2341
  timestamp: Date.now()
@@ -2247,7 +2375,7 @@ var SSEConnectionManager = class {
2247
2375
  async readResource(params) {
2248
2376
  const { sessionId, uri } = params;
2249
2377
  const client = await this.getOrCreateClient(sessionId);
2250
- return await client.readResource(uri);
2378
+ return client.readResource(uri);
2251
2379
  }
2252
2380
  /**
2253
2381
  * Emit connection event
@@ -2277,19 +2405,17 @@ function createSSEHandler(options) {
2277
2405
  "Connection": "keep-alive",
2278
2406
  "Access-Control-Allow-Origin": "*"
2279
2407
  });
2280
- sendSSE(res, "connected", { timestamp: Date.now() });
2408
+ writeSSEEvent(res, "connected", { timestamp: Date.now() });
2281
2409
  const manager = new SSEConnectionManager(options, (event) => {
2282
2410
  if ("id" in event) {
2283
- sendSSE(res, "rpc-response", event);
2411
+ writeSSEEvent(res, "rpc-response", event);
2284
2412
  } else if ("type" in event && "sessionId" in event) {
2285
- sendSSE(res, "connection", event);
2413
+ writeSSEEvent(res, "connection", event);
2286
2414
  } else {
2287
- sendSSE(res, "observability", event);
2415
+ writeSSEEvent(res, "observability", event);
2288
2416
  }
2289
2417
  });
2290
- req.on("close", () => {
2291
- manager.dispose();
2292
- });
2418
+ req.on("close", () => manager.dispose());
2293
2419
  if (req.method === "POST") {
2294
2420
  let body = "";
2295
2421
  req.on("data", (chunk) => {
@@ -2299,14 +2425,13 @@ function createSSEHandler(options) {
2299
2425
  try {
2300
2426
  const request = JSON.parse(body);
2301
2427
  await manager.handleRequest(request);
2302
- } catch (error) {
2303
- console.error("[SSE] Error handling request:", error);
2428
+ } catch {
2304
2429
  }
2305
2430
  });
2306
2431
  }
2307
2432
  };
2308
2433
  }
2309
- function sendSSE(res, event, data) {
2434
+ function writeSSEEvent(res, event, data) {
2310
2435
  res.write(`event: ${event}
2311
2436
  `);
2312
2437
  res.write(`data: ${JSON.stringify(data)}
@@ -2341,7 +2466,7 @@ function createNextMcpHandler(options = {}) {
2341
2466
  const stream = new TransformStream();
2342
2467
  const writer = stream.writable.getWriter();
2343
2468
  const encoder = new TextEncoder();
2344
- const sendSSE2 = (event, data) => {
2469
+ const sendSSE = (event, data) => {
2345
2470
  const message = `event: ${event}
2346
2471
  data: ${JSON.stringify(data)}
2347
2472
 
@@ -2349,7 +2474,6 @@ data: ${JSON.stringify(data)}
2349
2474
  writer.write(encoder.encode(message)).catch(() => {
2350
2475
  });
2351
2476
  };
2352
- sendSSE2("connected", { timestamp: Date.now() });
2353
2477
  const previousManager = managers.get(identity);
2354
2478
  if (previousManager) {
2355
2479
  previousManager.dispose();
@@ -2364,15 +2488,16 @@ data: ${JSON.stringify(data)}
2364
2488
  },
2365
2489
  (event) => {
2366
2490
  if ("id" in event) {
2367
- sendSSE2("rpc-response", event);
2491
+ sendSSE("rpc-response", event);
2368
2492
  } else if ("type" in event && "sessionId" in event) {
2369
- sendSSE2("connection", event);
2493
+ sendSSE("connection", event);
2370
2494
  } else {
2371
- sendSSE2("observability", event);
2495
+ sendSSE("observability", event);
2372
2496
  }
2373
2497
  }
2374
2498
  );
2375
2499
  managers.set(identity, manager);
2500
+ sendSSE("connected", { timestamp: Date.now() });
2376
2501
  const abortController = new AbortController();
2377
2502
  request.signal?.addEventListener("abort", () => {
2378
2503
  manager.dispose();
@@ -2415,8 +2540,8 @@ data: ${JSON.stringify(data)}
2415
2540
  { status: 400 }
2416
2541
  );
2417
2542
  }
2418
- await manager.handleRequest(body);
2419
- return Response.json({ acknowledged: true });
2543
+ const response = await manager.handleRequest(body);
2544
+ return Response.json(response);
2420
2545
  } catch (error) {
2421
2546
  return Response.json(
2422
2547
  {