Skip to content

basecamp mcp: rich-text fields are stored as literal Markdown instead of being converted like the CLI does #896

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 inherits the CLI's Markdown conversion and passes an optional format: "markdown" | "html" through to --format on its ten rich-text tools.

See also #895.

What happens

Rich-text fields sent through basecamp mcp go to the API exactly as written. Agents write Markdown by default, so it is stored as literal text.

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

basecamp_todos → create_todo with:

{ "todolistId": <id>, "content": "test",
  "description": "**bold** and a [link](https://example.com)\n\n- item one\n- item two" }

Stored description:

**bold** and a [link](<a … class="autolinked" href="https://example.com">https://example.com</a>)\n\n- item one\n- item two

The bold markers and list dashes are stored as typed, and Basecamp's autolinker breaks the Markdown link syntax apart. The same content through basecamp todos create … --description renders correctly, because the CLI converts Markdown by default (#832).

Why it matters

The CLI made Markdown the stated default for every rich-text field precisely because agents write Markdown (#692, #832). basecamp mcp is the agent-facing surface, yet it is the one place that doesn't convert. Every agent-written description, message, comment and document is affected.

Suggestion

Run rich-text fields (content/description on todos, cards, messages, comments, documents, uploads) through the same richTextToHTML path the CLI uses. Give each a format: "markdown" | "html" parameter matching the CLI's --format flag, so an agent writing back HTML it read from a get action can opt out. create_comment's synthetic mentions already does client-side expansion before posting, so there is precedent for this kind of preprocessing in the gateway.

AI Disclosure

This issue was written and researched with the help of Claude Code.

Activity

  1. dyve commented on Oct 31, 2026

    @dyve
    Author

    Re-tested on v0.22.0. A replace_todo description of Some **bold** text and a [link](https://basecamp.com) followed by a two-item list is stored with the asterisks, brackets and dashes as literal text. The CLI turns the same input into bold, a link and a list.

    An idea for a fix: give the gateway the CLI's own rich-text handling. Agents write Markdown by default, and the CLI already does the right thing with it: Markdown is converted, --format html passes HTML through, and a URL alone on its line becomes an embed.

    As far as I can see, what's missing is knowing which fields are rich text. The model has no marker for it, and only some field descriptions say "rich text (HTML)". One way to close that gap:

    • Mark rich-text request fields in the SDK model, e.g. x-basecamp-rich-text: true on description, content and body where they are HTML. The same pattern as x-basecamp-clearable.
    • In the gateway, run marked fields through the CLI's existing Markdown conversion. Add an optional format: "markdown" | "html" param per call, mirroring --format, so an agent writing back HTML it just read isn't converted twice.

    Until then, it would help if those parameter schemas said the field is HTML. An agent could then at least send HTML on purpose instead of guessing.

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