@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
@@ -4,6 +4,7 @@ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/
4
4
  import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
5
5
  import { UnauthorizedError as UnauthorizedError$1, discoverOAuthProtectedResourceMetadata, discoverAuthorizationServerMetadata, refreshAuthorization } from '@modelcontextprotocol/sdk/client/auth.js';
6
6
  import { ListToolsResultSchema, CallToolResultSchema, ListPromptsResultSchema, GetPromptResultSchema, ListResourcesResultSchema, ReadResourceResultSchema } from '@modelcontextprotocol/sdk/types.js';
7
+ import * as fs2 from 'fs';
7
8
  import { promises } from 'fs';
8
9
  import * as path from 'path';
9
10
 
@@ -497,6 +498,148 @@ var FileStorageBackend = class {
497
498
  async disconnect() {
498
499
  }
499
500
  };
501
+ var SqliteStorage = class {
502
+ constructor(options = {}) {
503
+ __publicField(this, "db", null);
504
+ __publicField(this, "table");
505
+ __publicField(this, "initialized", false);
506
+ __publicField(this, "dbPath");
507
+ this.dbPath = options.path || "./sessions.db";
508
+ this.table = options.table || "mcp_sessions";
509
+ }
510
+ async init() {
511
+ if (this.initialized) return;
512
+ try {
513
+ const DatabaseConstructor = (await import('better-sqlite3')).default;
514
+ const dir = path.dirname(this.dbPath);
515
+ if (!fs2.existsSync(dir)) {
516
+ fs2.mkdirSync(dir, { recursive: true });
517
+ }
518
+ this.db = new DatabaseConstructor(this.dbPath);
519
+ this.db.exec(`
520
+ CREATE TABLE IF NOT EXISTS ${this.table} (
521
+ sessionId TEXT PRIMARY KEY,
522
+ identity TEXT NOT NULL,
523
+ data TEXT NOT NULL,
524
+ expiresAt INTEGER
525
+ );
526
+ CREATE INDEX IF NOT EXISTS idx_${this.table}_identity ON ${this.table}(identity);
527
+ `);
528
+ this.initialized = true;
529
+ } catch (error) {
530
+ if (error.code === "MODULE_NOT_FOUND" || error.message?.includes("better-sqlite3")) {
531
+ throw new Error(
532
+ "better-sqlite3 is not installed. Please install it with: npm install better-sqlite3"
533
+ );
534
+ }
535
+ throw error;
536
+ }
537
+ }
538
+ ensureInitialized() {
539
+ if (!this.initialized) {
540
+ throw new Error("SqliteStorage not initialized. Call init() first.");
541
+ }
542
+ }
543
+ generateSessionId() {
544
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
545
+ let result = "";
546
+ for (let i = 0; i < 32; i++) {
547
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
548
+ }
549
+ return result;
550
+ }
551
+ async createSession(session, ttl) {
552
+ this.ensureInitialized();
553
+ const { sessionId, identity } = session;
554
+ if (!sessionId || !identity) {
555
+ throw new Error("identity and sessionId required");
556
+ }
557
+ const expiresAt = ttl ? Date.now() + ttl * 1e3 : null;
558
+ try {
559
+ const stmt = this.db.prepare(
560
+ `INSERT INTO ${this.table} (sessionId, identity, data, expiresAt) VALUES (?, ?, ?, ?)`
561
+ );
562
+ stmt.run(sessionId, identity, JSON.stringify(session), expiresAt);
563
+ } catch (error) {
564
+ if (error.code === "SQLITE_CONSTRAINT_PRIMARYKEY") {
565
+ throw new Error(`Session ${sessionId} already exists`);
566
+ }
567
+ throw error;
568
+ }
569
+ }
570
+ async updateSession(identity, sessionId, data, ttl) {
571
+ this.ensureInitialized();
572
+ if (!sessionId || !identity) {
573
+ throw new Error("identity and sessionId required");
574
+ }
575
+ const currentSession = await this.getSession(identity, sessionId);
576
+ if (!currentSession) {
577
+ throw new Error(`Session ${sessionId} not found for identity ${identity}`);
578
+ }
579
+ const updatedSession = { ...currentSession, ...data };
580
+ const expiresAt = ttl ? Date.now() + ttl * 1e3 : null;
581
+ const stmt = this.db.prepare(
582
+ `UPDATE ${this.table} SET data = ?, expiresAt = ? WHERE sessionId = ? AND identity = ?`
583
+ );
584
+ stmt.run(JSON.stringify(updatedSession), expiresAt, sessionId, identity);
585
+ }
586
+ async getSession(identity, sessionId) {
587
+ this.ensureInitialized();
588
+ const stmt = this.db.prepare(
589
+ `SELECT data FROM ${this.table} WHERE sessionId = ? AND identity = ?`
590
+ );
591
+ const row = stmt.get(sessionId, identity);
592
+ if (!row) return null;
593
+ return JSON.parse(row.data);
594
+ }
595
+ async getIdentitySessionsData(identity) {
596
+ this.ensureInitialized();
597
+ const stmt = this.db.prepare(
598
+ `SELECT data FROM ${this.table} WHERE identity = ?`
599
+ );
600
+ const rows = stmt.all(identity);
601
+ return rows.map((row) => JSON.parse(row.data));
602
+ }
603
+ async getIdentityMcpSessions(identity) {
604
+ this.ensureInitialized();
605
+ const stmt = this.db.prepare(
606
+ `SELECT sessionId FROM ${this.table} WHERE identity = ?`
607
+ );
608
+ const rows = stmt.all(identity);
609
+ return rows.map((row) => row.sessionId);
610
+ }
611
+ async removeSession(identity, sessionId) {
612
+ this.ensureInitialized();
613
+ const stmt = this.db.prepare(
614
+ `DELETE FROM ${this.table} WHERE sessionId = ? AND identity = ?`
615
+ );
616
+ stmt.run(sessionId, identity);
617
+ }
618
+ async getAllSessionIds() {
619
+ this.ensureInitialized();
620
+ const stmt = this.db.prepare(`SELECT sessionId FROM ${this.table}`);
621
+ const rows = stmt.all();
622
+ return rows.map((row) => row.sessionId);
623
+ }
624
+ async clearAll() {
625
+ this.ensureInitialized();
626
+ const stmt = this.db.prepare(`DELETE FROM ${this.table}`);
627
+ stmt.run();
628
+ }
629
+ async cleanupExpiredSessions() {
630
+ this.ensureInitialized();
631
+ const now = Date.now();
632
+ const stmt = this.db.prepare(
633
+ `DELETE FROM ${this.table} WHERE expiresAt IS NOT NULL AND expiresAt < ?`
634
+ );
635
+ stmt.run(now);
636
+ }
637
+ async disconnect() {
638
+ if (this.db) {
639
+ this.db.close();
640
+ }
641
+ }
642
+ };
500
643
 
