@mcp-ts/sdk 1.3.3 → 1.3.5

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 (58) hide show
  1. package/README.md +404 -405
  2. package/dist/adapters/agui-adapter.d.mts +1 -1
  3. package/dist/adapters/agui-adapter.d.ts +1 -1
  4. package/dist/adapters/agui-middleware.d.mts +1 -1
  5. package/dist/adapters/agui-middleware.d.ts +1 -1
  6. package/dist/adapters/ai-adapter.d.mts +1 -1
  7. package/dist/adapters/ai-adapter.d.ts +1 -1
  8. package/dist/adapters/langchain-adapter.d.mts +1 -1
  9. package/dist/adapters/langchain-adapter.d.ts +1 -1
  10. package/dist/adapters/mastra-adapter.d.mts +1 -1
  11. package/dist/adapters/mastra-adapter.d.ts +1 -1
  12. package/dist/client/index.d.mts +1 -0
  13. package/dist/client/index.d.ts +1 -0
  14. package/dist/client/index.js +14 -5
  15. package/dist/client/index.js.map +1 -1
  16. package/dist/client/index.mjs +14 -5
  17. package/dist/client/index.mjs.map +1 -1
  18. package/dist/client/react.js +15 -6
  19. package/dist/client/react.js.map +1 -1
  20. package/dist/client/react.mjs +15 -6
  21. package/dist/client/react.mjs.map +1 -1
  22. package/dist/client/vue.js +15 -6
  23. package/dist/client/vue.js.map +1 -1
  24. package/dist/client/vue.mjs +15 -6
  25. package/dist/client/vue.mjs.map +1 -1
  26. package/dist/index.d.mts +1 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.js +201 -158
  29. package/dist/index.js.map +1 -1
  30. package/dist/index.mjs +201 -158
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/{multi-session-client-FAFpUzZ4.d.ts → multi-session-client-BYLarghq.d.ts} +29 -19
  33. package/dist/{multi-session-client-DzjmT7FX.d.mts → multi-session-client-CzhMkE0k.d.mts} +29 -19
  34. package/dist/server/index.d.mts +1 -1
  35. package/dist/server/index.d.ts +1 -1
  36. package/dist/server/index.js +193 -151
  37. package/dist/server/index.js.map +1 -1
  38. package/dist/server/index.mjs +193 -151
  39. package/dist/server/index.mjs.map +1 -1
  40. package/dist/shared/index.d.mts +2 -2
  41. package/dist/shared/index.d.ts +2 -2
  42. package/dist/shared/index.js +2 -2
  43. package/dist/shared/index.js.map +1 -1
  44. package/dist/shared/index.mjs +2 -2
  45. package/dist/shared/index.mjs.map +1 -1
  46. package/package.json +1 -1
  47. package/src/client/core/sse-client.ts +371 -354
  48. package/src/client/react/use-mcp.ts +31 -31
  49. package/src/client/vue/use-mcp.ts +77 -77
  50. package/src/server/handlers/nextjs-handler.ts +194 -197
  51. package/src/server/handlers/sse-handler.ts +62 -111
  52. package/src/server/mcp/oauth-client.ts +67 -79
  53. package/src/server/mcp/storage-oauth-provider.ts +71 -38
  54. package/src/server/storage/index.ts +15 -13
  55. package/src/server/storage/redis-backend.ts +93 -23
  56. package/src/server/storage/types.ts +12 -12
  57. package/src/shared/constants.ts +2 -2
  58. package/src/shared/event-routing.ts +28 -0
