Repository navigation
[bug] OpenAPI object JSON bodies always send Content-Type application/json, dropping vendor +json types #1930
Description
Executor version
Executor Cloud (hosted, 2026-09-03). Cloud MCP at https://executor.sh/<org>/mcp.
How do you run Executor?
Executor Cloud
Operating system
Linux
Integration involved
Built-in OpenAPI plugin (packages/plugins/openapi/src/sdk/invoke.ts). Observed on a JSON:API integration (application/vnd.api+json).
What happened
Writes (POST/PATCH) against a JSON:API server return HTTP 415. The server requires Content-Type: application/vnd.api+json. Executor sends application/json.
Callers cannot override it. OpenAPI header parameters named Content-Type are ignored (OAS). Tool arguments headers / header / params are rejected as unknown arguments. contentType is only exposed when the spec declares multiple requestBody media types.
Root cause is in applyRequestBody:
if (isJsonContentType(contentType)) {
if (typeof bodyValue === "string") {
return sent(HttpClientRequest.bodyText(request, bodyValue, contentType));
}
return sent(HttpClientRequest.bodyJsonUnsafe(request, bodyValue));
}isJsonContentType is true for any +json type (including application/vnd.api+json). Object/structured bodies then go through bodyJsonUnsafe without the declared media type, so the wire header becomes application/json. String bodies correctly keep the vendor type via bodyText.
updateSpec cannot set integration headers (it preserves existing ones). addSpec can set static headers, which would override after the body is applied — but there is no MCP/UI path to add those headers later.
Patching the spec so requestBodies declare application/vnd.api+json does not fix the normal calling convention (object body), because of the bodyJsonUnsafe branch above.
What you expected
When the selected requestBody media type is application/vnd.api+json (or any +json vendor type), the outbound Content-Type should be that type, not application/json.
Suggested fix: serialize object JSON bodies with the declared media type, e.g. HttpClientRequest.bodyText(request, JSON.stringify(bodyValue), contentType) (or pass the type into bodyJsonUnsafe if the client supports it).
Static integration headers (addSpec.headers) should also be editable after create (updateSpec or configure), so JSON:API Accept/Content-Type can be set without deleting the integration.
Steps to reproduce
- Add an OpenAPI integration whose POST requestBody content is
application/vnd.api+json(JSON:API). - Connect a credential and call a write tool with a structured
bodyobject (the generated TypeScript shape). - Observe the upstream
Content-Type: application/jsonand HTTP 415. - Passing
headers: { "Content-Type": "application/vnd.api+json" }on the tool call fails with unknown arguments. - A string
bodyplus a spec that already declaresapplication/vnd.api+jsondoes send the vendor type (bodyText path) — object bodies do not.
Diagnostics / logs
No secrets. Hosted Cloud. Upstream 415 body is the usual JSON:API unsupported media type. Reads on the same connection succeed (no request body).
Code: packages/plugins/openapi/src/sdk/invoke.ts (isJsonContentType, applyRequestBody). isJsonContentType already intends to treat +json as JSON for serialization; the missing piece is preserving the declared type on the header.
Before you submit
- I searched the open issues for a duplicate.
- I removed all keys, tokens, and credentials from this report.
Activity