# jortt-mcp A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for the [Jortt](https://www.jortt.nl) 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](https://api.jortt.nl/swagger_doc), 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.json` and bundles it into `dist/`. 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 `body` argument. ## Prerequisites 1. A [Jortt account](https://app.jortt.nl/van-start). 2. A registered API application. Create one under **Profile → API** → [OAuth applications](https://app.jortt.nl/new_profile/api/jortt/oauth_applications/list), selecting the scopes you want to grant. Registration gives you a **Client ID** and **Client secret**. ## Installation ```bash 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. Set `JORTT_OPENAPI_URL` to 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`): ```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: ```json "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 ```bash 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: ```bash 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 (`page` argument). - This is an unofficial, community project and is not affiliated with or endorsed by Jortt. ## License MIT — see [LICENSE](LICENSE).