@mcp-ts/sdk 2.5.2 → 2.6.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 (73) hide show
  1. package/README.md +3 -574
  2. package/dist/adapters/agui-adapter.d.mts +4 -4
  3. package/dist/adapters/agui-adapter.d.ts +4 -4
  4. package/dist/adapters/agui-middleware.d.mts +4 -4
  5. package/dist/adapters/agui-middleware.d.ts +4 -4
  6. package/dist/adapters/ai-adapter.d.mts +4 -4
  7. package/dist/adapters/ai-adapter.d.ts +4 -4
  8. package/dist/adapters/langchain-adapter.d.mts +4 -4
  9. package/dist/adapters/langchain-adapter.d.ts +4 -4
  10. package/dist/adapters/mastra-adapter.d.mts +3 -3
  11. package/dist/adapters/mastra-adapter.d.ts +3 -3
  12. package/dist/client/index.d.mts +2 -2
  13. package/dist/client/index.d.ts +2 -2
  14. package/dist/client/index.js +3 -0
  15. package/dist/client/index.js.map +1 -1
  16. package/dist/client/index.mjs +3 -0
  17. package/dist/client/index.mjs.map +1 -1
  18. package/dist/client/react.d.mts +10 -18
  19. package/dist/client/react.d.ts +10 -18
  20. package/dist/client/react.js +17 -0
  21. package/dist/client/react.js.map +1 -1
  22. package/dist/client/react.mjs +17 -0
  23. package/dist/client/react.mjs.map +1 -1
  24. package/dist/client/vue.d.mts +4 -4
  25. package/dist/client/vue.d.ts +4 -4
  26. package/dist/client/vue.js +3 -0
  27. package/dist/client/vue.js.map +1 -1
  28. package/dist/client/vue.mjs +3 -0
  29. package/dist/client/vue.mjs.map +1 -1
  30. package/dist/{index-B3GPsPsi.d.mts → index-BrDkbut5.d.ts} +2 -1
  31. package/dist/{index-gNdSQTSz.d.ts → index-DHQvlx4K.d.mts} +2 -1
  32. package/dist/index.d.mts +5 -5
  33. package/dist/index.d.ts +5 -5
  34. package/dist/index.js +1056 -863
  35. package/dist/index.js.map +1 -1
  36. package/dist/index.mjs +1048 -858
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/{multi-session-client-CB4oDrQX.d.ts → multi-session-client-CQzymvHl.d.ts} +183 -227
  39. package/dist/{multi-session-client-xj3iQIv6.d.mts → multi-session-client-C_Ja2TuV.d.mts} +183 -227
  40. package/dist/server/index.d.mts +338 -88
  41. package/dist/server/index.d.ts +338 -88
  42. package/dist/server/index.js +1054 -864
  43. package/dist/server/index.js.map +1 -1
  44. package/dist/server/index.mjs +1046 -859
  45. package/dist/server/index.mjs.map +1 -1
  46. package/dist/shared/index.d.mts +4 -4
  47. package/dist/shared/index.d.ts +4 -4
  48. package/dist/shared/index.js.map +1 -1
  49. package/dist/shared/index.mjs.map +1 -1
  50. package/dist/{tool-router-CsKVXbQB.d.mts → tool-router-C1n7OXbl.d.mts} +1 -1
  51. package/dist/{tool-router-C-Mw1_BQ.d.ts → tool-router-CBIawFnt.d.ts} +1 -1
  52. package/dist/{types-6SmXege4.d.mts → types-DX71u9gR.d.mts} +11 -3
  53. package/dist/{types-6SmXege4.d.ts → types-DX71u9gR.d.ts} +11 -3
  54. package/migrations/neon/20260513010000_install_mcp_sessions.sql +4 -34
  55. package/migrations/supabase/20260330195700_install_mcp_sessions.sql +5 -62
  56. package/package.json +2 -1
  57. package/src/client/core/sse-client.ts +5 -0
  58. package/src/client/react/use-mcp.ts +27 -28
  59. package/src/server/handlers/sse-handler.ts +671 -629
  60. package/src/server/index.ts +2 -1
  61. package/src/server/mcp/multi-session-client.ts +34 -10
  62. package/src/server/mcp/oauth-client.ts +197 -205
  63. package/src/server/mcp/storage-oauth-provider.ts +149 -29
  64. package/src/server/mcp/tool-policy-gateway.ts +11 -1
  65. package/src/server/storage/file-backend.ts +25 -21
  66. package/src/server/storage/index.ts +71 -0
  67. package/src/server/storage/memory-backend.ts +24 -12
  68. package/src/server/storage/neon-backend.ts +70 -72
  69. package/src/server/storage/redis-backend.ts +26 -36
  70. package/src/server/storage/sqlite-backend.ts +25 -39
  71. package/src/server/storage/supabase-backend.ts +45 -54
  72. package/src/server/storage/types.ts +22 -2
  73. package/src/shared/types.ts +13 -1
