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
body object (the generated TypeScript shape).
- Observe the upstream
Content-Type: application/json and HTTP 415.
- Passing
headers: { "Content-Type": "application/vnd.api+json" } on the tool call fails with unknown arguments.
- A string
body plus a spec that already declares application/vnd.api+json does 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
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 sendsapplication/json.Callers cannot override it. OpenAPI header parameters named
Content-Typeare ignored (OAS). Tool argumentsheaders/header/paramsare rejected as unknown arguments.contentTypeis only exposed when the spec declares multiple requestBody media types.Root cause is in
applyRequestBody:isJsonContentTypeis true for any+jsontype (includingapplication/vnd.api+json). Object/structured bodies then go throughbodyJsonUnsafewithout the declared media type, so the wire header becomesapplication/json. String bodies correctly keep the vendor type viabodyText.updateSpeccannot set integrationheaders(it preserves existing ones).addSpeccan 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+jsondoes not fix the normal calling convention (objectbody), because of thebodyJsonUnsafebranch above.What you expected
When the selected requestBody media type is
application/vnd.api+json(or any+jsonvendor type), the outboundContent-Typeshould be that type, notapplication/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 intobodyJsonUnsafeif the client supports it).Static integration headers (
addSpec.headers) should also be editable after create (updateSpecor configure), so JSON:API Accept/Content-Type can be set without deleting the integration.Steps to reproduce
application/vnd.api+json(JSON:API).bodyobject (the generated TypeScript shape).Content-Type: application/jsonand HTTP 415.headers: { "Content-Type": "application/vnd.api+json" }on the tool call fails with unknown arguments.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).isJsonContentTypealready intends to treat+jsonas JSON for serialization; the missing piece is preserving the declared type on the header.Before you submit