Skip to content

request-state-complete accepts tool-error results and completions missing its documented state-ok marker #505

Description

@YS-OH-CORE

Scope

While examining the concrete prerequisite problem in #440, I found a separate round-2 false-positive in InputRequiredResultRequestStateScenario. This case uses a non-empty, correctly keyed inputRequests map, so it does not depend on #440's manufactured "undefined" key. Credit for that original issue remains with its reporter.

Inspected main commit: 7169291ec0b68eb370fddcd9947313ab0d5e4156.

The fixture description requires round 2 to validate echoed state and return text containing state-ok. The check only rejects a JSON-RPC error, an absent result, or resultType: "input_required". It never checks the tool-result isError flag or the documented marker.

Executed local probe

I copied this scenario's run body into an isolated TypeScript wrapper, transpiled it with TypeScript 5.8.3, and executed it on Node 22.16.0. sendRpc was a controlled two-response stub; the type guards and mock-elicitation logic matched the pinned helper. Round 1 always returned a non-empty confirm elicitation and requestState: "s-1".

Round-2 response Observed sep-2322-request-state-complete Expected under this fixture's stated contract
complete, text state-ok SUCCESS SUCCESS
complete, text ordinary completion SUCCESS FAILURE: missing fixture marker
complete, isError: true, text state rejected SUCCESS FAILURE: tool error
complete, isError: true, text state-ok, but execution failed SUCCESS FAILURE: marker must not override tool error
JSON-RPC error FAILURE FAILURE
another input-required result FAILURE FAILURE
no result FAILURE FAILURE

Execution boundary: this is an isolated execution of the copied check body, not an upstream CLI run, HTTP transport test, or real-SDK conformance result. A local candidate adding both result predicates produced the expected outcomes in all seven cases. No upstream patch is asserted tested or ready to merge.

Minimal predicate reproduction

This can also be seen without any SDK dependencies; save as probe.cjs and run node probe.cjs:

const assert = require('node:assert/strict');
// Logic of the pinned helper and successful-result branch, types removed.
const isCompleteResult = r => !!r && r.resultType !== 'input_required';
function currentCheck(r2) {
  const result = r2.result;
  const errors = [];
  if (r2.error) errors.push('JSON-RPC error');
  else if (!result) errors.push('No result');
  else if (!isCompleteResult(result)) errors.push('Not complete');
  return errors.length === 0 ? 'SUCCESS' : 'FAILURE';
}
for (const result of [
  {resultType:'complete', content:[{type:'text', text:'ordinary completion'}]},
  {resultType:'complete', isError:true, content:[{type:'text', text:'state rejected'}]}
]) {
  assert.equal(currentCheck({result}), 'SUCCESS');
  console.log(currentCheck({result}));
}

Both print SUCCESS, despite violating the scenario's documented successful-completion requirement.

Suggested regression scope

Extend the existing MRTR negative-test/fixture path, rather than adding another runner: exercise both kinds of erroneous completion, keep a state-ok success control, and retain the JSON-RPC-error/input-required controls. Keep the same check ID for pass and fail. The marker requirement is fixture-specific, not a new normative MCP requirement for all servers. Checking a marker also cannot prove genuine state validation by itself; the separate tampered-state scenario remains necessary.

This does not show that a broken implementation passes the entire suite. It shows that this one named check can report successful state validation on these completions. Searched existing issues for state-ok and request-state plus isError; no matching report was returned.

Prepared by Youngseok Oh (@YS-OH-CORE) with Zero (ChatGPT); AI-assisted source analysis and local probe. Public synthetic inputs only.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions