Skip to content

test: every array-typed MCP argument must deliver its values to the API - #456

Open
leggetter wants to merge 1 commit into
mainfrom
test/array-args-reach-api
Open

leggetter wants to merge 1 commit into
mainfrom
test/array-args-reach-api

Conversation

@leggetter

Copy link
Copy Markdown
Collaborator

The follow-up #455 names in its Not covered section.

#455 makes every read that treats an MCP argument as a list go through StringList, so a bare or comma-separated string is never dropped. It cannot see the reverse: a handler that declares an argument as an array and reads it with in.String(), which returns "" for an array and drops it without an error.

What this adds

A test on each server that:

  • finds every array-typed argument from the live tool schemas, with writes enabled;
  • requires each to have a valid call in a table;
  • sends a genuine JSON array to a recording server, and requires every value to reach the request.

A new array argument fails until it has an entry; a stale entry fails too. The expected strings are the encodings captured from the recording server, not assumed.

Today

Ten array arguments, and all ten deliver correctly — a guard, not a fix.

Server Arguments
Gateway metrics_read.measures, metrics_read.dimensions, request_write.connection_ids, connections_write.rules
Outpost attempts_read.include, config_write.unset, destinations_read.topics, destinations_write.topics, metrics_read.measures, metrics_read.dimensions

Proven against the failure

  • Reading connection_ids with in.String() fails the Gateway test — and the recorded request shows why it matters: the retry goes out as {}, meaning retry every connection, instead of the two chosen. A silent widening of a write.
  • Reading include with in.String() fails the Outpost test.
  • Removing a table entry fails with a message naming the argument.

CI's unit-test steps (go test -short ./pkg/..., go vet ./...) pass locally by exit code.

Intended for v3.0.3.

🤖 Generated with Claude Code

https://claude.ai/code/session_012XtSQ2kfpcRXXqweskgXkH

The input-shape guard (#455) makes every read that treats an argument as a
list go through StringList, so a string is never dropped. It cannot see the
reverse: a handler that declares an argument as an array and reads it with
in.String(), which returns "" for an array and drops it without an error.

These tests find every array-typed argument from the live tool schemas on both
servers, with writes enabled, and require each to have a valid call in a table.
Each call sends a genuine JSON array to a recording server, and every value
must reach the request. A new array argument fails until it has an entry; a
stale entry fails too.

Ten arguments today -- four on Gateway (metrics measures and dimensions,
request connection_ids, connection rules) and six on Outpost -- and all ten
deliver correctly, so this is a guard, not a fix. The expected strings are the
encodings captured from the recording server, not assumed.

Verified against the failure: reading connection_ids with in.String() fails the
Gateway test -- and shows the retry going out as {}, i.e. retry every
connection instead of the two chosen, a silent widening. Reading include with
in.String() fails the Outpost test. Removing a table entry fails with a message
naming the argument.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XtSQ2kfpcRXXqweskgXkH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant