Repository navigation
Keep the loader cache the size of the spec, and off every MCP call - #101
Merged
Merged
Conversation
A spec whose schemas refer to each other in a ring wrote a 2.5 GB loader cache: every endpoint's schemas were stored with each $ref expanded along every path through the ring. Every MCP call read that file first, so the server answered `initialize` and then hung. Schemas now live in <id>.schemas.json as the document wrote them, each reachable definition once, and are bundled per endpoint on request with shared definitions under $defs. <id>.json holds only the endpoint list, which is all listing, searching and access decisions read. A cache from before the split is read only as far as its endpoint list. Request-body skeletons get a node budget, since the depth limit alone still let them branch into hundreds of kilobytes.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Refreshing a collection whose OpenAPI spec has schemas that refer to each other in a ring (Object → Function → Operand → Object) wrote
loaders/<section>.jsonat ~2.5 GB. After that every MCP tool call hung,list_sectionsincluded, whileinitializestill answered.openapi::resolve_schemaexpanded every$refin place and stopped only where a reference met itself on the current path. The number of such paths through a densely connected ring grows factorially, and every endpoint stored its own expanded copy of both its request and its response schema. The MCP server already cached the parsed file per section, but the first read loaded the whole 2.5 GB file to count endpoints and never finished.Fix
Schemas stored once, expanded on request.
loaders/<id>.schemas.json. Each is stored as the document wrote it, with every definition it reaches kept once, keyed by$ref.openapi::bundlemakes one endpoint's schema self-contained whenget_endpointor the editor asks for it. A definition used once is written in place. Anything used more than once is written a single time under$defs, so the output can't exceed the schema plus the definitions it reaches.$defs, and the old output left cyclic refs dangling so it couldn't validate them. That now works; there's a new test injson-schema.spec.ts.Calls that don't need schemas never read them.
<id>.jsonholds onlyloadedAtandendpoints, which is all listing, searching andsend_request's access decision need.get_endpointloads them.Older caches. The old format serialized
endpointsbeforeschemas, soread_cachestreams and stops once it has both fields. A 2.5 GB file is read only as far as its ~250 KB endpoint list. Its schemas aren't served:get_endpointreturnsnulluntil the next refresh writes both files.Request bodies. Body skeletons get a 1,000-node budget, and a body that doesn't fit is rebuilt one level shallower. The depth limit alone let the test spec produce a 440 KB body per endpoint.
Verification
src-tauri/tests/fixtures/cyclic-union.json(19.5 KB): a union whose branches contain the union again, over 7 schemas that all reference each other, shared by 20 endpoints.cargo fmt --check, clippy-D warningswith and without default features, andcargo testwith and without default features all pass.json-schema.spec.tspasses 19/19.Through the real MCP server over stdio:
list_sectionsrefresh_endpointslist_sections/get_endpointafter restart