miro-board-mcp
by Variience
README.md
# miro-board-mcp
[](https://github.com/Variience/miro-board-mcp/actions/workflows/test.yml)
[](LICENSE)
An MCP server that lets Claude build whole Miro boards, not just single sticky notes.
Ask for a funnel, a process, a course outline or a client tracker, and Claude lays it out in one call: nodes on a grid, arrows between them, styled for a dark or light board.
```
You: Turn my onboarding doc into a flow on the board, white text, arrows between every step.
Claude: [miro_layout_flow] Built 9 nodes and 9 arrows, starting from your "The Beginning" title.
```
Most Miro MCP servers wrap the REST API one item at a time. This one keeps those basics and adds three layout tools that do the tedious part for you:
| Tool | What it builds |
|---|---|
| `miro_layout_flow` | A connected flow: text nodes (bold title plus lines) on a grid, joined by arrows in order or by explicit edges for branches |
| `miro_layout_outline` | One frame with a column per section and a sticky note per bullet. Good for turning a doc or plan into a board |
| `miro_upsert_tracker` | A frame per client, project or person with one card per field. Call it again and the same cards update in place |
Plus the basics: `miro_get_board`, `miro_list_items`, `miro_create_items` (up to 50 at once), `miro_update_item`, `miro_delete_item`, `miro_connect`.
## Quick start
You need Node 20 or newer and a Miro access token.
### 1. Get a Miro token (free)
1. Go to [developers.miro.com](https://developers.miro.com) and create a free **Developer team**. Building apps in a regular free team asks you to upgrade; a Developer team does not.
2. In Miro, open your profile, then **Settings**, then **Your apps**. Accept the terms and click **Create new app**. Pick your Developer team.
3. Under **Permissions**, check `boards:read` and `boards:write`.
4. Click **Install app and get OAuth token**, pick the team, and copy the token.
5. The token only works on boards in the team where you installed the app. Create your board there, or move it there.
Your board id is the part of the board link after `/board/`: in `https://miro.com/app/board/uXjVKa1b2c3=/` it is `uXjVKa1b2c3=`.
### 2. Install
```bash
git clone https://github.com/Variience/miro-board-mcp.git
cd miro-board-mcp
npm install
npm test
```
### 3. Connect it
**Claude Code**
```bash
claude mcp add miro-board -s user \
-e MIRO_ACCESS_TOKEN=YOUR_TOKEN \
-e MIRO_BOARD_ID=YOUR_BOARD_ID \
-- node /full/path/to/miro-board-mcp/server.mjs
```
Restart Claude Code, then run `/mcp` to check that `miro-board` is connected.
**Claude Desktop** (or any client that reads `mcpServers` JSON)
```json
{
"mcpServers": {
"miro-board": {
"command": "node",
"args": ["/full/path/to/miro-board-mcp/server.mjs"],
"env": {
"MIRO_ACCESS_TOKEN": "YOUR_TOKEN",
"MIRO_BOARD_ID": "YOUR_BOARD_ID"
}
}
}
}
```
`MIRO_BOARD_ID` is optional. Without it, pass `board_id` to each tool.
## Things to ask Claude
- "Read my board and tell me what's on it."
- "Lay out this README as a flow, one node per section, white text and white arrows, starting from my title."
- "Make an outline frame for next week's sprint: To do, Doing, Done."
- "Add a tracker for client Acme: Stage Onboarding, Owner Sam, Next step kickoff Friday." Then later: "Move Acme to Live."
- "Draw arrows from each phase to its weeks."
## Good to know
- **Frames can't be arrow endpoints.** Miro's API rejects connectors attached to frames. Connect the items inside them, or use `miro_layout_flow`, which uses text nodes for this reason.
- **Positions inside a frame are relative** to the frame's top-left corner. Positions on the board are centered on the item.
- **Updates only change what you send.** Moving an item doesn't touch its text.
- **Rate limits.** Miro meters API calls in credits. Each item or arrow is one call, so a 60-node flow is roughly 120 calls.
## Security
- The token goes in your MCP client's env config, never in this repo. `.gitignore` excludes `.env` files.
- Claude Code stores MCP env values in plain text in `~/.claude.json`. Keep that file private, and rotate the token in Miro if it ever leaks.
- Every tool call runs against your real board, and `miro_delete_item` is permanent. Most MCP clients ask before running a tool; keep that on.
## Development
```bash
npm test # node --test, no network
node server.mjs # starts the server on stdio
```
`miro.mjs` holds the API client and the pure layout functions (`flowLayout`, `outlineLayout`, `buildItemPayload`). The tests cover them with a fake fetch, so they run offline.
## License
MIT. Use it, change it and ship it in your own projects; just keep the copyright notice in [LICENSE](LICENSE).