Plutio
Model Context Protocol server for Plutio β CRM, projects, invoices, proposals, forms, time tracking, scheduling, and more.
Ask AI about Plutio
Powered by Claude Β· Grounded in docs
I know everything about Plutio. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
plutio-mcp
A Model Context Protocol (MCP) server for Plutio β the all-in-one business platform for CRM, projects, invoicing, proposals, contracts, forms, time tracking, and scheduling.
Gives Claude (and any other MCP client) structured, safe access to every major resource in your Plutio workspace via one concise tool per resource.
What you get
- 31 resource-group tools covering CRM, project management, time tracking, financial, documents, forms, communication, scheduling, knowledge, files, automations, and admin.
- 4 escape-hatch tools (
plutio_api_reference,plutio_workspace_schema,plutio_rate_limit_status,plutio_request) for edge cases, workspace introspection, and agent self-orientation. - 4 analytics tools (
plutio_mrr_snapshot,plutio_upcoming_renewals,plutio_invoice_aging,plutio_cashflow_forecast) β single-call reports that replace multi-step manual aggregations. - 1 compound lookup tool (
plutio_client_360) β fetches a person + their company + projects + invoices + subscriptions in one call. - 5 MCP resources (
plutio://people/{id},plutio://companies/{id},plutio://projects/{id},plutio://invoices/{id},plutio://tasks/{id}) for clients that support resource browsing. - Read-only by default β no accidental destructive writes until you explicitly enable them.
- OAuth2 with auto-refresh β client-credentials grant; tokens refresh ~1 minute before expiry.
- Built-in rate limiting β a token bucket capped at Plutio's 1000 req/hr default; requests queue transparently.
- MongoDB-style filtering β pass rich query objects directly (
$or,$regex,$gte, etc.). - Bulk operations for resources that support them.
- Typed end-to-end with Zod β JSON Schema on the wire.
Quick start
1. Install
npm install -g @thecreativelabs/plutio-mcp
# or run without installing:
npx @thecreativelabs/plutio-mcp
2. Get Plutio API credentials
In your Plutio workspace go to Settings β API Manager β Create Connection. You'll get a Client ID and Client Secret. Copy them β you won't see the secret again.
3. Configure Claude Desktop / Claude Code
Add to your MCP config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, or .mcp.json / .claude/settings.json for Claude Code):
{
"mcpServers": {
"plutio": {
"command": "npx",
"args": ["-y", "@thecreativelabs/plutio-mcp"],
"env": {
"PLUTIO_CLIENT_ID": "your_client_id",
"PLUTIO_CLIENT_SECRET": "your_client_secret",
"PLUTIO_BUSINESS": "your_workspace_slug",
"PLUTIO_READ_ONLY": "true"
}
}
}
}
PLUTIO_BUSINESSis your workspace slug β the subdomain part of<slug>.plutio.com. If your OAuth client is tied to exactly one business, you can omit it and the server will auto-detect from the token response. When the client has access to multiple businesses, you must set it explicitly.
Restart Claude. You should now see plutio_* tools available.
4. Using ChatGPT?
plutio-mcp speaks HTTP natively since v0.7.0. Set PLUTIO_MCP_HTTP=true and the server listens on http://<host>:<port>/mcp instead of stdio. See examples/10-chatgpt-setup.md for the full walkthrough (local + ngrok, or hosted on Fly.io).
5. Enable writes (when you trust it)
Set PLUTIO_READ_ONLY=false to unlock create, update, delete, archive, unarchive, and bulk operations.
How writes actually work inside Plutio's API. Plutio's public API only supports mutations via bulk endpoints β
PUT /{resource}/{id}returns 403 everywhere. The MCP server handles this transparently: single-recordupdate/delete/archive/unarchiveactions route through/bulkinternally, so from your perspective the tool interface is the usual single-record CRUD. You don't need to think about it β but it explains the version bump to 0.3.0.
Environment variables
| Variable | Required | Default | Purpose |
|---|---|---|---|
PLUTIO_CLIENT_ID | yes | β | OAuth2 client ID from Plutio |
PLUTIO_CLIENT_SECRET | yes | β | OAuth2 client secret from Plutio |
PLUTIO_BUSINESS | conditional | auto-detected from token | Workspace slug. Required when your OAuth client has access to multiple businesses |
PLUTIO_READ_ONLY | no | true | When true, only list/get actions are exposed |
PLUTIO_API_BASE | no | https://api.plutio.com/v1.11 | Override for self-hosted / future API versions |
PLUTIO_OAUTH_URL | no | $PLUTIO_API_BASE/oauth/token | Override for the token endpoint |
PLUTIO_MAX_REQUESTS_PER_HOUR | no | 1000 | Raise if you have a higher-tier Plutio plan |
PLUTIO_LOG_LEVEL | no | info | error / warn / info / debug |
PLUTIO_MCP_HTTP | no | false | Set true to run as an HTTP server (needed for ChatGPT and remote deployments) |
PLUTIO_MCP_HTTP_PORT | no | 8080 | HTTP port when in HTTP mode |
PLUTIO_MCP_HTTP_HOST | no | 127.0.0.1 | HTTP host. Set to 0.0.0.0 for remote access (e.g. behind ngrok) |
PLUTIO_MCP_AUTH_TOKEN | no | β | If set, HTTP requests must carry Authorization: Bearer <token>. Strongly recommended when exposing publicly |
PLUTIO_USER_PRESETS_DIR | no | β | Path to a directory of your private contract/proposal preset JSON files. Loaded alongside built-ins. Use this for templates extracted from your own Plutio workspace via plutio_template_to_preset. See examples/13 |
See .env.example.
Tool catalog
Every resource tool uses the same shape:
plutio_<resource>({ action: "list"|"get"|"create"|"update"|"delete"|"archive"|"bulk_*", ...args })
CRM
plutio_peopleβ contacts, clients, leads, team membersplutio_companiesβ organizations/accountsplutio_notesβ free-form notes on any record
Project management
plutio_projectsplutio_tasksplutio_task_boardsΒ·plutio_task_groupsΒ·plutio_statuses
Time tracking
plutio_time_entriesβ billable/non-billable logs (API path:/time-tracks)plutio_time_categories
Financial
plutio_invoicesplutio_invoice_subscriptionsβ recurring invoicesplutio_transactionsβ payments
Documents
plutio_proposalsplutio_contracts
Forms / leads / marketing
plutio_formsplutio_form_responsesβ raw submissions before qualification
Communication
plutio_conversationsΒ·plutio_comments(comments requiresentityType+entityIdin the query)
Scheduling
plutio_schedulesβ availability windowsplutio_eventsβ calendar entries
Knowledge
plutio_templatesΒ·plutio_canned_responsesΒ·plutio_wiki_pagesΒ·plutio_items
Files
plutio_file_foldersΒ·plutio_files
Analytics / admin
plutio_dashboardsplutio_custom_fieldsplutio_automationsβ Plutio's native node-based automation workflows (list + create only; delete and single-GET are blocked by the REST API)plutio_businesses(workspace settings β read-only)
Analytics (v0.6.0)
plutio_mrr_snapshotβ active subscriptions aggregated into MRR, ARR, by frequency, top clients.plutio_upcoming_renewalsβ subs billing within the next N days (default 30), sorted by date.plutio_invoice_agingβ unpaid invoices bucketed by days overdue (current / 30β60 / 60β90 / 90+).plutio_cashflow_forecastβ projects expected income over N days by expanding each sub's recurrence.
Compound (v0.6.0)
plutio_client_360β one call, everything about a client: person + company + projects + invoices + subs.
Proposal builder (v0.8.0)
plutio_list_proposal_presetsβ see shipped presets (web-design, seo-services, consulting, creative-services, coaching).plutio_proposal_from_presetβ create a fully-populated proposal (blocks + items + client link) in one call.plutio_analyze_proposalβ inspect a past proposal's structure to mirror it for a new client.
Contract builder (v0.9.0)
plutio_list_contract_presetsβ shipped presets (service-agreement,nda).plutio_contract_from_presetβ create a contract end-to-end with{{ variable }}substitution. Note: shipped presets contain TODO placeholders for legal clauses β replace before sending for signature.
Template extractor (v0.10.0)
plutio_template_to_presetβ read any of your existing Plutio contract/proposal templates and emit a preset JSON ready for the builders. Run once per template, save to disk, your real prose becomes available to AI generation forever. See examples/13.
Custom Pages + Custom Fields config (v0.10.2)
plutio_dashboard_pagesβ list/get/create new pages on any of Plutio's role dashboards (Settings β Custom Pages). Update + delete blocked by REST (use UI).plutio_create_dashboard_page_from_presetβ instantiate a page from a starter scaffold (client-welcome,project-status) with content blocks pre-populated. Plutio's native{{ client.name }}/{{ business.name }}tokens render at view time.plutio_apply_custom_fields_bundleβ create a curated set of custom fields in one call. Shipped bundles:lead-intake,client-onboarding. Skips fields whose (entityType, title) already exists. See examples/14.
Escape hatches
plutio_api_referenceβ compact map of every tool + API path. Call first when unsure.plutio_workspace_schemaβ introspects custom fields. Returns{entityType: {fieldTitle: {_id, inputType, options: {optionLabel: optionId}}}}. Cached 5 min.plutio_requestβ raw API passthrough:{ method, path, query?, body? }.plutio_rate_limit_statusβ remaining requests in the current hour.
MCP resources (v0.6.0)
Some MCP clients let you browse typed resources. The server advertises these URI templates:
plutio://people/{id}Β·plutio://companies/{id}Β·plutio://projects/{id}Β·plutio://invoices/{id}Β·plutio://tasks/{id}
Example prompts
Once configured, try these in Claude:
- "Use Plutio to list my 10 most recent invoices by due date."
- "Find all active projects where the client is 'Acme Corp'."
- "Show me form responses from the last 7 days that haven't been converted to people yet."
- "How much billable time did I log against project ABC in March?"
- (with writes enabled) "Create a follow-up task on project ABC due next Monday."
π See examples/ for 6 fully worked end-to-end workflows
Each example shows the user prompt, the exact tool calls Claude will make, and a realistic answer. All verified against a live workspace.
Filtering syntax
List actions accept a query object that supports Plutio's MongoDB-style operators:
{
"action": "list",
"query": {
"status": "incomplete",
"createdAt": { "$gte": "2026-01-01" },
"$or": [
{ "tags": { "$in": ["lead", "hot"] } },
{ "companyId": "5f4..." }
]
},
"limit": 50,
"sort": "-createdAt"
}
Custom fields
Plutio lets you define custom fields on any resource. To set them on create/update:
{
"action": "update",
"id": "5f4...",
"data": {
"customFields": [
{ "_id": "<custom_field_id>", "value": "Enterprise" }
]
}
}
Fetch the custom-field definitions with plutio_custom_fields to see IDs and types.
Development
# clone + install
git clone https://github.com/thecreativelabs/plutio-mcp.git
cd plutio-mcp
npm install
# dev mode (watch + reload)
npm run dev
# typecheck / build
npm run typecheck
npm run build
# run against your env
PLUTIO_CLIENT_ID=... PLUTIO_CLIENT_SECRET=... node dist/index.js
Adding a new resource
All resources live in src/tools/registry.ts. Add a new entry and it's automatically exposed as a tool:
{
name: "my_resource",
path: "my-resource",
category: "crm",
description: "...",
archive: true,
bulk: true,
}
Adding a specialized action
For endpoints that don't fit the CRUD pattern (e.g. sending an invoice, publishing a proposal, starting a timer), add a standalone tool file under src/tools/ and register it in src/tools/index.ts. See escape-hatch.ts for the pattern.
Design choices
| Decision | Choice | Why |
|---|---|---|
| Tool granularity | Resource-grouped (one tool per resource with action param) | ~30 tools vs. 150+. Agents reason better over fewer, semantically meaningful tools. |
| Default write posture | Read-only | Public-safe by default; writes are an explicit opt-in. |
| Runtime | TypeScript / Node 20+ | Lines up with MCP's primary ecosystem and enables npx distribution. |
| Rate limiting | Client-side token bucket | Respects Plutio's 1000/hr cap even when the agent goes wild. |
| Escape hatch | plutio_request + plutio_api_reference | Lets agents handle new endpoints without a server release. |
Known limitations
Lifecycle actions (Send Invoice, Publish Proposal, Sign Contract, Start/Stop Timer) are not supported by Plutio's public REST API. Live probing confirmed:
PUT /invoices/bulk { status: "sent" }returns HTTP 200 but silently drops the status field.POST /invoices/{id}/sendand every variant returns 403.- The Plutio web app handles these via Meteor methods over WebSocket/DDP, which is not part of the public API surface.
Practical workarounds:
- Trigger lifecycle actions in the Plutio web UI, then use this server to read the resulting state.
- If you've reverse-engineered a specialized endpoint yourself, invoke it via
plutio_request. - For status-aware logic (e.g., "find all overdue invoices"), read the
statusand time fields β they're populated server-side once the Plutio app performs the transition.
If Plutio ever exposes these actions publicly, plutio_request will work without any server update.
Roadmap
- Workspace introspection β
plutio_workspace_schema(v0.4.0) - Transparent bulk routing β single-record writes use
/bulkinternally (v0.3.0) - Webhook support (once Plutio documents webhook endpoints)
- MCP resources (alongside tools) for read-heavy flows β expose
plutio://people/{id}URIs - Optional OpenAPI export of the generated schema
- SSE / streaming transport for hosted deployments
- Mocked-API integration test suite
Contributions welcome β see Contributing.
Contributing
- Fork the repo and create a feature branch.
npm install && npm run typecheckbefore you push.- Open a PR describing the problem you're solving and any API references.
Design principle: don't grow the tool count blindly. Before adding a tool, ask whether it can fit the existing resource-grouped pattern or belongs in plutio_request. The fewer tools, the better agents perform.
License
MIT Β© TheCreativeLabs
Disclaimer
This is an unofficial, community-maintained integration. Not affiliated with or endorsed by Plutio.
