Skip to content

execute_rest_write ignores the body argument — write payloads must be passed via query (GitLab returns 400 "... is missing") #41

@ttpears

Description

@ttpears

Summary

When calling the execute_rest_write tool, the body argument does not appear to be sent as the HTTP request payload. Fields placed in body are missing server-side and the GitLab API responds 400 ... is missing. Passing the same fields via the query argument works.

Environment

  • Tool: execute_rest_write (the arbitrary REST write escape hatch)
  • GitLab: self-managed EE, REST API v4
  • Client: Claude Code via MCP

Repro

Creating an inline diff discussion on a merge request.

Fails — fields in body:

execute_rest_write({
  method: "POST",
  path: "/projects/<url-encoded-path>/merge_requests/18/discussions",
  body: {
    "body": "comment text",
    "position": {
      "base_sha": "df0e5a44...", "head_sha": "53a77fd6...", "start_sha": "df0e5a44...",
      "position_type": "text",
      "new_path": "psicore.py", "old_path": "psicore.py",
      "new_line": 1760
    }
  }
})
// -> 400: body is missing

This also fails when body is passed as a JSON-encoded string instead of an object.

Works — identical fields moved to query (bracketed keys for the nested position):

execute_rest_write({
  method: "POST",
  path: "/projects/<url-encoded-path>/merge_requests/18/discussions",
  query: {
    "body": "comment text",
    "position[base_sha]": "df0e5a44...",
    "position[head_sha]": "53a77fd6...",
    "position[start_sha]": "df0e5a44...",
    "position[position_type]": "text",
    "position[new_path]": "psicore.py",
    "position[old_path]": "psicore.py",
    "position[new_line]": "1760"
  }
})
// -> 201 Created

The same pattern holds for PUT note edits (.../notes/:id and .../discussions/:discussion_id/notes/:id): the body argument is ignored, but query works.

Expected

The body argument (documented as "Request body — JSON-serialized as application/json") should be sent as the request body, so REST writes can use JSON payloads — including nested objects like position — rather than requiring everything to be flattened into query with bracket notation.

Notes

  • The dedicated create_note tool sends its body correctly, so JSON POST works in general; this looks specific to how execute_rest_write handles the body argument.
  • The query workaround is viable but awkward for nested/complex payloads.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions