Skip to content

MCP add_card_comment/update_card_comment broken: body field mismatch (content vs comment) #536

Description

@StenSeegel

🐛 Bug Report

Describe the bug

The MCP tools add_card_comment and update_card_comment (packages/mcp/src/tools/card.ts) send the comment text in the request body under the key content, but the REST endpoints POST /cards/{cardPublicId}/comments and PUT /cards/{cardPublicId}/comments/{commentPublicId} expect it under the key comment. Every comment create/update through the MCP server therefore fails input validation with BAD_REQUEST — it is impossible to write comments via MCP at all.

A second, related problem makes it look like reading comments is also broken: the get_card tool description promises "full details of a card including comments", but the card-detail response (cardDetailSchema) has no top-level comments array. Comments only surface nested inside activities[] entries of type card.updated.comment.added (at activity.comment.comment), and since tRPC-OpenAPI strips fields not in the output schema, there is no way to get a plain comments list. Agents looking for a comments field in the get_card response come up empty and conclude comments cannot be read.

To Reproduce

Steps to reproduce the behavior:

  1. Configure the Kan MCP server against a Kan instance.
  2. Ask the agent (or call the tool directly) to add a comment to a card: add_card_comment with { cardPublicId, content: "Hello" }.
  3. See the API reject the request with 400 BAD_REQUEST (comment is required but missing — the body key sent is content).
  4. Call get_card on a card that has comments (added via the web UI) and observe there is no comments field in the response; the comments are only found nested in activities[].comment.

Expected behavior

add_card_comment and update_card_comment should succeed — the MCP layer should send the body field the API expects (comment). The get_card / get_card_activities tool descriptions should tell the agent where comment text actually lives in the response.

Root cause

The MCP tools send content:

// packages/mcp/src/tools/card.ts
server.tool(
  "add_card_comment",
  "Add a comment to a card",
  {
    cardPublicId: z.string().describe("The card's public ID"),
    content: z.string().describe("Comment text"),
  },
  async ({ cardPublicId, content }) => {
    const data = await kanRequest("POST", `/cards/${cardPublicId}/comments`, { content });  // <-- wrong key
    ...
  },
);

But the REST API expects commentpackages/api/src/routers/card.ts, addComment mutation:

.input(
  z.object({
    cardPublicId: z.string().min(12),
    comment: z.string().min(1),   // <-- required, so `{ content: ... }` always fails validation
  }),
)

The same mismatch exists in updateComment (input: comment: z.string().min(1)) vs. the MCP update_card_comment tool (sends { content }). delete_card_comment is unaffected as it only uses path parameters.

For the read path, cardDetailSchema (packages/api/src/schemas/card.ts) contains labels, attachments, checklists, list, members and activities — but no comments array; comment text is only reachable via activities[].comment on card.updated.comment.added entries.

Proposed fix

Map the MCP tool parameter to the field name the API expects, in both tools:

async ({ cardPublicId, content }) => {
  const data = await kanRequest("POST", `/cards/${cardPublicId}/comments`, {
    comment: content,
  });
  ...
},

And update the tool descriptions so agents can find comments in the response, e.g. for get_card:

"… Note: the response has no top-level comments array — comments are nested in the activities array as entries of type card.updated.comment.added, with the text at activity.comment.comment."

(Optionally, adding a proper comments array to cardDetailSchema — or a dedicated GET /cards/{cardPublicId}/comments endpoint — would be the cleaner long-term fix for the read path.)

Screenshots

N/A.

Environment (please complete the following information):

  • OS: macOS (not relevant — field-name mismatch in the MCP request body, not platform-specific)
  • Browser: N/A (MCP server over stdio)
  • Node version: N/A — reproducible on any supported version (>=18); not a factor
  • App version/commit: main @ 9ec4bedd9ad0 (packages/mcp/src/tools/card.ts, Kan REST API v1)

Additional context

The write-path bug is a two-line fix in packages/mcp/src/tools/card.ts ({ content }{ comment: content } in add_card_comment and update_card_comment). The read-path confusion is purely a tool-description gap — the data is present, just nested under activities where agents don't expect it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions