Skip to main content
Glama
README.md
# favro-mcp

An MCP server that gives your AI assistant read access to [Favro](https://favro.com) — collections, boards, cards, comments and checklists.

**Read-only by design.** Every one of the 14 tools issues a `GET` and nothing else. There is no code path in this package that can create, change, archive or delete anything in your Favro account — a test asserts it on every commit. You are handing over an API token, so that guarantee is the point.

## Install

Nothing to install. Point your MCP client at `npx`:

```jsonc
{
  "mcpServers": {
    "favro": {
      "command": "npx",
      "args": ["-y", "favro-mcp"],
      "env": {
        "FAVRO_EMAIL": "you@example.com",
        "FAVRO_API_TOKEN": "your-api-token",
        "FAVRO_ORGANIZATION_ID": ""
      }
    }
  }
}
```

Requires Node 18 or newer.

### Getting a Favro API token

In Favro: **profile menu → My profile → API tokens → Create new token**. The token pairs with the email address you sign in with; both are needed.

`FAVRO_ORGANIZATION_ID` is optional. Leave it empty and ask your assistant to run `list-organizations` — it will return the ids you have access to, and you can either paste one into the config or let the assistant pass it per call.

### Per-client setup

<details>
<summary><b>Claude Code</b></summary>

```bash
claude mcp add favro --env FAVRO_EMAIL=you@example.com --env FAVRO_API_TOKEN=your-api-token -- npx -y favro-mcp
```

Or add the JSON block above to `.mcp.json` in your project root.
</details>

<details>
<summary><b>Claude Desktop</b></summary>

Edit `claude_desktop_config.json`:

- macOS — `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows — `%APPDATA%\Claude\claude_desktop_config.json`

Paste the JSON block above, then **fully quit and reopen** Claude Desktop — reloading the window is not enough.
</details>

<details>
<summary><b>Cursor</b></summary>

Edit `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per project) and paste the JSON block above.
</details>

<details>
<summary><b>VS Code</b></summary>

Add to `.vscode/mcp.json`, using `servers` rather than `mcpServers`:

```jsonc
{
  "servers": {
    "favro": {
      "command": "npx",
      "args": ["-y", "favro-mcp"],
      "env": {
        "FAVRO_EMAIL": "you@example.com",
        "FAVRO_API_TOKEN": "your-api-token"
      }
    }
  }
}
```
</details>

## Tools

| Tool | Purpose | Required arguments |
|---|---|---|
| `list-organizations` | Organizations the account belongs to | — |
| `list-collections` | Collections shared with the account | — |
| `get-collection` | One collection | `collectionId` |
| `list-boards` | Boards and backlogs, optionally by collection | — |
| `get-board` | One board, with its columns and lanes | `widgetCommonId` |
| `list-columns` | A board's columns | `widgetCommonId` |
| `list-cards` | Cards on a board, in a collection, or in your todo list | one of `widgetCommonId`, `collectionId`, `cardCommonId`, `cardSequentialId`, or `todoList: true` |
| `get-card` | Full detail on one card | `cardId` |
| `search-cards` | Find cards by text in their name or description | `query` plus `widgetCommonId` or `collectionId` |
| `list-card-comments` | A card's comments | `cardCommonId` |
| `list-card-tasklists` | A card's checklists | `cardCommonId` |
| `list-card-tasks` | Checklist items | `cardCommonId` |
| `list-users` | Users in the organization | — |
| `get-user` | One user | `userId` |

Every tool also accepts an optional `organizationId` to override the configured default.

## Configuration

| Variable | Required | Default | Purpose |
|---|---|---|---|
| `FAVRO_EMAIL` | yes | — | The email you sign in to Favro with |
| `FAVRO_API_TOKEN` | yes | — | An API token from your Favro profile |
| `FAVRO_ORGANIZATION_ID` | no | — | Default organization; otherwise pass `organizationId` per call |
| `FAVRO_CACHE_TTL` | no | `600` | Seconds to cache slow-changing entities. `0` disables caching |

## Things worth knowing

### The API's vocabulary differs from the UI

| API term | What you see in Favro |
|---|---|
| widget | A board or backlog |
| tasklist | A checklist on a card |
| task | A single checklist item |

### Cards have two ids

- **`cardId`** identifies one card on one board. `get-card` takes this.
- **`cardCommonId`** identifies the card across every board it appears on. The comment and checklist tools take this.

Both come back from `list-cards` and `get-card`.

### A typical path through the hierarchy

```
list-organizations           (only when FAVRO_ORGANIZATION_ID is unset)
  → list-collections         find the collection
    → list-boards            boards in that collection
      → get-board            its columns and lanes, in one call
        → list-cards         cards on the board or in a column
          → get-card         full detail on one card
            → list-card-comments / list-card-tasklists / list-card-tasks
```

### Pagination

Listings return up to 100 entities. When more remain, the response carries a cursor:

```json
"pagination": {
  "page": 0,
  "pages": 3,
  "requestId": "...",
  "backendId": "...",
  "next_page": { "page": 1, "requestId": "...", "backendId": "..." }
}
```

Call the same tool again passing `page`, `requestId` and `backendId` exactly as given. All three are required — Favro routes follow-up pages to the same backend server, and the `backendId` is what gets them there.

### `search-cards` is a local filter, not a search endpoint

Favro's API has no card search. `search-cards` reads cards from a board or collection and filters them by case-insensitive substring on name and description. It reads up to `maxPages` pages (default 3, maximum 10), each costing one API call, and reports what it covered:

```json
"scan": {
  "cards_scanned": 250,
  "matches_found": 4,
  "pages_read": 3,
  "pages_available": 5,
  "complete": false,
  "note": "Only 3 of 5 pages were searched. Raise maxPages..."
}
```

When `complete` is `false`, narrow the scope or raise `maxPages` rather than treating the result as exhaustive.

### Rate limits and caching

Favro's hourly budget is low and plan-dependent — 100/hour on Trial up to 10,000/hour on Enterprise, with `list-organizations` and the user tools sharing a separate 50/hour budget. Every response carries a `rate_limit` block showing what is left.

To conserve calls, organizations, users, collections, boards and columns are cached for `FAVRO_CACHE_TTL` seconds. Cached responses are marked `"cached": true`. Cards, comments and checklists are never cached, so they are always current.

## Not covered

Tags, custom field definitions, groups and webhooks are not exposed, and nothing writes to Favro. Open an issue if you need something added.

## Development

```bash
npm install
npm test
npm run build
```

Inspect the server interactively against your real account:

```bash
FAVRO_EMAIL=you@example.com FAVRO_API_TOKEN=your-token npx @modelcontextprotocol/inspector node dist/index.js
```

## License

MIT

TDQS

A4/5.0

Scored across 14 tools

Disambiguation5/5

Every tool targets a distinct resource and action, with clear boundaries between listing, getting, and searching. Even tools like list-cards and search-cards are differentiated by scoping and behavior.

Naming Consistency5/5

All tools follow a consistent verb_noun pattern using either 'list-' for collections or 'get-' for single entities, making the naming predictable and easy to understand.

Tool Count5/5

14 tools is a well-scoped set for a project management API, covering all major resource types without being bloated or sparse.

Completeness2/5

The tool set is entirely read-only, lacking any create, update, or delete operations for cards, boards, comments, etc. This is a significant gap for typical workflow automation, severely limiting the server's utility.

Maintenance

ActivitySlowing
ResponsivenessNo issues