Skip to content
Cashew.Tools

How it works, for the technically minded

MCP is the primary API, not a wrapper around a REST app.

Connect an assistant, then the tools, prompts, and errors it will see.

Connect

Create a space, paste the endpoint into the assistant, approve the grant, then ask what's on your plate.

  1. Create a space. Name it after the work, invite the people who do it, pick the statuses you use.
  2. Paste https://mcp.cashew.tools/mcp into the assistant's connector settings. Approve scopes, spaces, and expiry.
  3. Ask “What's on my plate?”
Assistant

Add this URL as a custom connector. Approve the grant in the browser.

https://mcp.cashew.tools/mcp

Add this URL as an MCP connector. Approve the same consent screen.

https://mcp.cashew.tools/mcp

Cursor cannot register itself, so it has a client id here. Put this in ~/.cursor/mcp.json, then relaunch: Cursor reads that file only at startup. Needs Cursor 3.10.17 or newer. There is no secret to paste. It names no scopes, which asks for the three the server advertises on its 401; anything beyond those is a step-up an agent asks for by name.

{
  "mcpServers": {
    "cashew-tools": {
      "url": "https://mcp.cashew.tools/mcp",
      "auth": { "CLIENT_ID": "cursor-desktop" }
    }
  }
}

Also registered by name rather than registering itself. Put this in settings.json. There is no secret to paste. Naming the scopes is optional: a request that names none asks for the three the server advertises on its 401, and anything beyond those is a step-up an agent asks for by name.

{
  "mcpServers": {
    "cashew-tools": {
      "url": "https://mcp.cashew.tools/mcp",
      "oauth": {
        "enabled": true,
        "issuer": "https://auth.cashew.tools",
        "authorizationUrl": "https://auth.cashew.tools/api/auth/oauth2/authorize",
        "tokenUrl": "https://auth.cashew.tools/api/auth/oauth2/token",
        "clientId": "gemini-cli",
        "scopes": ["identity:read", "tasks:read", "tasks:write", "offline_access"]
      }
    }
  }
}

Anything that speaks MCP over Streamable HTTP with OAuth connects the same way. Grants, expiry, and revoke are on Security.

Endpoint

Specification
2026-07-28
Transport
Stateless Streamable HTTP, POST only
URL
https://mcp.cashew.tools/mcp
Discovery
server/discover answers before a token exists
Auth
OAuth 2.1 with grants, not API keys. Passkeys first for people. How grants work.

A turn

  1. whoami
  2. get_workspace_map
  3. list_inbox or search_tasks
  4. get_task
  5. create_task, update_task, move_task, or comment_on_task. Use bulk_create_tasks or bulk_update_tasks when more than one.

Tools

Called via tools/call. Every mutating tool accepts an optional idempotencyKey.

Identity (identity:read)

ToolInputReturnsScope
whoamiNone.Principal, impersonated user, org, client, scopes, spaces, grant expiry, and a cannot list.identity:read
list_membersNone.Members by name and role.identity:read

Read tasks (tasks:read)

ToolInputReturnsScope
get_workspace_mapNone.Spaces, lists, and status names the grant can see.tasks:read
search_tasksOptional query, spaceId, listId, status, assigneeId, cursor, and limit.A page of tasks and a next cursor.tasks:read
get_tasktaskId (ta_…).The task with its subtasks, comments, and attachments.tasks:read
get_attachmentattachmentId (at_…). Optional format: auto, text, or url.A small text file inline; anything else as a download URL, signed and short-lived where the bucket can sign one.tasks:read
view_task_detailtaskId (ta_…).Backs the task view rather than the model: the task, plus the status names its list allows, the member roster, and whether the grant may write. Call get_task instead.tasks:read
list_inboxOptional cursor and limit.Open assigned tasks, excluding snoozed items, and a next cursor.tasks:read

Write tasks (tasks:write)

