@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.
- package/LICENSE +21 -21
- package/README.md +398 -404
- package/dist/adapters/agui-middleware.js.map +1 -1
- package/dist/adapters/agui-middleware.mjs.map +1 -1
- package/dist/bin/mcp-ts.js +0 -0
- package/dist/bin/mcp-ts.js.map +1 -1
- package/dist/bin/mcp-ts.mjs +0 -0
- package/dist/bin/mcp-ts.mjs.map +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs.map +1 -1
- package/dist/client/react.d.mts +2 -2
- package/dist/client/react.d.ts +2 -2
- package/dist/client/react.js +25 -2
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +26 -3
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs.map +1 -1
- package/package.json +185 -185
- package/src/adapters/agui-middleware.ts +382 -382
- package/src/bin/mcp-ts.ts +102 -102
- package/src/client/core/app-host.ts +417 -417
- package/src/client/core/sse-client.ts +371 -371
- package/src/client/core/types.ts +31 -31
- package/src/client/index.ts +27 -27
- package/src/client/react/index.ts +16 -16
- package/src/client/react/use-app-host.ts +73 -73
- package/src/client/react/use-mcp-apps.tsx +247 -214
- package/src/client/react/use-mcp.ts +641 -641
- package/src/client/vue/index.ts +10 -10
- package/src/client/vue/use-mcp.ts +617 -617
- package/src/index.ts +11 -11
- package/src/server/handlers/nextjs-handler.ts +204 -204
- package/src/server/handlers/sse-handler.ts +631 -631
- package/src/server/index.ts +57 -57
- package/src/server/mcp/multi-session-client.ts +228 -228
- package/src/server/mcp/oauth-client.ts +1188 -1188
- package/src/server/mcp/storage-oauth-provider.ts +272 -272
- package/src/server/storage/file-backend.ts +157 -157
- package/src/server/storage/index.ts +176 -176
- package/src/server/storage/memory-backend.ts +123 -123
- package/src/server/storage/redis-backend.ts +276 -276
- package/src/server/storage/redis.ts +160 -160
- package/src/server/storage/sqlite-backend.ts +182 -182
- package/src/server/storage/supabase-backend.ts +228 -228
- package/src/server/storage/types.ts +116 -116
- package/src/shared/constants.ts +29 -29
- package/src/shared/errors.ts +133 -133
- package/src/shared/event-routing.ts +28 -28
- package/src/shared/events.ts +180 -180
- package/src/shared/index.ts +75 -75
- package/src/shared/tool-utils.ts +61 -61
- package/src/shared/types.ts +282 -282
- package/src/shared/utils.ts +38 -38
- package/supabase/migrations/20260330195700_install_mcp_sessions.sql +84 -84
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Redis connection management with dependency injection support
|
|
3
|
-
* Allows configuration and testing without environment variables
|
|
4
|
-
*/
|
|
5
|
-
import type { Redis } from 'ioredis';
|
|
6
|
-
|
|
7
|
-
export interface RedisConfig {
|
|
8
|
-
/**
|
|
9
|
-
* Redis connection URL (defaults to REDIS_URL env var)
|
|
10
|
-
*/
|
|
11
|
-
url?: string;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Enable lazy connection (default: true)
|
|
15
|
-
*/
|
|
16
|
-
lazyConnect?: boolean;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Maximum retries per request (default: 1)
|
|
20
|
-
*/
|
|
21
|
-
maxRetriesPerRequest?: number;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Enable verbose logging (default: false)
|
|
25
|
-
*/
|
|
26
|
-
verbose?: boolean;
|
|
27
|
-
/**
|
|
28
|
-
* @internal For testing only - bypass ioredis import
|
|
29
|
-
*/
|
|
30
|
-
RedisConstructor?: any;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
declare global {
|
|
34
|
-
// eslint-disable-next-line no-var
|
|
35
|
-
var __redis: Redis | undefined;
|
|
36
|
-
var __redisConfig: RedisConfig | undefined;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
let redisInstance: Redis | null = null;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Initialize Redis with custom configuration
|
|
43
|
-
* Call this before any Redis operations if you need custom config
|
|
44
|
-
* @param config - Redis configuration options
|
|
45
|
-
*/
|
|
46
|
-
export async function initRedis(config: RedisConfig): Promise<Redis> {
|
|
47
|
-
if (redisInstance) {
|
|
48
|
-
// Already initialized, return existing instance
|
|
49
|
-
return redisInstance;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const url = config.url ?? process.env.REDIS_URL;
|
|
53
|
-
|
|
54
|
-
if (!url) {
|
|
55
|
-
throw new Error(
|
|
56
|
-
'Redis URL is required. Set REDIS_URL environment variable or pass url in config.'
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
let Redis: typeof import('ioredis').Redis;
|
|
61
|
-
if (config.RedisConstructor) {
|
|
62
|
-
Redis = config.RedisConstructor;
|
|
63
|
-
} else {
|
|
64
|
-
try {
|
|
65
|
-
const ioredis = await import('ioredis');
|
|
66
|
-
Redis = ioredis.Redis;
|
|
67
|
-
} catch (error) {
|
|
68
|
-
throw new Error(
|
|
69
|
-
'ioredis is not installed. Install it with:\n' +
|
|
70
|
-
' npm install ioredis\n\n' +
|
|
71
|
-
'Or use a different storage backend:\n' +
|
|
72
|
-
' MCP_TS_STORAGE_TYPE=memory (for development)\n' +
|
|
73
|
-
' MCP_TS_STORAGE_TYPE=file (for local persistence)'
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
redisInstance = new Redis(url, {
|
|
79
|
-
lazyConnect: config.lazyConnect ?? true,
|
|
80
|
-
maxRetriesPerRequest: config.maxRetriesPerRequest ?? 1,
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
if (config.verbose !== false) {
|
|
84
|
-
redisInstance.on('ready', () => {
|
|
85
|
-
console.log('✅ Redis connected');
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
redisInstance.on('error', (err) => {
|
|
89
|
-
console.error('❌ Redis error:', err.message);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
redisInstance.on('reconnecting', () => {
|
|
93
|
-
console.log('🔄 Redis reconnecting...');
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Store globally for hot reloading scenarios
|
|
98
|
-
global.__redis = redisInstance;
|
|
99
|
-
global.__redisConfig = config;
|
|
100
|
-
|
|
101
|
-
return redisInstance;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Get the Redis instance
|
|
106
|
-
* Automatically initializes with default config if not already initialized
|
|
107
|
-
*/
|
|
108
|
-
export async function getRedis(): Promise<Redis> {
|
|
109
|
-
if (redisInstance) {
|
|
110
|
-
return redisInstance;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Check for existing global instance (hot reload scenario)
|
|
114
|
-
if (global.__redis) {
|
|
115
|
-
redisInstance = global.__redis;
|
|
116
|
-
return redisInstance;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Initialize with default config
|
|
120
|
-
return await initRedis({});
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Set a custom Redis instance (useful for testing with mocks)
|
|
125
|
-
* @param instance - Redis instance or mock
|
|
126
|
-
*/
|
|
127
|
-
export function setRedisInstance(instance: Redis): void {
|
|
128
|
-
redisInstance = instance;
|
|
129
|
-
global.__redis = instance;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Close Redis connection and clear instance
|
|
134
|
-
*/
|
|
135
|
-
export async function closeRedis(): Promise<void> {
|
|
136
|
-
if (redisInstance) {
|
|
137
|
-
await redisInstance.quit();
|
|
138
|
-
redisInstance = null;
|
|
139
|
-
global.__redis = undefined;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Default Redis export for backward compatibility
|
|
145
|
-
* Will auto-initialize on first access
|
|
146
|
-
* Note: This is a lazy proxy that initializes Redis on first method call
|
|
147
|
-
*/
|
|
148
|
-
export const redis = new Proxy({} as Redis, {
|
|
149
|
-
get(_target, prop) {
|
|
150
|
-
// Return a function that handles async initialization
|
|
151
|
-
return async (...args: any[]) => {
|
|
152
|
-
const instance = await getRedis();
|
|
153
|
-
const value = (instance as any)[prop];
|
|
154
|
-
if (typeof value === 'function') {
|
|
155
|
-
return value.apply(instance, args);
|
|
156
|
-
}
|
|
157
|
-
return value;
|
|
158
|
-
};
|
|
159
|
-
},
|
|
160
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* Redis connection management with dependency injection support
|
|
3
|
+
* Allows configuration and testing without environment variables
|
|
4
|
+
*/
|
|
5
|
+
import type { Redis } from 'ioredis';
|
|
6
|
+
|
|
7
|
+
export interface RedisConfig {
|
|
8
|
+
/**
|
|
9
|
+
* Redis connection URL (defaults to REDIS_URL env var)
|
|
10
|
+
*/
|
|
11
|
+
url?: string;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Enable lazy connection (default: true)
|
|
15
|
+
*/
|
|
16
|
+
lazyConnect?: boolean;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Maximum retries per request (default: 1)
|
|
20
|
+
*/
|
|
21
|
+
maxRetriesPerRequest?: number;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Enable verbose logging (default: false)
|
|
25
|
+
*/
|
|
26
|
+
verbose?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* @internal For testing only - bypass ioredis import
|
|
29
|
+
*/
|
|
30
|
+
RedisConstructor?: any;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare global {
|
|
34
|
+
// eslint-disable-next-line no-var
|
|
35
|
+
var __redis: Redis | undefined;
|
|
36
|
+
var __redisConfig: RedisConfig | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let redisInstance: Redis | null = null;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Initialize Redis with custom configuration
|
|
43
|
+
* Call this before any Redis operations if you need custom config
|
|
44
|
+
* @param config - Redis configuration options
|
|
45
|
+
*/
|
|
46
|
+
export async function initRedis(config: RedisConfig): Promise<Redis> {
|
|
47
|
+
if (redisInstance) {
|
|
48
|
+
// Already initialized, return existing instance
|
|
49
|
+
return redisInstance;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const url = config.url ?? process.env.REDIS_URL;
|
|
53
|
+
|
|
54
|
+
if (!url) {
|
|
55
|
+
throw new Error(
|
|
56
|
+
'Redis URL is required. Set REDIS_URL environment variable or pass url in config.'
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let Redis: typeof import('ioredis').Redis;
|
|
61
|
+
if (config.RedisConstructor) {
|
|
62
|
+
Redis = config.RedisConstructor;
|
|
63
|
+
} else {
|
|
64
|
+
try {
|
|
65
|
+
const ioredis = await import('ioredis');
|
|
66
|
+
Redis = ioredis.Redis;
|
|
67
|
+
} catch (error) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
'ioredis is not installed. Install it with:\n' +
|
|
70
|
+
' npm install ioredis\n\n' +
|
|
71
|
+
'Or use a different storage backend:\n' +
|
|
72
|
+
' MCP_TS_STORAGE_TYPE=memory (for development)\n' +
|
|
73
|
+
' MCP_TS_STORAGE_TYPE=file (for local persistence)'
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
redisInstance = new Redis(url, {
|
|
79
|
+
lazyConnect: config.lazyConnect ?? true,
|
|
80
|
+
maxRetriesPerRequest: config.maxRetriesPerRequest ?? 1,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (config.verbose !== false) {
|
|
84
|
+
redisInstance.on('ready', () => {
|
|
85
|
+
console.log('✅ Redis connected');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
redisInstance.on('error', (err) => {
|
|
89
|
+
console.error('❌ Redis error:', err.message);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
redisInstance.on('reconnecting', () => {
|
|
93
|
+
console.log('🔄 Redis reconnecting...');
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Store globally for hot reloading scenarios
|
|
98
|
+
global.__redis = redisInstance;
|
|
99
|
+
global.__redisConfig = config;
|
|
100
|
+
|
|
101
|
+
return redisInstance;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get the Redis instance
|
|
106
|
+
* Automatically initializes with default config if not already initialized
|
|
107
|
+
*/
|
|
108
|
+
export async function getRedis(): Promise<Redis> {
|
|
109
|
+
if (redisInstance) {
|
|
110
|
+
return redisInstance;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Check for existing global instance (hot reload scenario)
|
|
114
|
+
if (global.__redis) {
|
|
115
|
+
redisInstance = global.__redis;
|
|
116
|
+
return redisInstance;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Initialize with default config
|
|
120
|
+
return await initRedis({});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Set a custom Redis instance (useful for testing with mocks)
|
|
125
|
+
* @param instance - Redis instance or mock
|
|
126
|
+
*/
|
|
127
|
+
export function setRedisInstance(instance: Redis): void {
|
|
128
|
+
redisInstance = instance;
|
|
129
|
+
global.__redis = instance;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Close Redis connection and clear instance
|
|
134
|
+
*/
|
|
135
|
+
export async function closeRedis(): Promise<void> {
|
|
136
|
+
if (redisInstance) {
|
|
137
|
+
await redisInstance.quit();
|
|
138
|
+
redisInstance = null;
|
|
139
|
+
global.__redis = undefined;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Default Redis export for backward compatibility
|
|
145
|
+
* Will auto-initialize on first access
|
|
146
|
+
* Note: This is a lazy proxy that initializes Redis on first method call
|
|
147
|
+
*/
|
|
148
|
+
export const redis = new Proxy({} as Redis, {
|
|
149
|
+
get(_target, prop) {
|
|
150
|
+
// Return a function that handles async initialization
|
|
151
|
+
return async (...args: any[]) => {
|
|
152
|
+
const instance = await getRedis();
|
|
153
|
+
const value = (instance as any)[prop];
|
|
154
|
+
if (typeof value === 'function') {
|
|
155
|
+
return value.apply(instance, args);
|
|
156
|
+
}
|
|
157
|
+
return value;
|
|
158
|
+
};
|
|
159
|
+
},
|
|
160
|
+
});
|