@mcp-ts/sdk 2.2.0 → 2.3.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.
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +66 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +66 -2
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +13 -1
- package/dist/server/index.d.ts +13 -1
- package/dist/server/index.js +66 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +66 -2
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/server/index.ts +8 -1
- package/src/server/storage/index.ts +77 -2
- package/src/server/storage/types.ts +14 -0
package/package.json
CHANGED
package/src/server/index.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
/** Core MCP client and session management */
|
|
7
7
|
export { MCPClient } from './mcp/oauth-client.js';
|
|
8
8
|
export { UnauthorizedError } from '../shared/errors.js';
|
|
9
|
-
export { sessions, type SessionStore } from './storage/index.js';
|
|
9
|
+
export { sessions, onSessionMutation, type SessionStore } from './storage/index.js';
|
|
10
10
|
export { StorageOAuthClientProvider } from './mcp/storage-oauth-provider.js';
|
|
11
11
|
export { MultiSessionClient } from './mcp/multi-session-client.js';
|
|
12
12
|
|
|
@@ -44,6 +44,13 @@ export type {
|
|
|
44
44
|
CallToolResponse,
|
|
45
45
|
} from '../shared/types';
|
|
46
46
|
|
|
47
|
+
export type {
|
|
48
|
+
Session,
|
|
49
|
+
SessionMutationEvent,
|
|
50
|
+
SessionMutationListener,
|
|
51
|
+
SessionMutationType,
|
|
52
|
+
} from './storage/types.js';
|
|
53
|
+
|
|
47
54
|
/** Re-export MCP SDK types for convenience */
|
|
48
55
|
export type {
|
|
49
56
|
OAuthClientMetadata,
|
|
@@ -5,7 +5,7 @@ import { FileStorageBackend } from './file-backend';
|
|
|
5
5
|
import { SqliteStorage } from './sqlite-backend.js';
|
|
6
6
|
import { SupabaseStorageBackend } from './supabase-backend.js';
|
|
7
7
|
import { NeonStorageBackend, type NeonStorageOptions } from './neon-backend.js';
|
|
8
|
-
import type { SessionStore } from './types.js';
|
|
8
|
+
import type { SessionStore, Session, SessionMutationEvent, SessionMutationListener } from './types.js';
|
|
9
9
|
|
|
10
10
|
// Re-export types
|
|
11
11
|
export * from './types.js';
|
|
@@ -42,6 +42,65 @@ function warnIfNeonConnectionStringIsInsecure(connectionString: string): void {
|
|
|
42
42
|
|
|
43
43
|
let storageInstance: SessionStore | null = null;
|
|
44
44
|
let storagePromise: Promise<SessionStore> | null = null;
|
|
45
|
+
const sessionMutationListeners = new Set<SessionMutationListener>();
|
|
46
|
+
|
|
47
|
+
function emitSessionMutation(event: SessionMutationEvent): void {
|
|
48
|
+
for (const listener of sessionMutationListeners) {
|
|
49
|
+
try {
|
|
50
|
+
const result = listener(event);
|
|
51
|
+
if (result && typeof (result as Promise<void>).catch === 'function') {
|
|
52
|
+
void (result as Promise<void>).catch((error) => {
|
|
53
|
+
console.error('[mcp-ts][Storage] Session mutation listener failed:', error);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('[mcp-ts][Storage] Session mutation listener failed:', error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function createSessionMutationEvent(prop: PropertyKey, args: any[]): SessionMutationEvent | null {
|
|
63
|
+
const timestamp = Date.now();
|
|
64
|
+
|
|
65
|
+
if (prop === 'create') {
|
|
66
|
+
const [session, ttl] = args as [Session, number | undefined];
|
|
67
|
+
if (!session?.userId || !session?.sessionId) return null;
|
|
68
|
+
return {
|
|
69
|
+
type: 'create',
|
|
70
|
+
userId: session.userId,
|
|
71
|
+
sessionId: session.sessionId,
|
|
72
|
+
session,
|
|
73
|
+
ttl,
|
|
74
|
+
timestamp,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (prop === 'update') {
|
|
79
|
+
const [userId, sessionId, patch, ttl] = args as [string, string, Partial<Session>, number | undefined];
|
|
80
|
+
if (!userId || !sessionId) return null;
|
|
81
|
+
return {
|
|
82
|
+
type: 'update',
|
|
83
|
+
userId,
|
|
84
|
+
sessionId,
|
|
85
|
+
patch,
|
|
86
|
+
ttl,
|
|
87
|
+
timestamp,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (prop === 'delete') {
|
|
92
|
+
const [userId, sessionId] = args as [string, string];
|
|
93
|
+
if (!userId || !sessionId) return null;
|
|
94
|
+
return {
|
|
95
|
+
type: 'delete',
|
|
96
|
+
userId,
|
|
97
|
+
sessionId,
|
|
98
|
+
timestamp,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
45
104
|
|
|
46
105
|
async function initializeStorage<T extends SessionStore>(store: T): Promise<T> {
|
|
47
106
|
if (typeof store.init === 'function') {
|
|
@@ -215,6 +274,17 @@ export function _setStorageInstanceForTesting(instance: SessionStore | null): vo
|
|
|
215
274
|
}
|
|
216
275
|
}
|
|
217
276
|
|
|
277
|
+
export function onSessionMutation(listener: SessionMutationListener): () => void {
|
|
278
|
+
sessionMutationListeners.add(listener);
|
|
279
|
+
return () => {
|
|
280
|
+
sessionMutationListeners.delete(listener);
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function _resetSessionMutationListenersForTesting(): void {
|
|
285
|
+
sessionMutationListeners.clear();
|
|
286
|
+
}
|
|
287
|
+
|
|
218
288
|
/**
|
|
219
289
|
* Global session store instance
|
|
220
290
|
* Uses lazy initialization with a Proxy to handle async setup transparently
|
|
@@ -225,7 +295,12 @@ export const sessions: SessionStore = new Proxy({} as SessionStore, {
|
|
|
225
295
|
const instance = await getStorage();
|
|
226
296
|
const value = (instance as any)[prop];
|
|
227
297
|
if (typeof value === 'function') {
|
|
228
|
-
|
|
298
|
+
const result = await value.apply(instance, args);
|
|
299
|
+
const event = createSessionMutationEvent(prop, args);
|
|
300
|
+
if (event) {
|
|
301
|
+
emitSessionMutation(event);
|
|
302
|
+
}
|
|
303
|
+
return result;
|
|
229
304
|
}
|
|
230
305
|
return value;
|
|
231
306
|
};
|
|
@@ -29,6 +29,20 @@ export interface Session {
|
|
|
29
29
|
clientId?: string;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
export type SessionMutationType = 'create' | 'update' | 'delete';
|
|
33
|
+
|
|
34
|
+
export interface SessionMutationEvent {
|
|
35
|
+
type: SessionMutationType;
|
|
36
|
+
userId: string;
|
|
37
|
+
sessionId: string;
|
|
38
|
+
timestamp: number;
|
|
39
|
+
session?: Session;
|
|
40
|
+
patch?: Partial<Session>;
|
|
41
|
+
ttl?: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type SessionMutationListener = (event: SessionMutationEvent) => void | Promise<void>;
|
|
45
|
+
|
|
32
46
|
export interface SetClientOptions {
|
|
33
47
|
sessionId: string;
|
|
34
48
|
serverId?: string; // Database server ID
|