ToolInputReturnsScope
create_tasklistId and title. Optional description, status, assigneeId, priority (1 Urgent to 4 Low), and dueAt.The task.tasks:write
update_tasktaskId, plus any of title, description, status, assigneeId, priority (1 Urgent to 4 Low), dueAt, and snoozedUntil.The task.tasks:write
move_tasktaskId. Optional listId, status, position, beforeTaskId, and afterTaskId.The task.tasks:write
create_subtaskstaskId and titles (one to fifty).The subtasks.tasks:write
toggle_subtasksubtaskId. Optional done, to set rather than flip.The subtask.tasks:write
comment_on_tasktaskId and body.The comment.tasks:write
delete_tasktaskId.The task id. Recoverable for 30 days.tasks:write
restore_tasktaskId.The task.tasks:write
delete_commentcommentId (cm_…).The comment id. Recoverable for 30 days.tasks:write
restore_commentcommentId.The comment.tasks:write
delete_attachmentattachmentId (at_…).The attachment id. Recoverable for 30 days.tasks:write
restore_attachmentattachmentId.The attachment.tasks:write
start_attachment_uploadtaskId, filename, mimeType, and the exact size in bytes.A signed POST valid for 15 minutes, a ready curl command, and a board link for a human to upload instead.tasks:write
finish_attachment_uploadtaskId and the uploadId (up_…) from start_attachment_upload.The attachment, named and sized from what arrived.tasks:write
attach_filetaskId, filename, mimeType, and either text or base64 (up to 256 KB).The attachment.tasks:write

Bulk (tasks:bulk)

ToolInputReturnsScope
bulk_create_tasksitems: one to fifty create payloads.The tasks.tasks:bulk
bulk_update_tasksitems: one to fifty update payloads.The tasks.tasks:bulk

Shape the workspace (spaces:write)

ToolInputReturnsScope
create_spacename. Optional color and visibility (workspace or private).The space, with its seeded list.spaces:write
update_spacespaceId, plus any of name, color, and visibility.The space.spaces:write
archive_spacespaceId.The space id.spaces:write
create_listspaceId and name.The list, with its Open and Done statuses.spaces:write
update_listlistId and name.The list.spaces:write
archive_listlistId.The list id.spaces:write
create_statuslistId, name, and type (open or closed). Optional color. Open/custom land before closed.The status.spaces:write
update_statusstatusId, plus any of name, color, and type.The status.spaces:write
reorder_statuseslistId and statusIds (every live status on the list, closed last).The list id and statuses in the new order.spaces:write
delete_statusstatusId.The status id. Recoverable for 30 days.spaces:write
restore_statusstatusId.The status.spaces:write

Space access (members:write)

ToolInputReturnsScope
add_space_memberspaceId and userId (us_…).Everyone on the space.members:write
remove_space_memberspaceId and userId.Everyone left on the space.members:write
take_over_spacespaceId.Everyone on the space, now including you.members:write

Run the workspace (admin:write)

ToolInputReturnsScope
list_invitationsNone.Pending invitations with their role and expiry.admin:write
invite_memberemail and role (admin, member, or guest).The invitation, and whether a live one was refreshed instead. The invitee is emailed either way.admin:write
cancel_invitationinvitationId.The invitation id.admin:write
update_member_rolememberId (mb_…) and role.The member.admin:write
list_webhooksNone.Endpoints by id and URL. Never the secret.admin:write
add_webhookurl (https) and secret (16 to 256 characters). Optional events.The endpoint, without its secret.admin:write
remove_webhookwebhookId.The webhook id.admin:write

Audit (audit:read)

ToolInputReturnsScope
get_audit_logOptional entityType, entityId, cursor, and limit.Audit rows the grant can see, and a next cursor.audit:read

Prompts

These are prompts/get templates, not executable work. The host fills them in and the model then calls tools.

PromptArgsWhat it tells the model to do
prioritize_inboxNone.Call list_inbox, then get_task on anything blocked or due soon, and propose an order of attack.
standup_summaryNone.Call list_inbox, group by status name, and summarise what is in flight, blocked, and due soon.

Resources

Read-only documents, not tool calls. They return the same data as the matching tools.

URISame as
workspace://mapThe same document get_workspace_map returns.
task://{id}The same document get_task returns. The id is the prefixed task id (ta_…).
user://meThe same document whoami returns.
ui://task/detail.htmlThe task panel get_task renders in a host that supports MCP Apps. HTML, not data.

Errors

Tool errors include a code in the body. A dead grant is a 401 and never reaches a tool.

ErrorWhat to do
403 insufficient_scopeAsk the human to approve the missing scopes. The challenge lists the complete set. Do not retry the same token.
401The grant expired or was revoked. Ask the human to renew from Settings, under Agents. Nothing already created goes away.
unknown_statusUse a status name from get_workspace_map, not an id.
bulk_item_capSplit the work. Fifty items per call.