@ai-sdk/mcp 2.0.6 → 2.0.8
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 +16 -0
- package/dist/index.js +63 -17
- package/dist/index.js.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": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"pkce-challenge": "^5.0.1",
|
|
35
|
-
"@ai-sdk/provider": "4.0.
|
|
36
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
35
|
+
"@ai-sdk/provider": "4.0.2",
|
|
36
|
+
"@ai-sdk/provider-utils": "5.0.5"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "22.19.19",
|
package/src/tool/mcp-client.ts
CHANGED
|
@@ -556,39 +556,57 @@ class DefaultMCPClient implements MCPClient {
|
|
|
556
556
|
id: messageId,
|
|
557
557
|
};
|
|
558
558
|
|
|
559
|
+
const rejectWithAbortError = () => {
|
|
560
|
+
reject(
|
|
561
|
+
new MCPClientError({
|
|
562
|
+
message: 'Request was aborted',
|
|
563
|
+
cause: signal?.reason,
|
|
564
|
+
}),
|
|
565
|
+
);
|
|
566
|
+
};
|
|
567
|
+
|
|
559
568
|
const cleanup = () => {
|
|
560
569
|
this.responseHandlers.delete(messageId);
|
|
570
|
+
signal?.removeEventListener('abort', onAbort);
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
const rejectAndCleanup = (error: unknown) => {
|
|
574
|
+
cleanup();
|
|
575
|
+
reject(error);
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
const onAbort = () => {
|
|
579
|
+
cleanup();
|
|
580
|
+
rejectWithAbortError();
|
|
561
581
|
};
|
|
562
582
|
|
|
563
583
|
this.responseHandlers.set(messageId, response => {
|
|
564
584
|
if (signal?.aborted) {
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
message: 'Request was aborted',
|
|
568
|
-
cause: signal.reason,
|
|
569
|
-
}),
|
|
570
|
-
);
|
|
585
|
+
cleanup();
|
|
586
|
+
return rejectWithAbortError();
|
|
571
587
|
}
|
|
572
588
|
|
|
573
589
|
if (response instanceof Error) {
|
|
574
|
-
return
|
|
590
|
+
return rejectAndCleanup(response);
|
|
575
591
|
}
|
|
576
592
|
|
|
577
593
|
try {
|
|
578
594
|
const result = resultSchema.parse(response.result);
|
|
595
|
+
cleanup();
|
|
579
596
|
resolve(result);
|
|
580
597
|
} catch (error) {
|
|
581
598
|
const parseError = new MCPClientError({
|
|
582
599
|
message: 'Failed to parse server response',
|
|
583
600
|
cause: error,
|
|
584
601
|
});
|
|
585
|
-
|
|
602
|
+
rejectAndCleanup(parseError);
|
|
586
603
|
}
|
|
587
604
|
});
|
|
588
605
|
|
|
606
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
607
|
+
|
|
589
608
|
this.transport.send(jsonrpcRequest).catch(error => {
|
|
590
|
-
|
|
591
|
-
reject(error);
|
|
609
|
+
rejectAndCleanup(error);
|
|
592
610
|
});
|
|
593
611
|
});
|
|
594
612
|
}
|
|
@@ -186,7 +186,7 @@ export class HttpMCPTransport implements MCPTransport {
|
|
|
186
186
|
}
|
|
187
187
|
this.abortController = new AbortController();
|
|
188
188
|
|
|
189
|
-
|
|
189
|
+
this.startInboundSse();
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
async close(): Promise<void> {
|
|
@@ -260,7 +260,7 @@ export class HttpMCPTransport implements MCPTransport {
|
|
|
260
260
|
// If inbound SSE was not available earlier (e.g. 405 before init), try again now
|
|
261
261
|
// Do not await to avoid blocking send()
|
|
262
262
|
if (!this.inboundSseConnection) {
|
|
263
|
-
|
|
263
|
+
this.startInboundSse();
|
|
264
264
|
}
|
|
265
265
|
return;
|
|
266
266
|
}
|
|
@@ -355,7 +355,12 @@ export class HttpMCPTransport implements MCPTransport {
|
|
|
355
355
|
}
|
|
356
356
|
};
|
|
357
357
|
|
|
358
|
-
processEvents()
|
|
358
|
+
void processEvents().catch(error => {
|
|
359
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
this.onerror?.(error);
|
|
363
|
+
});
|
|
359
364
|
return;
|
|
360
365
|
}
|
|
361
366
|
|
|
@@ -400,12 +405,24 @@ export class HttpMCPTransport implements MCPTransport {
|
|
|
400
405
|
|
|
401
406
|
const delay = this.getNextReconnectionDelay(this.inboundReconnectAttempts);
|
|
402
407
|
this.inboundReconnectAttempts += 1;
|
|
403
|
-
setTimeout(
|
|
408
|
+
setTimeout(() => {
|
|
404
409
|
if (this.abortController?.signal.aborted) return;
|
|
405
|
-
|
|
410
|
+
this.startInboundSse(false, this.lastInboundEventId);
|
|
406
411
|
}, delay);
|
|
407
412
|
}
|
|
408
413
|
|
|
414
|
+
private startInboundSse(
|
|
415
|
+
triedAuth: boolean = false,
|
|
416
|
+
resumeToken?: string,
|
|
417
|
+
): void {
|
|
418
|
+
void this.openInboundSse(triedAuth, resumeToken).catch(error => {
|
|
419
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
this.onerror?.(error);
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
|
|
409
426
|
// Open optional inbound SSE stream; best-effort and resumable
|
|
410
427
|
private async openInboundSse(
|
|
411
428
|
triedAuth: boolean = false,
|
|
@@ -510,10 +527,25 @@ export class HttpMCPTransport implements MCPTransport {
|
|
|
510
527
|
};
|
|
511
528
|
|
|
512
529
|
this.inboundSseConnection = {
|
|
513
|
-
close: () =>
|
|
530
|
+
close: () => {
|
|
531
|
+
void reader.cancel().catch(error => {
|
|
532
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
this.onerror?.(error);
|
|
536
|
+
});
|
|
537
|
+
},
|
|
514
538
|
};
|
|
515
539
|
this.inboundReconnectAttempts = 0;
|
|
516
|
-
processEvents()
|
|
540
|
+
void processEvents().catch(error => {
|
|
541
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
this.onerror?.(error);
|
|
545
|
+
if (!this.abortController?.signal.aborted) {
|
|
546
|
+
this.scheduleInboundSseReconnection();
|
|
547
|
+
}
|
|
548
|
+
});
|
|
517
549
|
} catch (error) {
|
|
518
550
|
if (error instanceof Error && error.name === 'AbortError') {
|
|
519
551
|
return;
|