@mcp-ts/sdk 1.3.7 → 1.3.9

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 (61) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +398 -404
  3. package/dist/adapters/agui-middleware.js.map +1 -1
  4. package/dist/adapters/agui-middleware.mjs.map +1 -1
  5. package/dist/bin/mcp-ts.js +0 -0
  6. package/dist/bin/mcp-ts.js.map +1 -1
  7. package/dist/bin/mcp-ts.mjs +0 -0
  8. package/dist/bin/mcp-ts.mjs.map +1 -1
  9. package/dist/client/index.js.map +1 -1
  10. package/dist/client/index.mjs.map +1 -1
  11. package/dist/client/react.d.mts +2 -2
  12. package/dist/client/react.d.ts +2 -2
  13. package/dist/client/react.js +25 -2
  14. package/dist/client/react.js.map +1 -1
  15. package/dist/client/react.mjs +26 -3
  16. package/dist/client/react.mjs.map +1 -1
  17. package/dist/client/vue.js.map +1 -1
  18. package/dist/client/vue.mjs.map +1 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/server/index.js.map +1 -1
  22. package/dist/server/index.mjs.map +1 -1
  23. package/dist/shared/index.js.map +1 -1
  24. package/dist/shared/index.mjs.map +1 -1
  25. package/package.json +185 -185
  26. package/src/adapters/agui-middleware.ts +382 -382
  27. package/src/bin/mcp-ts.ts +102 -102
  28. package/src/client/core/app-host.ts +417 -417
  29. package/src/client/core/sse-client.ts +371 -371
  30. package/src/client/core/types.ts +31 -31
  31. package/src/client/index.ts +27 -27
  32. package/src/client/react/index.ts +16 -16
  33. package/src/client/react/use-app-host.ts +73 -73
  34. package/src/client/react/use-mcp-apps.tsx +247 -214
  35. package/src/client/react/use-mcp.ts +641 -641
  36. package/src/client/vue/index.ts +10 -10
  37. package/src/client/vue/use-mcp.ts +617 -617
  38. package/src/index.ts +11 -11
  39. package/src/server/handlers/nextjs-handler.ts +204 -204
  40. package/src/server/handlers/sse-handler.ts +631 -631
  41. package/src/server/index.ts +57 -57
  42. package/src/server/mcp/multi-session-client.ts +228 -228
  43. package/src/server/mcp/oauth-client.ts +1188 -1188
  44. package/src/server/mcp/storage-oauth-provider.ts +272 -272
  45. package/src/server/storage/file-backend.ts +157 -157
  46. package/src/server/storage/index.ts +176 -176
  47. package/src/server/storage/memory-backend.ts +123 -123
  48. package/src/server/storage/redis-backend.ts +276 -276
  49. package/src/server/storage/redis.ts +160 -160
  50. package/src/server/storage/sqlite-backend.ts +182 -182
  51. package/src/server/storage/supabase-backend.ts +228 -228
  52. package/src/server/storage/types.ts +116 -116
  53. package/src/shared/constants.ts +29 -29
  54. package/src/shared/errors.ts +133 -133
  55. package/src/shared/event-routing.ts +28 -28
  56. package/src/shared/events.ts +180 -180
  57. package/src/shared/index.ts +75 -75
  58. package/src/shared/tool-utils.ts +61 -61
  59. package/src/shared/types.ts +282 -282
  60. package/src/shared/utils.ts +38 -38
  61. package/supabase/migrations/20260330195700_install_mcp_sessions.sql +84 -84
