Skip to content

basecamp mcp: replace actions clear any field an agent leaves out, so a title-only edit wipes the to-do #895

Open

Description

@dyve

Context

Found while evaluating basecamp mcp as a replacement for dyve/basecamp-cli-mcp, a self-built MCP server, written with Claude, that wraps the basecamp CLI. It exists because we wanted read/write Basecamp access from Claude Cowork and Claude Desktop, which have no terminal for the CLI or the Basecamp skill. Now that the CLI ships its own MCP server, we would rather use that than maintain ours; this issue is one of the gaps in the way.

basecamp-cli-mcp gets merge-safe edits by calling todos update / files update, so a title-only update leaves the rest of the record intact.

What happens

basecamp_todos exposes only replace_todo for editing a to-do. Its describe text says the body is the full writable state and that any omitted field is cleared. That is accurate, but an agent only sees it if it calls describe before writing. The action list shows just "Replace a todo with a new complete representation". The natural call for "rename this to-do" sends only content, and it destroys the rest of the record.

Repro (v0.13.2, macOS, Basecamp 3 account)

  1. basecamp_todos → create_todo with content, description: "<div>keep me</div>", due_on: "2026-12-01", assignee_ids: [<person>].
  2. basecamp_todos → replace_todo with { "todoId": <id>, "content": "renamed" }.
  3. Read it back: description is "", due_on is gone, assignees is [].

replace_document documents the same behavior: omitting content clears the body, and omitting title leaves an "Untitled" document. Per the action catalog, replace_schedule_entry and update_todolist_or_group ("Replace a todolist…") are also full-replace operations. I verified only replace_todo live.

Why it matters for MCP specifically

The CLI does not have this problem: basecamp todos update <id> --title x and basecamp files update <id> --title x leave the other fields intact. Agents moving from the CLI, or from the Basecamp skill, to basecamp mcp will reasonably expect the same, and the failure is silent and destructive.

Suggestion

Offer a merge-safe update action next to each replace action, for example a synthetic update_todo that reads the record and merges in the given fields before the PUT. That is what the CLI's update commands already do, and the synthetic mentions parameter on create_comment shows the gateway already supports client-side composition. At minimum, the one-line action summary should say that omitted fields are cleared, since that line is all an agent sees without calling describe.

AI disclosure

This issue was discovered and described with assistance from Claude Code.

Activity

  1. dyve commented on Oct 31, 2026

    @dyve
    Author

    Re-tested on v0.22.0. A title-only replace_todo still clears the description, the due date and the assignees.

    An idea for a fix. The model already marks every operation this affects: x-basecamp-write-semantics: { mode: "replace", clearsOmitted: true } is on ReplaceTodo, ReplaceDocument, ReplaceScheduleEntry, UpdateTodolistOrGroup, UpdateCloudFile and UpdateGoogleDocument. So the gateway could handle all six with one rule. For an operation with clearsOmitted, read the current record, apply the fields the agent sent, and send back the full record. That is what the SDK's merge-safe update already does, and what replace_todo's own description tells callers to use. An agent then can't wipe fields by leaving them out. The race window is one round-trip, which the description already accepts for the SDK helpers.

    The move/copy actions in v0.21.0 (#988) already show the pattern: hand-written gateway actions that wrap an SDK helper. Serving update_todo and update_document on the merge-safe helpers, in place of or next to the replace actions, would also work.

    Agents write a title-only edit as a matter of course, and the result is silent data loss on the record. This is the one gap that keeps us from switching our Claude Desktop setup to basecamp mcp for writes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions