@mcp-ts/sdk 1.0.0 → 1.1.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 (77) hide show
  1. package/README.md +25 -13
  2. package/dist/adapters/agui-adapter.d.mts +21 -44
  3. package/dist/adapters/agui-adapter.d.ts +21 -44
  4. package/dist/adapters/agui-adapter.js +93 -67
  5. package/dist/adapters/agui-adapter.js.map +1 -1
  6. package/dist/adapters/agui-adapter.mjs +93 -68
  7. package/dist/adapters/agui-adapter.mjs.map +1 -1
  8. package/dist/adapters/agui-middleware.d.mts +32 -134
  9. package/dist/adapters/agui-middleware.d.ts +32 -134
  10. package/dist/adapters/agui-middleware.js +314 -350
  11. package/dist/adapters/agui-middleware.js.map +1 -1
  12. package/dist/adapters/agui-middleware.mjs +314 -351
  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 +184 -57
  21. package/dist/client/index.d.ts +184 -57
  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 +40 -6
  27. package/dist/client/react.d.ts +40 -6
  28. package/dist/client/react.js +587 -142
  29. package/dist/client/react.js.map +1 -1
  30. package/dist/client/react.mjs +586 -143
  31. package/dist/client/react.mjs.map +1 -1
  32. package/dist/client/vue.d.mts +5 -5
  33. package/dist/client/vue.d.ts +5 -5
  34. package/dist/client/vue.js +545 -140
  35. package/dist/client/vue.js.map +1 -1
  36. package/dist/client/vue.mjs +545 -141
  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 +779 -248
  43. package/dist/index.js.map +1 -1
  44. package/dist/index.mjs +775 -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 +44 -40
  49. package/dist/server/index.d.ts +44 -40
  50. package/dist/server/index.js +242 -116
  51. package/dist/server/index.js.map +1 -1
  52. package/dist/server/index.mjs +238 -112
  53. package/dist/server/index.mjs.map +1 -1
  54. package/dist/shared/index.d.mts +2 -2
  55. package/dist/shared/index.d.ts +2 -2
  56. package/dist/shared/index.js.map +1 -1
  57. package/dist/shared/index.mjs.map +1 -1
  58. package/dist/{types-SbDlA2VX.d.mts → types-CLccx9wW.d.mts} +1 -1
  59. package/dist/{types-SbDlA2VX.d.ts → types-CLccx9wW.d.ts} +1 -1
  60. package/package.json +8 -1
  61. package/src/adapters/agui-adapter.ts +121 -107
  62. package/src/adapters/agui-middleware.ts +474 -512
  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/index.ts +1 -0
  68. package/src/client/react/use-mcp-app.ts +73 -0
  69. package/src/client/react/useMcp.ts +18 -0
  70. package/src/server/handlers/nextjs-handler.ts +8 -7
  71. package/src/server/handlers/sse-handler.ts +131 -164
  72. package/src/server/mcp/oauth-client.ts +32 -2
  73. package/src/server/storage/index.ts +17 -1
  74. package/src/server/storage/sqlite-backend.ts +185 -0
  75. package/src/server/storage/types.ts +1 -1
  76. package/src/shared/events.ts +12 -0
  77. package/src/shared/types.ts +4 -2
