@mcp-ts/sdk 1.3.6 → 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 (103) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +398 -404
  3. package/dist/adapters/agui-adapter.d.mts +1 -1
  4. package/dist/adapters/agui-adapter.d.ts +1 -1
  5. package/dist/adapters/agui-adapter.js +2 -2
  6. package/dist/adapters/agui-adapter.js.map +1 -1
  7. package/dist/adapters/agui-adapter.mjs +2 -2
  8. package/dist/adapters/agui-adapter.mjs.map +1 -1
  9. package/dist/adapters/agui-middleware.d.mts +1 -1
  10. package/dist/adapters/agui-middleware.d.ts +1 -1
  11. package/dist/adapters/agui-middleware.js.map +1 -1
  12. package/dist/adapters/agui-middleware.mjs.map +1 -1
  13. package/dist/adapters/ai-adapter.d.mts +1 -1
  14. package/dist/adapters/ai-adapter.d.ts +1 -1
  15. package/dist/adapters/ai-adapter.js +1 -1
  16. package/dist/adapters/ai-adapter.js.map +1 -1
  17. package/dist/adapters/ai-adapter.mjs +1 -1
  18. package/dist/adapters/ai-adapter.mjs.map +1 -1
  19. package/dist/adapters/langchain-adapter.d.mts +1 -1
  20. package/dist/adapters/langchain-adapter.d.ts +1 -1
  21. package/dist/adapters/langchain-adapter.js +1 -1
  22. package/dist/adapters/langchain-adapter.js.map +1 -1
  23. package/dist/adapters/langchain-adapter.mjs +1 -1
  24. package/dist/adapters/langchain-adapter.mjs.map +1 -1
  25. package/dist/adapters/mastra-adapter.d.mts +1 -1
  26. package/dist/adapters/mastra-adapter.d.ts +1 -1
  27. package/dist/adapters/mastra-adapter.js +1 -1
  28. package/dist/adapters/mastra-adapter.js.map +1 -1
  29. package/dist/adapters/mastra-adapter.mjs +1 -1
  30. package/dist/adapters/mastra-adapter.mjs.map +1 -1
  31. package/dist/bin/mcp-ts.js +0 -0
  32. package/dist/bin/mcp-ts.js.map +1 -1
  33. package/dist/bin/mcp-ts.mjs +0 -0
  34. package/dist/bin/mcp-ts.mjs.map +1 -1
  35. package/dist/client/index.js.map +1 -1
  36. package/dist/client/index.mjs.map +1 -1
  37. package/dist/client/react.d.mts +2 -2
  38. package/dist/client/react.d.ts +2 -2
  39. package/dist/client/react.js +25 -2
  40. package/dist/client/react.js.map +1 -1
  41. package/dist/client/react.mjs +26 -3
  42. package/dist/client/react.mjs.map +1 -1
  43. package/dist/client/vue.js.map +1 -1
  44. package/dist/client/vue.mjs.map +1 -1
  45. package/dist/index.d.mts +1 -1
  46. package/dist/index.d.ts +1 -1
  47. package/dist/index.js +134 -71
  48. package/dist/index.js.map +1 -1
  49. package/dist/index.mjs +134 -71
  50. package/dist/index.mjs.map +1 -1
  51. package/dist/{multi-session-client-BYLarghq.d.ts → multi-session-client-CHE8QpVE.d.ts} +75 -5
  52. package/dist/{multi-session-client-CzhMkE0k.d.mts → multi-session-client-CQsRbxYI.d.mts} +75 -5
  53. package/dist/server/index.d.mts +1 -1
  54. package/dist/server/index.d.ts +1 -1
  55. package/dist/server/index.js +134 -71
  56. package/dist/server/index.js.map +1 -1
  57. package/dist/server/index.mjs +134 -71
  58. package/dist/server/index.mjs.map +1 -1
  59. package/dist/shared/index.js +10 -2
  60. package/dist/shared/index.js.map +1 -1
  61. package/dist/shared/index.mjs +10 -2
  62. package/dist/shared/index.mjs.map +1 -1
  63. package/package.json +185 -185
  64. package/src/adapters/agui-adapter.ts +222 -222
  65. package/src/adapters/agui-middleware.ts +382 -382
  66. package/src/adapters/ai-adapter.ts +115 -115
  67. package/src/adapters/langchain-adapter.ts +127 -127
  68. package/src/adapters/mastra-adapter.ts +126 -126
  69. package/src/bin/mcp-ts.ts +102 -102
  70. package/src/client/core/app-host.ts +417 -417
  71. package/src/client/core/sse-client.ts +371 -371
  72. package/src/client/core/types.ts +31 -31
  73. package/src/client/index.ts +27 -27
  74. package/src/client/react/index.ts +16 -16
  75. package/src/client/react/use-app-host.ts +73 -73
  76. package/src/client/react/use-mcp-apps.tsx +247 -214
  77. package/src/client/react/use-mcp.ts +641 -641
  78. package/src/client/vue/index.ts +10 -10
  79. package/src/client/vue/use-mcp.ts +617 -617
  80. package/src/index.ts +11 -11
  81. package/src/server/handlers/nextjs-handler.ts +204 -204
  82. package/src/server/handlers/sse-handler.ts +631 -631
  83. package/src/server/index.ts +57 -57
  84. package/src/server/mcp/multi-session-client.ts +228 -132
  85. package/src/server/mcp/oauth-client.ts +1188 -1188
  86. package/src/server/mcp/storage-oauth-provider.ts +272 -272
  87. package/src/server/storage/file-backend.ts +157 -170
  88. package/src/server/storage/index.ts +176 -175
  89. package/src/server/storage/memory-backend.ts +123 -136
  90. package/src/server/storage/redis-backend.ts +276 -289
  91. package/src/server/storage/redis.ts +160 -160
  92. package/src/server/storage/sqlite-backend.ts +182 -186
  93. package/src/server/storage/supabase-backend.ts +228 -227
  94. package/src/server/storage/types.ts +116 -116
  95. package/src/shared/constants.ts +29 -29
  96. package/src/shared/errors.ts +133 -133
  97. package/src/shared/event-routing.ts +28 -28
  98. package/src/shared/events.ts +180 -180
  99. package/src/shared/index.ts +75 -75
  100. package/src/shared/tool-utils.ts +61 -61
  101. package/src/shared/types.ts +282 -282
  102. package/src/shared/utils.ts +38 -16
  103. package/supabase/migrations/20260330195700_install_mcp_sessions.sql +84 -84
