@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
@@ -115,6 +115,14 @@ var init_redis = __esm({
115
115
  var SESSION_TTL_SECONDS = 43200;
116
116
  var STATE_EXPIRATION_MS = 10 * 60 * 1e3;
117
117
  var TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
118
+ var DEFAULT_CLIENT_NAME = "MCP Assistant";
119
+ var DEFAULT_CLIENT_URI = "https://mcp-assistant.in";
120
+ var DEFAULT_LOGO_URI = "https://mcp-assistant.in/logo.svg";
121
+ var DEFAULT_POLICY_URI = "https://mcp-assistant.in/privacy";
122
+ var SOFTWARE_ID = "@mcp-ts";
123
+ var SOFTWARE_VERSION = "1.3.4";
124
+ var MCP_CLIENT_NAME = "mcp-ts-oauth-client";
125
+ var MCP_CLIENT_VERSION = "2.0";
118
126
 
119
127
  // src/server/storage/redis-backend.ts
120
128
  var firstChar = customAlphabet(
@@ -130,6 +138,8 @@ var RedisStorageBackend = class {
130
138
  this.redis = redis2;
131
139
  __publicField(this, "DEFAULT_TTL", SESSION_TTL_SECONDS);
132
140
  __publicField(this, "KEY_PREFIX", "mcp:session:");
141
+ __publicField(this, "IDENTITY_KEY_PREFIX", "mcp:identity:");
142
+ __publicField(this, "IDENTITY_KEY_SUFFIX", ":sessions");
133
143
  }
134
144
  /**
135
145
  * Generates Redis key for a specific session
@@ -143,7 +153,34 @@ var RedisStorageBackend = class {
143
153
  * @private
144
154
  */
145
155
  getIdentityKey(identity) {
146
- return `mcp:identity:${identity}:sessions`;
156
+ return `${this.IDENTITY_KEY_PREFIX}${identity}${this.IDENTITY_KEY_SUFFIX}`;
157
+ }
158
+ parseIdentityFromKey(identityKey) {
159
+ return identityKey.slice(
160
+ this.IDENTITY_KEY_PREFIX.length,
161
+ identityKey.length - this.IDENTITY_KEY_SUFFIX.length
162
+ );
163
+ }
164
+ async scanKeys(pattern) {
165
+ const redis2 = this.redis;
166
+ if (typeof redis2.scan !== "function") {
167
+ return await this.redis.keys(pattern);
168
+ }
169
+ const keys = /* @__PURE__ */ new Set();
170
+ let cursor = "0";
171
+ try {
172
+ do {
173
+ const [nextCursor, batch] = await redis2.scan(cursor, "MATCH", pattern, "COUNT", 100);
174
+ cursor = nextCursor;
175
+ for (const key of batch) {
176
+ keys.add(key);
177
+ }
178
+ } while (cursor !== "0");
179
+ } catch (error) {
180
+ console.warn("[RedisStorage] SCAN failed, falling back to KEYS:", error);
181
+ return await this.redis.keys(pattern);
182
+ }
183
+ return Array.from(keys);
147
184
  }
148
185
  generateSessionId() {
149
186
  return firstChar() + rest();
@@ -211,17 +248,13 @@ var RedisStorageBackend = class {
211
248
  }
212
249
  }
213
250
  async getIdentityMcpSessions(identity) {
214
- const identityKey = this.getIdentityKey(identity);
215
- try {
216
- return await this.redis.smembers(identityKey);
217
- } catch (error) {
218
- console.error(`[RedisStorage] Failed to get sessions for ${identity}:`, error);
219
- return [];
220
- }
251
+ const sessions = await this.getIdentitySessionsData(identity);
252
+ return sessions.map((session) => session.sessionId);
221
253
  }
222
254
  async getIdentitySessionsData(identity) {
223
255
  try {
224
- const sessionIds = await this.redis.smembers(this.getIdentityKey(identity));
256
+ const identityKey = this.getIdentityKey(identity);
257
+ const sessionIds = await this.redis.smembers(identityKey);
225
258
  if (sessionIds.length === 0) return [];
226
259
  const results = await Promise.all(
227
260
  sessionIds.map(async (sessionId) => {
@@ -229,6 +262,10 @@ var RedisStorageBackend = class {
229
262
  return data ? JSON.parse(data) : null;
230
263
  })
231
264
  );
265
+ const staleSessionIds = sessionIds.filter((_, index) => results[index] === null);
266
+ if (staleSessionIds.length > 0) {
267
+ await this.redis.srem(identityKey, ...staleSessionIds);
268
+ }
232
269
  return results.filter((session) => session !== null);
233
270
  } catch (error) {
234
271
  console.error(`[RedisStorage] Failed to get session data for ${identity}:`, error);
@@ -247,9 +284,22 @@ var RedisStorageBackend = class {
247
284
  }
248
285
  async getAllSessionIds() {
249
286
  try {
250
- const pattern = `${this.KEY_PREFIX}*`;
251
- const keys = await this.redis.keys(pattern);
252
- return keys.map((key) => key.replace(this.KEY_PREFIX, ""));
287
+ const keys = await this.scanKeys(`${this.KEY_PREFIX}*`);
288
+ const sessions = await Promise.all(
289
+ keys.map(async (key) => {
290
+ const data = await this.redis.get(key);
291
+ if (!data) {
292
+ return null;
293
+ }
294
+ try {
295
+ return JSON.parse(data).sessionId;
296
+ } catch (error) {
297
+ console.error("[RedisStorage] Failed to parse session while listing all session IDs:", error);
298
+ return null;
299
+ }
300
+ })
301
+ );
302
+ return sessions.filter((sessionId) => sessionId !== null);
253
303
  } catch (error) {
254
304
  console.error("[RedisStorage] Failed to get all sessions:", error);
255
305
  return [];
@@ -257,10 +307,11 @@ var RedisStorageBackend = class {
257
307
  }
258
308
  async clearAll() {
259
309
  try {
260
- const pattern = `${this.KEY_PREFIX}*`;
261
- const keys = await this.redis.keys(pattern);
262
- if (keys.length > 0) {
263
- await this.redis.del(...keys);
310
+ const keys = await this.scanKeys(`${this.KEY_PREFIX}*`);
311
+ const identityKeys = await this.scanKeys(`${this.IDENTITY_KEY_PREFIX}*${this.IDENTITY_KEY_SUFFIX}`);
312
+ const allKeys = [...keys, ...identityKeys];
313
+ if (allKeys.length > 0) {
314
+ await this.redis.del(...allKeys);
264
315
  }
265
316
  } catch (error) {
266
317
  console.error("[RedisStorage] Failed to clear sessions:", error);
@@ -268,12 +319,24 @@ var RedisStorageBackend = class {
268
319
  }
269
320
  async cleanupExpiredSessions() {
270
321
  try {
271
- const pattern = `${this.KEY_PREFIX}*`;
272
- const keys = await this.redis.keys(pattern);
273
- for (const key of keys) {
274
- const ttl = await this.redis.ttl(key);
275
- if (ttl <= 0) {
276
- await this.redis.del(key);
322
+ const identityKeys = await this.scanKeys(`${this.IDENTITY_KEY_PREFIX}*${this.IDENTITY_KEY_SUFFIX}`);
323
+ for (const identityKey of identityKeys) {
324
+ const identity = this.parseIdentityFromKey(identityKey);
325
+ const sessionIds = await this.redis.smembers(identityKey);
326
+ if (sessionIds.length === 0) {
327
+ await this.redis.del(identityKey);
328
+ continue;
329
+ }
330
+ const existenceChecks = await Promise.all(
331
+ sessionIds.map((sessionId) => this.redis.exists(this.getSessionKey(identity, sessionId)))
332
+ );
333
+ const staleSessionIds = sessionIds.filter((_, index) => existenceChecks[index] === 0);
334
+ if (staleSessionIds.length > 0) {
335
+ await this.redis.srem(identityKey, ...staleSessionIds);
336
+ }
337
+ const remainingCount = await this.redis.scard(identityKey);
338
+ if (remainingCount === 0) {
339
+ await this.redis.del(identityKey);
277
340
  }
278
341
  }
279
342
  } catch (error) {
@@ -644,6 +707,12 @@ var SqliteStorage = class {
644
707
  // src/server/storage/index.ts
645
708
  var storageInstance = null;
646
709
  var storagePromise = null;
710
+ async function initializeStorage(store) {
711
+ if (typeof store.init === "function") {
712
+ await store.init();
713
+ }
714
+ return store;
715
+ }
647
716
  async function createStorage() {
648
717
  const type = process.env.MCP_TS_STORAGE_TYPE?.toLowerCase();
649
718
  if (type === "redis") {
@@ -667,16 +736,12 @@ async function createStorage() {
667
736
  console.warn('[Storage] MCP_TS_STORAGE_TYPE is "file" but MCP_TS_STORAGE_FILE is missing');
668
737
  }
669
738
  console.log(`[Storage] Using File storage (${filePath}) (Explicit)`);
670
- const store = new FileStorageBackend({ path: filePath });
671
- store.init().catch((err) => console.error("[Storage] Failed to initialize file storage:", err));
672
- return store;
739
+ return await initializeStorage(new FileStorageBackend({ path: filePath }));
673
740
  }
674
741
  if (type === "sqlite") {
675
742
  const dbPath = process.env.MCP_TS_STORAGE_SQLITE_PATH;
676
743
  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;
744
+ return await initializeStorage(new SqliteStorage({ path: dbPath }));
680
745
  }
681
746
  if (type === "memory") {
682
747
  console.log("[Storage] Using In-Memory storage (Explicit)");
@@ -696,15 +761,11 @@ async function createStorage() {
696
761
  }
697
762
  if (process.env.MCP_TS_STORAGE_FILE) {
698
763
  console.log(`[Storage] Auto-detected MCP_TS_STORAGE_FILE. Using File storage (${process.env.MCP_TS_STORAGE_FILE}).`);
699
- const store = new FileStorageBackend({ path: process.env.MCP_TS_STORAGE_FILE });
700
- store.init().catch((err) => console.error("[Storage] Failed to initialize file storage:", err));
701
- return store;
764
+ return await initializeStorage(new FileStorageBackend({ path: process.env.MCP_TS_STORAGE_FILE }));
702
765
  }
703
766
  if (process.env.MCP_TS_STORAGE_SQLITE_PATH) {
704
767
  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;
768
+ return await initializeStorage(new SqliteStorage({ path: process.env.MCP_TS_STORAGE_SQLITE_PATH }));
708
769
  }
709
770
  console.log("[Storage] No storage configured. Using In-Memory storage (Default).");
710
771
  return new MemoryStorageBackend();
@@ -714,7 +775,10 @@ async function getStorage() {
714
775
  return storageInstance;
715
776
  }
716
777
  if (!storagePromise) {
717
- storagePromise = createStorage();
778
+ storagePromise = createStorage().catch((error) => {
779
+ storagePromise = null;
780
+ throw error;
781
+ });
718
782
  }
719
783
  storageInstance = await storagePromise;
720
784
  return storageInstance;
@@ -735,43 +799,49 @@ var storage = new Proxy({}, {
735
799
  // src/server/mcp/storage-oauth-provider.ts
736
800
  var StorageOAuthClientProvider = class {
737
801
  /**
738
- * Creates a new Storage-backed OAuth provider
739
- * @param identity - User/Client identifier
740
- * @param serverId - Server identifier (for tracking which server this OAuth session belongs to)
741
- * @param sessionId - Session identifier (used as OAuth state)
742
- * @param clientName - OAuth client name
743
- * @param baseRedirectUrl - OAuth callback URL
744
- * @param onRedirect - Optional callback when redirect to authorization is needed
802
+ * Creates a new storage-backed OAuth provider
803
+ * @param options - Provider configuration
745
804
  */
746
- constructor(identity, serverId, sessionId, clientName, baseRedirectUrl, onRedirect) {
747
- this.identity = identity;
748
- this.serverId = serverId;
749
- this.sessionId = sessionId;
750
- this.clientName = clientName;
751
- this.baseRedirectUrl = baseRedirectUrl;
805
+ constructor(options) {
806
+ __publicField(this, "identity");
807
+ __publicField(this, "serverId");
808
+ __publicField(this, "sessionId");
809
+ __publicField(this, "redirectUrl");
810
+ __publicField(this, "clientName");
811
+ __publicField(this, "clientUri");
812
+ __publicField(this, "logoUri");
813
+ __publicField(this, "policyUri");
814
+ __publicField(this, "clientSecret");
752
815
  __publicField(this, "_authUrl");
753
816
  __publicField(this, "_clientId");
754
817
  __publicField(this, "onRedirectCallback");
755
818
  __publicField(this, "tokenExpiresAt");
756
- this.onRedirectCallback = onRedirect;
819
+ this.identity = options.identity;
820
+ this.serverId = options.serverId;
821
+ this.sessionId = options.sessionId;
822
+ this.redirectUrl = options.redirectUrl;
823
+ this.clientName = options.clientName;
824
+ this.clientUri = options.clientUri;
825
+ this.logoUri = options.logoUri;
826
+ this.policyUri = options.policyUri;
827
+ this._clientId = options.clientId;
828
+ this.clientSecret = options.clientSecret;
829
+ this.onRedirectCallback = options.onRedirect;
757
830
  }
758
831
  get clientMetadata() {
759
832
  return {
760
- client_name: this.clientName,
761
- client_uri: this.clientUri,
833
+ client_name: this.clientName || DEFAULT_CLIENT_NAME,
834
+ client_uri: this.clientUri || DEFAULT_CLIENT_URI,
835
+ logo_uri: this.logoUri || DEFAULT_LOGO_URI,
836
+ policy_uri: this.policyUri || DEFAULT_POLICY_URI,
762
837
  grant_types: ["authorization_code", "refresh_token"],
763
838
  redirect_uris: [this.redirectUrl],
764
839
  response_types: ["code"],
765
- token_endpoint_auth_method: "none",
766
- ...this._clientId ? { client_id: this._clientId } : {}
840
+ token_endpoint_auth_method: this.clientSecret ? "client_secret_basic" : "none",
841
+ software_id: SOFTWARE_ID,
842
+ software_version: SOFTWARE_VERSION
767
843
  };
768
844
  }
769
- get clientUri() {
770
- return new URL(this.redirectUrl).origin;
771
- }
772
- get redirectUrl() {
773
- return this.baseRedirectUrl;
774
- }
775
845
  get clientId() {
776
846
  return this._clientId;
777
847
  }
@@ -806,7 +876,16 @@ var StorageOAuthClientProvider = class {
806
876
  if (data.clientId && !this._clientId) {
807
877
  this._clientId = data.clientId;
808
878
  }
809
- return data.clientInformation;
879
+ if (data.clientInformation) {
880
+ return data.clientInformation;
881
+ }
882
+ if (!this._clientId) {
883
+ return void 0;
884
+ }
885
+ return {
886
+ client_id: this._clientId,
887
+ ...this.clientSecret ? { client_secret: this.clientSecret } : {}
888
+ };
810
889
  }
811
890
  /**
812
891
  * Stores OAuth client information
@@ -834,14 +913,14 @@ var StorageOAuthClientProvider = class {
834
913
  async state() {
835
914
  return this.sessionId;
836
915
  }
837
- async checkState(state) {
916
+ async checkState(_state) {
838
917
  const data = await storage.getSession(this.identity, this.sessionId);
839
918
  if (!data) {
840
919
  return { valid: false, error: "Session not found" };
841
920
  }
842
921
  return { valid: true, serverId: this.serverId };
843
922
  }
844
- async consumeState(state) {
923
+ async consumeState(_state) {
845
924
  }
846
925
  async redirectToAuthorization(authUrl) {
847
926
  this._authUrl = authUrl.toString();
@@ -853,7 +932,6 @@ var StorageOAuthClientProvider = class {
853
932
  if (scope === "all") {
854
933
  await storage.removeSession(this.identity, this.sessionId);
855
934
  } else {
856
- await this.getSessionData();
857
935
  const updates = {};
858
936
  if (scope === "client") {
859
937
  updates.clientInformation = void 0;
@@ -1173,41 +1251,33 @@ var MCPClient = class _MCPClient {
1173
1251
  if (!this.serverUrl || !this.callbackUrl || !this.serverId) {
1174
1252
  throw new Error("Missing required connection metadata");
1175
1253
  }
1176
- const clientMetadata = {
1177
- client_name: this.clientName || "MCP Assistant",
1178
- redirect_uris: [this.callbackUrl],
1179
- token_endpoint_auth_method: this.clientSecret ? "client_secret_basic" : "none",
1180
- client_uri: this.clientUri || "https://mcp-assistant.in",
1181
- logo_uri: this.logoUri || "https://mcp-assistant.in/logo.png",
1182
- policy_uri: this.policyUri || "https://mcp-assistant.in/privacy",
1183
- ...this.clientId ? { client_id: this.clientId } : {},
1184
- ...this.clientSecret ? { client_secret: this.clientSecret } : {}
1185
- };
1186
1254
  if (!this.oauthProvider) {
1187
1255
  if (!this.serverId) {
1188
1256
  throw new Error("serverId required for OAuth provider initialization");
1189
1257
  }
1190
- this.oauthProvider = new StorageOAuthClientProvider(
1191
- this.identity,
1192
- this.serverId,
1193
- this.sessionId,
1194
- clientMetadata.client_name ?? "MCP Assistant",
1195
- this.callbackUrl,
1196
- (redirectUrl) => {
1258
+ this.oauthProvider = new StorageOAuthClientProvider({
1259
+ identity: this.identity,
1260
+ serverId: this.serverId,
1261
+ sessionId: this.sessionId,
1262
+ redirectUrl: this.callbackUrl,
1263
+ clientName: this.clientName,
1264
+ clientUri: this.clientUri,
1265
+ logoUri: this.logoUri,
1266
+ policyUri: this.policyUri,
1267
+ clientId: this.clientId,
1268
+ clientSecret: this.clientSecret,
1269
+ onRedirect: (redirectUrl) => {
1197
1270
  if (this.onRedirect) {
1198
1271
  this.onRedirect(redirectUrl);
1199
1272
  }
1200
1273
  }
1201
- );
1202
- if (this.clientId && this.oauthProvider) {
1203
- this.oauthProvider.clientId = this.clientId;
1204
- }
1274
+ });
1205
1275
  }
1206
1276
  if (!this.client) {
1207
1277
  this.client = new Client(
1208
1278
  {
1209
- name: "mcp-ts-oauth-client",
1210
- version: "2.0"
1279
+ name: MCP_CLIENT_NAME,
1280
+ version: MCP_CLIENT_VERSION
1211
1281
  },
1212
1282
  {
1213
1283
  capabilities: {
@@ -1402,8 +1472,8 @@ var MCPClient = class _MCPClient {
1402
1472
  this.emitProgress("Creating authenticated client...");
1403
1473
  this.client = new Client(
1404
1474
  {
1405
- name: "mcp-ts-oauth-client",
1406
- version: "2.0"
1475
+ name: MCP_CLIENT_NAME,
1476
+ version: MCP_CLIENT_VERSION
1407
1477
  },
1408
1478
  {
1409
1479
  capabilities: {
@@ -1698,8 +1768,8 @@ var MCPClient = class _MCPClient {
1698
1768
  }
1699
1769
  this.client = new Client(
1700
1770
  {
1701
- name: "mcp-ts-oauth-client",
1702
- version: "2.0"
1771
+ name: MCP_CLIENT_NAME,
1772
+ version: MCP_CLIENT_VERSION
1703
1773
  },
1704
1774
  { capabilities: {} }
1705
1775
  );
@@ -1968,6 +2038,27 @@ var MultiSessionClient = class {
1968
2038
  }
1969
2039
  };
1970
2040
 
2041
+ // src/shared/event-routing.ts
2042
+ function isRpcResponseEvent(event) {
2043
+ return "id" in event && ("result" in event || "error" in event);
2044
+ }
2045
+ function isConnectionEvent(event) {
2046
+ if (!("type" in event)) {
2047
+ return false;
2048
+ }
2049
+ switch (event.type) {
2050
+ case "state_changed":
2051
+ case "tools_discovered":
2052
+ case "auth_required":
2053
+ case "error":
2054
+ case "disconnected":
2055
+ case "progress":
2056
+ return true;
2057
+ default:
2058
+ return false;
2059
+ }
2060
+ }
2061
+
1971
2062
  // src/server/handlers/sse-handler.ts
1972
2063
  var DEFAULT_HEARTBEAT_INTERVAL = 3e4;
1973
2064
  var SSEConnectionManager = class {
@@ -2110,16 +2201,6 @@ var SSEConnectionManager = class {
2110
2201
  throw new Error(`Connection already exists for server: ${duplicate.serverUrl || duplicate.serverId} (${duplicate.serverName})`);
2111
2202
  }
2112
2203
  const sessionId = await storage.generateSessionId();
2113
- this.emitConnectionEvent({
2114
- type: "state_changed",
2115
- sessionId,
2116
- serverId,
2117
- serverName,
2118
- serverUrl,
2119
- state: "CONNECTING",
2120
- previousState: "DISCONNECTED",
2121
- timestamp: Date.now()
2122
- });
2123
2204
  try {
2124
2205
  const clientMetadata = await this.getResolvedClientMetadata();
2125
2206
  const client = new MCPClient({
@@ -2130,17 +2211,8 @@ var SSEConnectionManager = class {
2130
2211
  serverUrl,
2131
2212
  callbackUrl,
2132
2213
  transportType,
2133
- ...clientMetadata,
2214
+ ...clientMetadata
2134
2215
  // Spread client metadata (clientName, clientUri, logoUri, policyUri)
2135
- onRedirect: (authUrl) => {
2136
- this.emitConnectionEvent({
2137
- type: "auth_required",
2138
- sessionId,
2139
- serverId,
2140
- authUrl,
2141
- timestamp: Date.now()
2142
- });
2143
- }
2144
2216
  });
2145
2217
  this.clients.set(sessionId, client);
2146
2218
  client.onConnectionEvent((event) => {
@@ -2150,20 +2222,19 @@ var SSEConnectionManager = class {
2150
2222
  this.sendEvent(event);
2151
2223
  });
2152
2224
  await client.connect();
2153
- const tools = await client.listTools();
2154
- this.emitConnectionEvent({
2155
- type: "tools_discovered",
2156
- sessionId,
2157
- serverId,
2158
- toolCount: tools.tools.length,
2159
- tools: tools.tools,
2160
- timestamp: Date.now()
2161
- });
2225
+ await client.listTools();
2162
2226
  return {
2163
2227
  sessionId,
2164
2228
  success: true
2165
2229
  };
2166
2230
  } catch (error) {
2231
+ if (error instanceof UnauthorizedError) {
2232
+ this.clients.delete(sessionId);
2233
+ return {
2234
+ sessionId,
2235
+ success: true
2236
+ };
2237
+ }
2167
2238
  this.emitConnectionEvent({
2168
2239
  type: "error",
2169
2240
  sessionId,
@@ -2265,14 +2336,6 @@ var SSEConnectionManager = class {
2265
2336
  await client.connect();
2266
2337
  this.clients.set(sessionId, client);
2267
2338
  const tools = await client.listTools();
2268
- this.emitConnectionEvent({
2269
- type: "tools_discovered",
2270
- sessionId,
2271
- serverId: session.serverId ?? "unknown",
2272
- toolCount: tools.tools.length,
2273
- tools: tools.tools,
2274
- timestamp: Date.now()
2275
- });
2276
2339
  return { success: true, toolCount: tools.tools.length };
2277
2340
  } catch (error) {
2278
2341
  this.emitConnectionEvent({
@@ -2295,16 +2358,6 @@ var SSEConnectionManager = class {
2295
2358
  if (!session) {
2296
2359
  throw new Error("Session not found");
2297
2360
  }
2298
- this.emitConnectionEvent({
2299
- type: "state_changed",
2300
- sessionId,
2301
- serverId: session.serverId ?? "unknown",
2302
- serverName: session.serverName ?? "Unknown",
2303
- serverUrl: session.serverUrl,
2304
- state: "AUTHENTICATING",
2305
- previousState: "DISCONNECTED",
2306
- timestamp: Date.now()
2307
- });
2308
2361
  try {
2309
2362
  const client = new MCPClient({
2310
2363
  identity: this.identity,
@@ -2314,14 +2367,6 @@ var SSEConnectionManager = class {
2314
2367
  await client.finishAuth(code);
2315
2368
  this.clients.set(sessionId, client);
2316
2369
  const tools = await client.listTools();
2317
- this.emitConnectionEvent({
2318
- type: "tools_discovered",
2319
- sessionId,
2320
- serverId: session.serverId ?? "unknown",
2321
- toolCount: tools.tools.length,
2322
- tools: tools.tools,
2323
- timestamp: Date.now()
2324
- });
2325
2370
  return { success: true, toolCount: tools.tools.length };
2326
2371
  } catch (error) {
2327
2372
  this.emitConnectionEvent({
@@ -2399,9 +2444,9 @@ function createSSEHandler(options) {
2399
2444
  });
2400
2445
  writeSSEEvent(res, "connected", { timestamp: Date.now() });
2401
2446
  const manager = new SSEConnectionManager(options, (event) => {
2402
- if ("id" in event) {
2447
+ if (isRpcResponseEvent(event)) {
2403
2448
  writeSSEEvent(res, "rpc-response", event);
2404
- } else if ("type" in event && "sessionId" in event) {
2449
+ } else if (isConnectionEvent(event)) {
2405
2450
  writeSSEEvent(res, "connection", event);
2406
2451
  } else {
2407
2452
  writeSSEEvent(res, "observability", event);
@@ -2432,9 +2477,6 @@ function writeSSEEvent(res, event, data) {
2432
2477
  }
2433
2478
 
2434
2479
  // src/server/handlers/nextjs-handler.ts
2435
- function isRpcResponseEvent(event) {
2436
- return "id" in event && ("result" in event || "error" in event);
2437
- }
2438
2480
  function createNextMcpHandler(options = {}) {
2439
2481
  const {
2440
2482
  getIdentity = (request) => new URL(request.url).searchParams.get("identity"),
@@ -2525,7 +2567,7 @@ data: ${JSON.stringify(data)}
2525
2567
  (event) => {
2526
2568
  if (isRpcResponseEvent(event)) {
2527
2569
  sendSSE("rpc-response", event);
2528
- } else if ("type" in event && "sessionId" in event) {
2570
+ } else if (isConnectionEvent(event)) {
2529
2571
  sendSSE("connection", event);
2530
2572
  } else {
2531
2573
  sendSSE("observability", event);