@ai-sdk/mcp 1.0.59 → 1.0.60
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/CHANGELOG.md +9 -0
- package/dist/index.js +63 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +63 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/tool/mcp-client.ts +28 -10
- package/src/tool/mcp-http-transport.ts +39 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.60",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"pkce-challenge": "^5.0.0",
|
|
36
|
-
"@ai-sdk/provider
|
|
37
|
-
"@ai-sdk/provider": "
|
|
36
|
+
"@ai-sdk/provider": "3.0.13",
|
|
37
|
+
"@ai-sdk/provider-utils": "4.0.37"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "20.17.24",
|
package/src/tool/mcp-client.ts
CHANGED
|
@@ -508,39 +508,57 @@ class DefaultMCPClient implements MCPClient {
|
|
|
508
508
|
id: messageId,
|
|
509
509
|
};
|
|
510
510
|
|
|
511
|
+
const rejectWithAbortError = () => {
|
|
512
|
+
reject(
|
|
513
|
+
new MCPClientError({
|
|
514
|
+
message: 'Request was aborted',
|
|
515
|
+
cause: signal?.reason,
|
|
516
|
+
}),
|
|
517
|
+
);
|
|
518
|
+
};
|
|
519
|
+
|
|
511
520
|
const cleanup = () => {
|
|
512
521
|
this.responseHandlers.delete(messageId);
|
|
522
|
+
signal?.removeEventListener('abort', onAbort);
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
const rejectAndCleanup = (error: unknown) => {
|
|
526
|
+
cleanup();
|
|
527
|
+
reject(error);
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
const onAbort = () => {
|
|
531
|
+
cleanup();
|
|
532
|
+
rejectWithAbortError();
|
|
513
533
|
};
|
|
514
534
|
|
|
515
535
|
this.responseHandlers.set(messageId, response => {
|
|
516
536
|
if (signal?.aborted) {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
message: 'Request was aborted',
|
|
520
|
-
cause: signal.reason,
|
|
521
|
-
}),
|
|
522
|
-
);
|
|
537
|
+
cleanup();
|
|
538
|
+
return rejectWithAbortError();
|
|
523
539
|
}
|
|
524
540
|
|
|
525
541
|
if (response instanceof Error) {
|
|
526
|
-
return
|
|
542
|
+
return rejectAndCleanup(response);
|
|
527
543
|
}
|
|
528
544
|
|
|
529
545
|
try {
|
|
530
546
|
const result = resultSchema.parse(response.result);
|
|
547
|
+
cleanup();
|
|
531
548
|
resolve(result);
|
|
532
549
|
} catch (error) {
|
|
533
550
|
const parseError = new MCPClientError({
|
|
534
551
|
message: 'Failed to parse server response',
|
|
535
552
|
cause: error,
|
|
536
553
|
});
|
|
537
|
-
|
|
554
|
+
rejectAndCleanup(parseError);
|
|
538
555
|
}
|
|
539
556
|
});
|
|
540
557
|
|
|
558
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
559
|
+
|
|
541
560
|
this.transport.send(jsonrpcRequest).catch(error => {
|
|
542
|
-
|
|
543
|
-
reject(error);
|
|
561
|
+
rejectAndCleanup(error);
|
|
544
562
|
});
|
|
545
563
|
});
|
|
546
564
|
}
|
|
@@ -140,7 +140,7 @@ export class HttpMCPTransport implements MCPTransport {
|
|
|
140
140
|
}
|
|
141
141
|
this.abortController = new AbortController();
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
this.startInboundSse();
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
async close(): Promise<void> {
|
|
@@ -208,7 +208,7 @@ export class HttpMCPTransport implements MCPTransport {
|
|
|
208
208
|
// If inbound SSE was not available earlier (e.g. 405 before init), try again now
|
|
209
209
|
// Do not await to avoid blocking send()
|
|
210
210
|
if (!this.inboundSseConnection) {
|
|
211
|
-
|
|
211
|
+
this.startInboundSse();
|
|
212
212
|
}
|
|
213
213
|
return;
|
|
214
214
|
}
|
|
@@ -297,7 +297,12 @@ export class HttpMCPTransport implements MCPTransport {
|
|
|
297
297
|
}
|
|
298
298
|
};
|
|
299
299
|
|
|
300
|
-
processEvents()
|
|
300
|
+
void processEvents().catch(error => {
|
|
301
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
this.onerror?.(error);
|
|
305
|
+
});
|
|
301
306
|
return;
|
|
302
307
|
}
|
|
303
308
|
|
|
@@ -342,12 +347,24 @@ export class HttpMCPTransport implements MCPTransport {
|
|
|
342
347
|
|
|
343
348
|
const delay = this.getNextReconnectionDelay(this.inboundReconnectAttempts);
|
|
344
349
|
this.inboundReconnectAttempts += 1;
|
|
345
|
-
setTimeout(
|
|
350
|
+
setTimeout(() => {
|
|
346
351
|
if (this.abortController?.signal.aborted) return;
|
|
347
|
-
|
|
352
|
+
this.startInboundSse(false, this.lastInboundEventId);
|
|
348
353
|
}, delay);
|
|
349
354
|
}
|
|
350
355
|
|
|
356
|
+
private startInboundSse(
|
|
357
|
+
triedAuth: boolean = false,
|
|
358
|
+
resumeToken?: string,
|
|
359
|
+
): void {
|
|
360
|
+
void this.openInboundSse(triedAuth, resumeToken).catch(error => {
|
|
361
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
this.onerror?.(error);
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
|
|
351
368
|
// Open optional inbound SSE stream; best-effort and resumable
|
|
352
369
|
private async openInboundSse(
|
|
353
370
|
triedAuth: boolean = false,
|
|
@@ -448,10 +465,25 @@ export class HttpMCPTransport implements MCPTransport {
|
|
|
448
465
|
};
|
|
449
466
|
|
|
450
467
|
this.inboundSseConnection = {
|
|
451
|
-
close: () =>
|
|
468
|
+
close: () => {
|
|
469
|
+
void reader.cancel().catch(error => {
|
|
470
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
this.onerror?.(error);
|
|
474
|
+
});
|
|
475
|
+
},
|
|
452
476
|
};
|
|
453
477
|
this.inboundReconnectAttempts = 0;
|
|
454
|
-
processEvents()
|
|
478
|
+
void processEvents().catch(error => {
|
|
479
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
this.onerror?.(error);
|
|
483
|
+
if (!this.abortController?.signal.aborted) {
|
|
484
|
+
this.scheduleInboundSseReconnection();
|
|
485
|
+
}
|
|
486
|
+
});
|
|
455
487
|
} catch (error) {
|
|
456
488
|
if (error instanceof Error && error.name === 'AbortError') {
|
|
457
489
|
return;
|