usememos/memos · error

missing required request body "body"

Error message

missing required request body "body"

What it means

Thrown by the MCP-to-OpenAPI adapter in server/router/mcp/adapter.go when an OpenAPI operation declares a required request body but the MCP tool call arguments do not include a "body" key (or it is JSON null). The adapter maps MCP tool arguments onto an HTTP request; a required body must arrive as arguments["body"]. The error surfaces to the MCP client as a tool error result.

Source

Thrown at server/router/mcp/adapter.go:72

		if parameter.In != "query" {
			continue
		}
		value, ok := arguments[parameter.Name]
		if !ok || value == nil {
			continue
		}
		query.Set(parameter.Name, valueToString(value))
	}
	if encoded := query.Encode(); encoded != "" {
		path += "?" + encoded
	}

	var body io.Reader
	if operation.RequestBody != nil {
		bodyValue, ok := arguments["body"]
		if !ok || bodyValue == nil {
			if operation.RequestBody.Required {
				return nil, errors.New(`missing required request body "body"`)
			}
			bodyValue = map[string]any{}
		}

		data, err := json.Marshal(bodyValue)
		if err != nil {
			return nil, errors.Wrap(err, "failed to marshal request body")
		}
		body = bytes.NewReader(data)
	}

	req := httptest.NewRequest(operation.Method, path, body).WithContext(ctx)
	if body != nil {
		req.Header.Set("Content-Type", "application/json")
	}
	if authorization != "" {
		req.Header.Set("Authorization", authorization)
	}

View on GitHub (pinned to 14d757ce1f)

Solutions

  1. Include a "body" object in the tool call arguments matching the operation's request schema, e.g. {"body": {"content": "...", "visibility": "PRIVATE"}}
  2. Check the tool's input schema (derived from the OpenAPI spec) to confirm the body shape before invoking
  3. If the operation should accept an empty payload, fix the OpenAPI definition so requestBody is not required

Example fix

// before (MCP tool call)
await client.callTool({ name: "memos_createMemo", arguments: {} });
// after
await client.callTool({ name: "memos_createMemo", arguments: { body: { content: "hello" } } });
Defensive patterns

Strategy: validation

Validate before calling

// Before calling the MCP tool, confirm the operation requires a body and include it.
const requiresBody = operation.requestBody?.required === true;
const args = { ...toolArgs };
if (requiresBody && (args.body === undefined || args.body === null)) {
  throw new Error(`Tool ${operation.operationId} requires a "body" argument`);
}

Type guard

const hasRequiredBody = (args: Record<string, unknown>): boolean =>
  args.body !== undefined && args.body !== null;

Try / catch

// The adapter returns tool errors inside CallToolResult (isError), not as thrown errors:
const result = await client.callTool({ name, arguments });
if (result.isError) {
  const text = result.content?.[0]?.text ?? "";
  if (text.includes('missing required request body')) {
    // re-invoke with a body built from the tool's input schema
  }
}

Prevention

When it happens

Trigger: Calling an MCP tool derived from a POST/PUT/PATCH OpenAPI operation whose requestBody.required is true without supplying the "body" argument, or passing body: null in the tool arguments.

Common situations: LLM agents omitting the body object for create/update tools; tool schemas that describe body properties at the top level instead of nested under "body"; optional-looking tool arguments for endpoints that actually require a payload.

Related errors


AI-assisted analysis of usememos/memos@14d757ce1f (2026-08-15). Data as JSON: /api/errors/b7b1b3292d4c28c1. Report an issue: GitHub.