@mcp-ts/sdk 2.4.2 → 2.4.4
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.
- package/dist/adapters/agui-adapter.d.mts +3 -3
- package/dist/adapters/agui-adapter.d.ts +3 -3
- package/dist/adapters/agui-middleware.d.mts +3 -3
- package/dist/adapters/agui-middleware.d.ts +3 -3
- package/dist/adapters/ai-adapter.d.mts +3 -3
- package/dist/adapters/ai-adapter.d.ts +3 -3
- package/dist/adapters/langchain-adapter.d.mts +3 -3
- package/dist/adapters/langchain-adapter.d.ts +3 -3
- package/dist/adapters/mastra-adapter.d.mts +2 -2
- package/dist/adapters/mastra-adapter.d.ts +2 -2
- package/dist/bin/mcp-ts.js +5 -5
- package/dist/bin/mcp-ts.js.map +1 -1
- package/dist/bin/mcp-ts.mjs +5 -5
- package/dist/bin/mcp-ts.mjs.map +1 -1
- package/dist/client/index.d.mts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/client/react.d.mts +4 -5
- package/dist/client/react.d.ts +4 -5
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.d.mts +4 -5
- package/dist/client/vue.d.ts +4 -5
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs.map +1 -1
- package/dist/{index-B8kJSrBJ.d.ts → index-CZk2gu2E.d.ts} +1 -1
- package/dist/{index-DiJsm_lK.d.mts → index-CkM3p0eE.d.mts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +99 -63
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +99 -63
- package/dist/index.mjs.map +1 -1
- package/dist/{multi-session-client-CWs-AE78.d.mts → multi-session-client-ChQrBZhF.d.mts} +21 -5
- package/dist/{multi-session-client-BluyCPo9.d.ts → multi-session-client-QOOPdEVp.d.ts} +21 -5
- package/dist/server/index.d.mts +4 -4
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +99 -63
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +99 -63
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +4 -4
- package/dist/shared/index.d.ts +4 -4
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs.map +1 -1
- package/dist/{tool-router-CbG4Tum6.d.mts → tool-router-CGs3IDOJ.d.mts} +1 -1
- package/dist/{tool-router-ChIhPwgP.d.ts → tool-router-DQ-HrD7W.d.ts} +1 -1
- package/dist/{types-CjczQwNX.d.mts → types-Bf-7GOLW.d.mts} +0 -2
- package/dist/{types-CjczQwNX.d.ts → types-Bf-7GOLW.d.ts} +0 -2
- package/package.json +1 -1
- package/src/bin/mcp-ts.ts +5 -5
- package/src/client/react/use-mcp.ts +0 -1
- package/src/client/vue/use-mcp.ts +0 -1
- package/src/server/mcp/multi-session-client.ts +13 -0
- package/src/server/mcp/oauth-client.ts +82 -75
- package/src/server/storage/index.ts +8 -8
- package/src/shared/events.ts +0 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import { A as ToolClientProvider, T as ToolClient } from './types-
|
|
2
|
+
import { A as ToolClientProvider, T as ToolClient } from './types-Bf-7GOLW.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* ToolIndex — Lightweight in-memory search index for MCP tool discovery.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import { A as ToolClientProvider, T as ToolClient } from './types-
|
|
2
|
+
import { A as ToolClientProvider, T as ToolClient } from './types-Bf-7GOLW.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* ToolIndex — Lightweight in-memory search index for MCP tool discovery.
|
|
@@ -2,7 +2,6 @@ import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Simple event emitter pattern for MCP connection events
|
|
5
|
-
* Inspired by Cloudflare's agents pattern but adapted for serverless
|
|
6
5
|
*/
|
|
7
6
|
type Disposable = {
|
|
8
7
|
dispose(): void;
|
|
@@ -10,7 +9,6 @@ type Disposable = {
|
|
|
10
9
|
type Event<T> = (listener: (event: T) => void) => Disposable;
|
|
11
10
|
/**
|
|
12
11
|
* Event emitter class for type-safe event handling
|
|
13
|
-
* Similar to Cloudflare's Emitter but simplified for our use case
|
|
14
12
|
*/
|
|
15
13
|
declare class Emitter<T> {
|
|
16
14
|
private listeners;
|
|
@@ -2,7 +2,6 @@ import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Simple event emitter pattern for MCP connection events
|
|
5
|
-
* Inspired by Cloudflare's agents pattern but adapted for serverless
|
|
6
5
|
*/
|
|
7
6
|
type Disposable = {
|
|
8
7
|
dispose(): void;
|
|
@@ -10,7 +9,6 @@ type Disposable = {
|
|
|
10
9
|
type Event<T> = (listener: (event: T) => void) => Disposable;
|
|
11
10
|
/**
|
|
12
11
|
* Event emitter class for type-safe event handling
|
|
13
|
-
* Similar to Cloudflare's Emitter but simplified for our use case
|
|
14
12
|
*/
|
|
15
13
|
declare class Emitter<T> {
|
|
16
14
|
private listeners;
|
package/package.json
CHANGED
package/src/bin/mcp-ts.ts
CHANGED
|
@@ -82,13 +82,13 @@ async function initSupabase() {
|
|
|
82
82
|
console.log(' npx supabase db push');
|
|
83
83
|
console.log('\n3. Add your Supabase credentials to .env:');
|
|
84
84
|
console.log(' SUPABASE_URL=https://<your-project-id>.supabase.co');
|
|
85
|
-
console.log('
|
|
86
|
-
console.log('\n⚠️ Important: Use the
|
|
87
|
-
console.log(' The
|
|
88
|
-
console.log(' Find it in: Supabase Dashboard -> Project Settings -> API ->
|
|
85
|
+
console.log(' SUPABASE_SECRET_KEY=<your-secret-key>');
|
|
86
|
+
console.log('\n⚠️ Important: Use the secret key (not the anon key) for server-side storage.');
|
|
87
|
+
console.log(' The secret key bypasses RLS policies and is required for mcp-ts to work correctly.');
|
|
88
|
+
console.log(' Find it in: Supabase Dashboard -> Project Settings -> API -> Secret key');
|
|
89
89
|
} else if (files.length > 0) {
|
|
90
90
|
console.log('\n👍 All migration files are already present in your project.');
|
|
91
|
-
console.log(' Ensure
|
|
91
|
+
console.log(' Ensure SUPABASE_SECRET_KEY (not SUPABASE_ANON_KEY) is set in your .env');
|
|
92
92
|
} else {
|
|
93
93
|
console.log('⚠️ No migration files found to copy.');
|
|
94
94
|
}
|
|
@@ -152,6 +152,19 @@ export class MultiSessionClient implements ToolClientProvider {
|
|
|
152
152
|
return this.clients;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Removes and disconnects a single session by ID.
|
|
157
|
+
*
|
|
158
|
+
* @returns `true` if the session was found and removed, `false` if not found.
|
|
159
|
+
*/
|
|
160
|
+
async removeSession(sessionId: string): Promise<boolean> {
|
|
161
|
+
const idx = this.clients.findIndex(c => c.getSessionId() === sessionId);
|
|
162
|
+
if (idx === -1) return false;
|
|
163
|
+
const [client] = this.clients.splice(idx, 1);
|
|
164
|
+
await client.disconnect();
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
|
|
155
168
|
/**
|
|
156
169
|
* Gracefully disconnects all active MCP clients and clears the internal list.
|
|
157
170
|
*
|
|
@@ -79,7 +79,7 @@ export interface MCPOAuthClientOptions {
|
|
|
79
79
|
* Emits connection lifecycle events for observability
|
|
80
80
|
*/
|
|
81
81
|
export class MCPClient {
|
|
82
|
-
private client: Client
|
|
82
|
+
private client: Client;
|
|
83
83
|
public oauthProvider: AgentsOAuthProvider | null = null;
|
|
84
84
|
private transport: StreamableHTTPClientTransport | SSEClientTransport | null = null;
|
|
85
85
|
private userId: string;
|
|
@@ -131,6 +131,22 @@ export class MCPClient {
|
|
|
131
131
|
this.clientUri = options.clientUri;
|
|
132
132
|
this.logoUri = options.logoUri;
|
|
133
133
|
this.policyUri = options.policyUri;
|
|
134
|
+
|
|
135
|
+
this.client = new Client(
|
|
136
|
+
{
|
|
137
|
+
name: MCP_CLIENT_NAME,
|
|
138
|
+
version: MCP_CLIENT_VERSION,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
capabilities: {
|
|
142
|
+
extensions: {
|
|
143
|
+
'io.modelcontextprotocol/ui': {
|
|
144
|
+
mimeTypes: ['text/html+mcp'],
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
} as McpAppClientCapabilities,
|
|
148
|
+
}
|
|
149
|
+
);
|
|
134
150
|
}
|
|
135
151
|
|
|
136
152
|
/**
|
|
@@ -257,7 +273,6 @@ export class MCPClient {
|
|
|
257
273
|
const hasSessionHeader = init?.headers && new Headers(init.headers as HeadersInit).has('mcp-session-id');
|
|
258
274
|
|
|
259
275
|
if (response.status === 404 && hasSessionHeader) {
|
|
260
|
-
this.client = null;
|
|
261
276
|
throw new Error("MCP_SESSION_EXPIRED: Downstream session was not found on the server.");
|
|
262
277
|
}
|
|
263
278
|
|
|
@@ -276,13 +291,12 @@ export class MCPClient {
|
|
|
276
291
|
}
|
|
277
292
|
|
|
278
293
|
/**
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
* This method is idempotent and safe to call multiple times
|
|
294
|
+
* Ensures session metadata and OAuth provider are loaded.
|
|
295
|
+
* Does NOT create the SDK Client — callers that need one create it themselves.
|
|
282
296
|
* @private
|
|
283
297
|
*/
|
|
284
|
-
private async
|
|
285
|
-
if (this.
|
|
298
|
+
private async ensureSession(): Promise<void> {
|
|
299
|
+
if (this.oauthProvider) {
|
|
286
300
|
return;
|
|
287
301
|
}
|
|
288
302
|
|
|
@@ -337,24 +351,6 @@ export class MCPClient {
|
|
|
337
351
|
});
|
|
338
352
|
}
|
|
339
353
|
|
|
340
|
-
if (!this.client) {
|
|
341
|
-
this.client = new Client(
|
|
342
|
-
{
|
|
343
|
-
name: MCP_CLIENT_NAME,
|
|
344
|
-
version: MCP_CLIENT_VERSION,
|
|
345
|
-
},
|
|
346
|
-
{
|
|
347
|
-
capabilities: {
|
|
348
|
-
extensions: {
|
|
349
|
-
'io.modelcontextprotocol/ui': {
|
|
350
|
-
mimeTypes: ['text/html+mcp'],
|
|
351
|
-
},
|
|
352
|
-
},
|
|
353
|
-
} as McpAppClientCapabilities
|
|
354
|
-
}
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
354
|
// Create session in the session store if it doesn't exist yet
|
|
359
355
|
// This is needed BEFORE OAuth flow starts because the OAuth provider
|
|
360
356
|
// will call saveCodeVerifier() which requires the session to exist
|
|
@@ -381,6 +377,8 @@ export class MCPClient {
|
|
|
381
377
|
}
|
|
382
378
|
}
|
|
383
379
|
|
|
380
|
+
|
|
381
|
+
|
|
384
382
|
/**
|
|
385
383
|
* Saves current session state to the session store
|
|
386
384
|
* Creates new session if it doesn't exist, updates if it does
|
|
@@ -510,31 +508,21 @@ export class MCPClient {
|
|
|
510
508
|
* @throws {Error} When connection fails for other reasons
|
|
511
509
|
*/
|
|
512
510
|
async connect(): Promise<void> {
|
|
513
|
-
//
|
|
514
|
-
//
|
|
515
|
-
//
|
|
516
|
-
//
|
|
517
|
-
|
|
518
|
-
// causing "Session not found. Reconnect without session header." errors.
|
|
519
|
-
//
|
|
520
|
-
// We also null out this.client so that initialize() creates a fresh Client
|
|
521
|
-
// instance with a clean transport slot, rather than reusing the old one.
|
|
522
|
-
// The oauthProvider is intentionally preserved — OAuth tokens remain valid
|
|
523
|
-
// across reconnects; only the transport session needs to be renegotiated.
|
|
524
|
-
if (this.client?.transport) {
|
|
511
|
+
// Close any existing transport so we can negotiate a fresh session.
|
|
512
|
+
// The SDK Client throws if asked to connect() while a transport is
|
|
513
|
+
// already attached; close() detaches it cleanly so the same Client
|
|
514
|
+
// instance can be reused.
|
|
515
|
+
if (this.client.transport) {
|
|
525
516
|
this.transport = null;
|
|
526
|
-
try {
|
|
527
|
-
await this.client.close();
|
|
528
|
-
} catch {
|
|
517
|
+
try { await this.client.close(); } catch {
|
|
529
518
|
// Closing a transport that may have already failed is best-effort.
|
|
530
519
|
}
|
|
531
|
-
this.client = null;
|
|
532
520
|
}
|
|
533
521
|
|
|
534
|
-
await this.
|
|
522
|
+
await this.ensureSession();
|
|
535
523
|
|
|
536
|
-
if (!this.
|
|
537
|
-
const error = '
|
|
524
|
+
if (!this.oauthProvider) {
|
|
525
|
+
const error = 'OAuth provider not initialized';
|
|
538
526
|
this.emitError(error, 'connection');
|
|
539
527
|
this.emitStateChange('FAILED');
|
|
540
528
|
throw new Error(error);
|
|
@@ -644,7 +632,7 @@ export class MCPClient {
|
|
|
644
632
|
this.emitStateChange('AUTHENTICATING');
|
|
645
633
|
this.emitProgress('Exchanging authorization code for tokens...');
|
|
646
634
|
|
|
647
|
-
await this.
|
|
635
|
+
await this.ensureSession();
|
|
648
636
|
|
|
649
637
|
if (!this.oauthProvider) {
|
|
650
638
|
const error = 'OAuth provider not initialized';
|
|
@@ -791,7 +779,9 @@ export class MCPClient {
|
|
|
791
779
|
params: {},
|
|
792
780
|
};
|
|
793
781
|
|
|
794
|
-
const result = await this.
|
|
782
|
+
const result = await this.withRetry(() =>
|
|
783
|
+
this.client!.request(request, ListToolsResultSchema)
|
|
784
|
+
);
|
|
795
785
|
|
|
796
786
|
if (this.serverId) {
|
|
797
787
|
this._onConnectionEvent.fire({
|
|
@@ -837,7 +827,9 @@ export class MCPClient {
|
|
|
837
827
|
};
|
|
838
828
|
|
|
839
829
|
try {
|
|
840
|
-
const result = await this.
|
|
830
|
+
const result = await this.withRetry(() =>
|
|
831
|
+
this.client!.request(request, CallToolResultSchema)
|
|
832
|
+
);
|
|
841
833
|
|
|
842
834
|
this._onObservabilityEvent.fire({
|
|
843
835
|
type: 'mcp:client:tool_call',
|
|
@@ -897,7 +889,9 @@ export class MCPClient {
|
|
|
897
889
|
params: {},
|
|
898
890
|
};
|
|
899
891
|
|
|
900
|
-
const result = await this.
|
|
892
|
+
const result = await this.withRetry(() =>
|
|
893
|
+
this.client!.request(request, ListPromptsResultSchema)
|
|
894
|
+
);
|
|
901
895
|
|
|
902
896
|
this.emitStateChange('READY');
|
|
903
897
|
this.emitProgress(`Discovered ${result.prompts.length} prompts`);
|
|
@@ -931,7 +925,9 @@ export class MCPClient {
|
|
|
931
925
|
},
|
|
932
926
|
};
|
|
933
927
|
|
|
934
|
-
return await this.
|
|
928
|
+
return await this.withRetry(() =>
|
|
929
|
+
this.client!.request(request, GetPromptResultSchema)
|
|
930
|
+
);
|
|
935
931
|
}
|
|
936
932
|
|
|
937
933
|
/**
|
|
@@ -952,7 +948,9 @@ export class MCPClient {
|
|
|
952
948
|
params: {},
|
|
953
949
|
};
|
|
954
950
|
|
|
955
|
-
const result = await this.
|
|
951
|
+
const result = await this.withRetry(() =>
|
|
952
|
+
this.client!.request(request, ListResourcesResultSchema)
|
|
953
|
+
);
|
|
956
954
|
|
|
957
955
|
this.emitStateChange('READY');
|
|
958
956
|
this.emitProgress(`Discovered ${result.resources.length} resources`);
|
|
@@ -984,7 +982,33 @@ export class MCPClient {
|
|
|
984
982
|
},
|
|
985
983
|
};
|
|
986
984
|
|
|
987
|
-
return await this.
|
|
985
|
+
return await this.withRetry(() =>
|
|
986
|
+
this.client!.request(request, ReadResourceResultSchema)
|
|
987
|
+
);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
/**
|
|
991
|
+
* Wraps an MCP request with automatic transport-session recovery.
|
|
992
|
+
*
|
|
993
|
+
* When the downstream MCP server rejects the request with a 404 indicating
|
|
994
|
+
* the transport session has expired, this method tears down the stale SDK
|
|
995
|
+
* client and transport, calls {@link reconnect} to negotiate a fresh session,
|
|
996
|
+
* and retries the request once.
|
|
997
|
+
*
|
|
998
|
+
* Non-transient errors (network failures, auth errors, etc.) propagate as-is.
|
|
999
|
+
*/
|
|
1000
|
+
private async withRetry<T>(fn: () => Promise<T>): Promise<T> {
|
|
1001
|
+
try {
|
|
1002
|
+
return await fn();
|
|
1003
|
+
} catch (error) {
|
|
1004
|
+
if (!(error instanceof Error && error.message.includes('MCP_SESSION_EXPIRED'))) throw error;
|
|
1005
|
+
if (this.client.transport) {
|
|
1006
|
+
try { await this.client.close(); } catch {}
|
|
1007
|
+
this.transport = null;
|
|
1008
|
+
}
|
|
1009
|
+
await this.reconnect();
|
|
1010
|
+
return await fn();
|
|
1011
|
+
}
|
|
988
1012
|
}
|
|
989
1013
|
|
|
990
1014
|
/**
|
|
@@ -994,25 +1018,9 @@ export class MCPClient {
|
|
|
994
1018
|
* @throws {Error} When OAuth provider is not initialized
|
|
995
1019
|
*/
|
|
996
1020
|
async reconnect(): Promise<void> {
|
|
997
|
-
await this.
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
throw new Error('OAuth provider not initialized');
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
this.client = new Client(
|
|
1004
|
-
{
|
|
1005
|
-
name: MCP_CLIENT_NAME,
|
|
1006
|
-
version: MCP_CLIENT_VERSION,
|
|
1007
|
-
},
|
|
1008
|
-
{ capabilities: {} }
|
|
1009
|
-
);
|
|
1010
|
-
|
|
1011
|
-
// Use default logic to get transport, defaulting to what's stored or auto
|
|
1012
|
-
const tt = this.transportType || 'streamable-http';
|
|
1013
|
-
this.transport = this.getTransport(tt);
|
|
1014
|
-
|
|
1015
|
-
await this.client.connect(this.transport);
|
|
1021
|
+
await this.ensureSession();
|
|
1022
|
+
if (!this.oauthProvider) throw new Error('OAuth provider not initialized');
|
|
1023
|
+
await this.connect();
|
|
1016
1024
|
}
|
|
1017
1025
|
|
|
1018
1026
|
/**
|
|
@@ -1021,7 +1029,7 @@ export class MCPClient {
|
|
|
1021
1029
|
*/
|
|
1022
1030
|
async clearSession(): Promise<void> {
|
|
1023
1031
|
try {
|
|
1024
|
-
await this.
|
|
1032
|
+
await this.ensureSession();
|
|
1025
1033
|
} catch (error) {
|
|
1026
1034
|
console.warn('[MCPClient] Initialization failed during clearSession:', error);
|
|
1027
1035
|
}
|
|
@@ -1039,7 +1047,7 @@ export class MCPClient {
|
|
|
1039
1047
|
* @returns True if connected, false otherwise
|
|
1040
1048
|
*/
|
|
1041
1049
|
isConnected(): boolean {
|
|
1042
|
-
return this.client !==
|
|
1050
|
+
return this.client.transport !== undefined;
|
|
1043
1051
|
}
|
|
1044
1052
|
|
|
1045
1053
|
/**
|
|
@@ -1066,10 +1074,9 @@ export class MCPClient {
|
|
|
1066
1074
|
}
|
|
1067
1075
|
}
|
|
1068
1076
|
|
|
1069
|
-
if (this.client) {
|
|
1070
|
-
this.client.close();
|
|
1077
|
+
if (this.client.transport) {
|
|
1078
|
+
try { await this.client.close(); } catch {}
|
|
1071
1079
|
}
|
|
1072
|
-
this.client = null;
|
|
1073
1080
|
this.oauthProvider = null;
|
|
1074
1081
|
this.transport = null;
|
|
1075
1082
|
|
|
@@ -141,13 +141,13 @@ async function createStorage(): Promise<SessionStore> {
|
|
|
141
141
|
|
|
142
142
|
if (type === 'supabase') {
|
|
143
143
|
const url = process.env.SUPABASE_URL;
|
|
144
|
-
const key = process.env.
|
|
144
|
+
const key = process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY;
|
|
145
145
|
|
|
146
146
|
if (!url || !key) {
|
|
147
|
-
console.warn('[mcp-ts][Storage] Explicit selection "supabase" requires SUPABASE_URL and
|
|
147
|
+
console.warn('[mcp-ts][Storage] Explicit selection "supabase" requires SUPABASE_URL and SUPABASE_SECRET_KEY.');
|
|
148
148
|
} else {
|
|
149
|
-
if (!process.env.
|
|
150
|
-
console.warn('[mcp-ts][Storage] ⚠️ Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "
|
|
149
|
+
if (!process.env.SUPABASE_SECRET_KEY) {
|
|
150
|
+
console.warn('[mcp-ts][Storage] ⚠️ Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "SUPABASE_SECRET_KEY" is recommended.');
|
|
151
151
|
}
|
|
152
152
|
try {
|
|
153
153
|
const { createClient } = await import('@supabase/supabase-js');
|
|
@@ -210,14 +210,14 @@ async function createStorage(): Promise<SessionStore> {
|
|
|
210
210
|
return await initializeStorage(new SqliteStorage({ path: process.env.MCP_TS_STORAGE_SQLITE_PATH }));
|
|
211
211
|
}
|
|
212
212
|
|
|
213
|
-
if (process.env.SUPABASE_URL && (process.env.
|
|
213
|
+
if (process.env.SUPABASE_URL && (process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY)) {
|
|
214
214
|
try {
|
|
215
215
|
const { createClient } = await import('@supabase/supabase-js');
|
|
216
216
|
const url = process.env.SUPABASE_URL;
|
|
217
|
-
const key = process.env.
|
|
217
|
+
const key = process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY!;
|
|
218
218
|
|
|
219
|
-
if (!process.env.
|
|
220
|
-
console.warn('[mcp-ts][Storage] ⚠️ Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "
|
|
219
|
+
if (!process.env.SUPABASE_SECRET_KEY) {
|
|
220
|
+
console.warn('[mcp-ts][Storage] ⚠️ Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "SUPABASE_SECRET_KEY" is recommended.');
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
const client = createClient(url, key);
|
package/src/shared/events.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Simple event emitter pattern for MCP connection events
|
|
3
|
-
* Inspired by Cloudflare's agents pattern but adapted for serverless
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
export type Disposable = {
|
|
@@ -11,7 +10,6 @@ export type Event<T> = (listener: (event: T) => void) => Disposable;
|
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* Event emitter class for type-safe event handling
|
|
14
|
-
* Similar to Cloudflare's Emitter but simplified for our use case
|
|
15
13
|
*/
|
|
16
14
|
export class Emitter<T> {
|
|
17
15
|
private listeners: Set<(event: T) => void> = new Set();
|