Skip to content

APIM MCP server forwards only one argument value (last-write-wins) instead of full JSON object body on tools/call POST #315

Description

@redhatpeter

Summary

When an APIM-MCP server (created from an OpenAPI-imported REST API) receives
tools/call with a JSON object arguments payload, the gateway forwards
only one field's raw value as the backend HTTP body — not the assembled
JSON object. The result is a last-write-wins byte-string body, which
backends correctly reject as malformed JSON.

This appears related to but distinct from the empty-body bug fixed in
release-service-2026-03
("Resolved issue where MCP POST request bodies were not forwarded to backend APIs").
Symptoms in our case are non-empty but scalar / partial.

Environment

  • APIM instance: Developer SKU, platformVersion: stv2.1, releaseChannel: Preview
  • Region: eastus
  • API Version used for management: 2024-06-01-preview
  • MCP server: created from OpenAPI 3.1 import (FastAPI-generated spec)
  • Backend: FastAPI behind ngrok (verified working when called directly)
  • No custom policies attached to the MCP server (default <base/> only)
  • Date observed: 2026-05-08 (~2 months after the March 2026 release notes fix)

Reproduction

OpenAPI snippet (operation finance_customer_create):

"POST /governed/customers": {
  "operationId": "finance_customer_create",
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": { "$ref": "#/components/schemas/CreateCustomerRequest" }
      }
    }
  }
}
Schema 
"CreateCustomerRequest": {
  "type": "object",
  "required": ["name", "email"],
  "properties": {
    "name":  { "type": "string" },
    "email": { "type": "string" },
    "tier":  { "type": "string", "default": "bronze" }
  }
}
Call:
curl -X POST https://<apim>.azure-api.net/governed-mcp/mcp \
  -H "Ocp-Apim-Subscription-Key: ***" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"financeCustomerCreate",
                 "arguments":{"name":"AAA","email":"BBB","tier":"CCC"}}}'
Backend (verified via the ngrok request inspector) receives:
POST /governed/customers
Content-Type: application/json
Content-Length: 3
Body: CCC

Expected:
POST /governed/customers
Content-Type: application/json
Body: {"name":"AAA","email":"BBB","tier":"CCC"}

Hypothesis
The fix in release-service-2026-03 for the empty-body case may have replaced
"don't forward anything" with "forward each property in turn into a single
body buffer", overwriting prior content with each property and ending on the
last one. This would explain why public reports between Jul 2025 (Q&A
[4371821](vscode-file://vscode-app/c:/Users/leepete/AppData/Local/Programs/Microsoft%20VS%20Code/034f571df5/resources/app/out/vs/code/electron-browser/workbench/workbench.html)) and Oct 2025
(Q&A [5597117](vscode-file://vscode-app/c:/Users/leepete/AppData/Local/Programs/Microsoft%20VS%20Code/034f571df5/resources/app/out/vs/code/electron-browser/workbench/workbench.html)) showed
zero-length bodies, while our post-March-2026 instance shows
short scalar bodies.

Workaround tested (does not work)
Attaching the unwrap policy from
[Q&A 5597117](vscode-file://vscode-app/c:/Users/leepete/AppData/Local/Programs/Microsoft%20VS%20Code/034f571df5/resources/app/out/vs/code/electron-browser/workbench/workbench.html):

… at the MCP-server policy level breaks even tools/list and GET ops with
500s. APIM-MCP's own JSON-RPC parser appears to consume the same body stream
upstream of the policy chain.

Ask
Has the release-service-2026-03 fix landed for Developer SKU / stv2.1 /
eastus yet? Is there a way to verify the deployed gateway build for an
instance via ARM?
Is the schema shape (typed $ref, multiple required, one property with
default) the trigger?
Is there a known workaround that works on v1-tier MCP servers today, or is
the right action to wait / migrate to a v2 SKU?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions