Saku

MCP server Max

Connect Claude, Cursor, and any other MCP-compatible AI tool to your Saku workspace. The Saku MCP server exposes boards, cards, team notes, and CRM as callable tools so agents can read, create, and update your work without leaving the AI chat. For REST details and permissions, see the API reference.

Published npm package: @florianindustries/saku-mcp (npm). Use npx -y @florianindustries/saku-mcp in your host config (see below).

How it works

Saku's hosted MCP endpoint uses Streamable HTTP at https://mcp.saku.ie/mcp. Connect it in any host that supports remote MCP servers and send your scoped key as a Bearer token. The endpoint lists its tools publicly for discovery, but requires the key before it can access workspace data.

The @florianindustries/saku-mcp npm package remains available as a local process that speaks the Model Context Protocol over stdio. Your AI host (Claude Desktop, Cursor, etc.) spawns it and routes tool calls through it to the Saku REST API. The server never stores your data; it forwards requests and returns responses.

Requirements

  • Saku Max plan (API keys are a Max feature)
  • An MCP-compatible host with Streamable HTTP support
  • Node.js 20 or later only when using the local npm package

Setup

1. Add the hosted endpoint

In your host's remote MCP settings, add https://mcp.saku.ie/mcp with Streamable HTTP transport and an Authorization: Bearer YOUR_SAKU_API_KEY header.

2. Create an API key

Visit the authorisation page to create a scoped API key in your browser. You'll pick exactly which permissions to grant and which team to connect.

Authorise MCP access →

Alternatively, go to Boards → Settings → API and create a key manually. Copy the key: it's shown only once.

3a. Claude Desktop with the local package

Open your Claude Desktop configuration file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add the following, replacing the placeholder with your real key:

{
  "mcpServers": {
    "saku": {
      "command": "npx",
      "args": ["-y", "@florianindustries/saku-mcp"],
      "env": {
        "SAKU_API_KEY": "<your SAKU_API_KEY from .env>"
      }
    }
  }
}

Restart Claude Desktop. You should see a hammer icon: Saku tools are now available.

3b. Cursor with the local package

Open Cursor → Settings → MCP and add a new server with the following JSON:

{
  "mcpServers": {
    "saku": {
      "command": "npx",
      "args": ["-y", "@florianindustries/saku-mcp"],
      "env": {
        "SAKU_API_KEY": "<your SAKU_API_KEY from .env>"
      }
    }
  }
}

3c. Other local MCP hosts

Any host that supports the stdio transport can run Saku MCP. The command is:

SAKU_API_KEY=YOUR_SAKU_API_KEY npx -y @florianindustries/saku-mcp

Available tools

Tools are only available if the API key includes the required permission. Create a key with broader permissions later if needed (you'll need to create a new key; permissions can't be changed after creation).

list_boardsboards:read

List all active boards with their lists, labels, and members. Start here to discover IDs.

get_boardboards:read

Get a specific board with lists and cards (paginated per list). Each list includes cardsTotalCount for non-archived cards; use listCardLimit (default 200, max 500) and listCardOffset on the API or MCP tool to page.

ArgumentTypeRequired
boardIdstringYes
listCardLimitnumberNo
listCardOffsetnumberNo
create_cardcards:create

Create a new card in a list.

ArgumentTypeRequired
listIdstringYes
titlestringYes
descriptionstringNo
labelsstring[]No
assigneesstring[]No
sourcestringNo
get_cardcards:read

Get full card details including checklists, priority, due date, and assignees.

ArgumentTypeRequired
cardIdstringYes
update_cardcards:update

Update a card's title, description, priority, or due date. Only send the fields you want to change.

ArgumentTypeRequired
cardIdstringYes
titlestringNo
descriptionstringNo
priorityCRITICAL | URGENT | HIGH | MEDIUM | LOW | MINOR | nullNo
dueDateISO 8601 string | nullNo
archive_cardcards:delete

Archive a card (reversible in the app). Uses DELETE /api/v1/cards/:id.

ArgumentTypeRequired
cardIdstringYes
create_listlists:create

Add a new list (column) to a board. The list is appended after existing lists.

ArgumentTypeRequired
boardIdstringYes
namestringYes
list_membersmembers:read

List all team members with their IDs, names, and emails (useful for resolving assignees). Uses GET /api/v1/members.

list_notesnotes:read

List team-visible notes with pagination. Also returns writable team vaults; start here to discover vault IDs for create_note.

ArgumentTypeRequired
vaultIdstringNo
limitnumberNo
offsetnumberNo
get_notenotes:read

Get a note by ID, including full contentMarkdown.

ArgumentTypeRequired
noteIdstringYes
create_notenotes:create

Create a note in a team vault. Content is Markdown; wiki-links like [[note:ID]] are resolved automatically.

ArgumentTypeRequired
vaultIdstringYes
titlestringNo
contentMarkdownstringNo
update_notenotes:update

Update a note's title and/or content. Send only fields to change; contentMarkdown REPLACES the whole body (read-modify-write via get_note first).

ArgumentTypeRequired
noteIdstringYes
titlestringNo
contentMarkdownstringNo
list_crm_accountscrm:read

List CRM accounts (companies) with cursor pagination. Use nextCursor from the previous response. Offset is rejected.

ArgumentTypeRequired
limitnumberNo
cursorstringNo
get_crm_accountcrm:read

Get a CRM account by ID, including its contacts.

ArgumentTypeRequired
accountIdstringYes
create_crm_accountcrm:write

Create a CRM account (company).

ArgumentTypeRequired
companyNamestringYes
primaryEmailstringNo
phonestringNo
websitestringNo
create_crm_contactcrm:write

Create a CRM contact. Optionally link to an account via accountId (mapped to clientId in the API).

ArgumentTypeRequired
namestringYes
accountIdstringNo
emailstringNo
phonestringNo
jobTitlestringNo
list_crm_contactscrm:read

List CRM contacts with optional account filter and cursor pagination. accountId maps to clientId in the API. Offset is rejected.

ArgumentTypeRequired
accountIdstringNo
limitnumberNo
cursorstringNo
list_crm_stagescrm:read

List lead and deal pipeline stages. Call before creating or moving leads/deals to discover stage IDs.

list_crm_pipelinecrm:read

List leads or deals in the CRM pipeline with optional filters and cursor pagination. Offset is rejected.

ArgumentTypeRequired
kind"leads" | "deals"Yes
stageIdstringNo
accountIdstringNo
statusstringNo
limitnumberNo
cursorstringNo
create_crm_leadcrm:write

Create a CRM lead. Use list_crm_stages for stage IDs if not providing stageId.

ArgumentTypeRequired
titlestringYes
descriptionstringNo
sourcestringNo
stageIdstringNo
accountIdstringNo
contactIdstringNo
create_crm_dealcrm:write

Create a CRM deal. Use list_crm_stages for stage IDs if not providing stageId.

ArgumentTypeRequired
titlestringYes
descriptionstringNo
stageIdstringNo
accountIdstringNo
contactIdstringNo
leadIdstringNo
valueCentsnumberNo
closeDateISO 8601 stringNo
update_crm_leadcrm:write

Update a CRM lead. Only send fields to change; use list_crm_stages for stage IDs.

ArgumentTypeRequired
leadIdstringYes
titlestringNo
descriptionstringNo
sourcestringNo
stageIdstringNo
statusOPEN | QUALIFIED | LOSTNo
update_crm_dealcrm:write

Update a CRM deal. Only send fields to change; use list_crm_stages for stage IDs.

ArgumentTypeRequired
dealIdstringYes
titlestringNo
descriptionstringNo
stageIdstringNo
statusOPEN | WON | LOSTNo
valueCentsnumberNo
closeDateISO 8601 string | nullNo
list_crm_communicationscrm:read

List CRM communications for an account with optional filters and cursor pagination.

ArgumentTypeRequired
accountIdstringYes
limitnumberNo
cursorstringNo
kindEMAIL | CALL | MEETING | NOTE | OTHERNo
create_crm_communicationcrm:write

Log a CRM communication on an account.

ArgumentTypeRequired
accountIdstringYes
kindEMAIL | CALL | MEETING | NOTE | OTHERYes
subjectstringNo
bodystringNo
occurredAtISO 8601 stringNo
list_time_entriestime:read

List your time entries with pagination.

ArgumentTypeRequired
limitnumberNo
offsetnumberNo
create_time_entrytime:write

Create a manual time entry. Provide startTime and endTime, or durationMinutes.

