Projonatics MCP Server
Exposes the Projonatics API to Claude Code (or any MCP client) as tools: read clients, projects, tasks, milestones, payment milestones, financial summaries, dashboard and alerts, and — unless registered read-only — create and update them too.
It talks to a running Projonatics backend over HTTPS using a personal API token, so it sees and can change exactly what that user can in the app (role-based scoping applies), and every change is recorded in the audit log under that user.
1. Get an API token
In the app: open your profile menu (top right) → Claude Code (MCP) → Generate token. The key is shown once.
Or mint one on the server:
# production (docker)
docker compose -f docker-compose.prod.yml exec backend python manage.py drf_create_token you@company.com
# local
cd backend && python manage.py drf_create_token you@company.com
GET /api/me/api-token/ reports whether a token exists; DELETE revokes it; POST again rotates it.
2. Register with Claude Code
Published on PyPI as projonatics-mcp; uvx installs it on first run:
claude mcp add -s user projonatics \
-e PROJONATICS_URL=https://<your-domain> \
-e PROJONATICS_TOKEN=<token> \
-- uvx projonatics-mcp
From a local clone (development): -- uv run --directory /absolute/path/to/projonatics/mcp projonatics-mcp.
To pick up a newer release: uv cache clean projonatics-mcp and restart Claude Code.
Check with claude mcp get projonatics. Re-run claude mcp remove projonatics -s user then add to change the URL or token.
Read-only mode
Add PROJONATICS_READ_ONLY=1 to register only the read tools (Claude cannot create, edit or delete anything):
claude mcp add -s user projonatics \
-e PROJONATICS_URL=https://<your-domain> \
-e PROJONATICS_TOKEN=<token> \
-e PROJONATICS_READ_ONLY=1 \
-- uvx projonatics-mcp
This is a client-side switch: it decides which tools the server offers, not what the token can do. Accepted values: 1, true, yes, on.
Tools
Read tools
| Tool | What it returns |
|---|---|
whoami |
User the token belongs to (id, email, role) |
list_clients |
All clients |
list_projects(client_id?) |
Projects visible to the user |
get_project(project_id) |
Full project detail |
list_milestones(project_id?) |
Work milestones |
list_tasks(project_id?, status?, assignee_id?, assigned_to_me?, ordering?) |
Tasks with filters |
get_task(task_id) |
One task |
get_project_financials(project_id) |
Revenue vs cost summary, payment milestones, cost breakdown (admin) |
list_payment_milestones(project_id?) |
Invoicing schedule |
get_dashboard |
Metrics, pulse and per-group counts (small) |
get_todays_focus(group?) |
Today's focus lists: blocked, overdue, due_today, due_this_week, ongoing, at_risk_projects |
get_pending_payments(bucket?) |
Unpaid payment milestones: overdue, upcoming, ready_to_invoice (admin) |
get_alerts |
Overdue tasks, upcoming milestones, overdue payments, budget warnings, ready-to-invoice |
list_team_members |
Team roster |
estimate_cost(project_id, num_engineers, num_days) |
Cost estimate (admin) |
export_data(dataset, …) |
CSV text of the financials / project-financials / workload / tasks export (admin) |
Write tools
Not registered when PROJONATICS_READ_ONLY is set. Update tools change only the fields you pass; pass '' to clear a nullable field. Money is passed as decimal strings, dates as YYYY-MM-DD.
| Tool | What it does | Role |
|---|---|---|
create_task(milestone_id, title, …) |
New task under a work milestone (assignee, collaborators, dates, status, type) | admin, user |
update_task(task_id, …) |
Change status/assignee/dates/blocker note, or move to another milestone | admin, user |
delete_task(task_id, confirm) |
Permanent delete; refuses unless confirm=true |
admin, user |
create_milestone(project_id, name, …) |
New work milestone; amount sets its paired payment milestone |
admin, user |
update_milestone(milestone_id, …) |
Rename, due date, sequence, amount. Status is derived from tasks and not settable | admin, user |
delete_milestone(milestone_id, confirm) |
Permanent delete of the milestone, all its tasks and its payment milestone; refuses unless confirm=true |
admin, user |
create_client(name, …) / update_client(client_id, …) |
Client contact details | admin |
create_project(client_id, name, …) |
New project under a client (status, type, category, rate, budget, leads) | admin |
update_project(project_id, …) |
Change project fields; a manday_rate change is tracked in rate history |
admin |
archive_project(project_id, archived=true) |
Archive / un-archive (preferred over deleting) | admin |
plan_project(client_id, name, milestones, …) |
Create a project with all its milestones (and their tasks) atomically in one call | admin |
reschedule_project(project_id, shift_days) |
Shift every date on a project by N days (unpaid payment dates included, received ones untouched) | admin |
delete_project(project_id, confirm) |
Permanent delete of the project, all its milestones, tasks and payment milestones; refuses unless confirm=true |
admin |
delete_client(client_id, confirm) |
Permanent delete; the API answers 409 while the client still has projects; refuses unless confirm=true |
admin |
update_payment_milestone(payment_milestone_id, …) |
Name, amount, expected date | admin |
mark_payment_received(payment_milestone_id, received_date, received=true) |
Record (or reverse) a payment | admin |
create_team_member(email, job_title, monthly_salary, …) |
Add a team member (creates a viewer login if the email is new) | admin |
update_team_member(team_member_id, …) |
Display name, job title, salary | admin |
deactivate_team_member(team_member_id, active=false) |
Deactivate / reactivate (team members are never deleted) | admin |
The token's role is enforced by the API: a viewer token gets 403 on every write, a user
token can write tasks and milestones on its projects, admins can write everything. The error
message says which role is needed. Every tool carries MCP annotations (readOnlyHint,
destructiveHint), so clients such as Claude Code can ask for confirmation appropriately.
Development
cd mcp
uv sync
uv run pytest
Tests mock the HTTP transport; no backend needed.
Releasing
Bump version in pyproject.toml, commit, then tag and push:
git tag mcp-v0.2.0 && git push origin mcp-v0.2.0
.github/workflows/publish-mcp.yml runs the tests, builds, and publishes to PyPI via trusted publishing.
Metadata
Release files for projonatics-mcp 0.4.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| projonatics_mcp-0.4.0.tar.gz | 13.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| projonatics_mcp-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.5 kB
Release files / projonatics_mcp-0.4.0.tar.gz
| Download URL | projonatics_mcp-0.4.0.tar.gz |
|---|---|
| Size | 13.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
19049d55993429cf413ebc82120fb50607e043bb93c3b9b4372021be302fa82e
|
|
BLAKE2b-256 checksum How to use checksums |
92405804936e8e8e61ee284a151e6b64ffd4a0779cc3af72c35f480609db8135
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency logRelease files / projonatics_mcp-0.4.0-py3-none-any.whl
| Download URL | projonatics_mcp-0.4.0-py3-none-any.whl |
|---|---|
| Size | 14.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
066c037d289828384af84740e53adece9ef5bda8546fe89da0623a6ccba97077
|
|
BLAKE2b-256 checksum How to use checksums |
bdbe5d493a6fdaee4e0ccb4a6765ad1f5814c6657df2a6761647318ec58c0d5b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 27, 2026.
Transparency log