@@ -1,157 +1,157 @@
1
- import { promises as fs } from 'fs';
2
- import * as path from 'path';
3
- import { StorageBackend, SessionData, SetClientOptions } from './types.js';
4
- import { generateSessionId } from '../../shared/utils.js';
5
-
6
- /**
7
- * File system implementation of StorageBackend
8
- * Persists sessions to a JSON file
9
- */
10
- export class FileStorageBackend implements StorageBackend {
11
- private filePath: string;
12
- private memoryCache: Map<string, SessionData> | null = null;
13
- private initialized = false;
14
-
15
- /**
16
- * @param options.path Path to the JSON file storage (default: ./sessions.json)
17
- */
18
- constructor(options: { path?: string } = {}) {
19
- this.filePath = options.path || './sessions.json';
20
- }
21
-
22
- /**
23
- * Initialize storage: ensure file exists and load into memory cache
24
- */
25
- async init(): Promise<void> {
26
- if (this.initialized) return;
27
-
28
- try {
29
- // Ensure directory exists
30
- const dir = path.dirname(this.filePath);
31
- await fs.mkdir(dir, { recursive: true });
32
-
33
- // Try to read file
34
- const data = await fs.readFile(this.filePath, 'utf-8');
35
- const json = JSON.parse(data);
36
-
37
- this.memoryCache = new Map();
38
- if (Array.isArray(json)) {
39
- json.forEach((s: SessionData) => {
40
- this.memoryCache!.set(this.getSessionKey(s.identity || 'unknown', s.sessionId), s);
41
- });
42
- }
43
- } catch (error: any) {
44
- if (error.code === 'ENOENT') {
45
- // File does not exist, initialize empty
46
- this.memoryCache = new Map();
47
- await this.flush();
48
- } else {
49
- console.error('[FileStorage] Failed to load sessions:', error);
50
- throw error;
51
- }
52
- }
53
-
54
- this.initialized = true;
55
- console.log(`[mcp-ts][Storage] File: ✓ storage directory at ${path.dirname(this.filePath)} verified.`);
56
- }
57
-
58
- private async ensureInitialized() {
59
- if (!this.initialized) await this.init();
60
- }
61
-
62
- private async flush(): Promise<void> {
63
- if (!this.memoryCache) return;
64
- const sessions = Array.from(this.memoryCache.values());
65
- await fs.writeFile(this.filePath, JSON.stringify(sessions, null, 2), 'utf-8');
66
- }
67
-
68
- private getSessionKey(identity: string, sessionId: string): string {
69
- return `${identity}:${sessionId}`;
70
- }
71
-
72
- generateSessionId(): string {
73
- return generateSessionId();
74
- }
75
-
76
- async createSession(session: SessionData, ttl?: number): Promise<void> {
77
- await this.ensureInitialized();
78
- const { sessionId, identity } = session;
79
- if (!sessionId || !identity) throw new Error('identity and sessionId required');
80
-
81
- const sessionKey = this.getSessionKey(identity, sessionId);
82
- if (this.memoryCache!.has(sessionKey)) {
83
- throw new Error(`Session ${sessionId} already exists`);
84
- }
85
-
86
- this.memoryCache!.set(sessionKey, session);
87
- await this.flush();
88
- // Note: TTL is ignored in file backend - sessions don't auto-expire
89
- }
90
-
91
- async updateSession(identity: string, sessionId: string, data: Partial<SessionData>, ttl?: number): Promise<void> {
92
- await this.ensureInitialized();
93
- if (!identity || !sessionId) throw new Error('identity and sessionId required');
94
-
95
- const sessionKey = this.getSessionKey(identity, sessionId);
96
- const current = this.memoryCache!.get(sessionKey);
97
-
98
- if (!current) {
99
- throw new Error(`Session ${sessionId} not found`);
100
- }
101
-
102
- const updated = {
103
- ...current,
104
- ...data
105
- };
106
-
107
- this.memoryCache!.set(sessionKey, updated);
108
- await this.flush();
109
- // Note: TTL is ignored in file backend - sessions don't auto-expire
110
- }
111
-
112
- async getSession(identity: string, sessionId: string): Promise<SessionData | null> {
113
- await this.ensureInitialized();
114
- const sessionKey = this.getSessionKey(identity, sessionId);
115
- return this.memoryCache!.get(sessionKey) || null;
116
- }
117
-
118
- async getIdentitySessionsData(identity: string): Promise<SessionData[]> {
119
- await this.ensureInitialized();
120
- return Array.from(this.memoryCache!.values()).filter(s => s.identity === identity);
121
- }
122
-
123
- async getIdentityMcpSessions(identity: string): Promise<string[]> {
124
- await this.ensureInitialized();
125
- return Array.from(this.memoryCache!.values())
126
- .filter(s => s.identity === identity)
127
- .map(s => s.sessionId);
128
- }
129
-
130
- async removeSession(identity: string, sessionId: string): Promise<void> {
131
- await this.ensureInitialized();
132
- const sessionKey = this.getSessionKey(identity, sessionId);
133
- if (this.memoryCache!.delete(sessionKey)) {
134
- await this.flush();
135
- }
136
- }
137
-
138
- async getAllSessionIds(): Promise<string[]> {
139
- await this.ensureInitialized();
140
- return Array.from(this.memoryCache!.values()).map(s => s.sessionId);
141
- }
142
-
143
- async clearAll(): Promise<void> {
144
- await this.ensureInitialized();
145
- this.memoryCache!.clear();
146
- await this.flush();
147
- }
148
-
149
- async cleanupExpiredSessions(): Promise<void> {
150
- // Could implement TTL check here using createdAt
151
- await this.ensureInitialized();
152
- }
153
-
154
- async disconnect(): Promise<void> {
155
- // No explicit disconnect needed for file
156
- }
157
- }
1
+ import { promises as fs } from 'fs';
2
+ import * as path from 'path';
3
+ import { StorageBackend, SessionData, SetClientOptions } from './types.js';
4
+ import { generateSessionId } from '../../shared/utils.js';
5
+
6
+ /**
7
+ * File system implementation of StorageBackend
8
+ * Persists sessions to a JSON file
9
+ */
10
+ export class FileStorageBackend implements StorageBackend {
11
+ private filePath: string;
12
+ private memoryCache: Map<string, SessionData> | null = null;
13
+ private initialized = false;
14
+
15
+ /**
16
+ * @param options.path Path to the JSON file storage (default: ./sessions.json)
17
+ */
18
+ constructor(options: { path?: string } = {}) {
19
+ this.filePath = options.path || './sessions.json';
20
+ }
21
+
22
+ /**
23
+ * Initialize storage: ensure file exists and load into memory cache
24
+ */
25
+ async init(): Promise<void> {
26
+ if (this.initialized) return;
27
+
28
+ try {
29
+ // Ensure directory exists
30
+ const dir = path.dirname(this.filePath);
31
+ await fs.mkdir(dir, { recursive: true });
32
+
33
+ // Try to read file
34
+ const data = await fs.readFile(this.filePath, 'utf-8');
35
+ const json = JSON.parse(data);
36
+
37
+ this.memoryCache = new Map();
38
+ if (Array.isArray(json)) {
39
+ json.forEach((s: SessionData) => {
40
+ this.memoryCache!.set(this.getSessionKey(s.identity || 'unknown', s.sessionId), s);
41
+ });
42
+ }
43
+ } catch (error: any) {
44
+ if (error.code === 'ENOENT') {
45
+ // File does not exist, initialize empty
46
+ this.memoryCache = new Map();
47
+ await this.flush();
48
+ } else {
49
+ console.error('[FileStorage] Failed to load sessions:', error);
50
+ throw error;
51
+ }
52
+ }
53
+
54
+ this.initialized = true;
55
+ console.log(`[mcp-ts][Storage] File: ✓ storage directory at ${path.dirname(this.filePath)} verified.`);
56
+ }
57
+
58
+ private async ensureInitialized() {
59
+ if (!this.initialized) await this.init();
60
+ }
61
+
62
+ private async flush(): Promise<void> {
63
+ if (!this.memoryCache) return;
64
+ const sessions = Array.from(this.memoryCache.values());
65
+ await fs.writeFile(this.filePath, JSON.stringify(sessions, null, 2), 'utf-8');
66
+ }
67
+
68
+ private getSessionKey(identity: string, sessionId: string): string {
69
+ return `${identity}:${sessionId}`;
70
+ }
71
+
72
+ generateSessionId(): string {
73
+ return generateSessionId();
74
+ }
75
+
76
+ async createSession(session: SessionData, ttl?: number): Promise<void> {
77
+ await this.ensureInitialized();
78
+ const { sessionId, identity } = session;
79
+ if (!sessionId || !identity) throw new Error('identity and sessionId required');
80
+
81
+ const sessionKey = this.getSessionKey(identity, sessionId);
82
+ if (this.memoryCache!.has(sessionKey)) {
83
+ throw new Error(`Session ${sessionId} already exists`);
84
+ }
85
+
86
+ this.memoryCache!.set(sessionKey, session);
87
+ await this.flush();
88
+ // Note: TTL is ignored in file backend - sessions don't auto-expire
89
+ }
90
+
91
+ async updateSession(identity: string, sessionId: string, data: Partial<SessionData>, ttl?: number): Promise<void> {
92
+ await this.ensureInitialized();
93
+ if (!identity || !sessionId) throw new Error('identity and sessionId required');
94
+
95
+ const sessionKey = this.getSessionKey(identity, sessionId);
96
+ const current = this.memoryCache!.get(sessionKey);
97
+
98
+ if (!current) {
99
+ throw new Error(`Session ${sessionId} not found`);
100
+ }
101
+
102
+ const updated = {
103
+ ...current,
104
+ ...data
105
+ };
106
+
107
+ this.memoryCache!.set(sessionKey, updated);
108
+ await this.flush();
109
+ // Note: TTL is ignored in file backend - sessions don't auto-expire
110
+ }
111
+
112
+ async getSession(identity: string, sessionId: string): Promise<SessionData | null> {
113
+ await this.ensureInitialized();
114
+ const sessionKey = this.getSessionKey(identity, sessionId);
115
+ return this.memoryCache!.get(sessionKey) || null;
116
+ }
117
+
118
+ async getIdentitySessionsData(identity: string): Promise<SessionData[]> {
119
+ await this.ensureInitialized();
120
+ return Array.from(this.memoryCache!.values()).filter(s => s.identity === identity);
121
+ }
122
+
123
+ async getIdentityMcpSessions(identity: string): Promise<string[]> {
124
+ await this.ensureInitialized();
125
+ return Array.from(this.memoryCache!.values())
126
+ .filter(s => s.identity === identity)
127
+ .map(s => s.sessionId);
128
+ }
129
+
130
+ async removeSession(identity: string, sessionId: string): Promise<void> {
131
+ await this.ensureInitialized();
132
+ const sessionKey = this.getSessionKey(identity, sessionId);
133
+ if (this.memoryCache!.delete(sessionKey)) {
134
+ await this.flush();
135
+ }
136
+ }
137
+
138
+ async getAllSessionIds(): Promise<string[]> {
139
+ await this.ensureInitialized();
140
+ return Array.from(this.memoryCache!.values()).map(s => s.sessionId);
141
+ }
142
+
143
+ async clearAll(): Promise<void> {
144
+ await this.ensureInitialized();
145
+ this.memoryCache!.clear();
146
+ await this.flush();
147
+ }
148
+
149
+ async cleanupExpiredSessions(): Promise<void> {
150
+ // Could implement TTL check here using createdAt
151
+ await this.ensureInitialized();
152
+ }
153
+
154
+ async disconnect(): Promise<void> {
155
+ // No explicit disconnect needed for file
156
+ }
157
+ }