codemode: openApiMcpServer search deep-clones every resolved $ref, so large specs exceed Worker memory · Issue #2596 · cloudflare/agents · GitHub
Skip to content

codemode: openApiMcpServer search deep-clones every resolved $ref, so large specs exceed Worker memory #2596

Open

Description

@dillionverma

openApiMcpServer's sandbox code (createOpenApiSandboxCode in dist/mcp.js, 0.5.4) resolves $refs with a cache, but returns structuredClone(cached) at every use:

const __cloneResolvedRef = (value) => structuredClone(value);
...
if (__refCache.has(ref)) return __cloneResolvedRef(__refCache.get(ref));

For a spec that reuses large schemas in many places, every use becomes a full deep copy, so codemode.spec() grows far beyond the raw spec. The Google Ads REST spec (v24, 2.2 MB, 171 paths) is an example. GoogleAdsRow and MutateOperation are unions of every resource and appear in many operations. A search call that only does Object.keys((await codemode.spec()).paths) fails in production with Worker exceeded memory limit.

Measured locally (V8 heap after GC, resolving the whole spec):

spec raw heap with clone heap with shared refs
Google Ads v24 2.2 MB 348 MB 2.6 MB
Google Workspace (merged) 3.4 MB 275 MB 4.0 MB
App Store Connect 3.2 MB 76 MB 11.3 MB

Suggested fix: return the cached object (const __cloneResolvedRef = (value) => value;). The JSON.stringify output of the resolved spec was the same for all 19 specs we tested, including the $circular markers. __resolvedSpec is rebuilt for each sandbox run, so a mutation does not persist to the next call. The only change is that sandbox code which mutates the resolved spec mutates every place that shares the object. If that is a concern, a frozen object or a lazy per-path resolve would also keep memory flat.

We ran this as a one-line patch in production. We replaced it with a trimmed spec because we keep zero dependency patches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions