release: 0.1.6 — relay notifications/progress to MCP client
Long-running upstream skills emit MCP notifications/progress on the SSE stream. Without forwarding, the gateway swallows them and the MCP client (Claude Code, Cursor) aborts the tools/call on its idle timer after ~60s — even though the HTTP stream stays warm. Gateway now passes the SDK's extra.sendNotification through to UpstreamAgent.callTool. Any non-response frame with a method but no id becomes a notification on the client side. Each tools/call carries a progressToken (client-supplied or request-id fallback) so the client can correlate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -95,7 +95,7 @@ export async function buildGateway(opts: GatewayOptions = {}): Promise<GatewayHa
|
||||
return { tools };
|
||||
});
|
||||
|
||||
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
||||
server.setRequestHandler(CallToolRequestSchema, async (req, extra) => {
|
||||
const fullName = req.params.name;
|
||||
const idx = fullName.indexOf(SEP);
|
||||
if (idx < 0) {
|
||||
@@ -107,10 +107,30 @@ export async function buildGateway(opts: GatewayOptions = {}): Promise<GatewayHa
|
||||
if (!upstream) {
|
||||
return _softError(`unknown agent: ${agentName}`) as any;
|
||||
}
|
||||
// Honor the client's progressToken if it supplied one; else fall
|
||||
// back to the request id. Either way, when upstream emits
|
||||
// notifications/progress we forward them via the SDK's
|
||||
// sendNotification so clients like Claude Code reset their idle
|
||||
// tool-call timer and don't abort long builds.
|
||||
const clientToken = (req.params._meta as any)?.progressToken as
|
||||
| string
|
||||
| number
|
||||
| undefined;
|
||||
const progressToken = clientToken ?? (extra.requestId as string | number);
|
||||
try {
|
||||
const result = await upstream.callTool(
|
||||
toolName,
|
||||
(req.params.arguments as Record<string, unknown>) ?? {},
|
||||
{
|
||||
progressToken,
|
||||
onNotification: async (notif) => {
|
||||
try {
|
||||
await extra.sendNotification(notif as any);
|
||||
} catch {
|
||||
// best effort
|
||||
}
|
||||
},
|
||||
},
|
||||
);
|
||||
// Pass through the upstream's CallToolResult as-is. Upstreams already
|
||||
// populate content / structuredContent / isError per the MCP spec.
|
||||
|
||||
Reference in New Issue
Block a user