input-required-result: harness sends the literal string `"undefined"` as an inputResponses key when round 1 names no input requests

Open
#440 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
76/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
typescript
Domain
testing-qa

Research direction

Start in src/scenarios/server/input-required-result.ts at the round-2 sites on lines 539, 865, 908, 1095, and 1337, then run the input-required-result-request-state scenario against the described probe server. Use negative-mrtr.test.ts and sep-2322-mrtr-broken-server for the regression assertion. Done means round 2 reports the missing prerequisite instead of sending an inputResponses key named "undefined".

Written by the indexing model from the issue text.

Description

Following up on #439 item 3 — I went to look at that one guard and found a
round-2 consequence that issue doesn't cover.

InputRequiredResult.inputRequests is optional (required: ["resultType"] in the
draft schema), and sep-2322.yaml states the rule as "at least one of
inputRequests or requestState". So a server answering

{ "resultType": "input_required", "requestState": "s-1", "inputRequests": {} }

is conformant, and the round-1 checks are right to pass it. But five round-2 sites
then take the first key of that map without checking it exists:

const inputKey = Object.keys(r1Result.inputRequests!)[0];   // undefined
// ...
inputResponses: { [inputKey]: mockElicitResponse({ ok: true }) }

A computed key stringifies, so the harness puts the literal string "undefined" on
the wire.

Repro

Against a probe server returning the result above for every MRTR tool and
prompts/get, with requestState rotating so round 2 is reachable:

node dist/index.js server --url http://localhost:PORT/mcp \
  --scenario input-required-result-request-state --spec-version 2026-07-28

The probe logged the inputResponses keys it received across four scenarios:

tools/call  test_input_required_result_request_state   -> ["undefined"]
tools/call  test_input_required_result_multi_round     -> ["undefined"]
tools/call  test_input_required_result_multi_round     -> ["undefined"]
prompts/get test_input_required_result_prompt          -> ["undefined"]
tools/call  test_input_required_result_tampered_state  -> ["undefined"]

Sites: :539, :865, :908, :1095, :1337. The two equivalents at
:269 and :405 are unreachable here — their round-1 arms use
Object.keys(...)[0] behind a !key guard that already failed the scenario.

Why it matters

The round-2 check then fails, and the report attributes that to the server:

[sep-2322-request-state-incomplete] SUCCESS Server returns InputRequiredResult with both inputRequests and requestState
[sep-2322-request-state-complete  ] FAILURE Server validates echoed requestState and returns complete result
[wire-schema-valid                ] SUCCESS Every JSON-RPC message the implementation sent is valid ...

wire-schema-valid passes because inputResponses keys are unconstrained, so
nothing else catches it either.

Suggested direction

Gate round 2 on actually having a key, and report the prerequisite rather than
sending a request that can't be answered — the convention #372 established for
missing prerequisites. Each of the five sites is two lines; happy to send a PR.

negative-mrtr.test.ts plus sep-2322-mrtr-broken-server already give a place to
assert it, so this can carry a regression test without new harness plumbing.

Dominant language
TypeScript
Stars
127
Forks
101
Avg merge
6d 1h
Merged PRs (30d)
7

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from modelcontextprotocol/conformance

All issues in modelcontextprotocol/conformance

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.