@@ -137,6 +137,14 @@ var init_redis = __esm({
137
137
  var SESSION_TTL_SECONDS = 43200;
138
138
  var STATE_EXPIRATION_MS = 10 * 60 * 1e3;
139
139
  var TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
140
+ var DEFAULT_CLIENT_NAME = "MCP Assistant";
141
+ var DEFAULT_CLIENT_URI = "https://mcp-assistant.in";
142
+ var DEFAULT_LOGO_URI = "https://mcp-assistant.in/logo.svg";
143
+ var DEFAULT_POLICY_URI = "https://mcp-assistant.in/privacy";
144
+ var SOFTWARE_ID = "@mcp-ts";
145
+ var SOFTWARE_VERSION = "1.3.4";
146
+ var MCP_CLIENT_NAME = "mcp-ts-oauth-client";
147
+ var MCP_CLIENT_VERSION = "2.0";
140
148
 
141
149
  // src/server/storage/redis-backend.ts
142
150
  var firstChar = nanoid.customAlphabet(
@@ -152,6 +160,8 @@ var RedisStorageBackend = class {
152
160
  this.redis = redis2;
153
161
  __publicField(this, "DEFAULT_TTL", SESSION_TTL_SECONDS);
154
162
  __publicField(this, "KEY_PREFIX", "mcp:session:");
163
+ __publicField(this, "IDENTITY_KEY_PREFIX", "mcp:identity:");
164
+ __publicField(this, "IDENTITY_KEY_SUFFIX", ":sessions");
155
165
  }
156
166
  /**
157
167
  * Generates Redis key for a specific session
@@ -165,7 +175,34 @@ var RedisStorageBackend = class {
165
175
  * @private
166
176
  */
167
177
  getIdentityKey(identity) {
168
- return `mcp:identity:${identity}:sessions`;
178
+ return `${this.IDENTITY_KEY_PREFIX}${identity}${this.IDENTITY_KEY_SUFFIX}`;
179
+ }
180
+ parseIdentityFromKey(identityKey) {
181
+ return identityKey.slice(
182
+ this.IDENTITY_KEY_PREFIX.length,
183
+ identityKey.length - this.IDENTITY_KEY_SUFFIX.length
184
+ );
185
+ }
186
+ async scanKeys(pattern) {
187
+ const redis2 = this.redis;
188
+ if (typeof redis2.scan !== "function") {
189
+ return await this.redis.keys(pattern);
190
+ }
191
+ const keys = /* @__PURE__ */ new Set();
192
+ let cursor = "0";
193
+ try {
194
+ do {
195
+ const [nextCursor, batch] = await redis2.scan(cursor, "MATCH", pattern, "COUNT", 100);
196
+ cursor = nextCursor;
197
+ for (const key of batch) {
198
+ keys.add(key);
199
+ }
200
+ } while (cursor !== "0");
201
+ } catch (error) {
202
+ console.warn("[RedisStorage] SCAN failed, falling back to KEYS:", error);
203
+ return await this.redis.keys(pattern);
204
+ }
205
+ return Array.from(keys);
169
206
  }
170
207
  generateSessionId() {
171
208
  return firstChar() + rest();
@@ -233,17 +270,13 @@ var RedisStorageBackend = class {
233
270
  }
234
271
  }
235
272
  async getIdentityMcpSessions(identity) {
236
- const identityKey = this.getIdentityKey(identity);
237
- try {
238
- return await this.redis.smembers(identityKey);
239
- } catch (error) {
240
- console.error(`[RedisStorage] Failed to get sessions for ${identity}:`, error);
241
- return [];
242
- }
273
+ const sessions = await this.getIdentitySessionsData(identity);
274
+ return sessions.map((session) => session.sessionId);
243
275
  }
244
276
  async getIdentitySessionsData(identity) {
245
277
  try {
246
- const sessionIds = await this.redis.smembers(this.getIdentityKey(identity));
278
+ const identityKey = this.getIdentityKey(identity);
279
+ const sessionIds = await this.redis.smembers(identityKey);
247
280
  if (sessionIds.length === 0) return [];
248
281
  const results = await Promise.all(
249
282
  sessionIds.map(async (sessionId) => {
@@ -251,6 +284,10 @@ var RedisStorageBackend = class {
251
284
  return data ? JSON.parse(data) : null;
252
285
  })
253
286
  );
287
+ const staleSessionIds = sessionIds.filter((_, index) => results[index] === null);
288
+ if (staleSessionIds.length > 0) {
289
+ await this.redis.srem(identityKey, ...staleSessionIds);
290
+ }
254
291
  return results.filter((session) => session !== null);
255
292
  } catch (error) {
256
293
  console.error(`[RedisStorage] Failed to get session data for ${identity}:`, error);
@@ -269,9 +306,22 @@ var RedisStorageBackend = class {
269
306
  }
270
307
  async getAllSessionIds() {
271
308
  try {
272
- const pattern = `${this.KEY_PREFIX}*`;
273
- const keys = await this.redis.keys(pattern);
274
- return keys.map((key) => key.replace(this.KEY_PREFIX, ""));
309
+ const keys = await this.scanKeys(`${this.KEY_PREFIX}*`);
310
+ const sessions = await Promise.all(
311
+ keys.map(async (key) => {
312
+ const data = await this.redis.get(key);
313
+ if (!data) {
314
+ return null;
315
+ }
316
+ try {
317
+ return JSON.parse(data).sessionId;
318
+ } catch (error) {
319
+ console.error("[RedisStorage] Failed to parse session while listing all session IDs:", error);
320
+ return null;
321
+ }
322
+ })
323
+ );
324
+ return sessions.filter((sessionId) => sessionId !== null);
275
325
  } catch (error) {
276
326
  console.error("[RedisStorage] Failed to get all sessions:", error);
277
327
  return [];
@@ -279,10 +329,11 @@ var RedisStorageBackend = class {
279
329
  }
280
330
  async clearAll() {
281
331
  try {
282
- const pattern = `${this.KEY_PREFIX}*`;
283
- const keys = await this.redis.keys(pattern);
284
- if (keys.length > 0) {
285
- await this.redis.del(...keys);
332
+ const keys = await this.scanKeys(`${this.KEY_PREFIX}*`);
333
+ const identityKeys = await this.scanKeys(`${this.IDENTITY_KEY_PREFIX}*${this.IDENTITY_KEY_SUFFIX}`);
334
+ const allKeys = [...keys, ...identityKeys];
335
+ if (allKeys.length > 0) {
336
+ await this.redis.del(...allKeys);
286
337
  }
287
338
  } catch (error) {
288
339
  console.error("[RedisStorage] Failed to clear sessions:", error);
@@ -290,12 +341,24 @@ var RedisStorageBackend = class {
290
341
  }
291
342
  async cleanupExpiredSessions() {
292
343
  try {
293
- const pattern = `${this.KEY_PREFIX}*`;
294
- const keys = await this.redis.keys(pattern);
295
- for (const key of keys) {
296
- const ttl = await this.redis.ttl(key);
297
- if (ttl <= 0) {
298
- await this.redis.del(key);
344
+ const identityKeys = await this.scanKeys(`${this.IDENTITY_KEY_PREFIX}*${this.IDENTITY_KEY_SUFFIX}`);
345
+ for (const identityKey of identityKeys) {
346
+ const identity = this.parseIdentityFromKey(identityKey);
347
+ const sessionIds = await this.redis.smembers(identityKey);
348
+ if (sessionIds.length === 0) {
349
+ await this.redis.del(identityKey);
350
+ continue;
351
+ }
352
+ const existenceChecks = await Promise.all(
353
+ sessionIds.map((sessionId) => this.redis.exists(this.getSessionKey(identity, sessionId)))
354
+ );
355
+ const staleSessionIds = sessionIds.filter((_, index) => existenceChecks[index] === 0);
356
+ if (staleSessionIds.length > 0) {
357
+ await this.redis.srem(identityKey, ...staleSessionIds);
358
+ }
359
+ const remainingCount = await this.redis.scard(identityKey);
360
+ if (remainingCount === 0) {
361
+ await this.redis.del(identityKey);
299
362
  }
300
363
  }
301
364
  } catch (error) {
@@ -666,6 +729,12 @@ var SqliteStorage = class {
666
729
  // src/server/storage/index.ts
667
730
  var storageInstance = null;
668
731
  var storagePromise = null;
732
+ async function initializeStorage(store) {
733
+ if (typeof store.init === "function") {
734
+ await store.init();
735
+ }
736
+ return store;
737
+ }
669
738
  async function createStorage() {
670
739
  const type = process.env.MCP_TS_STORAGE_TYPE?.toLowerCase();
671
740
  if (type === "redis") {
@@ -689,16 +758,12 @@ async function createStorage() {
689
758
  console.warn('[Storage] MCP_TS_STORAGE_TYPE is "file" but MCP_TS_STORAGE_FILE is missing');
690
759
  }
691
760
  console.log(`[Storage] Using File storage (${filePath}) (Explicit)`);
692
- const store = new FileStorageBackend({ path: filePath });
693
- store.init().catch((err) => console.error("[Storage] Failed to initialize file storage:", err));
694
- return store;
761
+ return await initializeStorage(new FileStorageBackend({ path: filePath }));
695
762
  }
696
763
  if (type === "sqlite") {
697
764
  const dbPath = process.env.MCP_TS_STORAGE_SQLITE_PATH;
698
765
  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;
766
+ return await initializeStorage(new SqliteStorage({ path: dbPath }));
702
767
  }
703
768
  if (type === "memory") {
704
769
  console.log("[Storage] Using In-Memory storage (Explicit)");
@@ -718,15 +783,11 @@ async function createStorage() {
718
783
  }
719
784
  if (process.env.MCP_TS_STORAGE_FILE) {
720
785
  console.log(`[Storage] Auto-detected MCP_TS_STORAGE_FILE. Using File storage (${process.env.MCP_TS_STORAGE_FILE}).`);
721
- const store = new FileStorageBackend({ path: process.env.MCP_TS_STORAGE_FILE });
722
- store.init().catch((err) => console.error("[Storage] Failed to initialize file storage:", err));
723
- return store;
786
+ return await initializeStorage(new FileStorageBackend({ path: process.env.MCP_TS_STORAGE_FILE }));
724
787
  }
725
788
  if (process.env.MCP_TS_STORAGE_SQLITE_PATH) {
726
789
  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;
790
+ return await initializeStorage(new SqliteStorage({ path: process.env.MCP_TS_STORAGE_SQLITE_PATH }));
730
791
  }
731
792
  console.log("[Storage] No storage configured. Using In-Memory storage (Default).");
732
793
  return new MemoryStorageBackend();
@@ -736,7 +797,10 @@ async function getStorage() {
736
797
  return storageInstance;
737
798
  }
738
799
  if (!storagePromise) {
739
- storagePromise = createStorage();
800
+ storagePromise = createStorage().catch((error) => {
801
+ storagePromise = null;
802
+ throw error;
803
+ });
740
804
  }
741
805
  storageInstance = await storagePromise;
742
806
  return storageInstance;
@@ -757,43 +821,49 @@ var storage = new Proxy({}, {
757
821
  // src/server/mcp/storage-oauth-provider.ts
758
822
  var StorageOAuthClientProvider = class {
759
823
  /**
760
- * Creates a new Storage-backed OAuth provider
761
- * @param identity - User/Client identifier
762
- * @param serverId - Server identifier (for tracking which server this OAuth session belongs to)
763
- * @param sessionId - Session identifier (used as OAuth state)
764
- * @param clientName - OAuth client name
765
- * @param baseRedirectUrl - OAuth callback URL
766
- * @param onRedirect - Optional callback when redirect to authorization is needed
824
+ * Creates a new storage-backed OAuth provider
825
+ * @param options - Provider configuration
767
826
  */
768
- constructor(identity, serverId, sessionId, clientName, baseRedirectUrl, onRedirect) {
769
- this.identity = identity;
770
- this.serverId = serverId;
771
- this.sessionId = sessionId;
772
- this.clientName = clientName;
773
- this.baseRedirectUrl = baseRedirectUrl;
827
+ constructor(options) {
828
+ __publicField(this, "identity");
829
+ __publicField(this, "serverId");
830
+ __publicField(this, "sessionId");
831
+ __publicField(this, "redirectUrl");
832
+ __publicField(this, "clientName");
833
+ __publicField(this, "clientUri");
834
+ __publicField(this, "logoUri");
835
+ __publicField(this, "policyUri");
836
+ __publicField(this, "clientSecret");
774
837
  __publicField(this, "_authUrl");
775
838
  __publicField(this, "_clientId");
776
839
  __publicField(this, "onRedirectCallback");
777
840
  __publicField(this, "tokenExpiresAt");
778
- this.onRedirectCallback = onRedirect;
841
+ this.identity = options.identity;
842
+ this.serverId = options.serverId;
843
+ this.sessionId = options.sessionId;
844
+ this.redirectUrl = options.redirectUrl;
845
+ this.clientName = options.clientName;
846
+ this.clientUri = options.clientUri;
847
+ this.logoUri = options.logoUri;
848
+ this.policyUri = options.policyUri;
849
+ this._clientId = options.clientId;
850
+ this.clientSecret = options.clientSecret;
851
+ this.onRedirectCallback = options.onRedirect;
779
852
  }
780
853
  get clientMetadata() {
781
854
  return {
782
- client_name: this.clientName,
783
- client_uri: this.clientUri,
855
+ client_name: this.clientName || DEFAULT_CLIENT_NAME,
856
+ client_uri: this.clientUri || DEFAULT_CLIENT_URI,
857
+ logo_uri: this.logoUri || DEFAULT_LOGO_URI,
858
+ policy_uri: this.policyUri || DEFAULT_POLICY_URI,
784
859
  grant_types: ["authorization_code", "refresh_token"],
785
860
  redirect_uris: [this.redirectUrl],
786
861
  response_types: ["code"],
787
- token_endpoint_auth_method: "none",
788
- ...this._clientId ? { client_id: this._clientId } : {}
862
+ token_endpoint_auth_method: this.clientSecret ? "client_secret_basic" : "none",
863
+ software_id: SOFTWARE_ID,
864
+ software_version: SOFTWARE_VERSION
789
865
  };
790
866
  }
791
- get clientUri() {
792
- return new URL(this.redirectUrl).origin;
793
- }
794
- get redirectUrl() {
795
- return this.baseRedirectUrl;
796
- }
797
867
  get clientId() {
798
868
  return this._clientId;
799
869
  }
@@ -828,7 +898,16 @@ var StorageOAuthClientProvider = class {
828
898
  if (data.clientId && !this._clientId) {
829
899
  this._clientId = data.clientId;
830
900
  }
831
- return data.clientInformation;
901
+ if (data.clientInformation) {
902
+ return data.clientInformation;
903
+ }
904
+ if (!this._clientId) {
905
+ return void 0;
906
+ }
907
+ return {
908
+ client_id: this._clientId,
909
+ ...this.clientSecret ? { client_secret: this.clientSecret } : {}
910
+ };
832
911
  }
833
912
  /**
834
913
  * Stores OAuth client information
@@ -856,14 +935,14 @@ var StorageOAuthClientProvider = class {
856
935
  async state() {
857
936
  return this.sessionId;
858
937
  }
859
- async checkState(state) {
938
+ async checkState(_state) {
860
939
  const data = await storage.getSession(this.identity, this.sessionId);
861
940
  if (!data) {
862
941
  return { valid: false, error: "Session not found" };
863
942
  }
864
943
  return { valid: true, serverId: this.serverId };
865
944
  }
866
- async consumeState(state) {
945
+ async consumeState(_state) {
867
946
  }
868
947
  async redirectToAuthorization(authUrl) {
869
948
  this._authUrl = authUrl.toString();
@@ -875,7 +954,6 @@ var StorageOAuthClientProvider = class {
875
954
  if (scope === "all") {
876
955
  await storage.removeSession(this.identity, this.sessionId);
877
956
  } else {
878
- await this.getSessionData();
879
957
  const updates = {};
880
958
  if (scope === "client") {
881
959
  updates.clientInformation = void 0;
@@ -1195,41 +1273,33 @@ var MCPClient = class _MCPClient {
1195
1273
  if (!this.serverUrl || !this.callbackUrl || !this.serverId) {
1196
1274
  throw new Error("Missing required connection metadata");
1197
1275
  }
1198
- const clientMetadata = {
1199
- client_name: this.clientName || "MCP Assistant",
1200
- redirect_uris: [this.callbackUrl],
1201
- token_endpoint_auth_method: this.clientSecret ? "client_secret_basic" : "none",
1202
- client_uri: this.clientUri || "https://mcp-assistant.in",
1203
- logo_uri: this.logoUri || "https://mcp-assistant.in/logo.png",
1204
- policy_uri: this.policyUri || "https://mcp-assistant.in/privacy",
1205
- ...this.clientId ? { client_id: this.clientId } : {},
1206
- ...this.clientSecret ? { client_secret: this.clientSecret } : {}
1207
- };
1208
1276
  if (!this.oauthProvider) {
1209
1277
  if (!this.serverId) {
1210
1278
  throw new Error("serverId required for OAuth provider initialization");
1211
1279
  }
1212
- this.oauthProvider = new StorageOAuthClientProvider(
1213
- this.identity,
1214
- this.serverId,
1215
- this.sessionId,
1216
- clientMetadata.client_name ?? "MCP Assistant",
1217
- this.callbackUrl,
1218
- (redirectUrl) => {
1280
+ this.oauthProvider = new StorageOAuthClientProvider({
1281
+ identity: this.identity,
1282
+ serverId: this.serverId,
1283
+ sessionId: this.sessionId,
1284
+ redirectUrl: this.callbackUrl,
1285
+ clientName: this.clientName,
1286
+ clientUri: this.clientUri,
1287
+ logoUri: this.logoUri,
1288
+ policyUri: this.policyUri,
1289
+ clientId: this.clientId,
1290
+ clientSecret: this.clientSecret,
1291
+ onRedirect: (redirectUrl) => {
1219
1292
  if (this.onRedirect) {
1220
1293
  this.onRedirect(redirectUrl);
1221
1294
  }
1222
1295
  }
1223
- );
1224
- if (this.clientId && this.oauthProvider) {
1225
- this.oauthProvider.clientId = this.clientId;
1226
- }
1296
+ });
1227
1297
  }
1228
1298
  if (!this.client) {
1229
1299
  this.client = new index_js.Client(
1230
1300
  {
1231
- name: "mcp-ts-oauth-client",
1232
- version: "2.0"
1301
+ name: MCP_CLIENT_NAME,
1302
+ version: MCP_CLIENT_VERSION
1233
1303
  },
1234
1304
  {
1235
1305
  capabilities: {
@@ -1424,8 +1494,8 @@ var MCPClient = class _MCPClient {
1424
1494
  this.emitProgress("Creating authenticated client...");
1425
1495
  this.client = new index_js.Client(
1426
1496
  {
1427
- name: "mcp-ts-oauth-client",
1428
- version: "2.0"
1497
+ name: MCP_CLIENT_NAME,
1498
+ version: MCP_CLIENT_VERSION
1429
1499
  },
1430
1500
  {
1431
1501
  capabilities: {
@@ -1720,8 +1790,8 @@ var MCPClient = class _MCPClient {
1720
1790
  }
1721
1791
  this.client = new index_js.Client(
1722
1792
  {
1723
- name: "mcp-ts-oauth-client",
1724
- version: "2.0"
1793
+ name: MCP_CLIENT_NAME,
1794
+ version: MCP_CLIENT_VERSION
1725
1795
  },
1726
1796
  { capabilities: {} }
1727
1797
  );
@@ -1990,6 +2060,27 @@ var MultiSessionClient = class {
1990
2060
  }
1991
2061
  };
1992
2062
 
2063
+ // src/shared/event-routing.ts
2064
+ function isRpcResponseEvent(event) {
2065
+ return "id" in event && ("result" in event || "error" in event);
2066
+ }
2067
+ function isConnectionEvent(event) {
2068
+ if (!("type" in event)) {
2069
+ return false;
2070
+ }
2071
+ switch (event.type) {
2072
+ case "state_changed":
2073
+ case "tools_discovered":
2074
+ case "auth_required":
2075
+ case "error":
2076
+ case "disconnected":
2077
+ case "progress":
2078
+ return true;
2079
+ default:
2080
+ return false;
2081
+ }
2082
+ }
2083
+
1993
2084
  // src/server/handlers/sse-handler.ts
1994
2085
  var DEFAULT_HEARTBEAT_INTERVAL = 3e4;
1995
2086
  var SSEConnectionManager = class {
@@ -2132,16 +2223,6 @@ var SSEConnectionManager = class {
2132
2223
  throw new Error(`Connection already exists for server: ${duplicate.serverUrl || duplicate.serverId} (${duplicate.serverName})`);
2133
2224
  }
2134
2225
  const sessionId = await storage.generateSessionId();
2135
- this.emitConnectionEvent({
2136
- type: "state_changed",
2137
- sessionId,
2138
- serverId,
2139
- serverName,
2140
- serverUrl,
2141
- state: "CONNECTING",
2142
- previousState: "DISCONNECTED",
2143
- timestamp: Date.now()
2144
- });
2145
2226
  try {
2146
2227
  const clientMetadata = await this.getResolvedClientMetadata();
2147
2228
  const client = new MCPClient({
@@ -2152,17 +2233,8 @@ var SSEConnectionManager = class {
2152
2233
  serverUrl,
2153
2234
  callbackUrl,
2154
2235
  transportType,
2155
- ...clientMetadata,
2236
+ ...clientMetadata
2156
2237
  // Spread client metadata (clientName, clientUri, logoUri, policyUri)
2157
- onRedirect: (authUrl) => {
2158
- this.emitConnectionEvent({
2159
- type: "auth_required",
2160
- sessionId,
2161
- serverId,
2162
- authUrl,
2163
- timestamp: Date.now()
2164
- });
2165
- }
2166
2238
  });
2167
2239
  this.clients.set(sessionId, client);
2168
2240
  client.onConnectionEvent((event) => {
@@ -2172,20 +2244,19 @@ var SSEConnectionManager = class {
2172
2244
  this.sendEvent(event);
2173
2245
  });
2174
2246
  await client.connect();
2175
- const tools = await client.listTools();
2176
- this.emitConnectionEvent({
2177
- type: "tools_discovered",
2178
- sessionId,
2179
- serverId,
2180
- toolCount: tools.tools.length,
2181
- tools: tools.tools,
2182
- timestamp: Date.now()
2183
- });
2247
+ await client.listTools();
2184
2248
  return {
2185
2249
  sessionId,
2186
2250
  success: true
2187
2251
  };
2188
2252
  } catch (error) {
2253
+ if (error instanceof UnauthorizedError) {
2254
+ this.clients.delete(sessionId);
2255
+ return {
2256
+ sessionId,
2257
+ success: true
2258
+ };
2259
+ }
2189
2260
  this.emitConnectionEvent({
2190
2261
  type: "error",
2191
2262
  sessionId,
@@ -2287,14 +2358,6 @@ var SSEConnectionManager = class {
2287
2358
  await client.connect();
2288
2359
  this.clients.set(sessionId, client);
2289
2360
  const tools = await client.listTools();
2290
- this.emitConnectionEvent({
2291
- type: "tools_discovered",
2292
- sessionId,
2293
- serverId: session.serverId ?? "unknown",
2294
- toolCount: tools.tools.length,
2295
- tools: tools.tools,
2296
- timestamp: Date.now()
2297
- });
2298
2361
  return { success: true, toolCount: tools.tools.length };
2299
2362
  } catch (error) {
2300
2363
  this.emitConnectionEvent({
@@ -2317,16 +2380,6 @@ var SSEConnectionManager = class {
2317
2380
  if (!session) {
2318
2381
  throw new Error("Session not found");
2319
2382
  }
2320
- this.emitConnectionEvent({
2321
- type: "state_changed",
2322
- sessionId,
2323
- serverId: session.serverId ?? "unknown",
2324
- serverName: session.serverName ?? "Unknown",
2325
- serverUrl: session.serverUrl,
2326
- state: "AUTHENTICATING",
2327
- previousState: "DISCONNECTED",
2328
- timestamp: Date.now()
2329
- });
2330
2383
  try {
2331
2384
  const client = new MCPClient({
2332
2385
  identity: this.identity,
@@ -2336,14 +2389,6 @@ var SSEConnectionManager = class {
2336
2389
  await client.finishAuth(code);
2337
2390
  this.clients.set(sessionId, client);
2338
2391
  const tools = await client.listTools();
2339
- this.emitConnectionEvent({
2340
- type: "tools_discovered",
2341
- sessionId,
2342
- serverId: session.serverId ?? "unknown",
2343
- toolCount: tools.tools.length,
2344
- tools: tools.tools,
2345
- timestamp: Date.now()
2346
- });
2347
2392
  return { success: true, toolCount: tools.tools.length };
2348
2393
  } catch (error) {
2349
2394
  this.emitConnectionEvent({
@@ -2421,9 +2466,9 @@ function createSSEHandler(options) {
2421
2466
  });
2422
2467
  writeSSEEvent(res, "connected", { timestamp: Date.now() });
2423
2468
  const manager = new SSEConnectionManager(options, (event) => {
2424
- if ("id" in event) {
2469
+ if (isRpcResponseEvent(event)) {
2425
2470
  writeSSEEvent(res, "rpc-response", event);
2426
- } else if ("type" in event && "sessionId" in event) {
2471
+ } else if (isConnectionEvent(event)) {
2427
2472
  writeSSEEvent(res, "connection", event);
2428
2473
  } else {
2429
2474
  writeSSEEvent(res, "observability", event);
@@ -2454,9 +2499,6 @@ function writeSSEEvent(res, event, data) {
2454
2499
  }
2455
2500
 
2456
2501
  // src/server/handlers/nextjs-handler.ts
2457
- function isRpcResponseEvent(event) {
2458
- return "id" in event && ("result" in event || "error" in event);
2459
- }
2460
2502
  function createNextMcpHandler(options = {}) {
2461
2503
  const {
2462
2504
  getIdentity = (request) => new URL(request.url).searchParams.get("identity"),
@@ -2547,7 +2589,7 @@ data: ${JSON.stringify(data)}
2547
2589
  (event) => {
2548
2590
  if (isRpcResponseEvent(event)) {
2549
2591
  sendSSE("rpc-response", event);
2550
- } else if ("type" in event && "sessionId" in event) {
2592
+ } else if (isConnectionEvent(event)) {
2551
2593
  sendSSE("connection", event);
2552
2594
  } else {
2553
2595
  sendSSE("observability", event);