@@ -1,13 +1,32 @@
1
- import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-CB4oDrQX.js';
2
- export { M as MCPClient, a as MultiSessionClient, S as Session, b as SessionMutationEvent, d as SessionMutationType, f as StorageOAuthClientProvider } from '../multi-session-client-CB4oDrQX.js';
1
+ import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-CQzymvHl.js';
2
+ export { M as MCPClient, a as MultiSessionClient, S as Session, b as SessionMutationEvent, d as SessionMutationType } from '../multi-session-client-CQzymvHl.js';
3
3
  export { U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-DELRKQPU.js';
4
- import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-6SmXege4.js';
5
- export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, k as Disposable, E as Emitter, m as Event, q as ListToolsResponse, s as McpConnectionState, T as ToolClient, A as ToolClientProvider, B as ToolInfo } from '../types-6SmXege4.js';
4
+ import { t as McpObservabilityEvent, M as McpConnectionEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-DX71u9gR.js';
5
+ export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, k as Disposable, E as Emitter, m as Event, q as ListToolsResponse, s as McpConnectionState, T as ToolClient, A as ToolClientProvider, B as ToolInfo } from '../types-DX71u9gR.js';
6
+ import { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';
7
+ import { OAuthTokens, OAuthClientMetadata, OAuthClientInformationMixed, OAuthClientInformationFull } from '@modelcontextprotocol/sdk/shared/auth.js';
6
8
  export { OAuthClientInformation, OAuthClientInformationFull, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
7
9
  export { CallToolResult, ListToolsResult, Tool } from '@modelcontextprotocol/sdk/types.js';
8
- import '@modelcontextprotocol/sdk/client/auth.js';
9
10
 
10
11
  declare function onSessionMutation(listener: SessionMutationListener): () => void;
12
+ /**
13
+ * Wraps a SessionStore with a Proxy that emits an McpObservabilityEvent for every
14
+ * method call — reads (`db:read`) and writes (`db:write`) — including duration
15
+ * and any error. Useful for debugging connection flows end-to-end.
16
+ *
17
+ * Usage:
18
+ * ```ts
19
+ * import { sessions, withDbObservability } from '@mcp-ts/sdk/server/storage';
20
+ * const db = withDbObservability(sessions, (event) => console.log('[DB]', event));
21
+ * // Use `db` instead of `sessions` throughout the request
22
+ * ```
23
+ *
24
+ * @param store - The underlying SessionStore instance to wrap.
25
+ * @param emit - Called synchronously after each store method completes
26
+ * (or rejects) with a typed observability event.
27
+ * @returns A drop-in SessionStore replacement.
28
+ */
29
+ declare function withDbObservability(store: SessionStore, emit: (event: McpObservabilityEvent) => void): SessionStore;
11
30
  /**
12
31
  * Global session store instance
13
32
  * Uses lazy initialization with a Proxy to handle async setup transparently
@@ -15,170 +34,390 @@ declare function onSessionMutation(listener: SessionMutationListener): () => voi
15
34
  declare const sessions: SessionStore;
16
35
 
17
36
  /**
18
- * SSE (Server-Sent Events) Handler for MCP Connections
37
+ * Extension of OAuthClientProvider interface with additional methods
38
+ * Enables server-specific tracking and state management
39
+ */
40
+ interface AgentsOAuthProvider extends OAuthClientProvider {
41
+ authUrl: string | undefined;
42
+ clientId: string | undefined;
43
+ serverId: string | undefined;
44
+ checkState(state: string): Promise<{
45
+ valid: boolean;
46
+ serverId?: string;
47
+ error?: string;
48
+ }>;
49
+ consumeState(state: string): Promise<void>;
50
+ deleteCodeVerifier(): Promise<void>;
51
+ }
52
+ interface StorageOAuthClientProviderOptions {
53
+ userId: string;
54
+ serverId: string;
55
+ sessionId: string;
56
+ redirectUrl: string;
57
+ clientName?: string;
58
+ clientUri?: string;
59
+ logoUri?: string;
60
+ policyUri?: string;
61
+ clientId?: string;
62
+ clientSecret?: string;
63
+ cachedTokens?: OAuthTokens;
64
+ sessionStore?: SessionStore;
65
+ onRedirect?: (url: string) => void;
66
+ }
67
+ /**
68
+ * Storage-backed OAuth provider implementation for MCP
69
+ * Stores OAuth tokens, client information, and PKCE verifiers using the configured SessionStore
70
+ */
71
+ declare class StorageOAuthClientProvider implements AgentsOAuthProvider {
72
+ readonly userId: string;
73
+ readonly serverId: string;
74
+ readonly sessionId: string;
75
+ readonly redirectUrl: string;
76
+ private readonly clientName?;
77
+ private readonly clientUri?;
78
+ private readonly logoUri?;
79
+ private readonly policyUri?;
80
+ private readonly clientSecret?;
81
+ private _store;
82
+ private _authUrl;
83
+ private _clientId;
84
+ private _cachedCodeVerifier;
85
+ private _hasCodeVerifier;
86
+ private _cachedTokens;
87
+ private onRedirectCallback?;
88
+ /**
89
+ * Creates a new session-backed OAuth provider
90
+ * @param options - Provider configuration
91
+ */
92
+ constructor(options: StorageOAuthClientProviderOptions);
93
+ get clientMetadata(): OAuthClientMetadata;
94
+ get clientId(): string | undefined;
95
+ set clientId(clientId_: string | undefined);
96
+ /**
97
+ * Loads OAuth credentials from the session store
98
+ * @private
99
+ */
100
+ private getCredentials;
101
+ /**
102
+ * Saves OAuth credentials to the session store
103
+ * @param data - Partial OAuth credentials to save
104
+ * @private
105
+ * @throws Error if session doesn't exist (session must be created by controller layer)
106
+ */
107
+ private patchCredentials;
108
+ /**
109
+ * Retrieves stored OAuth client information.
110
+ */
111
+ clientInformation(): Promise<OAuthClientInformationMixed | undefined>;
112
+ /**
113
+ * Stores OAuth client information
114
+ */
115
+ saveClientInformation(clientInformation: OAuthClientInformationFull): Promise<void>;
116
+ /**
117
+ * Stores OAuth tokens
118
+ */
119
+ saveTokens(tokens: OAuthTokens): Promise<void>;
120
+ /**
121
+ * Persists static client credentials to DB immediately on creation.
122
+ * Ensures getOrCreateClient() finds them on rehydration, even when the
123
+ * server allows anonymous connect and never triggers DCR.
124
+ */
125
+ initializeCredentials(): Promise<void>;
126
+ get authUrl(): string | undefined;
127
+ state(): Promise<string>;
128
+ checkState(state: string): Promise<{
129
+ valid: boolean;
130
+ serverId?: string;
131
+ error?: string;
132
+ }>;
133
+ consumeState(state: string): Promise<void>;
134
+ redirectToAuthorization(authUrl: URL): Promise<void>;
135
+ invalidateCredentials(scope: "all" | "client" | "tokens" | "verifier"): Promise<void>;
136
+ saveCodeVerifier(verifier: string): Promise<void>;
137
+ codeVerifier(): Promise<string>;
138
+ deleteCodeVerifier(): Promise<void>;
139
+ tokens(): Promise<OAuthTokens | undefined>;
140
+ }
141
+
142
+ /**
143
+ * SSE (Server-Sent Events) Handler for MCP Connections.
144
+ *
145
+ * Provides real-time bidirectional communication between browser clients and
146
+ * MCP servers via a single HTTP endpoint:
147
+ * - GET → opens an SSE stream for server → client events
148
+ * - POST → delivers client → server RPC requests with direct HTTP response
19
149
  *
20
- * Manages real-time bidirectional communication with MCP clients:
21
- * - SSE stream for server client events (connection state, tools, logs)
22
- * - HTTP POST for client server RPC requests
150
+ * Built on {@link SSEConnectionManager} which handles the RPC dispatch logic,
151
+ * session lifecycle, OAuth 2.1 flows, tool-policy enforcement, and heartbeat
152
+ * keep-alive all while remaining stateless across serverless invocations.
23
153
  *
24
- * Key features:
25
- * - Direct HTTP response for RPC calls (bypasses SSE latency)
26
- * - Automatic session restoration and validation
27
- * - OAuth 2.1 authentication flow support
28
- * - Heartbeat to keep connections alive
154
+ * @module sse-handler
29
155
  */
30
156
 
157
+ /** OAuth client metadata surfaced during connection and authorization. */
31
158
  interface ClientMetadata {
32
159
  clientName?: string;
33
160
  clientUri?: string;
34
161
  logoUri?: string;
35
162
  policyUri?: string;
36
163
  }
164
+ /** Options passed to {@link createSSEHandler}. */
37
165
  interface SSEHandlerOptions {
38
- /** User/Client identifier */
166
+ /** Authenticated user / tenant identifier. */
39
167
  userId: string;
40
- /** Optional callback for authentication/authorization */
168
+ /** Optional auth check called per-request before any RPC dispatch. */
41
169
  onAuth?: (userId: string) => Promise<boolean>;
42
- /** Heartbeat interval in milliseconds @default 30000 */
170
+ /** SSE heartbeat interval in milliseconds. @default 30000 */
43
171
  heartbeatInterval?: number;
44
- /** Static OAuth client metadata defaults (for all connections) */
172
+ /** Static OAuth client metadata applied to all connections. */
45
173
  clientDefaults?: ClientMetadata;
46
- /** Dynamic OAuth client metadata getter (per-request, useful for multi-tenant) */
174
+ /**
175
+ * Dynamic OAuth client metadata resolver, called once per connection.
176
+ * Overrides `clientDefaults`. Useful for multi-tenant scenarios where
177
+ * metadata varies by request (headers, subdomain, etc.).
178
+ */
47
179
  getClientMetadata?: (request?: unknown) => ClientMetadata | Promise<ClientMetadata>;
48
180
  }
49
181
  /**
50
- * Manages a single SSE connection and handles MCP operations.
51
- * Each instance corresponds to one connected browser client.
182
+ * Manages a single browser-facing SSE connection and all MCP server sessions
183
+ * owned by the associated user.
184
+ *
185
+ * ## Responsibilities
186
+ * - RPC method dispatch (`connect`, `disconnect`, `callTool`, `listTools`, …)
187
+ * - Session lifecycle: create, restore, re-validate, OAuth completion
188
+ * - In-memory client cache (`Map<string, MCPClient>`) for active transports
189
+ * - SSE event emission for connection state, tool discovery, and errors
190
+ * - Periodic heartbeat to prevent proxy/CDN timeouts
191
+ * - Unified observability: RPC timing, DB operations, connection lifecycle
192
+ *
193
+ * Each instance is tied to one browser client. It is **not** a singleton —
194
+ * a new instance is created per incoming SSE connection.
52
195
  */
53
196
  declare class SSEConnectionManager {
54
197
  private readonly options;
55
198
  private readonly sendEvent;
56
199
  private readonly userId;
200
+ /** Active MCP transports keyed by sessionId. */
57
201
  private readonly clients;
58
- private heartbeatTimer?;
59
- private isActive;
202
+ /** Instrumented session store — always wraps `sessions` with DB observability. */
203
+ private readonly observedStore;
204
+ private heartbeatTimer;
205
+ private active;
206
+ /**
207
+ * @param options - Handler configuration (userId, auth, metadata, heartbeat, observability).
208
+ * @param sendEvent - Callback that writes a typed event onto the SSE stream.
209
+ */
60
210
  constructor(options: SSEHandlerOptions, sendEvent: (event: McpConnectionEvent | McpObservabilityEvent | McpRpcResponse) => void);
61
211
  /**
62
- * Get resolved client metadata (dynamic > static > defaults)
212
+ * Dispatches an incoming RPC request, emits timing observability,
213
+ * and returns the response.
214
+ *
215
+ * Emits `rpc:start` before dispatch and `rpc:end` on completion
216
+ * (success or error), each carrying the method name, sessionId, and
217
+ * duration. All events flow through the unified `onObservability`
218
+ * and the SSE stream.
219
+ *
220
+ * @param request - The deserialized RPC envelope.
221
+ * @returns The RPC response (success or error).
63
222
  */
64
- private getResolvedClientMetadata;
223
+ handleRequest(request: McpRpcRequest): Promise<McpRpcResponse>;
65
224
  /**
66
- * Start heartbeat to keep connection alive
225
+ * Tears down all active MCP transports and stops the heartbeat timer.
226
+ *
227
+ * Disconnects are issued in parallel across all sessions. After calling
228
+ * this method the manager instance should be discarded.
67
229
  */
68
- private startHeartbeat;
230
+ dispose(): Promise<void>;
69
231
  /**
70
- * Handle incoming RPC requests
71
- * Returns the RPC response directly for immediate HTTP response (bypassing SSE latency)
232
+ * Routes an RPC method name to the appropriate private handler.
233
+ *
234
+ * @throws {Error} When the method name is unrecognized.
72
235
  */
73
- handleRequest(request: McpRpcRequest): Promise<McpRpcResponse>;
236
+ private dispatchImpl;
74
237
  /**
75
- * Get all sessions for the current userId
238
+ * Lists all sessions owned by the current user.
239
+ *
240
+ * Returns a lightweight view — session metadata only, no credential fields.
76
241
  */
77
242
  private listSessions;
78
243
  /**
79
- * Connect to an MCP server
244
+ * Restores and validates a previously persisted session.
245
+ *
246
+ * Loads the full session row (including credentials) from storage, creates
247
+ * a new MCP transport, connects to the remote server, and emits the
248
+ * discovered (policy-filtered) tool list via SSE.
249
+ */
250
+ private getSession;
251
+ /**
252
+ * Initiates a connection to a new MCP server.
253
+ *
254
+ * If a session for the same `serverId` or `serverUrl` already exists and
255
+ * is still in a `pending` (OAuth) state, the existing session is resumed
256
+ * instead of creating a duplicate.
257
+ *
258
+ * `UnauthorizedError` is treated as a pending-auth state and returned as
259
+ * a successful result (the client will then redirect to the auth URL).
80
260
  */
81
261
  private connect;
82
262
  /**
83
- * Reconnect to an MCP server tears down the active client transport/connection
84
- * and creates a fresh connection while reusing the existing session credentials in a single RPC call.
263
+ * Reconnects to an MCP server by tearing down the active transport if one
264
+ * exists and instantiating a fresh connection, reusing the existing session
265
+ * (and its stored credentials / DCR client info) from the database.
85
266
  */
86
267
  private reconnect;
87
268
  /**
88
- * Disconnect from an MCP server
269
+ * Disconnects from an MCP server.
270
+ *
271
+ * If an active in-memory transport exists it delegates to `clearSession()`
272
+ * (which sends the server an HTTP DELETE per the Streamable spec). If no
273
+ * active transport is available (orphaned session from a failed OAuth flow),
274
+ * the session row is removed directly from storage.
89
275
  */
90
276
  private disconnect;
91
277
  /**
92
- * Get an existing client or create and connect a new one for the session.
278
+ * Completes the OAuth 2.1 authorization code flow for a pending session.
279
+ *
280
+ * Loads the stored session (with credentials), creates a fresh `MCPClient`,
281
+ * and calls `finishAuth` inside a {@link runWithCodeVerifierState} context
282
+ * so the PKCE code verifier is available without a DB read.
283
+ *
284
+ * The session's stored `transportType` is intentionally **omitted** from the
285
+ * client config — this lets `MCPClient` auto-negotiate (try Streamable HTTP
286
+ * first, fall back to SSE), which is required for servers like Neon that
287
+ * only support SSE transport.
93
288
  */
94
- private getOrCreateClient;
289
+ private finishAuth;
95
290
  /**
96
- * Fetches all tools from the remote MCP server and emits a `tools_discovered` event.
291
+ * Fetches the complete tool list from the remote MCP server and emits a
292
+ * `tools_discovered` SSE event with two lists:
97
293
  *
98
- * Two lists are always published together:
99
- * - `tools` policy-filtered list that agents are allowed to call.
100
- * - `allTools` — the complete, unfiltered list used by the management UI so
101
- * that blocked tools still appear as checkboxes in the dialog.
294
+ * - `tools` — policy-filtered (what agents are allowed to call)
295
+ * - `allTools` complete, unfiltered (used by the management UI)
102
296
  *
103
- * `fetchTools()` is called first (populates the in-memory cache), then
104
- * `gateway.listTools()` re-uses that cache internally — so only one remote
105
- * network round-trip is made regardless of how many callers follow.
297
+ * Only a single network round-trip is made: `fetchTools()` populates the
298
+ * in-memory cache, then `gateway.listTools()` reuses that cache.
106
299
  *
107
- * @param sessionId - The session whose tools should be discovered.
108
- * @returns The session record and the policy-filtered tool list.
109
- * @throws {Error} When the session does not exist in the store.
300
+ * @param sessionId - The session to discover tools for.
301
+ * @returns The session record and the filtered tool result.
302
+ * @throws {Error} If the session does not exist in storage.
110
303
  */
111
304
  private listPolicyFilteredTools;
112
305
  /**
113
- * Returns the policy-filtered tool list for a session (agent-facing).
114
- * Internally re-uses `listPolicyFilteredTools` which also emits a
115
- * `tools_discovered` SSE event to keep client state up to date.
306
+ * Returns the policy-filtered tool list for a session.
307
+ *
308
+ * Delegates to {@link listPolicyFilteredTools}, which also emits a
309
+ * `tools_discovered` SSE event to keep the client state current.
116
310
  */
117
311
  private listTools;
118
312
  /**
119
- * Get all raw tools with effective access state for management UI.
313
+ * Returns all raw tools annotated with their effective policy state
314
+ * for display in the management UI.
120
315
  */
121
316
  private getToolPolicy;
122
317
  /**
123
- * Persists a new tool access policy for a session and broadcasts the updated
124
- * filtered tool list to all connected browser clients via a `tools_discovered` event.
318
+ * Persists a new tool access policy and broadcasts the updated filtered
319
+ * tool list via a `tools_discovered` SSE event.
125
320
  *
126
- * Both `tools` (policy-filtered) and `allTools` (complete list) are emitted
127
- * so the management UI can immediately reflect the new checkbox states without
128
- * an additional round-trip to the server.
129
- *
130
- * @param params - Session ID and the new `{ mode, toolIds }` policy to apply.
131
- * @throws {Error} When the session does not exist or the policy references unknown tool IDs.
321
+ * @throws {Error} If the session does not exist or the policy references
322
+ * tool IDs that don't match any known tool.
132
323
  */
133
324
  private setToolPolicy;
134
325
  /**
135
- * Proxies a tool invocation to the remote MCP server.
136
- * Resolves the client for the given session and delegates to the tool router.
137
- */
138
- private callTool;
139
- /**
140
- * Restore and validate an existing session
141
- */
142
- private getSession;
143
- /**
144
- * Complete OAuth authorization flow
326
+ * Enables or disables a session for agent tool discovery.
327
+ *
328
+ * Disabled sessions retain their OAuth tokens and connection metadata
329
+ * but are hidden from `MultiSessionClient.connect()` and blocked from
330
+ * RPC tool access. Re-enabling does not require re-authentication.
331
+ *
332
+ * @param params - `{ sessionId, enabled: boolean }`
333
+ * @returns `{ success: true }`
334
+ * @throws {Error} If the session does not exist.
145
335
  */
146
- private finishAuth;
336
+ private updateSession;
147
337
  /**
148
- * List prompts from a session
338
+ * Proxies a tool invocation to the remote MCP server.
339
+ *
340
+ * Resolves (or creates) the transport for the given session, runs the call
341
+ * through the tool-policy gateway, and injects `sessionId` into the result
342
+ * metadata so the client can route the response without scanning all sessions.
149
343
  */
344
+ private callTool;
345
+ /** Lists all prompts exposed by the remote MCP server. */
150
346
  private listPrompts;
347
+ /** Retrieves a specific prompt by name with optional arguments. */
348
+ private getPrompt;
349
+ /** Lists all resources exposed by the remote MCP server. */
350
+ private listResources;
351
+ /** Reads a specific resource identified by URI. */
352
+ private readResource;
353
+ /** Resolves client metadata: `getClientMetadata()` → `clientDefaults` → `{}`. */
354
+ private getResolvedClientMetadata;
355
+ /** Ensures the given session exists in storage and throws otherwise. */
356
+ private requireSession;
357
+ /** Finds an existing session matching the given serverId or serverUrl. */
358
+ private findExistingSession;
359
+ /** Normalizes a serverId to max 12 chars (DeepSeek/OpenAI 64-char tool-name limit). */
360
+ private normalizeServerId;
151
361
  /**
152
- * Get a specific prompt
362
+ * Returns the cached in-memory transport for `sessionId`, or creates one
363
+ * from the persisted session row (with credentials) and connects it.
153
364
  */
154
- private getPrompt;
365
+ private getOrCreateClient;
155
366
  /**
156
- * List resources from a session
367
+ * Builds an `MCPClient` from a stored session row.
368
+ *
369
+ * Extracts `clientId` and `clientSecret` from the session's credential
370
+ * fields and passes `hasSession: true` + `cachedCredentials` so the client
371
+ * can skip redundant existence checks and credential reads.
157
372
  */
158
- private listResources;
373
+ private restoreClient;
159
374
  /**
160
- * Read a specific resource
375
+ * Wires connection and observability events from the client into the
376
+ * unified observability channel. Connection events go to `sendEvent`
377
+ * (SSE stream); observability events go to `emitObs` (user callback
378
+ * + SSE stream).
161
379
  */
162
- private readResource;
380
+ private attachClientEvents;
163
381
  /**
164
- * Emit connection event
382
+ * Registers the client in the in-memory cache and attaches its event
383
+ * listeners to the unified observability channel.
165
384
  */
166
- private emitConnectionEvent;
385
+ private cacheClient;
167
386
  /**
168
- * Cleanup and close all connections
387
+ * Attempts a `client.connect()` and, on success, discovers tools.
388
+ *
389
+ * If the server responds with `UnauthorizedError`, the session is
390
+ * treated as pending OAuth — a successful result is returned with
391
+ * the sessionId so the browser client can redirect to the auth URL.
392
+ *
393
+ * For any other error an `error` connection event is emitted and the
394
+ * client is removed from the in-memory cache before re-throwing.
169
395
  */
170
- dispose(): Promise<void>;
396
+ private connectAndDiscover;
397
+ /** Starts the periodic heartbeat timer. */
398
+ private startHeartbeat;
171
399
  }
172
400
  /**
173
- * Create an SSE endpoint handler compatible with Node.js HTTP frameworks.
174
- * Handles both SSE streaming (GET) and RPC requests (POST).
401
+ * Creates a Node.js-compatible HTTP handler that serves an SSE stream (GET)
402
+ * and accepts RPC calls (POST) for a single browser client.
403
+ *
404
+ * @example
405
+ * ```ts
406
+ * import { createSSEHandler } from '@mcp-ts/sdk/server';
407
+ *
408
+ * const handler = createSSEHandler({ userId: 'user-123' });
409
+ * // Mount `handler` on both GET and POST for your HTTP framework.
410
+ * ```
411
+ *
412
+ * @param options - Handler configuration (userId, optional auth check, metadata).
413
+ * @returns An async function `(req, res) => void` suitable as an HTTP handler.
175
414
  */
176
415
  declare function createSSEHandler(options: SSEHandlerOptions): (req: {
177
416
  method?: string;
178
- on: Function;
417
+ on: (event: string, cb: (...args: any[]) => void) => void;
179
418
  }, res: {
180
- writeHead: Function;
181
- write: Function;
419
+ writeHead: (status: number, headers: Record<string, string>) => void;
420
+ write: (chunk: string) => void;
182
421
  }) => Promise<void>;
183
422
 
184
423
  /**
@@ -220,4 +459,15 @@ declare function createNextMcpHandler(options?: NextMcpHandlerOptions): {
220
459
  POST: (request: Request) => Promise<Response>;
221
460
  };
222
461
 
223
- export { type ClientMetadata, McpConnectionEvent, McpObservabilityEvent, McpRpcRequest, McpRpcResponse, type NextMcpHandlerOptions, SSEConnectionManager, type SSEHandlerOptions, SessionMutationListener, SessionStore, createNextMcpHandler, createSSEHandler, onSessionMutation, sessions };
462
+ /**
463
+ * Encrypts an object into a secure string.
464
+ * Falls back to returning the original object if the encryption key is missing or encryption fails.
465
+ */
466
+ declare function encryptObject(data: any): any;
467
+ /**
468
+ * Decrypts a secure string back into an object.
469
+ * Returns the original data if it is unencrypted or if decryption fails.
470
+ */
471
+ declare function decryptObject(data: any): any;
472
+
473
+ export { type ClientMetadata, McpConnectionEvent, McpObservabilityEvent, McpRpcRequest, McpRpcResponse, type NextMcpHandlerOptions, SSEConnectionManager, type SSEHandlerOptions, SessionMutationListener, SessionStore, StorageOAuthClientProvider, createNextMcpHandler, createSSEHandler, decryptObject, encryptObject, onSessionMutation, sessions, withDbObservability };