Skip to content

fix(mcp): return raw body on 2xx decode failure from generated client#96

Merged
electather merged 4 commits into
mainfrom
fix/mcp-decode-error-fallback
Mar 29, 2026
Merged

fix(mcp): return raw body on 2xx decode failure from generated client#96
electather merged 4 commits into
mainfrom
fix/mcp-decode-error-fallback

Conversation

@electather
Copy link
Copy Markdown
Owner

Summary

The generated UserSettings model uses DisallowUnknownFields() but Overseerr returns extra fields (id, pgpKey, push notification fields, notificationTypes) not present in the OpenAPI spec. Any MCP tool that calls an endpoint whose response embeds a User object (with nested UserSettings) would fail with json: unknown field "id" even though the HTTP call succeeded and the resource was created/modified.

Discovered while using request_create to request Dororo — the TV show was queued in Sonarr but the MCP client received an error.

Changes

  • Add marshalResult(res, httpResp, err) helper in cmd/mcp/mcp.go: when Execute() returns a *GenericOpenAPIError on a 2xx response, the raw body is returned instead of treating it as a tool failure
  • Apply marshalResult to all request handlers (request_create, request_get, request_list, request_approve, request_decline, request_retry) and user handlers (users_list, users_get, users_update, users_quota) that embed User/UserSettings in their response

Test plan

  • go test -v ./... passes
  • go fmt ./... produces no diff
  • go build succeeds

New tests in tests/mcp_marshal_result_test.go:

  • TestMCPRequestCreateFallbackOnDecodeError — 201 response with settings.id (unknown field) returns success with correct id/status in body
  • TestMCPRequestCreateRealErrorStillFails — 400 response is still surfaced as a tool error

Checklist

  • New tests added for new behaviour
  • Documentation updated (README, command --help, comments)
  • No unrelated changes included

X-Api-Key on the MCP endpoint is for client authentication (checked
against --auth-token), not for forwarding the Seerr API key. The Seerr
API key is always read from the application config (seerr.api_key).

Remove SeerrAPIKeyMiddleware, which incorrectly extracted X-Api-Key from
incoming requests and injected it as the Seerr API key. Replace the
bearer-only auth middleware with MCPAuthMiddleware, which accepts the
configured auth token via Authorization: Bearer, X-Api-Key header, or
?api_key= query parameter (when --allow-api-key-query-param is set).

Clients configured with no auth token no longer receive spurious 401s.
Overseerr requires a seasons field for tv requests. The MCP tool was
missing this parameter, causing a server-side crash when the API tried
to filter an undefined seasons array.
Cover movie requests (no seasons), tv with "all", tv with specific
season numbers, and invalid season input producing a tool error.
The generated UserSettings model uses DisallowUnknownFields() but
Overseerr returns extra fields (id, pgpKey, notification settings) not
in the OpenAPI spec. This caused request_create and other tools to
surface a false tool error even though the HTTP call succeeded.

Add marshalResult() which falls back to the raw response body when
Execute() returns a *GenericOpenAPIError on a 2xx response. Apply it
to all request and user handlers that embed User/UserSettings in their
response.
@electather electather merged commit 60d3f15 into main Mar 29, 2026
2 checks passed
@electather electather deleted the fix/mcp-decode-error-fallback branch March 29, 2026 11:50
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