501
644
  // src/server/storage/index.ts
502
645
  var storageInstance = null;
@@ -528,6 +671,13 @@ async function createStorage() {
528
671
  store.init().catch((err) => console.error("[Storage] Failed to initialize file storage:", err));
529
672
  return store;
530
673
  }
674
+ if (type === "sqlite") {
675
+ const dbPath = process.env.MCP_TS_STORAGE_SQLITE_PATH;
676
+ console.log(`[Storage] Using SQLite storage (${dbPath || "default"}) (Explicit)`);
677
+ const store = new SqliteStorage({ path: dbPath });
678
+ store.init().catch((err) => console.error("[Storage] Failed to initialize SQLite storage:", err));
679
+ return store;
680
+ }
531
681
  if (type === "memory") {
532
682
  console.log("[Storage] Using In-Memory storage (Explicit)");
533
683
  return new MemoryStorageBackend();
@@ -550,6 +700,12 @@ async function createStorage() {
550
700
  store.init().catch((err) => console.error("[Storage] Failed to initialize file storage:", err));
551
701
  return store;
552
702
  }
703
+ if (process.env.MCP_TS_STORAGE_SQLITE_PATH) {
704
+ console.log(`[Storage] Auto-detected MCP_TS_STORAGE_SQLITE_PATH. Using SQLite storage (${process.env.MCP_TS_STORAGE_SQLITE_PATH}).`);
705
+ const store = new SqliteStorage({ path: process.env.MCP_TS_STORAGE_SQLITE_PATH });
706
+ store.init().catch((err) => console.error("[Storage] Failed to initialize SQLite storage:", err));
707
+ return store;
708
+ }
553
709
  console.log("[Storage] No storage configured. Using In-Memory storage (Default).");
554
710
  return new MemoryStorageBackend();
555
711
  }
