Skip to content

t27mcp: one spec declares every tool's input and output schema; the MCP JSON schemas are generated from it #10444

Closed

Description

@gHashTag

Boundary

The t27 MCP server (gHashTag/t27-mcp) declares each tool's inputSchema by hand in server.mjs and telegram.mjs, and no tool declares an outputSchema. MCP schemas are plumbing a client parses, so by the own-language-first rule they are generated from a .t27 source, never hand-written.

In scope: one spec, specs/t27mcp/tool_schema.t27, with one row per tool and one row per input or output field; its seal; and, in gHashTag/t27-mcp, a generated wasm/tool_schema_table.mjs, a table-driven builder that replaces the inline schemas, and smoke checks. Out of scope: changing what any tool returns, and new tools. No hand-written foreign logic: the glue in t27-mcp is net <= 0 lines.

User Scenarios

  • A client calls tools/list and reads an inputSchema in which limit is an integer with a minimum, health is an enum, status of t27f_view is an array of at most 27 items each 0..255, and chat of a Telegram tool has the pattern the server enforces. It no longer finds out by failing a call.
  • A client that cached the catalog sees _meta["t27/catalog"] change when the spec changes, because the identity is the spec's seal hash plus the output profile.
  • An author who adds a tool without a row in the spec gets a startup error, not a silently loose schema.
  • A client that opts into the output profile receives outputSchema and matching structuredContent; a client that does not, receives neither (protocol 2024-11-05 has no outputSchema).

Requirements

  1. specs/t27mcp/tool_schema.t27 lists every advertised tool (27 with t27_paper_claims: recompute the numbers printed in the GoldenFloat, Golden Ruler and TNF papers t27-mcp#23) and, per tool, input fields and output fields as rows with kind, required, nullable, bounds, enum, pattern and description. Tuple, array, boolean and nested-object rows are all expressible; the shared spec filters of t27_specs and t27_grep are one group, not two copies.
  2. The spec's tests cover: every row well formed, property names unique, every tool has rows (or declares a text or any result), tuple/array/nested fixtures, and negative controls. 0 vacuous.
  3. t27c gen-js produces the table; the JSON Schema is built from it. Inputs are self-contained: no $ref, no definitions, additionalProperties: false at the top. A tuple is prefixItems plus minItems/maxItems, so it holds in draft-07 and 2020-12 readers.
  4. The catalog identity is <spec_hash>/p<profile>, carried in tools/list _meta. The vendored seal is checked against the table at build.
  5. Two profiles: inputs only (default, protocol 2024-11-05) and inputs plus outputs (opt-in, 2025-06-18, with structuredContent).

Success Criteria

  • t27c test-report specs/t27mcp/tool_schema.t27 is all pass with 0 vacuous, and a mutated row fails a test.
  • smoke.mjs in t27-mcp asserts every advertised tool has a row, no $ref appears in any schema, and the tuple, array, boolean and nested-object constraints survive the round trip.
  • Lines of hand-written JS in t27-mcp: net <= 0 across the PR.
  • The PR lists the tools whose schema was missing or loose before, and what each looks like after.

Requirements

FR-001: The spec specs/t27mcp/tool_schema.t27 MUST list every advertised tool (27 with gHashTag/t27-mcp#23) and, per tool, input fields and output fields as rows with kind, required, nullable, bounds, enum, pattern, and description. Tuple, array, boolean, and nested-object rows MUST be expressible; the shared spec filters of t27_specs and t27_grep MUST be one group, not two copies.

FR-002: The spec's tests MUST cover: every row well formed, property names unique, every tool has rows (or declares a text or any result), tuple/array/nested fixtures, and negative controls. There MUST be 0 vacuous tests.

FR-003: t27c gen-js MUST produce the table; the JSON Schema MUST be built from it. Inputs MUST be self-contained: no $ref, no definitions, additionalProperties: false at the top. A tuple MUST be prefixItems plus minItems/maxItems, so it holds in draft-07 and 2020-12 readers.

FR-004: The catalog identity MUST be <spec_hash>/p<profile>, carried in tools/list _meta. The vendored seal MUST be checked against the table at build.

FR-005: Two profiles MUST exist: inputs only (default, protocol 2024-11-05) and inputs plus outputs (opt-in, 2025-06-18, with structuredContent).

Activity

  1. added a commit that references this issue on Oct 18, 2026
    0220854
  2. added
    shape-refusedClosed by the issue-shape gate (specs/policy/issue_shape.t27); a passing edit reopens it
    on Oct 18, 2026
  3. github-actions commented on Oct 18, 2026

    @github-actions
    Contributor

    Closed by the issue-shape gate (specs/policy/issue_shape.t27, #7498): an issue must have the template's sections. Edit the body; an edit that passes reopens it.

    • missing: ## Requirements -- numbered obligations, FR-001: ... MUST ...
  4. added a commit that references this issue on Oct 18, 2026
    b200c3a
  5. removed
    shape-refusedClosed by the issue-shape gate (specs/policy/issue_shape.t27); a passing edit reopens it
    on Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions