Skip to content

Commit 1ed59d1

Browse files
committed
fix(cloudflare): preserve scopes and cancellation
1 parent 47bbbd0 commit 1ed59d1

2 files changed

Lines changed: 27 additions & 4 deletions

File tree

src/providers/cloudflare_mcp/executors.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,20 @@ describe("Cloudflare MCP executors", () => {
3838
expect(apiKeyResult?.metadata?.mcpTools).toEqual(["docs", "execute", "search"]);
3939
expect(oauthResult?.metadata?.mcpTools).toEqual(["docs", "execute", "search"]);
4040
});
41+
42+
it("does not start MCP traffic after the execution is cancelled", async () => {
43+
const controller = new AbortController();
44+
controller.abort();
45+
const fetcher = createMcpFetch([], "cf-token");
46+
47+
await expect(
48+
cloudflareMcpActionHandlers.search(
49+
{ code: "async () => ['workers']" },
50+
{ accessToken: "cf-token", fetcher, signal: controller.signal },
51+
),
52+
).rejects.toThrow();
53+
expect(fetcher).not.toHaveBeenCalled();
54+
});
4155
});
4256

4357
function createMcpFetch(calls: Array<Record<string, unknown>>, expectedToken: string): typeof fetch {

src/providers/cloudflare_mcp/executors.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ async function validateCloudflareMcpCredential(accessToken: string, fetcher: typ
5757
accountId: `cloudflare:mcp:${tokenHash}`,
5858
displayName: `Cloudflare MCP · ${tokenHash.slice(-6)}`,
5959
},
60-
grantedScopes: [],
6160
metadata: {
6261
mcpEndpoint: cloudflareMcpEndpoint,
6362
mcpTools: toolNames,
@@ -67,7 +66,13 @@ async function validateCloudflareMcpCredential(accessToken: string, fetcher: typ
6766

6867
async function listCloudflareMcpTools(input: { accessToken: string; fetcher: typeof fetch; signal?: AbortSignal }) {
6968
return withCloudflareMcpClient(input, async (client) => {
70-
const result = await client.listTools({}, { timeout: cloudflareMcpRequestTimeoutMs });
69+
const result = await client.listTools(
70+
{},
71+
{
72+
timeout: cloudflareMcpRequestTimeoutMs,
73+
signal: input.signal,
74+
},
75+
);
7176
return result.tools;
7277
});
7378
}
@@ -80,6 +85,7 @@ async function callCloudflareMcpTool(
8085
return withCloudflareMcpClient(context, async (client) => {
8186
const result = await client.callTool({ name: toolName, arguments: argumentsInput }, undefined, {
8287
timeout: cloudflareMcpRequestTimeoutMs,
88+
signal: context.signal,
8389
});
8490
return normalizeCloudflareMcpToolResult(toolName, result);
8591
});
@@ -94,12 +100,15 @@ async function withCloudflareMcpClient<T>(
94100
headers.set("user-agent", providerUserAgent);
95101
const transport = new StreamableHTTPClientTransport(new URL(cloudflareMcpEndpoint), {
96102
fetch: input.fetcher,
97-
requestInit: { headers, signal: input.signal },
103+
requestInit: { headers },
98104
});
99105
const client = new Client({ name: "oomol-connect-cloudflare-mcp", version: "1.0.0" });
100106

101107
try {
102-
await client.connect(transport, { timeout: cloudflareMcpRequestTimeoutMs });
108+
await client.connect(transport, {
109+
timeout: cloudflareMcpRequestTimeoutMs,
110+
signal: input.signal,
111+
});
103112
return await run(client);
104113
} catch (error) {
105114
throw mapCloudflareMcpError(error);

0 commit comments

Comments
 (0)