@@ -1,186 +1,182 @@
1
- import type { Database } from 'better-sqlite3';
2
- import { StorageBackend, SessionData } from './types.js'; // Ensure .js extension
3
- import * as fs from 'fs';
4
- import * as path from 'path';
5
-
6
- export interface SqliteStorageOptions {
7
- path?: string;
8
- table?: string;
9
- }
10
-
11
- export class SqliteStorage implements StorageBackend {
12
- private db: Database | null = null;
13
- private table: string;
14
- private initialized = false;
15
- private dbPath: string;
16
-
17
- constructor(options: SqliteStorageOptions = {}) {
18
- this.dbPath = options.path || './sessions.db';
19
- this.table = options.table || 'mcp_sessions';
20
- }
21
-
22
- async init(): Promise<void> {
23
- if (this.initialized) return;
24
-
25
- try {
26
- // Dynamic import for peer dependency
27
- const DatabaseConstructor = (await import('better-sqlite3')).default;
28
-
29
- // Ensure directory exists
30
- const dir = path.dirname(this.dbPath);
31
- if (!fs.existsSync(dir)) {
32
- fs.mkdirSync(dir, { recursive: true });
33
- }
34
-
35
- this.db = new DatabaseConstructor(this.dbPath);
36
- this.db.exec(`
37
- CREATE TABLE IF NOT EXISTS ${this.table} (
38
- sessionId TEXT PRIMARY KEY,
39
- identity TEXT NOT NULL,
40
- data TEXT NOT NULL,
41
- expiresAt INTEGER
42
- );
43
- CREATE INDEX IF NOT EXISTS idx_${this.table}_identity ON ${this.table}(identity);
44
- `);
45
-
46
- this.initialized = true;
47
- console.log(`[mcp-ts][Storage] SQLite: ✓ database at ${this.dbPath} verified.`);
48
- } catch (error: any) {
49
- if (error.code === 'MODULE_NOT_FOUND' || error.message?.includes('better-sqlite3')) {
50
- throw new Error(
51
- 'better-sqlite3 is not installed. Please install it with: npm install better-sqlite3'
52
- );
53
- }
54
- throw error;
55
- }
56
- }
57
-
58
- private ensureInitialized() {
59
- if (!this.initialized) {
60
- throw new Error('SqliteStorage not initialized. Call init() first.');
61
- }
62
- }
63
-
64
- generateSessionId(): string {
65
- const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
66
- let result = '';
67
- for (let i = 0; i < 32; i++) {
68
- result += chars.charAt(Math.floor(Math.random() * chars.length));
69
- }
70
- return result;
71
- }
72
-
73
- async createSession(session: SessionData, ttl?: number): Promise<void> {
74
- this.ensureInitialized();
75
- const { sessionId, identity } = session;
76
-
77
- if (!sessionId || !identity) {
78
- throw new Error('identity and sessionId required');
79
- }
80
-
81
- const expiresAt = ttl ? Date.now() + ttl * 1000 : null;
82
-
83
- try {
84
- const stmt = this.db!.prepare(
85
- `INSERT INTO ${this.table} (sessionId, identity, data, expiresAt) VALUES (?, ?, ?, ?)`
86
- );
87
- stmt.run(sessionId, identity, JSON.stringify(session), expiresAt);
88
- } catch (error: any) {
89
- if (error.code === 'SQLITE_CONSTRAINT_PRIMARYKEY') {
90
- throw new Error(`Session ${sessionId} already exists`);
91
- }
92
- throw error;
93
- }
94
- }
95
-
96
- async updateSession(identity: string, sessionId: string, data: Partial<SessionData>, ttl?: number): Promise<void> {
97
- this.ensureInitialized();
98
- if (!sessionId || !identity) {
99
- throw new Error('identity and sessionId required');
100
- }
101
-
102
- const currentSession = await this.getSession(identity, sessionId);
103
- if (!currentSession) {
104
- throw new Error(`Session ${sessionId} not found for identity ${identity}`);
105
- }
106
-
107
- const updatedSession = { ...currentSession, ...data };
108
- const expiresAt = ttl ? Date.now() + ttl * 1000 : null;
109
-
110
- const stmt = this.db!.prepare(
111
- `UPDATE ${this.table} SET data = ?, expiresAt = ? WHERE sessionId = ? AND identity = ?`
112
- );
113
-
114
- stmt.run(JSON.stringify(updatedSession), expiresAt, sessionId, identity);
115
- }
116
-
117
- async getSession(identity: string, sessionId: string): Promise<SessionData | null> {
118
- this.ensureInitialized();
119
-
120
- const stmt = this.db!.prepare(
121
- `SELECT data FROM ${this.table} WHERE sessionId = ? AND identity = ?`
122
- );
123
- const row = stmt.get(sessionId, identity) as { data: string } | undefined;
124
-
125
- if (!row) return null;
126
- return JSON.parse(row.data) as SessionData;
127
- }
128
-
129
- async getIdentitySessionsData(identity: string): Promise<SessionData[]> {
130
- this.ensureInitialized();
131
-
132
- const stmt = this.db!.prepare(
133
- `SELECT data FROM ${this.table} WHERE identity = ?`
134
- );
135
- const rows = stmt.all(identity) as { data: string }[];
136
-
137
- return rows.map(row => JSON.parse(row.data) as SessionData);
138
- }
139
-
140
- async getIdentityMcpSessions(identity: string): Promise<string[]> {
141
- this.ensureInitialized();
142
-
143
- const stmt = this.db!.prepare(
144
- `SELECT sessionId FROM ${this.table} WHERE identity = ?`
145
- );
146
- const rows = stmt.all(identity) as { sessionId: string }[];
147
-
148
- return rows.map(row => row.sessionId);
149
- }
150
-
151
- async removeSession(identity: string, sessionId: string): Promise<void> {
152
- this.ensureInitialized();
153
- const stmt = this.db!.prepare(
154
- `DELETE FROM ${this.table} WHERE sessionId = ? AND identity = ?`
155
- );
156
- stmt.run(sessionId, identity);
157
- }
158
-
159
- async getAllSessionIds(): Promise<string[]> {
160
- this.ensureInitialized();
161
- const stmt = this.db!.prepare(`SELECT sessionId FROM ${this.table}`);
162
- const rows = stmt.all() as { sessionId: string }[];
163
- return rows.map(row => row.sessionId);
164
- }
165
-
166
- async clearAll(): Promise<void> {
167
- this.ensureInitialized();
168
- const stmt = this.db!.prepare(`DELETE FROM ${this.table}`);
169
- stmt.run();
170
- }
171
-
172
- async cleanupExpiredSessions(): Promise<void> {
173
- this.ensureInitialized();
174
- const now = Date.now();
175
- const stmt = this.db!.prepare(
176
- `DELETE FROM ${this.table} WHERE expiresAt IS NOT NULL AND expiresAt < ?`
177
- );
178
- stmt.run(now);
179
- }
180
-
181
- async disconnect(): Promise<void> {
182
- if (this.db) {
183
- this.db.close();
184
- }
185
- }
186
- }
1
+ import type { Database } from 'better-sqlite3';
2
+ import { StorageBackend, SessionData } from './types.js'; // Ensure .js extension
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import { generateSessionId } from '../../shared/utils.js';
6
+
7
+ export interface SqliteStorageOptions {
8
+ path?: string;
9
+ table?: string;
10
+ }
11
+
12
+ export class SqliteStorage implements StorageBackend {
13
+ private db: Database | null = null;
14
+ private table: string;
15
+ private initialized = false;
16
+ private dbPath: string;
17
+
18
+ constructor(options: SqliteStorageOptions = {}) {
19
+ this.dbPath = options.path || './sessions.db';
20
+ this.table = options.table || 'mcp_sessions';
21
+ }
22
+
23
+ async init(): Promise<void> {
24
+ if (this.initialized) return;
25
+
26
+ try {
27
+ // Dynamic import for peer dependency
28
+ const DatabaseConstructor = (await import('better-sqlite3')).default;
29
+
30
+ // Ensure directory exists
31
+ const dir = path.dirname(this.dbPath);
32
+ if (!fs.existsSync(dir)) {
33
+ fs.mkdirSync(dir, { recursive: true });
34
+ }
35
+
36
+ this.db = new DatabaseConstructor(this.dbPath);
37
+ this.db.exec(`
38
+ CREATE TABLE IF NOT EXISTS ${this.table} (
39
+ sessionId TEXT PRIMARY KEY,
40
+ identity TEXT NOT NULL,
41
+ data TEXT NOT NULL,
42
+ expiresAt INTEGER
43
+ );
44
+ CREATE INDEX IF NOT EXISTS idx_${this.table}_identity ON ${this.table}(identity);
45
+ `);
46
+
47
+ this.initialized = true;
48
+ console.log(`[mcp-ts][Storage] SQLite: database at ${this.dbPath} verified.`);
49
+ } catch (error: any) {
50
+ if (error.code === 'MODULE_NOT_FOUND' || error.message?.includes('better-sqlite3')) {
51
+ throw new Error(
52
+ 'better-sqlite3 is not installed. Please install it with: npm install better-sqlite3'
53
+ );
54
+ }
55
+ throw error;
56
+ }
57
+ }
58
+
59
+ private ensureInitialized() {
60
+ if (!this.initialized) {
61
+ throw new Error('SqliteStorage not initialized. Call init() first.');
62
+ }
63
+ }
64
+
65
+ generateSessionId(): string {
66
+ return generateSessionId();
67
+ }
68
+
69
+ async createSession(session: SessionData, ttl?: number): Promise<void> {
70
+ this.ensureInitialized();
71
+ const { sessionId, identity } = session;
72
+
73
+ if (!sessionId || !identity) {
74
+ throw new Error('identity and sessionId required');
75
+ }
76
+
77
+ const expiresAt = ttl ? Date.now() + ttl * 1000 : null;
78
+
79
+ try {
80
+ const stmt = this.db!.prepare(
81
+ `INSERT INTO ${this.table} (sessionId, identity, data, expiresAt) VALUES (?, ?, ?, ?)`
82
+ );
83
+ stmt.run(sessionId, identity, JSON.stringify(session), expiresAt);
84
+ } catch (error: any) {
85
+ if (error.code === 'SQLITE_CONSTRAINT_PRIMARYKEY') {
86
+ throw new Error(`Session ${sessionId} already exists`);
87
+ }
88
+ throw error;
89
+ }
90
+ }
91
+
92
+ async updateSession(identity: string, sessionId: string, data: Partial<SessionData>, ttl?: number): Promise<void> {
93
+ this.ensureInitialized();
94
+ if (!sessionId || !identity) {
95
+ throw new Error('identity and sessionId required');
96
+ }
97
+
98
+ const currentSession = await this.getSession(identity, sessionId);
99
+ if (!currentSession) {
100
+ throw new Error(`Session ${sessionId} not found for identity ${identity}`);
101
+ }
102
+
103
+ const updatedSession = { ...currentSession, ...data };
104
+ const expiresAt = ttl ? Date.now() + ttl * 1000 : null;
105
+
106
+ const stmt = this.db!.prepare(
107
+ `UPDATE ${this.table} SET data = ?, expiresAt = ? WHERE sessionId = ? AND identity = ?`
108
+ );
109
+
110
+ stmt.run(JSON.stringify(updatedSession), expiresAt, sessionId, identity);
111
+ }
112
+
113
+ async getSession(identity: string, sessionId: string): Promise<SessionData | null> {
114
+ this.ensureInitialized();
115
+
116
+ const stmt = this.db!.prepare(
117
+ `SELECT data FROM ${this.table} WHERE sessionId = ? AND identity = ?`
118
+ );
119
+ const row = stmt.get(sessionId, identity) as { data: string } | undefined;
120
+
121
+ if (!row) return null;
122
+ return JSON.parse(row.data) as SessionData;
123
+ }
124
+
125
+ async getIdentitySessionsData(identity: string): Promise<SessionData[]> {
126
+ this.ensureInitialized();
127
+
128
+ const stmt = this.db!.prepare(
129
+ `SELECT data FROM ${this.table} WHERE identity = ?`
130
+ );
131
+ const rows = stmt.all(identity) as { data: string }[];
132
+
133
+ return rows.map(row => JSON.parse(row.data) as SessionData);
134
+ }
135
+
136
+ async getIdentityMcpSessions(identity: string): Promise<string[]> {
137
+ this.ensureInitialized();
138
+
139
+ const stmt = this.db!.prepare(
140
+ `SELECT sessionId FROM ${this.table} WHERE identity = ?`
141
+ );
142
+ const rows = stmt.all(identity) as { sessionId: string }[];
143
+
144
+ return rows.map(row => row.sessionId);
145
+ }
146
+
147
+ async removeSession(identity: string, sessionId: string): Promise<void> {
148
+ this.ensureInitialized();
149
+ const stmt = this.db!.prepare(
150
+ `DELETE FROM ${this.table} WHERE sessionId = ? AND identity = ?`
151
+ );
152
+ stmt.run(sessionId, identity);
153
+ }
154
+
155
+ async getAllSessionIds(): Promise<string[]> {
156
+ this.ensureInitialized();
157
+ const stmt = this.db!.prepare(`SELECT sessionId FROM ${this.table}`);
158
+ const rows = stmt.all() as { sessionId: string }[];
159
+ return rows.map(row => row.sessionId);
160
+ }
161
+
162
+ async clearAll(): Promise<void> {
163
+ this.ensureInitialized();
164
+ const stmt = this.db!.prepare(`DELETE FROM ${this.table}`);
165
+ stmt.run();
166
+ }
167
+
168
+ async cleanupExpiredSessions(): Promise<void> {
169
+ this.ensureInitialized();
170
+ const now = Date.now();
171
+ const stmt = this.db!.prepare(
172
+ `DELETE FROM ${this.table} WHERE expiresAt IS NOT NULL AND expiresAt < ?`
173
+ );
174
+ stmt.run(now);
175
+ }
176
+
177
+ async disconnect(): Promise<void> {
178
+ if (this.db) {
179
+ this.db.close();
180
+ }
181
+ }
182
+ }