@@ -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,
@@ -1947,7 +2111,8 @@ var SSEConnectionManager = class {
1947
2111
  * Connect to an MCP server
1948
2112
  */
1949
2113
  async connect(params) {
1950
- const { serverId, serverName, serverUrl, callbackUrl, transportType } = params;
2114
+ const { serverName, serverUrl, callbackUrl, transportType } = params;
2115
+ const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : await storage.generateSessionId();
1951
2116
  const existingSessions = await storage.getIdentitySessionsData(this.identity);
1952
2117
  const duplicate = existingSessions.find(
1953
2118
  (s) => s.serverId === serverId || s.serverUrl === serverUrl
@@ -1996,10 +2161,6 @@ var SSEConnectionManager = class {
1996
2161
  });
1997
2162
  await client.connect();
1998
2163
  const tools = await client.listTools();
1999
- const sessionAfterConnect = await storage.getSession(this.identity, sessionId);
2000
- console.log(`[SSE Handler] After connect() - Session ${sessionId}:`, {
2001
- serverId: sessionAfterConnect?.serverId
2002
- });
2003
2164
  this.emitConnectionEvent({
2004
2165
  type: "tools_discovered",
2005
2166
  sessionId,
@@ -2041,24 +2202,21 @@ var SSEConnectionManager = class {
2041
2202
  return { success: true };
2042
2203
  }
2043
2204
  /**
2044
- * Helper to get or restore a client
2205
+ * Get an existing client or create and connect a new one for the session.
2045
2206
  */
2046
2207
  async getOrCreateClient(sessionId) {
2047
- let client = this.clients.get(sessionId);
2048
- if (!client) {
2049
- client = new MCPClient({
2050
- identity: this.identity,
2051
- sessionId
2052
- });
2053
- client.onConnectionEvent((event) => {
2054
- this.emitConnectionEvent(event);
2055
- });
2056
- client.onObservabilityEvent((event) => {
2057
- this.sendEvent(event);
2058
- });
2059
- await client.connect();
2060
- this.clients.set(sessionId, client);
2208
+ const existing = this.clients.get(sessionId);
2209
+ if (existing) {
2210
+ return existing;
2061
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);
2062
2220
  return client;
2063
2221
  }
2064
2222
  /**
@@ -2071,51 +2229,35 @@ var SSEConnectionManager = class {
2071
2229
  return { tools: result.tools };
2072
2230
  }
2073
2231
  /**
2074
- * Call a tool
2232
+ * Call a tool on the MCP server
2075
2233
  */
2076
2234
  async callTool(params) {
2077
2235
  const { sessionId, toolName, toolArgs } = params;
2078
2236
  const client = await this.getOrCreateClient(sessionId);
2079
- 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
+ };
2080
2246
  }
2081
2247
  /**
2082
- * Refresh/validate a session
2248
+ * Restore and validate an existing session
2083
2249
  */
2084
2250
  async restoreSession(params) {
2085
2251
  const { sessionId } = params;
2086
- this.sendEvent({
2087
- level: "debug",
2088
- message: `Starting session refresh for ${sessionId}`,
2089
- timestamp: Date.now(),
2090
- metadata: { sessionId, identity: this.identity }
2091
- });
2092
2252
  const session = await storage.getSession(this.identity, sessionId);
2093
2253
  if (!session) {
2094
- this.sendEvent({
2095
- level: "error",
2096
- message: `Session not found: ${sessionId}`,
2097
- timestamp: Date.now(),
2098
- metadata: { sessionId, identity: this.identity }
2099
- });
2100
2254
  throw new Error("Session not found");
2101
2255
  }
2102
- this.sendEvent({
2103
- level: "debug",
2104
- message: `Session found in Redis`,
2105
- timestamp: Date.now(),
2106
- metadata: {
2107
- sessionId,
2108
- serverId: session.serverId,
2109
- serverName: session.serverName,
2110
- serverUrl: session.serverUrl,
2111
- transportType: session.transportType
2112
- }
2113
- });
2114
2256
  this.emitConnectionEvent({
2115
2257
  type: "state_changed",
2116
2258
  sessionId,
2117
- serverId: session.serverId || "unknown",
2118
- serverName: session.serverName || "Unknown",
2259
+ serverId: session.serverId ?? "unknown",
2260
+ serverName: session.serverName ?? "Unknown",
2119
2261
  state: "VALIDATING",
2120
2262
  previousState: "DISCONNECTED",
2121
2263
  timestamp: Date.now()
@@ -2126,21 +2268,16 @@ var SSEConnectionManager = class {
2126
2268
  identity: this.identity,
2127
2269
  sessionId,
2128
2270
  ...clientMetadata
2129
- // Include metadata for consistency
2130
- });
2131
- client.onConnectionEvent((event) => {
2132
- this.emitConnectionEvent(event);
2133
- });
2134
- client.onObservabilityEvent((event) => {
2135
- this.sendEvent(event);
2136
2271
  });
2272
+ client.onConnectionEvent((event) => this.emitConnectionEvent(event));
2273
+ client.onObservabilityEvent((event) => this.sendEvent(event));
2137
2274
  await client.connect();
2138
2275
  this.clients.set(sessionId, client);
2139
2276
  const tools = await client.listTools();
2140
2277
  this.emitConnectionEvent({
2141
2278
  type: "tools_discovered",
2142
2279
  sessionId,
2143
- serverId: session.serverId || "unknown",
2280
+ serverId: session.serverId ?? "unknown",
2144
2281
  toolCount: tools.tools.length,
2145
2282
  tools: tools.tools,
2146
2283
  timestamp: Date.now()
@@ -2150,7 +2287,7 @@ var SSEConnectionManager = class {
2150
2287
  this.emitConnectionEvent({
2151
2288
  type: "error",
2152
2289
  sessionId,
2153
- serverId: session.serverId || "unknown",
2290
+ serverId: session.serverId ?? "unknown",
2154
2291
  error: error instanceof Error ? error.message : "Validation failed",
2155
2292
  errorType: "validation",
2156
2293
  timestamp: Date.now()
@@ -2159,16 +2296,10 @@ var SSEConnectionManager = class {
2159
2296
  }
2160
2297
  }
2161
2298
  /**
2162
- * Complete OAuth authorization
2299
+ * Complete OAuth authorization flow
2163
2300
  */
2164
2301
  async finishAuth(params) {
2165
2302
  const { sessionId, code } = params;
2166
- this.sendEvent({
2167
- level: "debug",
2168
- message: `Completing OAuth for session ${sessionId}`,
2169
- timestamp: Date.now(),
2170
- metadata: { sessionId, identity: this.identity }
2171
- });
2172
2303
  const session = await storage.getSession(this.identity, sessionId);
2173
2304
  if (!session) {
2174
2305
  throw new Error("Session not found");
@@ -2176,8 +2307,8 @@ var SSEConnectionManager = class {
2176
2307
  this.emitConnectionEvent({
2177
2308
  type: "state_changed",
2178
2309
  sessionId,
2179
- serverId: session.serverId || "unknown",
2180
- serverName: session.serverName || "Unknown",
2310
+ serverId: session.serverId ?? "unknown",
2311
+ serverName: session.serverName ?? "Unknown",
2181
2312
  state: "AUTHENTICATING",
2182
2313
  previousState: "DISCONNECTED",
2183
2314
  timestamp: Date.now()
@@ -2187,16 +2318,14 @@ var SSEConnectionManager = class {
2187
2318
  identity: this.identity,
2188
2319
  sessionId
2189
2320
  });
2190
- client.onConnectionEvent((event) => {
2191
- this.emitConnectionEvent(event);
2192
- });
2321
+ client.onConnectionEvent((event) => this.emitConnectionEvent(event));
2193
2322
  await client.finishAuth(code);
2194
2323
  this.clients.set(sessionId, client);
2195
2324
  const tools = await client.listTools();
2196
2325
  this.emitConnectionEvent({
2197
2326
  type: "tools_discovered",
2198
2327
  sessionId,
2199
- serverId: session.serverId || "unknown",
2328
+ serverId: session.serverId ?? "unknown",
2200
2329
  toolCount: tools.tools.length,
2201
2330
  tools: tools.tools,
2202
2331
  timestamp: Date.now()
@@ -2206,7 +2335,7 @@ var SSEConnectionManager = class {
2206
2335
  this.emitConnectionEvent({
2207
2336
  type: "error",
2208
2337
  sessionId,
2209
- serverId: session.serverId || "unknown",
2338
+ serverId: session.serverId ?? "unknown",
2210
2339
  error: error instanceof Error ? error.message : "OAuth completion failed",
2211
2340
  errorType: "auth",
2212
2341
  timestamp: Date.now()
@@ -2246,7 +2375,7 @@ var SSEConnectionManager = class {
2246
2375
  async readResource(params) {
2247
2376
  const { sessionId, uri } = params;
2248
2377
  const client = await this.getOrCreateClient(sessionId);
2249
- return await client.readResource(uri);
2378
+ return client.readResource(uri);
2250
2379
  }
2251
2380
  /**
2252
2381
  * Emit connection event
@@ -2276,19 +2405,17 @@ function createSSEHandler(options) {
2276
2405
  "Connection": "keep-alive",
2277
2406
  "Access-Control-Allow-Origin": "*"
2278
2407
  });
2279
- sendSSE(res, "connected", { timestamp: Date.now() });
2408
+ writeSSEEvent(res, "connected", { timestamp: Date.now() });
2280
2409
  const manager = new SSEConnectionManager(options, (event) => {
2281
2410
  if ("id" in event) {
2282
- sendSSE(res, "rpc-response", event);
2411
+ writeSSEEvent(res, "rpc-response", event);
2283
2412
  } else if ("type" in event && "sessionId" in event) {
2284
- sendSSE(res, "connection", event);
2413
+ writeSSEEvent(res, "connection", event);
2285
2414
  } else {
2286
- sendSSE(res, "observability", event);
2415
+ writeSSEEvent(res, "observability", event);
2287
2416
  }
2288
2417
  });
2289
- req.on("close", () => {
2290
- manager.dispose();
2291
- });
2418
+ req.on("close", () => manager.dispose());
2292
2419
  if (req.method === "POST") {
2293
2420
  let body = "";
2294
2421
  req.on("data", (chunk) => {
@@ -2298,14 +2425,13 @@ function createSSEHandler(options) {
2298
2425
  try {
2299
2426
  const request = JSON.parse(body);
2300
2427
  await manager.handleRequest(request);
2301
- } catch (error) {
2302
- console.error("[SSE] Error handling request:", error);
2428
+ } catch {
2303
2429
  }
2304
2430
  });
2305
2431
  }
2306
2432
  };
2307
2433
  }
2308
- function sendSSE(res, event, data) {
2434
+ function writeSSEEvent(res, event, data) {
2309
2435
  res.write(`event: ${event}
2310
2436
  `);
2311
2437
  res.write(`data: ${JSON.stringify(data)}
@@ -2340,7 +2466,7 @@ function createNextMcpHandler(options = {}) {
2340
2466
  const stream = new TransformStream();
2341
2467
  const writer = stream.writable.getWriter();
2342
2468
  const encoder = new TextEncoder();
2343
- const sendSSE2 = (event, data) => {
2469
+ const sendSSE = (event, data) => {
2344
2470
  const message = `event: ${event}
2345
2471
  data: ${JSON.stringify(data)}
2346
2472
 
@@ -2348,7 +2474,6 @@ data: ${JSON.stringify(data)}
2348
2474
  writer.write(encoder.encode(message)).catch(() => {
2349
2475
  });
2350
2476
  };
2351
- sendSSE2("connected", { timestamp: Date.now() });
2352
2477
  const previousManager = managers.get(identity);
2353
2478
  if (previousManager) {
2354
2479
  previousManager.dispose();
@@ -2363,15 +2488,16 @@ data: ${JSON.stringify(data)}
2363
2488
  },
2364
2489
  (event) => {
2365
2490
  if ("id" in event) {
2366
- sendSSE2("rpc-response", event);
2491
+ sendSSE("rpc-response", event);
2367
2492
  } else if ("type" in event && "sessionId" in event) {
2368
- sendSSE2("connection", event);
2493
+ sendSSE("connection", event);
2369
2494
  } else {
2370
- sendSSE2("observability", event);
2495
+ sendSSE("observability", event);
2371
2496
  }
2372
2497
  }
2373
2498
  );
2374
2499
  managers.set(identity, manager);
2500
+ sendSSE("connected", { timestamp: Date.now() });
2375
2501
  const abortController = new AbortController();
2376
2502
  request.signal?.addEventListener("abort", () => {
2377
2503
  manager.dispose();
@@ -2414,8 +2540,8 @@ data: ${JSON.stringify(data)}
2414
2540
  { status: 400 }
2415
2541
  );
2416
2542
  }
2417
- await manager.handleRequest(body);
2418
- return Response.json({ acknowledged: true });
2543
+ const response = await manager.handleRequest(body);
2544
+ return Response.json(response);
2419
2545
  } catch (error) {
2420
2546
  return Response.json(
2421
2547
  {