@@ -1057,7 +1213,15 @@ var MCPClient = class _MCPClient {
1057
1213
  name: "mcp-ts-oauth-client",
1058
1214
  version: "2.0"
1059
1215
  },
1060
- { capabilities: {} }
1216
+ {
1217
+ capabilities: {
1218
+ extensions: {
1219
+ "io.modelcontextprotocol/ui": {
1220
+ mimeTypes: ["text/html+mcp"]
1221
+ }
1222
+ }
1223
+ }
1224
+ }
1061
1225
  );
1062
1226
  }
1063
1227
  const existingSession = await storage.getSession(this.identity, this.sessionId);
@@ -1239,7 +1403,15 @@ var MCPClient = class _MCPClient {
1239
1403
  name: "mcp-ts-oauth-client",
1240
1404
  version: "2.0"
1241
1405
  },
1242
- { capabilities: {} }
1406
+ {
1407
+ capabilities: {
1408
+ extensions: {
1409
+ "io.modelcontextprotocol/ui": {
1410
+ mimeTypes: ["text/html+mcp"]
1411
+ }
1412
+ }
1413
+ }
1414
+ }
1243
1415
  );
1244
1416
  this.emitStateChange("CONNECTING");
1245
1417
  await this.client.connect(this.transport);
@@ -1795,6 +1967,7 @@ var MultiSessionClient = class {
1795
1967
  };
1796
1968
 
1797
1969
  // src/server/handlers/sse-handler.ts
