paymo-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@paymo-mcplog 2 hours to the website redesign project"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
paymo-mcp
An unofficial Model Context Protocol (MCP) server for the Paymo time-tracking API. Read and
write Paymo tasks, workflow statuses and time entries from any MCP client with npx.
Not affiliated with Paymo — no warranty and no endorsement.
Install
No install needed. Any MCP client can launch it with npx -y paymo-mcp into any project that has
a Paymo API key. Example .mcp.json:
{
"mcpServers": {
"paymo": {
"command": "npx",
"args": ["-y", "paymo-mcp"],
"env": {
"PAYMO_API_KEY": "your-key-here"
}
}
}
}Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"paymo": {
"command": "npx",
"args": ["-y", "paymo-mcp"],
"env": {
"PAYMO_API_KEY": "your-key-here"
}
}
}
}Related MCP server: Paymo MCP Server
Configuration
Environment variables read by paymo-mcp:
Variable | Required | Default | Description |
| yes | — | Paymo API key used with HTTP Basic auth. |
| no |
| API base URL. |
| no | — | Project used when a project id argument is omitted. |
| no | discovered automatically | JSON object overriding status aliases, e.g. |
| no |
| Comma-separated toolset names, plus the keywords |
| no | — | Comma-separated tool names, additive on top of the toolsets. Matched exactly as registered. |
| no | — | One JS regex, matched against tool names and subtracted from the resolved set last. |
| no |
| One of |
| no | — | Deprecated. Use |
An unusable value in any of these aborts startup with an error instead of falling back to a default:
a typo that silently granted write access would be worse than a server that refuses to boot. Setting
both PAYMO_PERMISSION_MODE and PAYMO_READ_ONLY also aborts — drop the deprecated one rather than
guessing which variable won.
Toolsets
Toolset | Covers | Tools | Schema cost (chars) |
|
| 2 | 1,008 |
| tasks, tasklists (read), comments, subtasks | 7 | 5,453 |
| time entries: timer control, manual logging, deletion | 4 | 795 |
| project CRUD, project templates, project statuses, tasklists (write) — milestones deferred | 9 | 5,794 |
| client CRUD (no delete), client contacts, company — portal access included | 8 | 6,136 |
| invoices, invoice payments, estimates, invoice templates — read-only, deliberately | 6 | 4,124 |
| every toolset above | 34 | 21,710 |
default = context + tasks + time, which is approximately the surface the package exposed
before toolsets existed — an existing user upgrading sees no change. Names are additive and
order-independent, so PAYMO_TOOLSETS=default,billing would mean defaults plus billing.
Schema cost is measured in characters of inputSchema, not tokens: no count_tokens key was
available, and a characters-per-token estimate would be guessing. The projects toolset references
paymo_list_projects and paymo_list_tasklists by name from tasks, so selecting projects alone
still gives you the lookups you need to create a task.
How the tool set is resolved
PAYMO_TOOLSETSexpands to a set of tool names (default→ the default toolsets;all→ every toolset; names are additive).PAYMO_TOOLSis unioned in.PAYMO_DENIED_TOOLS_REGEXis subtracted.PAYMO_PERMISSION_MODEfilters last — never overridable by naming a tool explicitly.
The resolved set is fixed at startup and never changes mid-session. Changing any of these variables
requires restarting the MCP client; a fixed tools array is what keeps the prompt cache valid.
Permission modes
Mode | Registers |
| reads only |
| reads + create/update; all delete tools omitted |
| everything, deletes included |
modify is the default: an MCP server handing a model an API key with full account access should not
delete by default. paymo_delete_entry is the only delete tool, and it exists because Paymo refuses
to set an end_time on an entry under a minute old — such a timer can only be closed by deleting it.
It therefore requires PAYMO_PERMISSION_MODE=full; under modify, paymo_stop_timer's error names
that requirement instead of leaving you at a dead end.
Examples
Defaults — read and write, no deletes:
{
"mcpServers": {
"paymo": {
"command": "npx",
"args": ["-y", "paymo-mcp"],
"env": {
"PAYMO_API_KEY": "your-key-here"
}
}
}
}A single toolset — just identity and workflow statuses:
{
"mcpServers": {
"paymo": {
"command": "npx",
"args": ["-y", "paymo-mcp"],
"env": {
"PAYMO_API_KEY": "your-key-here",
"PAYMO_TOOLSETS": "context"
}
}
}
}A single-tool allowlist — the context toolset plus exactly one write tool:
{
"mcpServers": {
"paymo": {
"command": "npx",
"args": ["-y", "paymo-mcp"],
"env": {
"PAYMO_API_KEY": "your-key-here",
"PAYMO_TOOLSETS": "context",
"PAYMO_TOOLS": "paymo_create_task"
}
}
}
}Getting an API key
Your Paymo API key grants full read and write access to your Paymo account. Get it from your
Paymo account settings. Unless you need to create or mutate data, set PAYMO_PERMISSION_MODE=readonly
— an accident with a write tool is much harder to undo than a wrong read.
Tools
Read — registered in every permission mode, subject to the selected toolsets.
Tool | Args | Endpoint |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Write — registered under modify and full.
Tool | Args | Endpoint |
|
|
|
|
|
|
|
|
|
|
|
|
| — |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Delete — registered under full only.
Tool | Args | Endpoint |
|
|
|
A timer that ran for under a minute cannot be stopped: Paymo rejects an end_time that would make
the entry shorter than that. Delete it with paymo_delete_entry instead — that is the documented
way out, and the only reason this package ships a delete tool at all. Because full is not the
default, the stop error names that requirement when the tool is not registered.
Response size
Paymo answers with 20–40 fields per record; a project listing comes back several times larger than
the whole tool catalogue. The list and detail tools therefore return a documented field subset —
an agent needs id, name, code, not flat_billing or cover_file_id. List tools take
limit (default 50) and offset for paging, and return a narrower summary subset than
detail reads: a
listing exists to pick a record, so it carries id/name/code and the couple of fields needed to
choose, while paymo_get_task and paymo_me keep the fuller set. Pass verbose: true to any read
tool when you genuinely need every field Paymo provides — it bypasses both subsets.
Rate limiting
Paymo answers a 429 with X-Ratelimit-Decay-Period, and a request that hits one is retried once
after waiting exactly that long (capped at 60s) before the error surfaces. Bursts still hurt: a
single tool call can cost two or three requests, since resolving a task code and the current user
are separate lookups.
Where a task is expected, pass either a numeric id or a human task code (e.g. ABC-1).
Where a status is expected, pass a numeric id or a slug alias such as in_progress; aliases are
discovered from your workflow, overridable with PAYMO_STATUS_ALIASES.
Projects
There is no project or tasklist delete tool on purpose: DELETE /projects/{id} destroys the
project's tasks and their time entries — cascading, unrecoverable loss of billing data. Archive
instead with paymo_update_project and active: false; that is why the tool accepts it. Milestones
are not covered yet: paymo_update_tasklist accepts a milestone_id created in the Paymo UI.
Creating a project from a template_id may copy the template's tasklists and tasks into the new
project, and the created project is what comes back.
The project and tasklist writes are unverified live: the account this package was developed
against uses an Employee key, and Paymo answers POST /projects with a 403. The reads are verified
against a real account; the writes are covered by stub-client unit tests and await a human-run
verification pass with an administrator key. template_id is doubly unverified — that account has
no project templates.
Clients
There is no client or client-contact delete tool on purpose: DELETE /clients/{id} destroys every
project, task and time entry attached to the client — cascading, unrecoverable loss of billing data.
Archive instead with paymo_update_client and active: false, the same active-boolean pattern
projects uses. To reach a person at a client, list contacts with paymo_list_client_contacts; to
know your own billing identity and invoice defaults, read paymo_get_company.
Granting a contact access to the client portal is part of updating or creating the contact: send
access: true together with a password. paymo_update_client_contact with access: false
revokes it.
The client, client-contact, and company writes are unverified live: the package's example key is
an Employee, and Paymo answers admin-level creates (POST /clients, POST /clientcontacts) with a
403. The reads are verified against a real account; the writes are covered by stub-client unit tests
and are slated for the human-run admin verification pass once an administrator key is available.
Billing
The billing toolset is read-only, deliberately — it is the one toolset that ships no write tool on purpose, and this is a decision, not an oversight. An invoice is a client-facing financial document: a wrong write lands as a draft in an accounting export, a payment against the wrong invoice, or a document sent to a client, and none of that is recoverable the way a wrong task status is. Automated invoicing was never a requirement; reading state to answer "has this been paid" is. If invoicing writes are ever needed, that is a separate, separately-argued addition built after the admin verification pass.
The billing reads (invoices, estimates, invoice templates) return 403 on the account this package
was developed against — {"message":"Listing invoices denied"}. That is the account role, not
the plan: the same account reports a six-figure invoice allowance, and an Employee simply cannot read
company invoices. An Administrator key reads them. So those reads are unverified live and covered
by stub-client unit tests instead; paymo_list_invoice_payments is readable and
paymo_get_estimate reaches Paymo's estimate lookup. If these 403 for you, check the role of the
key before suspecting the request.
Rich text
Task descriptions and comments accept HTML. Paymo keeps p, b, i, u, s, ul, ol, li,
h2, blockquote, a, br, code, pre and span (including inline style), adds
rel="noopener noreferrer" to links, and strips everything else — <script> included. Markdown is
not rendered: **bold** stays literal and backticks come back HTML-escaped, so use tags.
Note that a WAF sits in front of the Paymo API and can reject a request whose body merely looks
dangerous. Posting a comment containing <script> returns a 403 HTML page rather than a Paymo
error, even though Paymo itself would have stripped the tag.
Development
npm test # node --test, no framework
npm run build # tsc to dist/License
MIT — see LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Flicense-qualityDmaintenanceA comprehensive MCP server for time tracking, project management, and AI-powered memory storage using semantic search. It enables users to log time, manage client billing, and capture shared or personal ideas through integrated tools and team collaboration features.Last updated1
- Flicense-qualityBmaintenanceAn MCP server for the Paymo platform that enables AI assistants to manage time entries, projects, and tasks through natural language. It supports tracking unbilled revenue and generating detailed invoice timesheets for efficient project management.Last updated5
- Flicense-qualityDmaintenanceAn MCP server for controlling the TimeLiner project management system, enabling AI clients to manage projects, tasks, members, and more via natural language.Last updated
- Alicense-qualityDmaintenanceAn MCP server for time tracking and billing that allows freelancers to control timers, manage projects, and export invoices via natural language in any MCP-compatible AI assistant.Last updated3MIT
Related MCP Connectors
MCP server for generating rough-draft project plans from natural-language prompts.
MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Gestazion2023/paymo-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server