@mcp-ts/sdk 1.3.2 → 1.3.4
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/README.md +400 -406
- package/dist/adapters/agui-adapter.d.mts +1 -1
- package/dist/adapters/agui-adapter.d.ts +1 -1
- package/dist/adapters/agui-middleware.d.mts +1 -1
- package/dist/adapters/agui-middleware.d.ts +1 -1
- package/dist/adapters/ai-adapter.d.mts +1 -1
- package/dist/adapters/ai-adapter.d.ts +1 -1
- package/dist/adapters/langchain-adapter.d.mts +1 -1
- package/dist/adapters/langchain-adapter.d.ts +1 -1
- package/dist/adapters/mastra-adapter.d.mts +1 -1
- package/dist/adapters/mastra-adapter.d.ts +1 -1
- package/dist/client/index.d.mts +8 -64
- package/dist/client/index.d.ts +8 -64
- package/dist/client/index.js +91 -173
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +91 -173
- package/dist/client/index.mjs.map +1 -1
- package/dist/client/react.d.mts +12 -2
- package/dist/client/react.d.ts +12 -2
- package/dist/client/react.js +119 -182
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +119 -182
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.d.mts +24 -4
- package/dist/client/vue.d.ts +24 -4
- package/dist/client/vue.js +121 -182
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs +121 -182
- package/dist/client/vue.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +215 -250
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +215 -250
- package/dist/index.mjs.map +1 -1
- package/dist/{multi-session-client-B1DBx5yR.d.mts → multi-session-client-DzjmT7FX.d.mts} +1 -0
- package/dist/{multi-session-client-DyFzyJUx.d.ts → multi-session-client-FAFpUzZ4.d.ts} +1 -0
- package/dist/server/index.d.mts +16 -21
- package/dist/server/index.d.ts +16 -21
- package/dist/server/index.js +124 -77
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +124 -77
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +2 -2
- package/dist/shared/index.d.ts +2 -2
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs.map +1 -1
- package/dist/{types-PjM1W07s.d.mts → types-CW6lghof.d.mts} +5 -0
- package/dist/{types-PjM1W07s.d.ts → types-CW6lghof.d.ts} +5 -0
- package/package.json +1 -1
- package/src/client/core/sse-client.ts +354 -493
- package/src/client/react/use-mcp.ts +75 -23
- package/src/client/vue/use-mcp.ts +111 -48
- package/src/server/handlers/nextjs-handler.ts +207 -217
- package/src/server/handlers/sse-handler.ts +10 -0
- package/src/server/mcp/oauth-client.ts +41 -32
- package/src/server/storage/types.ts +12 -5
- package/src/shared/types.ts +5 -0
|
@@ -64,6 +64,13 @@ export interface UseMcpOptions {
|
|
|
64
64
|
* @default 60000
|
|
65
65
|
*/
|
|
66
66
|
requestTimeout?: number;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Enable client debug logs.
|
|
70
|
+
* @default false
|
|
71
|
+
*/
|
|
72
|
+
debug?: boolean;
|
|
73
|
+
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
export interface McpConnection {
|
|
@@ -74,6 +81,7 @@ export interface McpConnection {
|
|
|
74
81
|
transport?: string;
|
|
75
82
|
state: McpConnectionState;
|
|
76
83
|
tools: ToolInfo[];
|
|
84
|
+
authUrl?: string;
|
|
77
85
|
error?: string;
|
|
78
86
|
createdAt?: Date;
|
|
79
87
|
}
|
|
@@ -150,6 +158,11 @@ export interface McpClient {
|
|
|
150
158
|
*/
|
|
151
159
|
finishAuth: (sessionId: string, code: string) => Promise<FinishAuthResult>;
|
|
152
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Explicitly resume OAuth flow for an existing session
|
|
163
|
+
*/
|
|
164
|
+
resumeAuth: (sessionId: string) => Promise<void>;
|
|
165
|
+
|
|
153
166
|
/**
|
|
154
167
|
* Call a tool from a session
|
|
155
168
|
*/
|
|
@@ -207,6 +220,7 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
207
220
|
|
|
208
221
|
const clientRef = useRef<SSEClient | null>(null);
|
|
209
222
|
const isMountedRef = useRef(true);
|
|
223
|
+
const suppressAuthRedirectSessionsRef = useRef<Set<string>>(new Set());
|
|
210
224
|
|
|
211
225
|
const [connections, setConnections] = useState<McpConnection[]>([]);
|
|
212
226
|
const [status, setStatus] = useState<'connecting' | 'connected' | 'disconnected' | 'error'>(
|
|
@@ -239,7 +253,7 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
239
253
|
setStatus(newStatus);
|
|
240
254
|
}
|
|
241
255
|
},
|
|
242
|
-
|
|
256
|
+
debug: options.debug,
|
|
243
257
|
};
|
|
244
258
|
|
|
245
259
|
const client = new SSEClient(clientOptions);
|
|
@@ -262,21 +276,36 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
262
276
|
/**
|
|
263
277
|
* Update connections based on event
|
|
264
278
|
*/
|
|
265
|
-
const updateConnectionsFromEvent = useCallback((event: McpConnectionEvent) => {
|
|
266
|
-
if (!isMountedRef.current) return;
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
const updateConnectionsFromEvent = useCallback((event: McpConnectionEvent) => {
|
|
280
|
+
if (!isMountedRef.current) return;
|
|
281
|
+
|
|
282
|
+
const isTransientReconnectState = (state: McpConnectionState): boolean =>
|
|
283
|
+
state === 'INITIALIZING' ||
|
|
284
|
+
state === 'VALIDATING' ||
|
|
285
|
+
state === 'RECONNECTING' ||
|
|
286
|
+
state === 'CONNECTING' ||
|
|
287
|
+
state === 'CONNECTED' ||
|
|
288
|
+
state === 'DISCOVERING';
|
|
289
|
+
|
|
290
|
+
setConnections((prev: McpConnection[]) => {
|
|
291
|
+
switch (event.type) {
|
|
292
|
+
case 'state_changed': {
|
|
293
|
+
const existing = prev.find((c: McpConnection) => c.sessionId === event.sessionId);
|
|
294
|
+
if (existing) {
|
|
295
|
+
// In stateless per-request transport, tool calls can emit transient reconnect states.
|
|
296
|
+
// Keep READY sticky to avoid UI flicker from READY -> CONNECTING -> CONNECTED.
|
|
297
|
+
const nextState =
|
|
298
|
+
existing.state === 'READY' && isTransientReconnectState(event.state)
|
|
299
|
+
? existing.state
|
|
300
|
+
: event.state;
|
|
301
|
+
|
|
302
|
+
return prev.map((c: McpConnection) =>
|
|
303
|
+
c.sessionId === event.sessionId ? {
|
|
304
|
+
...c,
|
|
305
|
+
state: nextState,
|
|
306
|
+
// update createdAt if present in event, otherwise keep existing
|
|
307
|
+
createdAt: event.createdAt ? new Date(event.createdAt) : c.createdAt
|
|
308
|
+
} : c
|
|
280
309
|
);
|
|
281
310
|
} else {
|
|
282
311
|
// Fix: Don't add back disconnected sessions that were just removed
|
|
@@ -315,14 +344,17 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
315
344
|
if (event.authUrl) {
|
|
316
345
|
onLog?.('info', `OAuth required - redirecting to ${event.authUrl}`, { authUrl: event.authUrl });
|
|
317
346
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
347
|
+
// Suppress redirects/popups for auto-restore on page load.
|
|
348
|
+
if (!suppressAuthRedirectSessionsRef.current.has(event.sessionId)) {
|
|
349
|
+
if (onRedirect) {
|
|
350
|
+
onRedirect(event.authUrl);
|
|
351
|
+
} else if (typeof window !== 'undefined') {
|
|
352
|
+
window.location.href = event.authUrl;
|
|
353
|
+
}
|
|
322
354
|
}
|
|
323
355
|
}
|
|
324
356
|
return prev.map((c: McpConnection) =>
|
|
325
|
-
c.sessionId === event.sessionId ? { ...c, state: 'AUTHENTICATING' } : c
|
|
357
|
+
c.sessionId === event.sessionId ? { ...c, state: 'AUTHENTICATING', authUrl: event.authUrl } : c
|
|
326
358
|
);
|
|
327
359
|
}
|
|
328
360
|
|
|
@@ -340,7 +372,7 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
340
372
|
return prev;
|
|
341
373
|
}
|
|
342
374
|
});
|
|
343
|
-
}, [onLog]);
|
|
375
|
+
}, [onLog, onRedirect]);
|
|
344
376
|
|
|
345
377
|
/**
|
|
346
378
|
* Load sessions from server
|
|
@@ -363,7 +395,7 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
363
395
|
serverName: s.serverName ?? 'Unknown Server',
|
|
364
396
|
serverUrl: s.serverUrl,
|
|
365
397
|
transport: s.transport,
|
|
366
|
-
state: 'VALIDATING' as McpConnectionState,
|
|
398
|
+
state: (s.active === false ? 'AUTHENTICATING' : 'VALIDATING') as McpConnectionState,
|
|
367
399
|
createdAt: new Date(s.createdAt),
|
|
368
400
|
tools: [],
|
|
369
401
|
}))
|
|
@@ -375,9 +407,16 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
375
407
|
sessions.map(async (session: SessionInfo) => {
|
|
376
408
|
if (clientRef.current) {
|
|
377
409
|
try {
|
|
410
|
+
// Pending auth sessions should not auto-trigger popup/redirect on reload.
|
|
411
|
+
if (session.active === false) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
suppressAuthRedirectSessionsRef.current.add(session.sessionId);
|
|
378
415
|
await clientRef.current.restoreSession(session.sessionId);
|
|
379
416
|
} catch (error) {
|
|
380
417
|
console.error(`[useMcp] Failed to validate session ${session.sessionId}:`, error);
|
|
418
|
+
} finally {
|
|
419
|
+
suppressAuthRedirectSessionsRef.current.delete(session.sessionId);
|
|
381
420
|
}
|
|
382
421
|
}
|
|
383
422
|
})
|
|
@@ -461,6 +500,18 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
461
500
|
return await clientRef.current.finishAuth(sessionId, code);
|
|
462
501
|
}, []);
|
|
463
502
|
|
|
503
|
+
/**
|
|
504
|
+
* Explicit user action to resume OAuth for an existing pending session.
|
|
505
|
+
*/
|
|
506
|
+
const resumeAuth = useCallback(async (sessionId: string): Promise<void> => {
|
|
507
|
+
if (!clientRef.current) {
|
|
508
|
+
throw new Error('SSE client not initialized');
|
|
509
|
+
}
|
|
510
|
+
// Ensure this attempt is not suppressed as background restore.
|
|
511
|
+
suppressAuthRedirectSessionsRef.current.delete(sessionId);
|
|
512
|
+
await clientRef.current.restoreSession(sessionId);
|
|
513
|
+
}, []);
|
|
514
|
+
|
|
464
515
|
/**
|
|
465
516
|
* Call a tool
|
|
466
517
|
*/
|
|
@@ -578,6 +629,7 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
578
629
|
connectSSE,
|
|
579
630
|
disconnectSSE,
|
|
580
631
|
finishAuth,
|
|
632
|
+
resumeAuth,
|
|
581
633
|
callTool,
|
|
582
634
|
listTools,
|
|
583
635
|
listPrompts,
|
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
SessionInfo,
|
|
17
17
|
} from '../../shared/types';
|
|
18
18
|
|
|
19
|
-
export interface UseMcpOptions {
|
|
19
|
+
export interface UseMcpOptions {
|
|
20
20
|
/**
|
|
21
21
|
* SSE endpoint URL
|
|
22
22
|
*/
|
|
@@ -53,12 +53,24 @@ export interface UseMcpOptions {
|
|
|
53
53
|
* Debug logging callback
|
|
54
54
|
*/
|
|
55
55
|
onLog?: (level: string, message: string, metadata?: Record<string, unknown>) => void;
|
|
56
|
-
/**
|
|
57
|
-
* Optional callback to handle OAuth redirects (e.g. for popup flow)
|
|
58
|
-
* If provided, this will be called instead of window.location.href assignment
|
|
59
|
-
*/
|
|
60
|
-
onRedirect?: (url: string) => void;
|
|
61
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Optional callback to handle OAuth redirects (e.g. for popup flow)
|
|
58
|
+
* If provided, this will be called instead of window.location.href assignment
|
|
59
|
+
*/
|
|
60
|
+
onRedirect?: (url: string) => void;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Request timeout in milliseconds
|
|
64
|
+
* @default 60000
|
|
65
|
+
*/
|
|
66
|
+
requestTimeout?: number;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Enable client debug logs.
|
|
70
|
+
* @default false
|
|
71
|
+
*/
|
|
72
|
+
debug?: boolean;
|
|
73
|
+
}
|
|
62
74
|
|
|
63
75
|
export interface McpConnection {
|
|
64
76
|
sessionId: string;
|
|
@@ -68,6 +80,7 @@ export interface McpConnection {
|
|
|
68
80
|
transport?: string;
|
|
69
81
|
state: McpConnectionState;
|
|
70
82
|
tools: ToolInfo[];
|
|
83
|
+
authUrl?: string;
|
|
71
84
|
error?: string;
|
|
72
85
|
createdAt?: Date;
|
|
73
86
|
}
|
|
@@ -144,6 +157,11 @@ export interface McpClient {
|
|
|
144
157
|
*/
|
|
145
158
|
finishAuth: (sessionId: string, code: string) => Promise<FinishAuthResult>;
|
|
146
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Explicitly resume OAuth flow for an existing session
|
|
162
|
+
*/
|
|
163
|
+
resumeAuth: (sessionId: string) => Promise<void>;
|
|
164
|
+
|
|
147
165
|
/**
|
|
148
166
|
* Call a tool from a session
|
|
149
167
|
*/
|
|
@@ -173,11 +191,16 @@ export interface McpClient {
|
|
|
173
191
|
*/
|
|
174
192
|
listResources: (sessionId: string) => Promise<ListResourcesResult>;
|
|
175
193
|
|
|
176
|
-
/**
|
|
177
|
-
* Read a specific resource
|
|
178
|
-
*/
|
|
179
|
-
readResource: (sessionId: string, uri: string) => Promise<unknown>;
|
|
180
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Read a specific resource
|
|
196
|
+
*/
|
|
197
|
+
readResource: (sessionId: string, uri: string) => Promise<unknown>;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Access the underlying SSEClient instance (for advanced usage like AppHost)
|
|
201
|
+
*/
|
|
202
|
+
sseClient: SSEClient | null;
|
|
203
|
+
}
|
|
181
204
|
|
|
182
205
|
/**
|
|
183
206
|
* Vue Composable for MCP connection management with SSE
|
|
@@ -197,6 +220,7 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
197
220
|
// Use shallowRef for client instance as it doesn't need deep reactivity
|
|
198
221
|
const clientRef = shallowRef<SSEClient | null>(null);
|
|
199
222
|
const isMountedRef = ref(true);
|
|
223
|
+
const suppressAuthRedirectSessions = ref(new Set<string>());
|
|
200
224
|
|
|
201
225
|
const connections = ref<McpConnection[]>([]);
|
|
202
226
|
const status = ref<'connecting' | 'connected' | 'disconnected' | 'error'>('disconnected');
|
|
@@ -205,20 +229,35 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
205
229
|
/**
|
|
206
230
|
* Update connections based on event
|
|
207
231
|
*/
|
|
208
|
-
const updateConnectionsFromEvent = (event: McpConnectionEvent) => {
|
|
209
|
-
if (!isMountedRef.value) return;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
232
|
+
const updateConnectionsFromEvent = (event: McpConnectionEvent) => {
|
|
233
|
+
if (!isMountedRef.value) return;
|
|
234
|
+
|
|
235
|
+
const isTransientReconnectState = (state: McpConnectionState): boolean =>
|
|
236
|
+
state === 'INITIALIZING' ||
|
|
237
|
+
state === 'VALIDATING' ||
|
|
238
|
+
state === 'RECONNECTING' ||
|
|
239
|
+
state === 'CONNECTING' ||
|
|
240
|
+
state === 'CONNECTED' ||
|
|
241
|
+
state === 'DISCOVERING';
|
|
242
|
+
|
|
243
|
+
switch (event.type) {
|
|
244
|
+
case 'state_changed': {
|
|
245
|
+
const existing = connections.value.find((c) => c.sessionId === event.sessionId);
|
|
246
|
+
if (existing) {
|
|
247
|
+
// In stateless per-request transport, tool calls can emit transient reconnect states.
|
|
248
|
+
// Keep READY sticky to avoid UI flicker from READY -> CONNECTING -> CONNECTED.
|
|
249
|
+
const nextState =
|
|
250
|
+
existing.state === 'READY' && isTransientReconnectState(event.state)
|
|
251
|
+
? existing.state
|
|
252
|
+
: event.state;
|
|
253
|
+
|
|
254
|
+
const index = connections.value.indexOf(existing);
|
|
255
|
+
connections.value[index] = {
|
|
256
|
+
...existing,
|
|
257
|
+
state: nextState,
|
|
258
|
+
// update createdAt if present in event, otherwise keep existing
|
|
259
|
+
createdAt: event.createdAt ? new Date(event.createdAt) : existing.createdAt
|
|
260
|
+
};
|
|
222
261
|
} else {
|
|
223
262
|
// Fix: Don't add back disconnected sessions that were just removed
|
|
224
263
|
if (event.state === 'DISCONNECTED') {
|
|
@@ -250,15 +289,18 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
250
289
|
if (event.authUrl) {
|
|
251
290
|
onLog?.('info', `OAuth required - redirecting to ${event.authUrl}`, { authUrl: event.authUrl });
|
|
252
291
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
292
|
+
// Suppress redirects/popups for background auto-restore on page load.
|
|
293
|
+
if (!suppressAuthRedirectSessions.value.has(event.sessionId)) {
|
|
294
|
+
if (onRedirect) {
|
|
295
|
+
onRedirect(event.authUrl);
|
|
296
|
+
} else if (typeof window !== 'undefined') {
|
|
297
|
+
window.location.href = event.authUrl;
|
|
298
|
+
}
|
|
257
299
|
}
|
|
258
300
|
}
|
|
259
301
|
const index = connections.value.findIndex((c) => c.sessionId === event.sessionId);
|
|
260
302
|
if (index !== -1) {
|
|
261
|
-
connections.value[index] = { ...connections.value[index], state: 'AUTHENTICATING' };
|
|
303
|
+
connections.value[index] = { ...connections.value[index], state: 'AUTHENTICATING', authUrl: event.authUrl };
|
|
262
304
|
}
|
|
263
305
|
break;
|
|
264
306
|
}
|
|
@@ -298,7 +340,7 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
298
340
|
serverName: s.serverName ?? 'Unknown Server',
|
|
299
341
|
serverUrl: s.serverUrl,
|
|
300
342
|
transport: s.transport,
|
|
301
|
-
state: 'VALIDATING' as McpConnectionState,
|
|
343
|
+
state: (s.active === false ? 'AUTHENTICATING' : 'VALIDATING') as McpConnectionState,
|
|
302
344
|
createdAt: new Date(s.createdAt),
|
|
303
345
|
tools: [],
|
|
304
346
|
}));
|
|
@@ -309,9 +351,16 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
309
351
|
sessions.map(async (session: SessionInfo) => {
|
|
310
352
|
if (clientRef.value) {
|
|
311
353
|
try {
|
|
354
|
+
// Pending auth sessions should not auto-trigger popup/redirect on reload.
|
|
355
|
+
if (session.active === false) {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
suppressAuthRedirectSessions.value.add(session.sessionId);
|
|
312
359
|
await clientRef.value.restoreSession(session.sessionId);
|
|
313
360
|
} catch (error) {
|
|
314
361
|
console.error(`[useMcp] Failed to validate session ${session.sessionId}:`, error);
|
|
362
|
+
} finally {
|
|
363
|
+
suppressAuthRedirectSessions.value.delete(session.sessionId);
|
|
315
364
|
}
|
|
316
365
|
}
|
|
317
366
|
})
|
|
@@ -335,10 +384,10 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
335
384
|
clientRef.value.disconnect();
|
|
336
385
|
}
|
|
337
386
|
|
|
338
|
-
const clientOptions: SSEClientOptions = {
|
|
339
|
-
url,
|
|
340
|
-
identity,
|
|
341
|
-
authToken,
|
|
387
|
+
const clientOptions: SSEClientOptions = {
|
|
388
|
+
url,
|
|
389
|
+
identity,
|
|
390
|
+
authToken,
|
|
342
391
|
onConnectionEvent: (event) => {
|
|
343
392
|
// Update local state based on event
|
|
344
393
|
updateConnectionsFromEvent(event);
|
|
@@ -349,12 +398,13 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
349
398
|
onObservabilityEvent: (event) => {
|
|
350
399
|
onLog?.(event.level || 'info', event.message || event.displayMessage || 'No message', event.metadata);
|
|
351
400
|
},
|
|
352
|
-
onStatusChange: (newStatus) => {
|
|
353
|
-
if (isMountedRef.value) {
|
|
354
|
-
status.value = newStatus;
|
|
355
|
-
}
|
|
356
|
-
},
|
|
357
|
-
|
|
401
|
+
onStatusChange: (newStatus) => {
|
|
402
|
+
if (isMountedRef.value) {
|
|
403
|
+
status.value = newStatus;
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
debug: options.debug,
|
|
407
|
+
};
|
|
358
408
|
|
|
359
409
|
const client = new SSEClient(clientOptions);
|
|
360
410
|
clientRef.value = client;
|
|
@@ -444,6 +494,17 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
444
494
|
return await clientRef.value.finishAuth(sessionId, code);
|
|
445
495
|
};
|
|
446
496
|
|
|
497
|
+
/**
|
|
498
|
+
* Explicit user action to resume OAuth for an existing pending session.
|
|
499
|
+
*/
|
|
500
|
+
const resumeAuth = async (sessionId: string): Promise<void> => {
|
|
501
|
+
if (!clientRef.value) {
|
|
502
|
+
throw new Error('SSE client not initialized');
|
|
503
|
+
}
|
|
504
|
+
suppressAuthRedirectSessions.value.delete(sessionId);
|
|
505
|
+
await clientRef.value.restoreSession(sessionId);
|
|
506
|
+
};
|
|
507
|
+
|
|
447
508
|
/**
|
|
448
509
|
* Call a tool
|
|
449
510
|
*/
|
|
@@ -544,11 +605,13 @@ export function useMcp(options: UseMcpOptions): McpClient {
|
|
|
544
605
|
connectSSE,
|
|
545
606
|
disconnectSSE,
|
|
546
607
|
finishAuth,
|
|
608
|
+
resumeAuth,
|
|
547
609
|
callTool,
|
|
548
610
|
listTools,
|
|
549
|
-
listPrompts,
|
|
550
|
-
getPrompt,
|
|
551
|
-
listResources,
|
|
552
|
-
readResource,
|
|
553
|
-
|
|
554
|
-
}
|
|
611
|
+
listPrompts,
|
|
612
|
+
getPrompt,
|
|
613
|
+
listResources,
|
|
614
|
+
readResource,
|
|
615
|
+
sseClient: clientRef.value,
|
|
616
|
+
};
|
|
617
|
+
}
|