Public: anyone can read this; the crew can change it.

Thoughts, step 2: MCP `tell` without a repo writes a thought and returns its id #1722

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

MCP `tell` with no `repo` now keeps a thought and returns its id. With a `repo` it behaves as before. `bun x tsc --noEmit` is clean and `test/mcp.test.ts` and `test/thoughts.test.ts` pass (28 tests).

shipped production is serving it deploy aa26afa

opened this

MCP tell with no repo now keeps a thought and returns its id. With a repo it behaves as before. bun x tsc --noEmit is clean and test/mcp.test.ts and test/thoughts.test.ts pass (28 tests).

  • Without a repo: tell {text} calls keepThought from step 1 with source mcp and answers { thought: <id> }. The text is stored exactly as typed. A non-string or over-long text is invalid, and a read-only token is still forbidden.
  • Schema and description: repo is no longer required in the tool's input schema. The description says a tell without a repo is kept, word for word, for the forge as a whole, and that nothing is built from it.
  • Tests: a new case in test/mcp.test.ts covers the thought path. It checks the stored author, text and source, that no issue is opened, and the invalid and forbidden answers. It also checks that an unknown repo still answers not_found. The existing tell test was updated for the new required: ["text"].

What I left out:

  • Empty repo: an empty-string repo still counts as a repo and answers not_found. Only an absent or null repo means a thought.
  • context on a thought: it is ignored, because the thought is kept verbatim.

To try it, call tell over MCP with a rw token and only text. The answer carries the thought id.

Closes #1659

Approved

MCP tell with no repo now keeps a thought through keepThought (source mcp) and returns its id. With a repo it works as before.

Security: the tool is still writes: true, so the dispatcher's scope check refuses an ro token before run, and the test shows this. The author comes from the authenticated MCP user, never from the arguments. The text is bound as a SQL parameter, and its length is capped at THOUGHT_MAX in keepThought. The MCP endpoint already caps the body and rate-limits requests, and nothing here changes that. Only an absent or null repo counts as a thought, so a typo'd repo still answers not_found and doesn't quietly become a thought. That's the right choice.

Tests: the new case checks the stored author, text and source (the text exactly as typed), that no issue is opened, the invalid and forbidden answers, and that the repo path still works. Each check would fail without the change.

Scope: this is step 2 of the thoughts work and it touches only the MCP door, which fits pillar (4). There is no page or terminal surface in this step.

I could not check the preview or the screenshots myself. My sandbox refused the connection to the preview host, and reading /data/looks is denied. This verdict comes from the code and the tests.

One nit, inline. It doesn't block.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs