Mount the workspace in Claude Code.
One line adds a Tuval workspace to Claude Code or Cursor as an MCP server. Seven tools: search pages, databases, issues and projects in one call, open any of them as Markdown, list what is in flight — and, with a key made to write, file a new record, change one, or add to a page. The key decides which workspace, whether it may write at all, and the agent is shown exactly what the person who made that key can see.
The seven tools
search
Words in titles and bodies, across pages, databases, issues and projects in one call. Postgres full-text does the matching, and an excerpt comes back with each id so a result can be judged before it is opened.
read_page
One page or issue in full, as Markdown, with its headings, lists and code intact. Not the JSON shape of a row — the text a model can reason over.
list_records
Records of one kind, narrowed by status, project or assignee. Archived rows are left out, so an agent is never arguing about work somebody already put away.
workspace
What this key can reach, and the addresses inside it. It also says whether the key may write and how many writes are left today, so an agent finds out before it plans rather than after it fails.
create_record
File an issue, a page, a project, a person, a company or an event, with its status, assignee, priority, parent and opening text. Wants a key made to write; a read key is told so in words.
update_record
Change a title, a status, an assignee, a due date, or which project or cycle something belongs to. Only the fields you send move, and the change is signed with the key's name.
append_to_page
Add Markdown to the end of a page or issue. It becomes real paragraphs — headings, lists, code — the next time somebody opens that page, because a page is a shared document only a browser can edit. The band below says exactly what that delay costs.
Two lines
The server is a file in the repository and it speaks the protocol over stdin and stdout, so there is nothing to deploy and nothing listening on a port. It wants a key, made in Settings → API and webhooks, hashed the moment it exists and therefore shown exactly once. The full reference is docs/mcp.md in the checkout, rendered at /docs/mcp, because two copies of the same prose disagree within a month.
- claude mcp add tuval -- node /path/to/tuval/scripts/mcp.mjs
- TUVAL_API_KEY=tuv_... # in the environment, or in .env.local
What is not behind this door
Boards are not records, so no tool here opens one. A canvas reaches a model the other way and on purpose: the board turns its frames, connectors and comments into a Markdown brief you hand over. What this server reads is the rows — pages, databases, issues, projects, people, companies, events and files — and it stops there.
Writing is a key you choose to make
Scope is set when the key is made and cannot be raised by the agent holding it. A read key answers 403 to every write, in a sentence rather than a number, and a key past its daily allowance answers 429 — two different problems, told apart on purpose, because one means come back with a better key and the other means come back tomorrow. Every write is signed with the key's name and the person behind it, and leaves a version somebody can put back.
Where a written paragraph actually lands
A page is a shared document held in the browsers editing it, not a column in a table, so no server here can open one. Text an agent adds waits on the record and is folded onto the end of the page the next time somebody opens it, with its structure intact. Until then the agent can read it back where it will sit, but search will not find it and nobody scrolling past will see it. That is a delay rather than a second place for text to live, and it is written down here rather than discovered in week two.
A key is never more than the person who made it
The agent reads with its maker's eyes. A page with people named on it stays shut unless they are one of them. Taking that person out of the workspace closes their key with them, and no parameter can move a call into another workspace, because the caller never chooses the workspace — the key does.
Held for the paid plan, open on your own install
The API and the MCP server that rides on it are what the hosted plan charges for, so on a free hosted workspace every call answers 401. Run it yourself and the same check passes: the self-hosted setting is read as the team plan and the seat, storage and API limits stop applying. Either way the reason comes back as text the model can read rather than as a broken pipe.
The half that does not exist yet
A board goes out to an agent as a brief. A workspace comes back as records and goes back again as records. Neither direction ends with an agent drawing on a canvas: there is no endpoint that makes a board, adds a sticky note or draws a connector, so whatever a model concludes about a canvas still reaches it through a person. Nor can anything here rewrite a paragraph already in a page, delete one or reorder blocks. That is a limit rather than an oversight, and it belongs on the page where you are deciding rather than in week two.
You should not have to paste your own work into a prompt
The alternative to this door is copying a page into a chat window and copying the answer back. It works once. It does not survive the second week, and from the moment the tab closes the workspace and the model's idea of it drift apart. A key, one line, and the agent is reading the work rather than a paraphrase of it.