@mcp-ts/sdk 1.3.7 → 1.3.10

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 (66) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +397 -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 +10 -28
  12. package/dist/client/react.d.ts +10 -28
  13. package/dist/client/react.js +101 -52
  14. package/dist/client/react.js.map +1 -1
  15. package/dist/client/react.mjs +102 -53
  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 +78 -6
  20. package/dist/index.js.map +1 -1
  21. package/dist/index.mjs +73 -6
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/server/index.js +78 -6
  24. package/dist/server/index.js.map +1 -1
  25. package/dist/server/index.mjs +73 -6
  26. package/dist/server/index.mjs.map +1 -1
  27. package/dist/shared/index.js.map +1 -1
  28. package/dist/shared/index.mjs.map +1 -1
  29. package/package.json +185 -185
  30. package/src/adapters/agui-middleware.ts +382 -382
  31. package/src/bin/mcp-ts.ts +102 -102
  32. package/src/client/core/app-host.ts +417 -417
  33. package/src/client/core/sse-client.ts +371 -371
  34. package/src/client/core/types.ts +31 -31
  35. package/src/client/index.ts +27 -27
  36. package/src/client/react/index.ts +20 -16
  37. package/src/client/react/use-app-host.ts +74 -73
  38. package/src/client/react/use-mcp-apps.tsx +224 -214
  39. package/src/client/react/use-mcp.ts +669 -641
  40. package/src/client/vue/index.ts +10 -10
  41. package/src/client/vue/use-mcp.ts +617 -617
  42. package/src/index.ts +11 -11
  43. package/src/server/handlers/nextjs-handler.ts +204 -204
  44. package/src/server/handlers/sse-handler.ts +631 -631
  45. package/src/server/index.ts +57 -57
  46. package/src/server/mcp/multi-session-client.ts +228 -228
  47. package/src/server/mcp/oauth-client.ts +1188 -1188
  48. package/src/server/mcp/storage-oauth-provider.ts +272 -272
  49. package/src/server/storage/crypto.ts +92 -0
  50. package/src/server/storage/file-backend.ts +157 -157
  51. package/src/server/storage/index.ts +176 -176
  52. package/src/server/storage/memory-backend.ts +123 -123
  53. package/src/server/storage/redis-backend.ts +276 -276
  54. package/src/server/storage/redis.ts +160 -160
  55. package/src/server/storage/sqlite-backend.ts +182 -182
  56. package/src/server/storage/supabase-backend.ts +229 -228
  57. package/src/server/storage/types.ts +116 -116
  58. package/src/shared/constants.ts +29 -29
  59. package/src/shared/errors.ts +133 -133
  60. package/src/shared/event-routing.ts +28 -28
  61. package/src/shared/events.ts +180 -180
  62. package/src/shared/index.ts +75 -75
  63. package/src/shared/tool-utils.ts +61 -61
  64. package/src/shared/types.ts +282 -282
  65. package/src/shared/utils.ts +38 -38
  66. 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
+ }