Model Context Protocol server that exposes the full Jortt accounting API as MCP tools, generated from Jortt's OpenAPI specification. - OAuth 2.0 client-credentials auth with token caching and 401 refresh - 82 tools covering customers, invoices, estimates, expenses, projects, bank accounts, reports, labels, ledger accounts and payroll - Spec fetched at build time (with a runtime fetch fallback), so new API operations become new tools automatically with no code changes - Path/query/body parameters handled automatically; request bodies passed under a single `body` argument with a resolved JSON Schema - Readable, stable snake_case tool names derived from method, path and operation summary Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QhaFvGz9gfRg5qDV3ragu |
||
|---|---|---|
| scripts | ||
| src | ||
| .env.example | ||
| .gitignore | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
jortt-mcp
A Model Context Protocol (MCP) server for the Jortt accounting & invoicing API.
It exposes the full Jortt REST API — customers, invoices, estimates, expenses, projects, bank accounts, reports, and more — as MCP tools, so an MCP-capable assistant (Claude Desktop, Claude Code, etc.) can read and write your Jortt administration on your behalf.
The tools are generated directly from Jortt's published OpenAPI specification, so coverage stays faithful to the API: 82 tools across every documented resource.
How it works
- The build step downloads the Jortt OpenAPI spec to
src/openapi.jsonand bundles it intodist/. On startup the server reads that spec, resolves all schema references, and turns every operation into an MCP tool with a proper JSON Schema for its arguments. (If no bundled spec is found, it fetches one live from Jortt as a fallback.) - Authentication uses the OAuth 2.0 client credentials grant (the flow Jortt
recommends for applications bound to your own administration). The server
fetches a bearer token, caches it until shortly before it expires, and
transparently refreshes on expiry or a
401. - Path parameters, query parameters, and JSON request bodies are all handled
automatically. Request bodies are passed under a single
bodyargument.
Prerequisites
- A Jortt account.
- A registered API application. Create one under Profile → API → OAuth applications, selecting the scopes you want to grant. Registration gives you a Client ID and Client secret.
Installation
git clone https://github.com/deprekated/jortt-mcp.git
cd jortt-mcp
npm install # runs the build, which downloads the current Jortt OpenAPI spec
The build fetches
https://api.jortt.nl/swagger_doc, so it needs outbound network access. SetJORTT_OPENAPI_URLto point at a local copy or mirror if you build offline.
Configuration
The server is configured entirely through environment variables:
| Variable | Required | Description |
|---|---|---|
JORTT_CLIENT_ID |
yes | OAuth client ID of your registered application. |
JORTT_CLIENT_SECRET |
yes | OAuth client secret. |
JORTT_SCOPES |
no | Space-separated scopes to request. Defaults to all scopes; the token server only grants scopes your application was registered with. |
JORTT_OPENAPI_URL |
no | Override the OpenAPI spec source (used at build time and as a runtime fallback). Defaults to https://api.jortt.nl/swagger_doc. |
Claude Desktop / Claude Code
Add the server to your MCP client configuration (for Claude Desktop, this is
claude_desktop_config.json):
{
"mcpServers": {
"jortt": {
"command": "node",
"args": ["/absolute/path/to/jortt-mcp/dist/index.js"],
"env": {
"JORTT_CLIENT_ID": "your-client-id",
"JORTT_CLIENT_SECRET": "your-client-secret"
}
}
}
}
Restrict what the assistant can do by narrowing the scopes:
"env": {
"JORTT_CLIENT_ID": "your-client-id",
"JORTT_CLIENT_SECRET": "your-client-secret",
"JORTT_SCOPES": "invoices:read customers:read reports:read"
}
Tool overview
Tool names follow a predictable verb_resource convention derived from the API
path and version. A selection:
| Tool | Method & path | What it does |
|---|---|---|
list_customers |
GET /customers |
List / search customers |
create_customers |
POST /customers |
Create a customer |
get_customers |
GET /customers/{customer_id} |
Fetch a single customer |
list_invoices |
GET /invoices |
List / search invoices |
create_v3_invoices |
POST /v3/invoices |
Create an invoice (invoice-level VAT) |
send_invoices |
POST /invoices/{id}/send |
Send an invoice |
get_invoices_download |
GET /invoices/{id}/download |
Get a download URL for the invoice PDF |
list_v2_estimates |
GET /v2/estimates |
List estimates |
create_v2_estimates |
POST /v2/estimates |
Create an estimate |
list_v3_expenses |
GET /v3/expenses |
List expenses |
list_v3_bank_accounts |
GET /v3/bank-accounts |
List bank accounts |
get_reports_summaries_profit_and_loss |
GET /reports/summaries/profit_and_loss |
Dashboard profit & loss summary |
get_organizations_me |
GET /organizations/me |
The organization tied to your credentials |
Newer resources are versioned (v2, v3) and the version is part of the tool
name. Where Jortt offers multiple versions of the same operation (for example
invoice creation), prefer the highest version unless you have a reason not to —
create_v3_invoices supports invoice-level VAT.
Run the server and call tools/list to see the full, always-current set with
per-tool argument schemas.
Development
npm run build # compile TypeScript to dist/ (and copy the spec)
npm run dev # tsc --watch
npm run typecheck # type-check without emitting
Updating to the latest API
The tool set is generated from the OpenAPI spec, which the build downloads fresh each time. To pick up new Jortt endpoints, just rebuild:
npm run build
No code changes are needed — new operations become new tools automatically.
Notes & limits
- Jortt rate-limits the API to ~10 requests/second. List endpoints paginate at a
maximum of 100 items per page (
pageargument). - This is an unofficial, community project and is not affiliated with or endorsed by Jortt.
License
MIT — see LICENSE.