1970
+ var DEFAULT_HEARTBEAT_INTERVAL = 3e4;
1798
1971
  var SSEConnectionManager = class {
1799
1972
  constructor(options, sendEvent) {
1800
1973
  this.options = options;
@@ -1824,7 +1997,7 @@ var SSEConnectionManager = class {
1824
1997
  * Start heartbeat to keep connection alive
1825
1998
  */
1826
1999
  startHeartbeat() {
1827
- const interval = this.options.heartbeatInterval || 3e4;
2000
+ const interval = this.options.heartbeatInterval ?? DEFAULT_HEARTBEAT_INTERVAL;
1828
2001
  this.heartbeatTimer = setInterval(() => {
1829
2002
  if (this.isActive) {
1830
2003
  this.sendEvent({
@@ -1837,6 +2010,7 @@ var SSEConnectionManager = class {
1837
2010
  }
1838
2011
  /**
1839
2012
  * Handle incoming RPC requests
2013
+ * Returns the RPC response directly for immediate HTTP response (bypassing SSE latency)
1840
2014
  */
1841
2015
  async handleRequest(request) {
1842
2016
  try {
@@ -1878,39 +2052,29 @@ var SSEConnectionManager = class {
1878
2052
  default:
1879
2053
  throw new Error(`Unknown method: ${request.method}`);
1880
2054
  }
1881
- this.sendEvent({
2055
+ const response = {
1882
2056
  id: request.id,
1883
2057
  result
1884
- });
2058
+ };
2059
+ this.sendEvent(response);
2060
+ return response;
1885
2061
  } catch (error) {
1886
- this.sendEvent({
2062
+ const errorResponse = {
1887
2063
  id: request.id,
1888
2064
  error: {
1889
2065
  code: RpcErrorCodes.EXECUTION_ERROR,
1890
2066
  message: error instanceof Error ? error.message : "Unknown error"
1891
2067
  }
1892
- });
2068
+ };
2069
+ this.sendEvent(errorResponse);
2070
+ return errorResponse;
1893
2071
  }
1894
2072
  }
1895
2073
  /**
1896
- * Get all user sessions
2074
+ * Get all sessions for the current identity
1897
2075
  */
1898
2076
  async getSessions() {
1899
2077
  const sessions = await storage.getIdentitySessionsData(this.identity);
1900
- this.sendEvent({
1901
- level: "debug",
1902
- message: `Retrieved ${sessions.length} sessions for identity ${this.identity}`,
1903
- timestamp: Date.now(),
1904
- metadata: {
1905
- identity: this.identity,
1906
- sessionCount: sessions.length,
1907
- sessions: sessions.map((s) => ({
1908
- sessionId: s.sessionId,
1909
- serverId: s.serverId,
1910
- serverName: s.serverName
1911
- }))
1912
- }
1913
- });
1914
2078
  return {
1915
2079
  sessions: sessions.map((s) => ({
1916
2080
  sessionId: s.sessionId,
@@ -1925,7 +2089,8 @@ var SSEConnectionManager = class {
1925
2089
  * Connect to an MCP server
1926
2090
  */
1927
2091
  async connect(params) {
1928
- const { serverId, serverName, serverUrl, callbackUrl, transportType } = params;
2092
+ const { serverName, serverUrl, callbackUrl, transportType } = params;
2093
+ const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : await storage.generateSessionId();
1929
2094
  const existingSessions = await storage.getIdentitySessionsData(this.identity);
1930
2095
  const duplicate = existingSessions.find(
1931
2096
  (s) => s.serverId === serverId || s.serverUrl === serverUrl
@@ -1974,10 +2139,6 @@ var SSEConnectionManager = class {
1974
2139
  });
1975
2140
  await client.connect();
1976
2141
  const tools = await client.listTools();
1977
- const sessionAfterConnect = await storage.getSession(this.identity, sessionId);
1978
- console.log(`[SSE Handler] After connect() - Session ${sessionId}:`, {
1979
- serverId: sessionAfterConnect?.serverId
1980
- });
1981
2142
  this.emitConnectionEvent({
1982
2143
  type: "tools_discovered",
1983
2144
  sessionId,
@@ -2019,24 +2180,21 @@ var SSEConnectionManager = class {
2019
2180
  return { success: true };
2020
2181
  }
2021
2182
  /**
2022
- * Helper to get or restore a client
2183
+ * Get an existing client or create and connect a new one for the session.
2023
2184
  */
2024
2185
  async getOrCreateClient(sessionId) {
2025
- let client = this.clients.get(sessionId);
2026
- if (!client) {
2027
- client = new MCPClient({
2028
- identity: this.identity,
2029
- sessionId
2030
- });
2031
- client.onConnectionEvent((event) => {
2032
- this.emitConnectionEvent(event);
2033
- });
2034
- client.onObservabilityEvent((event) => {
2035
- this.sendEvent(event);
2036
- });
2037
- await client.connect();
2038
- this.clients.set(sessionId, client);
2186
+ const existing = this.clients.get(sessionId);
2187
+ if (existing) {
2188
+ return existing;
2039
2189
  }
2190
+ const client = new MCPClient({
2191
+ identity: this.identity,
2192
+ sessionId
2193
+ });
2194
+ client.onConnectionEvent((event) => this.emitConnectionEvent(event));
2195
+ client.onObservabilityEvent((event) => this.sendEvent(event));
2196
+ await client.connect();
2197
+ this.clients.set(sessionId, client);
2040
2198
  return client;
2041
2199
  }
2042
2200
  /**
@@ -2049,51 +2207,35 @@ var SSEConnectionManager = class {
2049
2207
  return { tools: result.tools };
2050
2208
  }
2051
2209
  /**
2052
- * Call a tool
2210
+ * Call a tool on the MCP server
2053
2211
  */
2054
2212
  async callTool(params) {
2055
2213
  const { sessionId, toolName, toolArgs } = params;
2056
2214
  const client = await this.getOrCreateClient(sessionId);
2057
- return await client.callTool(toolName, toolArgs);
2215
+ const result = await client.callTool(toolName, toolArgs);
2216
+ const meta = result._meta || {};
2217
+ return {
2218
+ ...result,
2219
+ _meta: {
2220
+ ...meta,
2221
+ sessionId
2222
+ }
2223
+ };
2058
2224
  }
2059
2225
  /**
2060
- * Refresh/validate a session
2226
+ * Restore and validate an existing session
2061
2227
  */
2062
2228
  async restoreSession(params) {
2063
2229
  const { sessionId } = params;
2064
- this.sendEvent({
2065
- level: "debug",
2066
- message: `Starting session refresh for ${sessionId}`,
2067
- timestamp: Date.now(),
2068
- metadata: { sessionId, identity: this.identity }
2069
- });
2070
2230
  const session = await storage.getSession(this.identity, sessionId);
2071
2231
  if (!session) {
2072
- this.sendEvent({
2073
- level: "error",
2074
- message: `Session not found: ${sessionId}`,
2075
- timestamp: Date.now(),
2076
- metadata: { sessionId, identity: this.identity }
2077
- });
2078
2232
  throw new Error("Session not found");
2079
2233
  }
2080
- this.sendEvent({
2081
- level: "debug",
2082
- message: `Session found in Redis`,
2083
- timestamp: Date.now(),
2084
- metadata: {
2085
- sessionId,
2086
- serverId: session.serverId,
2087
- serverName: session.serverName,
2088
- serverUrl: session.serverUrl,
2089
- transportType: session.transportType
2090
- }
2091
- });
2092
2234
  this.emitConnectionEvent({
2093
2235
  type: "state_changed",
2094
2236
  sessionId,
2095
- serverId: session.serverId || "unknown",
2096
- serverName: session.serverName || "Unknown",
2237
+ serverId: session.serverId ?? "unknown",
2238
+ serverName: session.serverName ?? "Unknown",
2097
2239
  state: "VALIDATING",
2098
2240
  previousState: "DISCONNECTED",
2099
2241
  timestamp: Date.now()
@@ -2104,21 +2246,16 @@ var SSEConnectionManager = class {
2104
2246
  identity: this.identity,
2105
2247
  sessionId,
2106
2248
  ...clientMetadata
2107
- // Include metadata for consistency
2108
- });
2109
- client.onConnectionEvent((event) => {
2110
- this.emitConnectionEvent(event);
2111
- });
2112
- client.onObservabilityEvent((event) => {
2113
- this.sendEvent(event);
2114
2249
  });
2250
+ client.onConnectionEvent((event) => this.emitConnectionEvent(event));
2251
+ client.onObservabilityEvent((event) => this.sendEvent(event));
2115
2252
  await client.connect();
2116
2253
  this.clients.set(sessionId, client);
2117
2254
  const tools = await client.listTools();
2118
2255
  this.emitConnectionEvent({
2119
2256
  type: "tools_discovered",
2120
2257
  sessionId,
2121
- serverId: session.serverId || "unknown",
2258
+ serverId: session.serverId ?? "unknown",
2122
2259
  toolCount: tools.tools.length,
2123
2260
  tools: tools.tools,
2124
2261
  timestamp: Date.now()
@@ -2128,7 +2265,7 @@ var SSEConnectionManager = class {
2128
2265
  this.emitConnectionEvent({
2129
2266
  type: "error",
2130
2267
  sessionId,
2131
- serverId: session.serverId || "unknown",
2268
+ serverId: session.serverId ?? "unknown",
2132
2269
  error: error instanceof Error ? error.message : "Validation failed",
2133
2270
  errorType: "validation",
2134
2271
  timestamp: Date.now()
@@ -2137,16 +2274,10 @@ var SSEConnectionManager = class {
2137
2274
  }
2138
2275
  }
2139
2276
  /**
2140
- * Complete OAuth authorization
2277
+ * Complete OAuth authorization flow
2141
2278
  */
2142
2279
  async finishAuth(params) {
2143
2280
  const { sessionId, code } = params;
2144
- this.sendEvent({
2145
- level: "debug",
2146
- message: `Completing OAuth for session ${sessionId}`,
2147
- timestamp: Date.now(),
2148
- metadata: { sessionId, identity: this.identity }
2149
- });
2150
2281
  const session = await storage.getSession(this.identity, sessionId);
2151
2282
  if (!session) {
2152
2283
  throw new Error("Session not found");
@@ -2154,8 +2285,8 @@ var SSEConnectionManager = class {
2154
2285
  this.emitConnectionEvent({
2155
2286
  type: "state_changed",
2156
2287
  sessionId,
2157
- serverId: session.serverId || "unknown",
2158
- serverName: session.serverName || "Unknown",
2288
+ serverId: session.serverId ?? "unknown",
2289
+ serverName: session.serverName ?? "Unknown",
2159
2290
  state: "AUTHENTICATING",
2160
2291
  previousState: "DISCONNECTED",
2161
2292
  timestamp: Date.now()
@@ -2165,16 +2296,14 @@ var SSEConnectionManager = class {
2165
2296
  identity: this.identity,
2166
2297
  sessionId
2167
2298
  });
2168
- client.onConnectionEvent((event) => {
2169
- this.emitConnectionEvent(event);
2170
- });
2299
+ client.onConnectionEvent((event) => this.emitConnectionEvent(event));
2171
2300
  await client.finishAuth(code);
2172
2301
  this.clients.set(sessionId, client);
2173
2302
  const tools = await client.listTools();
2174
2303
  this.emitConnectionEvent({
2175
2304
  type: "tools_discovered",
2176
2305
  sessionId,
2177
- serverId: session.serverId || "unknown",
2306
+ serverId: session.serverId ?? "unknown",
2178
2307
  toolCount: tools.tools.length,
2179
2308
  tools: tools.tools,
2180
2309
  timestamp: Date.now()
@@ -2184,7 +2313,7 @@ var SSEConnectionManager = class {
2184
2313
  this.emitConnectionEvent({
2185
2314
  type: "error",
2186
2315
  sessionId,
2187
- serverId: session.serverId || "unknown",
2316
+ serverId: session.serverId ?? "unknown",
2188
2317
  error: error instanceof Error ? error.message : "OAuth completion failed",
2189
2318
  errorType: "auth",
2190
2319
  timestamp: Date.now()
@@ -2224,7 +2353,7 @@ var SSEConnectionManager = class {
2224
2353
  async readResource(params) {
2225
2354
  const { sessionId, uri } = params;
2226
2355
  const client = await this.getOrCreateClient(sessionId);
2227
- return await client.readResource(uri);
2356
+ return client.readResource(uri);
2228
2357
  }
2229
2358
  /**
2230
2359
  * Emit connection event
@@ -2254,19 +2383,17 @@ function createSSEHandler(options) {
2254
2383
  "Connection": "keep-alive",
2255
2384
  "Access-Control-Allow-Origin": "*"
2256
2385
  });
2257
- sendSSE(res, "connected", { timestamp: Date.now() });
2386
+ writeSSEEvent(res, "connected", { timestamp: Date.now() });
2258
2387
  const manager = new SSEConnectionManager(options, (event) => {
2259
2388
  if ("id" in event) {
2260
- sendSSE(res, "rpc-response", event);
2389
+ writeSSEEvent(res, "rpc-response", event);
2261
2390
  } else if ("type" in event && "sessionId" in event) {
2262
- sendSSE(res, "connection", event);
2391
+ writeSSEEvent(res, "connection", event);
2263
2392
  } else {
2264
- sendSSE(res, "observability", event);
2393
+ writeSSEEvent(res, "observability", event);
2265
2394
  }
2266
2395
  });
2267
- req.on("close", () => {
2268
- manager.dispose();
2269
- });
2396
+ req.on("close", () => manager.dispose());
2270
2397
  if (req.method === "POST") {
2271
2398
  let body = "";
2272
2399
  req.on("data", (chunk) => {
@@ -2276,14 +2403,13 @@ function createSSEHandler(options) {
2276
2403
  try {
2277
2404
  const request = JSON.parse(body);
2278
2405
  await manager.handleRequest(request);
2279
- } catch (error) {
2280
- console.error("[SSE] Error handling request:", error);
2406
+ } catch {
2281
2407
  }
2282
2408
  });
2283
2409
  }
2284
2410
  };
2285
2411
  }
2286
- function sendSSE(res, event, data) {
2412
+ function writeSSEEvent(res, event, data) {
2287
2413
  res.write(`event: ${event}
2288
2414
  `);
2289
2415
  res.write(`data: ${JSON.stringify(data)}
@@ -2318,7 +2444,7 @@ function createNextMcpHandler(options = {}) {
2318
2444
  const stream = new TransformStream();
2319
2445
  const writer = stream.writable.getWriter();
2320
2446
  const encoder = new TextEncoder();
2321
- const sendSSE2 = (event, data) => {
2447
+ const sendSSE = (event, data) => {
2322
2448
  const message = `event: ${event}
2323
2449
  data: ${JSON.stringify(data)}
2324
2450
 
@@ -2326,7 +2452,6 @@ data: ${JSON.stringify(data)}
2326
2452
  writer.write(encoder.encode(message)).catch(() => {
2327
2453
  });
2328
2454
  };
2329
- sendSSE2("connected", { timestamp: Date.now() });
2330
2455
  const previousManager = managers.get(identity);
2331
2456
  if (previousManager) {
2332
2457
  previousManager.dispose();
@@ -2341,15 +2466,16 @@ data: ${JSON.stringify(data)}
2341
2466
  },
2342
2467
  (event) => {
2343
2468
  if ("id" in event) {
2344
- sendSSE2("rpc-response", event);
2469
+ sendSSE("rpc-response", event);
2345
2470
  } else if ("type" in event && "sessionId" in event) {
2346
- sendSSE2("connection", event);
2471
+ sendSSE("connection", event);
2347
2472
  } else {
2348
- sendSSE2("observability", event);
2473
+ sendSSE("observability", event);
2349
2474
  }
2350
2475
  }
2351
2476
  );
2352
2477
  managers.set(identity, manager);
2478
+ sendSSE("connected", { timestamp: Date.now() });
2353
2479
  const abortController = new AbortController();
2354
2480
  request.signal?.addEventListener("abort", () => {
2355
2481
  manager.dispose();
@@ -2392,8 +2518,8 @@ data: ${JSON.stringify(data)}
2392
2518
  { status: 400 }
2393
2519
  );
2394
2520
  }
2395
- await manager.handleRequest(body);
2396
- return Response.json({ acknowledged: true });
2521
+ const response = await manager.handleRequest(body);
2522
+ return Response.json(response);
2397
2523
  } catch (error) {
2398
2524
  return Response.json(
2399
2525
  {