Skip to content

fix(outpost mcp): refuse destination fields the type does not declare - #450

Merged
leggetter merged 1 commit into
mainfrom
fix/outpost-mcp-destination-field-validation
Sep 24, 2026
Merged

leggetter merged 1 commit into
mainfrom
fix/outpost-mcp-destination-field-validation

Conversation

@leggetter

Copy link
Copy Markdown
Collaborator

Fixes #447.

outpost_destinations_write accepted config and credential keys the destination type does not declare. An unknown config key was stored and an unknown credential was dropped, both reported as success. The CLI has always rejected them.

A misspelled optional field — custom_header for custom_headers — looked applied and never took effect.

Fix

  • Create and update now check config and credentials keys against the type schema. Update takes no type, so it reads the destination's; if that read fails, the update goes through and the API reports the problem.
  • Only unknown keys are checked. Required fields, allowed values and formats are already enforced by the API on both surfaces, and the CLI validator's messages for those are phrased as --config flags, which an agent cannot use. A new outposttypes.UnknownFields helper carries the one rule, with the same nested-value deferral as the CLI.
  • A schema fetch failure does not block the request, matching the CLI.

The error names the fields and the tool that lists the valid ones:

config has fields the webhook type does not accept: "custom_header". Call outpost_destination_types_read to see the fields this type accepts.

Tests

  • Unknown config key on create, unknown credential on create, unknown config key on update: each refused, and the write never reaches the API.
  • Declared fields pass through.
  • Verified to fail without the fix.
  • Verified against the live Outpost API on a build of this branch: the misspelled key is refused, a valid create succeeds. Test tenant deleted afterwards.

Found by the v3.0 Outpost end-to-end QA pass. Intended for v3.0.2.

🤖 Generated with Claude Code

https://claude.ai/code/session_012XtSQ2kfpcRXXqweskgXkH

The CLI rejects a destination config or credential key the type does not
declare. outpost_destinations_write accepted one: an unknown config key was
stored and an unknown credential was dropped, both reported as success. A
misspelled optional field -- custom_header for custom_headers -- looked applied
and never took effect.

The tool called outposttypes.ApplyDefaultsForType but never checked keys
against the schema. It now does, on create and update. Update takes no type, so
it reads the destination's; if that read fails the update is sent anyway, since
the API reports a missing destination better than a guess here would.

Only unknown keys are checked. Required fields, allowed values and formats are
already enforced by the API on both surfaces, and the CLI's messages for those
are phrased as flags, which an agent cannot use. The new UnknownFields helper in
outposttypes carries the one rule MCP needs, with the same nested-value
deferral as the CLI. A schema that cannot be fetched does not block the request,
matching the CLI.

Tests: unknown config key on create, unknown credential on create, unknown
config key on update -- each refused without reaching the API -- and declared
fields passing through. Verified to fail without the fix, and against the live
Outpost API: the misspelled key is refused, the valid create succeeds.

Fixes #447

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012XtSQ2kfpcRXXqweskgXkH
@leggetter
leggetter merged commit 069f85a into main Sep 24, 2026
14 checks passed
@leggetter
leggetter deleted the fix/outpost-mcp-destination-field-validation branch September 24, 2026 19:35
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.

outpost_destinations_write accepts config and credential fields the destination type does not have

1 participant