[GH-ISSUE #265] Harden MCP inputs with strict schemas, titles, and field descriptions #153

Closed
opened 2026-10-15 18:21:42 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @morluto on GitHub (Jul 16, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/265

Problem

REA's 84 MCP tools publish valid JSON Schema and strong tool-level descriptions, but most input contracts are open, untitled, and insufficiently described at field level. This makes typos silently disappear and forces hosts/agents to infer units, bounds, approval relationships, and continuation behavior.

Observed wire surface

Audited against the current 84-tool tools/list result from main:

  • 0/84 tools publish a top-level title or annotations.title;
  • only 7/84 input roots publish additionalProperties: false;
  • 385 top-level input fields exist, but only 99 have descriptions;
  • 244 top-level fields carry a bound, enum, pattern, or other constraint, but only 43 of those constrained fields have descriptions;
  • five no-argument tools publish open object schemas rather than an explicitly closed empty object;
  • internal ToolContract.examples are validated in tests but are not represented on the MCP wire surface.

The missing descriptions are concentrated in complex and approval-sensitive operations. Examples include:

  • inventory_artifact: 0/16 top-level fields described;
  • extract_artifact: 0/11;
  • run_controlled_replay: 0/10;
  • record_unknown: 0/11;
  • update_unknown: 0/13;
  • inspect_managed_artifact: 0/10;
  • analyze_javascript_application: 0/5;
  • compare_application_versions: 0/6.

Silent typo reproduction

binary_session accepted this misspelled field and returned success:

{
  "expected_package_verison": "typo-is-silently-ignored"
}

The undeclared field is accepted by the published open JSON Schema and stripped by the Zod object parser. At a caller boundary, a fixed-shape request should parse exactly or fail; silently deleting an unknown argument hides agent and user mistakes.

Protocol and SDK context

MCP requires object-root input schemas. The current specification recommends { "type": "object", "additionalProperties": false } for no-parameter tools. It also supports human-readable tool titles, with display precedence title, then annotations.title, then name.

The TypeScript SDK supports title, descriptions, Zod schemas, defaults, constraints, and raw JSON Schema. REA's internal ToolContract currently has no title field, while most caller-visible schemas use non-strict z.object().

Proposed contract policy

  1. Every fixed-shape caller input object is strict at the root and at nested fixed-shape boundaries.
  2. Intentional arbitrary-key maps remain explicit records and are not accidentally closed.
  3. Every tool has a concise human-readable top-level title.
  4. Every top-level input field has a caller-facing description.
  5. Constrained fields describe units, accepted range/enum, effective default, scope, and continuation behavior.
  6. Approval and opt-in fields describe their relationship, required operator policy, side effects, and restart requirements.
  7. Examples are exposed selectively through valid JSON Schema annotations or documented prompts where host support is useful; internal-only examples must not be mistaken for discovery metadata.

Acceptance criteria

  • All 84 tools publish a human-readable title.
  • Every fixed-shape input root publishes additionalProperties: false.
  • Nested fixed-shape objects reject unknown fields; intentional records still accept declared arbitrary keys.
  • No-parameter tools publish explicitly closed empty-object schemas.
  • Unknown top-level and nested fields fail before provider, task, filesystem, session, or Evidence effects.
  • Every top-level caller-visible field has a useful description.
  • Bounds/defaults include units and scope where names alone are ambiguous.
  • Pagination fields explain offset/limit semantics and continuation.
  • Approval pairs and policy prerequisites are described together.
  • Actual MCP tools/list compatibility tests inspect titles, descriptions, constraints, and additionalProperties rather than only internal Zod schemas.
  • Wire tests cover a misspelled optional field, unknown nested field, closed empty input, intentional record, omitted default, and valid boundary values.
  • CLI schema/help remains semantically aligned with MCP discovery.

Relationships

  • #261 owns actionable range-validation errors and the SDK pre-handler validation boundary. This issue owns the broader exact-input and discovery-metadata policy.
  • #101 owns dynamic capability/policy availability and annotation semantics.

Non-goals

  • Weakening runtime validation to accommodate clients.
  • Closing intentional JSON maps.
  • Requiring hosts to render every JSON Schema annotation.
  • Treating titles or descriptions as security enforcement.
Originally created by @morluto on GitHub (Jul 16, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/265 ## Problem REA's 84 MCP tools publish valid JSON Schema and strong tool-level descriptions, but most input contracts are open, untitled, and insufficiently described at field level. This makes typos silently disappear and forces hosts/agents to infer units, bounds, approval relationships, and continuation behavior. ## Observed wire surface Audited against the current 84-tool `tools/list` result from `main`: - 0/84 tools publish a top-level `title` or `annotations.title`; - only 7/84 input roots publish `additionalProperties: false`; - 385 top-level input fields exist, but only 99 have descriptions; - 244 top-level fields carry a bound, enum, pattern, or other constraint, but only 43 of those constrained fields have descriptions; - five no-argument tools publish open object schemas rather than an explicitly closed empty object; - internal `ToolContract.examples` are validated in tests but are not represented on the MCP wire surface. The missing descriptions are concentrated in complex and approval-sensitive operations. Examples include: - `inventory_artifact`: 0/16 top-level fields described; - `extract_artifact`: 0/11; - `run_controlled_replay`: 0/10; - `record_unknown`: 0/11; - `update_unknown`: 0/13; - `inspect_managed_artifact`: 0/10; - `analyze_javascript_application`: 0/5; - `compare_application_versions`: 0/6. ## Silent typo reproduction `binary_session` accepted this misspelled field and returned success: ```json { "expected_package_verison": "typo-is-silently-ignored" } ``` The undeclared field is accepted by the published open JSON Schema and stripped by the Zod object parser. At a caller boundary, a fixed-shape request should parse exactly or fail; silently deleting an unknown argument hides agent and user mistakes. ## Protocol and SDK context MCP requires object-root input schemas. The current specification recommends `{ "type": "object", "additionalProperties": false }` for no-parameter tools. It also supports human-readable tool titles, with display precedence `title`, then `annotations.title`, then `name`. The TypeScript SDK supports `title`, descriptions, Zod schemas, defaults, constraints, and raw JSON Schema. REA's internal `ToolContract` currently has no title field, while most caller-visible schemas use non-strict `z.object()`. ## Proposed contract policy 1. Every fixed-shape caller input object is strict at the root and at nested fixed-shape boundaries. 2. Intentional arbitrary-key maps remain explicit records and are not accidentally closed. 3. Every tool has a concise human-readable top-level title. 4. Every top-level input field has a caller-facing description. 5. Constrained fields describe units, accepted range/enum, effective default, scope, and continuation behavior. 6. Approval and opt-in fields describe their relationship, required operator policy, side effects, and restart requirements. 7. Examples are exposed selectively through valid JSON Schema annotations or documented prompts where host support is useful; internal-only examples must not be mistaken for discovery metadata. ## Acceptance criteria - [ ] All 84 tools publish a human-readable title. - [ ] Every fixed-shape input root publishes `additionalProperties: false`. - [ ] Nested fixed-shape objects reject unknown fields; intentional records still accept declared arbitrary keys. - [ ] No-parameter tools publish explicitly closed empty-object schemas. - [ ] Unknown top-level and nested fields fail before provider, task, filesystem, session, or Evidence effects. - [ ] Every top-level caller-visible field has a useful description. - [ ] Bounds/defaults include units and scope where names alone are ambiguous. - [ ] Pagination fields explain offset/limit semantics and continuation. - [ ] Approval pairs and policy prerequisites are described together. - [ ] Actual MCP `tools/list` compatibility tests inspect titles, descriptions, constraints, and `additionalProperties` rather than only internal Zod schemas. - [ ] Wire tests cover a misspelled optional field, unknown nested field, closed empty input, intentional record, omitted default, and valid boundary values. - [ ] CLI schema/help remains semantically aligned with MCP discovery. ## Relationships - #261 owns actionable range-validation errors and the SDK pre-handler validation boundary. This issue owns the broader exact-input and discovery-metadata policy. - #101 owns dynamic capability/policy availability and annotation semantics. ## Non-goals - Weakening runtime validation to accommodate clients. - Closing intentional JSON maps. - Requiring hosts to render every JSON Schema annotation. - Treating titles or descriptions as security enforcement.
bsakaguchi 2026-10-15 18:21:42 +00:00
Author
Owner

@morluto commented on GitHub (Jul 16, 2026):

REA 2.0 schema-quality slice (separate from #261 error projection): every tool has a title, fixed-shape wire objects are closed recursively, intentional records remain open, and actual beta.4 tools/list tests audit field descriptions, strict roots/nesting, output schemas, annotations, and no-argument tools.

<!-- gh-comment-id:4990831330 --> @morluto commented on GitHub (Jul 16, 2026): REA 2.0 schema-quality slice (separate from #261 error projection): every tool has a title, fixed-shape wire objects are closed recursively, intentional records remain open, and actual beta.4 tools/list tests audit field descriptions, strict roots/nesting, output schemas, annotations, and no-argument tools.
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#153
No description provided.