[PR #7119] [MERGED] fix(mcp): fit every advertised input schema within the 64 KiB client limit #7653

Closed
opened 2026-11-03 13:39:25 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/7119
Author: @kaoru0822-kitauji
Created: 10/25/2026
Status: ✅ Merged
Merged: 10/25/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/4081-full-schema-size


📝 Commits (2)

  • f366d6b fix(mcp): fit every advertised input schema within the 64 KiB client limit
  • e1e82fa fix(mcp): keep fitted input summaries widening and at the deepest fitting level

📊 Changes

13 files changed (+1199 additions, -81 deletions)

View changed files

📝 docs/mcp-contracts.md (+22 -4)
📝 scripts/verify-copilot-client.mjs (+2 -2)
📝 src/catalogIdentity.ts (+3 -5)
➕ src/contracts/inputSchemaFitInvariants.test.ts (+264 -0)
➕ src/contracts/inputSchemaPresentation.test.ts (+371 -0)
📝 src/contracts/inputSchemaPresentation.ts (+423 -46)
📝 src/contracts/toolSchemaMetadata.ts (+9 -6)
📝 src/server/EvidenceMcpServerCore.ts (+3 -5)
📝 tests/boundary/mcp/browserComparisonInput.test.ts (+6 -2)
📝 tests/boundary/mcp/browserScenarioMcp.test.ts (+11 -6)
📝 tests/boundary/mcp/compactInputSchemaMcp.test.ts (+46 -2)
📝 tests/boundary/mcp/toolSchemaValidity.test.ts (+32 -2)
📝 tests/fixtures/mcpClientSchemaConstraints.ts (+7 -1)

📄 Description

What broke: Claude Desktop drops a local connector tool whose inputSchema, as compact JSON, is over 65,536 bytes, and shows "problem with that connector". On latest main, the opt-in full input profile still advertised compare_web_captures at 171,867 bytes and inspect_analysis_view at 71,632 bytes.
Fix: The full advertisement is now fitted to 64 KiB where it is produced (toolInputSchemaWithMetadata). A property that repeats an earlier sibling's schema points at that sibling. Below the deepest level that still fits, schemas are summarized as their types, size constraints and descriptions. Schemas that already fit are unchanged.
Risk: Only the advertised JSON of the two oversized tools changes. Nested detail below the cut is no longer advertised, but every rewrite only widens the schema, and the canonical contract still validates every call. The compact profile is byte-identical. Claude Desktop itself was not run.

Summary

Fixes #4081

The reporter and later commenters confirmed that the compact profile removes the warning. On main the compact profile is now the default, so this affects users who explicitly select REA_MCP_INPUT_SCHEMA_PROFILE=full. A commenter on #4081 traced the toast to a per-tool schema_too_large check in Claude Desktop (over 65,536 bytes of compact JSON). Nesting depth and $ref play no part in that check. This PR makes every advertised input schema fit that limit in both profiles. A catalog-wide regression test enforces it.

#4973 is not claimed. It also reports arguments that arrive as strings, which belongs to #3408 (#3486 / #3525).

Problem and expected behavior

  • Root cause: the full profile advertises self-contained input schemas, and the input schema of compare_web_captures is a root union of two groups. Each side inlines a complete producer result schema: before/after each carry inspect_web_page + discover_webmcp_tools (31.7 KB each), and before_scenario/after_scenario each carry capture_browser_scenario (50.5 KB each). So the same 31.7 KB and 50.5 KB subtrees are each serialized twice, plus a 6.1 KB example. inspect_analysis_view has no duplication: its view union of every view kind is 59.9 KB by itself.
  • Sharing definitions through $defs/$ref is ruled out. Input schemas must stay free of references (toolSchemaValidity asserts this, and #3408/#4058 show that Claude Desktop sends $ref'd arguments as strings). Without references, JSON Schema has no way to share a subtree, so a size bound is needed.
  • Invariant: every advertised input schema is at most 65,536 UTF-8 bytes of compact JSON, examples included, in both profiles.

Change and scope

  • src/contracts/inputSchemaPresentation.ts (the owner of advertised input presentation):
    • fitAdvertisedInputSchema returns a schema that fits unchanged. For a larger schema, it reruns the existing advertisement normalizer in a summary mode:
      1. A property whose nested schema equals an earlier sibling's (ignoring its description) becomes {type, description: "… Same schema as \before`."}`. This applies only when that is smaller.
      2. Nested schemas below instance level N are replaced by {type, items?, min/max size keywords, description}, where N is the deepest level that fits. A schema stays whole when its summary would not be smaller. Because of that, size is not monotone in N, so the search runs from the deepest level down. Array item types include tuple positions (prefixItems, draft-07 items arrays, additionalItems). Combinator and conditional branches count as the level of the instance they describe, so a union keeps every branch and their property names.
      3. The root description says the inputs are summarized and that the server validates complete canonical inputs.
    • Summaries go through the normalizer's existing widening rules: a changed oneOf becomes anyOf, and a changed not, if (with then/else) or contains with maxContains is dropped. New: unevaluatedProperties/unevaluatedItems are dropped when anything under them changes. Without that, a dropped then could narrow the schema; a module test covers this.
    • items is only advertised beside the single array type, never beside a type list (the Gemini/#7107 constraint). Required-name lists are not kept in summaries, because Gemini rejects required entries that are not declared properties.
    • A schema that contains local references, or that does not fit even at level 1, falls back to the existing compact projection at the 64 KiB budget. No catalog tool takes this path today.
    • presentAdvertisedInputProfile is the single place that picks the profile. Compact is still presented from the complete projection, not from the fitted one, so its output is unchanged. The server registration, catalog identity, the Copilot verifier and the profile digest test now use it. compactInputSchema.ts is not edited (#7107 changes it).
    • Literal relaxation moves into relaxUnsupportedLiterals. It now also relaxes numeric const/enum the same way as boolean literals. Main had 6 integer const: 2 values in the full compare_web_captures schema (projection_version, fingerprint_version). Gemini accepts only string enum members, and transports turn const into enum. That Gemini behavior is source-derived; it was not observed live.
  • Not included: retained-Evidence references for compare_web_captures inputs (a contract change), and any change to the compact projection.

Contract and boundary impact

  • Semantic owner and earliest changed stage: toolInputSchemaWithMetadata → fitAdvertisedInputSchema (full advertisement). The profile choice moves into presentAdvertisedInputProfile. Consumers: EvidenceMcpServerCore, catalogIdentity, scripts/verify-copilot-client.mjs.

  • Contribution scope fit and linked maintainer decision: not applicable (fix inside the existing advertisement boundary).

  • CLI and MCP/tool-catalog contract: the advertised full input schemas of compare_web_captures and inspect_analysis_view change, so the full-profile catalog digest changes. All other tools, output schemas and the compact profile are byte-identical. Canonical server-side validation is unchanged.

  • Provider, bridge, target-format, or platform compatibility: none.

  • Evidence, artifact, provenance, or reconstruction contract: none.

  • Target selection, authority, upstream behavior, and cleanup details: not applicable.

  • Generated metadata, package, or installation impact: the recorded catalog digests are regenerated at build. No committed generated files change.

  • Documentation or usability only; no target interaction.

Evidence and regression coverage

  • Tests added or updated:

    • tests/boundary/mcp/compactInputSchemaMcp.test.ts: new catalog-wide check that every input schema in both profiles (real EvidenceMcpServer, tools/list over a transport) is ≤ 65,536 bytes. It also checks that compare_web_captures points after → before and after_scenario → before_scenario. The profile digest test uses presentAdvertisedInputProfile.

    • tests/boundary/mcp/toolSchemaValidity.test.ts: the same limit on the generated catalog. Numeric-literal fixture cases. The existing relaxed scripts.items.source union assertion now runs on the complete projection, because the fitted advertisement summarizes that depth.

    • tests/boundary/mcp/browserScenarioMcp.test.ts: the fitted advertisement no longer rejects {before_scenario, after: <scenario>}, since after is summarized. The server still rejects it canonically; the test still asserts that rejection.

    • tests/boundary/mcp/browserComparisonInput.test.ts changes for the same reason. A malformed after.webmcp: {} moves to the runtime-only invalid cases, because after is advertised as "Same schema as before" to fit the limit, and the canonical parser and server still reject it. The same malformation on before, which is retained in full, is now an advertised-invalid case, so the advertisement's coverage of a malformed WebMCP capture is kept.

    • src/contracts/inputSchemaFitInvariants.test.ts (new) has property-style checks:

      • summary(x) accepts every value x accepts, for every input subschema in the catalog (probed with generic values and every value nested in canonical examples) and for synthetic tuple, union and conditional schemas, including draft-07 tuples;
      • the fitted schema is the deepest fitting candidate, for every oversized catalog projection and for a synthetic schema where a shallower summary is longer.

      Both synthetic cases fail with the first push's logic (Greptile P2s).

    • tests/fixtures/mcpClientSchemaConstraints.ts: also rejects numeric const/enum in input schemas.

    • src/contracts/inputSchemaPresentation.test.ts (new), with counterexamples a reviewer would try:

      • schemas that already fit are returned unchanged
      • sibling sharing
      • deepest-fitting level
      • union branches kept at their instance level
      • oneOf/not/if/contains+maxContains relaxed instead of narrowed
      • array summaries (items only beside array, [array, null] as anyOf, arrays of arrays)
      • schemas with $ref/$defs fall back with no reference
      • compact still derived from the complete projection
      • numeric literals
      • the unevaluatedProperties case, which fails without the new rule (checked by removing the rule)

      Every widening case checks with Ajv that inputs accepted by the original are also accepted by the advertisement.

  • Base reproduction: a stdio tools/list scan of the built server, node scripts/rea.mjs mcp.

    Profile Metric main bc143125e this PR
    full compare_web_captures input schema 171,867 B 64,890 B
    full inspect_analysis_view input schema 71,632 B 63,865 B
    full tools over 64 KiB 2 0
    full all input schemas 847,782 B 733,038 B
    full tools/list frame 4,231,262 B 4,116,518 B
    compact (default) tools over 64 KiB 0 0
    compact (default) all input schemas / frame 121,537 / 3,505,017 B identical bytes
    full non-string const/enum 6 0

    Sizes are UTF-8 bytes, not tokens. Projection cost, measured once per process because projections are memoized: all 229 input projections took 54 ms → 74 ms in one cold run each. Fitting takes about 21 ms for compare_web_captures and 11 ms for inspect_analysis_view, with the search running from the deepest level down. Peak memory was not measured separately; it is bounded by about seven ≤ 172 KB candidate trees per oversized tool.

  • User-visible MCP output: the full compare_web_captures schema keeps before → inspection/webmcp and their fields, the scenario's top-level fields and steps, normalization.rules[] and the tool example. after reads "The later or right-hand observation to compare. Same schema as \before`."`

  • Remaining proof gaps:

    • Claude Desktop itself was not run. The limit comes from the analysis of the client bundle in #4081, and this PR checks only the byte bound.
    • No live Gemini request.
    • scripts/verify-gemini-client.mjs still checks only boolean and empty-string literals; it was not changed or run.
    • schemaTypes partly duplicates detectedTypes in compactInputSchema.ts, which is off-limits while #7107 is open. They could be merged later.

Validation performed

  • Stdio tools/list scans of default, compact and full before and after (the table above): 0 tools over 64 KiB in each profile after; compact bytes identical.
  • Ajv check of the two fitted schemas: valid 2020-12, and every canonical example is accepted (1/1 and 10/10).
  • npm run test:focused -- on 17 files: inputSchemaPresentation, toolInputReferences, toolSchemaValidity, compactInputSchemaMcp, browserScenarioMcp, compactInputSchema, tupleSchemaParity, javascriptFactsViewMcp, analysisViewMcp, browserMcp, applicationEvidenceMcp, environmentServeWritesMcp, advertisedInputExamples, canonicalBase64Metadata, workflowInputContracts, browserToolContracts, accessibilityCaptureComparison. Result: 210 passed.
  • npm run test:focused -- on serverIdentity, outputSchemaProfile, mcpDoctor, cliStartupImports: 45 passed.
  • After the review fixes (e1e82fa3a), npm run test:focused -- on every test file that reads the advertised schema of compare_web_captures or inspect_analysis_view (36 files, found by grep), plus the fitting, compact and identity suites: 45 files, 459 passed, 1 skipped. This includes browserComparisonInput, which failed on CI for f366d6b5c.
  • Size scan after the review fixes: same bytes as above, compact byte-identical, 0 non-string literals.
  • npm run check:fast: passed.
  • npm run format:check: passed.
  • npm run docs:check: passed.
  • npm run metadata:check: passed.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Calls that were valid are still valid. A client that relied on the full advertisement to reject nested mistakes in these two tools now gets the server's canonical invalid_input rejection instead.
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable. No client application was run.
  • Package or release metadata impact: the full-profile catalog digest changes.
  • Security, privacy, process, or containment review: no target interaction. This changes advertisement only.

Author readiness

Human owner: @kaoru0822-kitauji

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/7119 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/25/2026 **Status:** ✅ Merged **Merged:** 10/25/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/4081-full-schema-size` --- ### 📝 Commits (2) - [`f366d6b`](https://github.com/morluto/rea/commit/f366d6b5ccbbdb3ffdc78613d965d5da9c4ca79a) fix(mcp): fit every advertised input schema within the 64 KiB client limit - [`e1e82fa`](https://github.com/morluto/rea/commit/e1e82fa3a0ce50e749a19ee94a133d3b92c588e4) fix(mcp): keep fitted input summaries widening and at the deepest fitting level ### 📊 Changes **13 files changed** (+1199 additions, -81 deletions) <details> <summary>View changed files</summary> 📝 `docs/mcp-contracts.md` (+22 -4) 📝 `scripts/verify-copilot-client.mjs` (+2 -2) 📝 `src/catalogIdentity.ts` (+3 -5) ➕ `src/contracts/inputSchemaFitInvariants.test.ts` (+264 -0) ➕ `src/contracts/inputSchemaPresentation.test.ts` (+371 -0) 📝 `src/contracts/inputSchemaPresentation.ts` (+423 -46) 📝 `src/contracts/toolSchemaMetadata.ts` (+9 -6) 📝 `src/server/EvidenceMcpServerCore.ts` (+3 -5) 📝 `tests/boundary/mcp/browserComparisonInput.test.ts` (+6 -2) 📝 `tests/boundary/mcp/browserScenarioMcp.test.ts` (+11 -6) 📝 `tests/boundary/mcp/compactInputSchemaMcp.test.ts` (+46 -2) 📝 `tests/boundary/mcp/toolSchemaValidity.test.ts` (+32 -2) 📝 `tests/fixtures/mcpClientSchemaConstraints.ts` (+7 -1) </details> ### 📄 Description **What broke:** Claude Desktop drops a local connector tool whose `inputSchema`, as compact JSON, is over 65,536 bytes, and shows "problem with that connector". On latest main, the opt-in `full` input profile still advertised `compare_web_captures` at 171,867 bytes and `inspect_analysis_view` at 71,632 bytes. **Fix:** The full advertisement is now fitted to 64 KiB where it is produced (`toolInputSchemaWithMetadata`). A property that repeats an earlier sibling's schema points at that sibling. Below the deepest level that still fits, schemas are summarized as their types, size constraints and descriptions. Schemas that already fit are unchanged. **Risk:** Only the advertised JSON of the two oversized tools changes. Nested detail below the cut is no longer advertised, but every rewrite only widens the schema, and the canonical contract still validates every call. The compact profile is byte-identical. Claude Desktop itself was not run. ## Summary Fixes #4081 The reporter and later commenters confirmed that the compact profile removes the warning. On main the compact profile is now the default, so this affects users who explicitly select `REA_MCP_INPUT_SCHEMA_PROFILE=full`. A commenter on #4081 traced the toast to a per-tool `schema_too_large` check in Claude Desktop (over 65,536 bytes of compact JSON). Nesting depth and `$ref` play no part in that check. This PR makes every advertised input schema fit that limit in both profiles. A catalog-wide regression test enforces it. #4973 is not claimed. It also reports arguments that arrive as strings, which belongs to #3408 (#3486 / #3525). ## Problem and expected behavior - Root cause: the full profile advertises self-contained input schemas, and the input schema of `compare_web_captures` is a root union of two groups. Each side inlines a complete producer result schema: `before`/`after` each carry `inspect_web_page` + `discover_webmcp_tools` (31.7 KB each), and `before_scenario`/`after_scenario` each carry `capture_browser_scenario` (50.5 KB each). So the same 31.7 KB and 50.5 KB subtrees are each serialized twice, plus a 6.1 KB example. `inspect_analysis_view` has no duplication: its `view` union of every view kind is 59.9 KB by itself. - Sharing definitions through `$defs`/`$ref` is ruled out. Input schemas must stay free of references (`toolSchemaValidity` asserts this, and #3408/#4058 show that Claude Desktop sends `$ref`'d arguments as strings). Without references, JSON Schema has no way to share a subtree, so a size bound is needed. - Invariant: every advertised input schema is at most 65,536 UTF-8 bytes of compact JSON, examples included, in both profiles. ## Change and scope - `src/contracts/inputSchemaPresentation.ts` (the owner of advertised input presentation): - `fitAdvertisedInputSchema` returns a schema that fits unchanged. For a larger schema, it reruns the existing advertisement normalizer in a summary mode: 1. A property whose nested schema equals an earlier sibling's (ignoring its description) becomes `{type, description: "… Same schema as \`before\`."}`. This applies only when that is smaller. 2. Nested schemas below instance level N are replaced by `{type, items?, min/max size keywords, description}`, where N is the deepest level that fits. A schema stays whole when its summary would not be smaller. Because of that, size is not monotone in N, so the search runs from the deepest level down. Array item types include tuple positions (`prefixItems`, draft-07 `items` arrays, `additionalItems`). Combinator and conditional branches count as the level of the instance they describe, so a union keeps every branch and their property names. 3. The root description says the inputs are summarized and that the server validates complete canonical inputs. - Summaries go through the normalizer's existing widening rules: a changed `oneOf` becomes `anyOf`, and a changed `not`, `if` (with `then`/`else`) or `contains` with `maxContains` is dropped. New: `unevaluatedProperties`/`unevaluatedItems` are dropped when anything under them changes. Without that, a dropped `then` could narrow the schema; a module test covers this. - `items` is only advertised beside the single `array` type, never beside a type list (the Gemini/#7107 constraint). Required-name lists are not kept in summaries, because Gemini rejects `required` entries that are not declared properties. - A schema that contains local references, or that does not fit even at level 1, falls back to the existing compact projection at the 64 KiB budget. No catalog tool takes this path today. - `presentAdvertisedInputProfile` is the single place that picks the profile. Compact is still presented from the complete projection, not from the fitted one, so its output is unchanged. The server registration, catalog identity, the Copilot verifier and the profile digest test now use it. `compactInputSchema.ts` is not edited (#7107 changes it). - Literal relaxation moves into `relaxUnsupportedLiterals`. It now also relaxes numeric `const`/`enum` the same way as boolean literals. Main had 6 integer `const: 2` values in the full `compare_web_captures` schema (`projection_version`, `fingerprint_version`). Gemini accepts only string enum members, and transports turn `const` into `enum`. That Gemini behavior is source-derived; it was not observed live. - Not included: retained-Evidence references for `compare_web_captures` inputs (a contract change), and any change to the compact projection. ## Contract and boundary impact - Semantic owner and earliest changed stage: `toolInputSchemaWithMetadata` → `fitAdvertisedInputSchema` (full advertisement). The profile choice moves into `presentAdvertisedInputProfile`. Consumers: `EvidenceMcpServerCore`, `catalogIdentity`, `scripts/verify-copilot-client.mjs`. - Contribution scope fit and linked maintainer decision: not applicable (fix inside the existing advertisement boundary). - CLI and MCP/tool-catalog contract: the advertised full input schemas of `compare_web_captures` and `inspect_analysis_view` change, so the full-profile catalog digest changes. All other tools, output schemas and the compact profile are byte-identical. Canonical server-side validation is unchanged. - Provider, bridge, target-format, or platform compatibility: none. - Evidence, artifact, provenance, or reconstruction contract: none. - Target selection, authority, upstream behavior, and cleanup details: not applicable. - Generated metadata, package, or installation impact: the recorded catalog digests are regenerated at build. No committed generated files change. - [x] Documentation or usability only; no target interaction. ## Evidence and regression coverage - Tests added or updated: - `tests/boundary/mcp/compactInputSchemaMcp.test.ts`: new catalog-wide check that every input schema in **both** profiles (real `EvidenceMcpServer`, `tools/list` over a transport) is ≤ 65,536 bytes. It also checks that `compare_web_captures` points `after` → `before` and `after_scenario` → `before_scenario`. The profile digest test uses `presentAdvertisedInputProfile`. - `tests/boundary/mcp/toolSchemaValidity.test.ts`: the same limit on the generated catalog. Numeric-literal fixture cases. The existing relaxed `scripts.items.source` union assertion now runs on the complete projection, because the fitted advertisement summarizes that depth. - `tests/boundary/mcp/browserScenarioMcp.test.ts`: the fitted advertisement no longer rejects `{before_scenario, after: <scenario>}`, since `after` is summarized. The server still rejects it canonically; the test still asserts that rejection. - `tests/boundary/mcp/browserComparisonInput.test.ts` changes for the same reason. A malformed `after.webmcp: {}` moves to the runtime-only invalid cases, because `after` is advertised as "Same schema as `before`" to fit the limit, and the canonical parser and server still reject it. The same malformation on `before`, which is retained in full, is now an advertised-invalid case, so the advertisement's coverage of a malformed WebMCP capture is kept. - `src/contracts/inputSchemaFitInvariants.test.ts` (new) has property-style checks: - `summary(x)` accepts every value `x` accepts, for every input subschema in the catalog (probed with generic values and every value nested in canonical examples) and for synthetic tuple, union and conditional schemas, including draft-07 tuples; - the fitted schema is the deepest fitting candidate, for every oversized catalog projection and for a synthetic schema where a shallower summary is longer. Both synthetic cases fail with the first push's logic (Greptile P2s). - `tests/fixtures/mcpClientSchemaConstraints.ts`: also rejects numeric `const`/`enum` in input schemas. - `src/contracts/inputSchemaPresentation.test.ts` (new), with counterexamples a reviewer would try: - schemas that already fit are returned unchanged - sibling sharing - deepest-fitting level - union branches kept at their instance level - `oneOf`/`not`/`if`/`contains`+`maxContains` relaxed instead of narrowed - array summaries (`items` only beside `array`, `[array, null]` as `anyOf`, arrays of arrays) - schemas with `$ref`/`$defs` fall back with no reference - compact still derived from the complete projection - numeric literals - the `unevaluatedProperties` case, which fails without the new rule (checked by removing the rule) Every widening case checks with Ajv that inputs accepted by the original are also accepted by the advertisement. - Base reproduction: a stdio `tools/list` scan of the built server, `node scripts/rea.mjs mcp`. | Profile | Metric | main `bc143125e` | this PR | |---|---|---:|---:| | full | `compare_web_captures` input schema | 171,867 B | 64,890 B | | full | `inspect_analysis_view` input schema | 71,632 B | 63,865 B | | full | tools over 64 KiB | 2 | 0 | | full | all input schemas | 847,782 B | 733,038 B | | full | `tools/list` frame | 4,231,262 B | 4,116,518 B | | compact (default) | tools over 64 KiB | 0 | 0 | | compact (default) | all input schemas / frame | 121,537 / 3,505,017 B | identical bytes | | full | non-string `const`/`enum` | 6 | 0 | Sizes are UTF-8 bytes, not tokens. Projection cost, measured once per process because projections are memoized: all 229 input projections took 54 ms → 74 ms in one cold run each. Fitting takes about 21 ms for `compare_web_captures` and 11 ms for `inspect_analysis_view`, with the search running from the deepest level down. Peak memory was not measured separately; it is bounded by about seven ≤ 172 KB candidate trees per oversized tool. - User-visible MCP output: the full `compare_web_captures` schema keeps `before` → `inspection`/`webmcp` and their fields, the scenario's top-level fields and steps, `normalization.rules[]` and the tool example. `after` reads `"The later or right-hand observation to compare. Same schema as \`before\`."` - Remaining proof gaps: - Claude Desktop itself was not run. The limit comes from the analysis of the client bundle in #4081, and this PR checks only the byte bound. - No live Gemini request. - `scripts/verify-gemini-client.mjs` still checks only boolean and empty-string literals; it was not changed or run. - `schemaTypes` partly duplicates `detectedTypes` in `compactInputSchema.ts`, which is off-limits while #7107 is open. They could be merged later. ## Validation performed - Stdio `tools/list` scans of `default`, `compact` and `full` before and after (the table above): 0 tools over 64 KiB in each profile after; compact bytes identical. - Ajv check of the two fitted schemas: valid 2020-12, and every canonical example is accepted (1/1 and 10/10). - `npm run test:focused --` on 17 files: `inputSchemaPresentation`, `toolInputReferences`, `toolSchemaValidity`, `compactInputSchemaMcp`, `browserScenarioMcp`, `compactInputSchema`, `tupleSchemaParity`, `javascriptFactsViewMcp`, `analysisViewMcp`, `browserMcp`, `applicationEvidenceMcp`, `environmentServeWritesMcp`, `advertisedInputExamples`, `canonicalBase64Metadata`, `workflowInputContracts`, `browserToolContracts`, `accessibilityCaptureComparison`. Result: 210 passed. - `npm run test:focused --` on `serverIdentity`, `outputSchemaProfile`, `mcpDoctor`, `cliStartupImports`: 45 passed. - After the review fixes (e1e82fa3a), `npm run test:focused --` on every test file that reads the advertised schema of `compare_web_captures` or `inspect_analysis_view` (36 files, found by grep), plus the fitting, compact and identity suites: 45 files, 459 passed, 1 skipped. This includes `browserComparisonInput`, which failed on CI for f366d6b5c. - Size scan after the review fixes: same bytes as above, compact byte-identical, 0 non-string literals. - `npm run check:fast`: passed. - `npm run format:check`: passed. - `npm run docs:check`: passed. - `npm run metadata:check`: passed. ## Compatibility, safety, and release - Breaking changes or migration steps: none. Calls that were valid are still valid. A client that relied on the full advertisement to reject nested mistakes in these two tools now gets the server's canonical `invalid_input` rejection instead. - Real Hopper/Ghidra, browser, or OS coverage: not applicable. No client application was run. - Package or release metadata impact: the full-profile catalog digest changes. - Security, privacy, process, or containment review: no target interaction. This changes advertisement only. ## Author readiness Human owner: @kaoru0822-kitauji - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [ ] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [ ] The PR has one focused outcome and the title follows `type(scope): outcome`. - [ ] Related issue is linked, or the reason for not linking one is stated above. - [ ] Tests cover changed observable behavior and meaningful failure paths. - [ ] Owning docs, contracts, and generated metadata are updated where needed. - [ ] User-visible CLI/MCP changes include representative output. - [ ] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-03 13:39:25 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#7653
No description provided.