ArgumentTypeRequired
cardIdstringNo
descriptionstringNo
startTimeISO 8601 stringNo
endTimeISO 8601 stringNo
durationMinutesnumberNo
isBillableboolean | nullNo
tagNamesstring[]No
start_timertime:write

Start a running timer. Any other active timer is stopped first (one active timer per person).

ArgumentTypeRequired
cardIdstringNo
descriptionstringNo
isBillableboolean | nullNo
tagNamesstring[]No
stop_timertime:write

Stop your active timer, optionally rounding the duration.

ArgumentTypeRequired
timeEntryIdstringNo
cardIdstringNo
descriptionstringNo
roundingMinutes0 | 6 | 15No
list_invoicesinvoices:read

List invoices for the API key team with optional status/client filters and cursor pagination.

ArgumentTypeRequired
clientIdstringNo
cursorstringNo
limitnumberNo
statusDRAFT | SENT | VIEWED | PAYMENT_PENDING | PAID | OVERDUE | VOIDNo
get_invoiceinvoices:read

Get an invoice by ID including lines, payments, activity, and payUrl.

ArgumentTypeRequired
invoiceIdstringYes
create_invoiceinvoices:write

Create a draft invoice for a CRM client, optionally with manual line items. Money fields use integer cent strings. Currency defaults from Stripe Connect when omitted (EUR/USD/GBP).

ArgumentTypeRequired
clientIdstringYes
currencyEUR | USD | GBPNo
linesarray of { title, description?, quantity, unitCents (string), vatRatePercent? }No
send_invoiceinvoices:write

Issue (if needed) and email an invoice with PDF attachment. API key owner must be team OWNER or ADMIN.

ArgumentTypeRequired
invoiceIdstringYes
recipientEmailsstring[]No

Permissions

API keys are scoped to specific permissions. Grant only what your use case needs.

PermissionLabelEnables
boards:readRead boardslist_boards, get_board
cards:readRead cardsget_card
cards:createCreate cardscreate_card
cards:updateUpdate cardsupdate_card
cards:deleteDelete cardsarchive_card
lists:createCreate listscreate_list
members:readRead memberslist_members (GET /api/v1/members); team member emails are omitted from board responses without this scope
notes:readRead noteslist_notes, get_note
notes:createCreate notescreate_note
notes:updateUpdate notesupdate_note
crm:readRead CRMlist_crm_accounts, get_crm_account, list_crm_contacts, list_crm_stages, list_crm_pipeline, list_crm_communications
crm:writeWrite CRMcreate_crm_account, create_crm_contact, create_crm_lead, create_crm_deal, update_crm_lead, update_crm_deal, create_crm_communication
crm:exportExport CRMExport CRM graph (Max API keys; not granted to existing keys by default)
crm:importImport CRMImport CRM data (Max API keys)
crm:mergeMerge CRMMerge CRM duplicates (Max API keys)
crm:forecastCRM forecastPipeline forecast (Max)
crm:automationCRM automationCRM workflow automation (Max)
time:readRead timelist_time_entries
time:writeWrite timecreate_time_entry, start_timer, stop_timer
expenses:readRead expensesREST expense reads and receipt metadata
expenses:writeWrite expensesREST expense creation, review, reimbursement, and invoicing
invoices:readRead invoiceslist_invoices, get_invoice
invoices:writeWrite invoicescreate_invoice, send_invoice

Security

  • Keys are team-scoped. One key = one team. Create separate keys for separate teams or tools.
  • Permissions can't be changed after creation; create a new key if you need different scopes.
  • Revoke a key any time in Boards → Settings → API. The MCP server will immediately start returning 401s.
  • The server runs locally on your machine; your key and data never pass through a third-party relay.

Troubleshooting

"SAKU_API_KEY is not set"
The SAKU_API_KEY env var is missing from your host config. Check that "env" is set correctly in your config JSON.
"Unauthorized" errors
The key may have been revoked or the value was copied incorrectly. Create a new key at /mcp/authorize and update your config.
"Missing permission: …" errors
The tool requires a permission not included in your key. Create a new key with the needed permissions; permissions can't be added to existing keys.
Tools don't appear in the host UI
Make sure Node.js 20+ is installed and accessible from your PATH. Restart the AI host after editing the config file.

The brain for your business

Saku is a product of Florian Industries, which is registered with the Companies Registration Office in Ireland (797293). © 2026 Saku.