Invoice Ninja MCP Server
Provides read and optional write access to an Invoice Ninja v5 instance, including tools for clients, invoices, quotes, payments, products, expenses, tasks, projects, time tracking, and outstanding AR summaries. Write operations are gated by configuration and can be restricted through safe mode or a disabled-tools list.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Invoice Ninja MCP Server
A self-hosted MCP server for Invoice Ninja v5 — built to talk only to your instance, with no third-party SaaS bridge in the data path. Runs locally over stdio (Claude Desktop / Claude Code) or remotely over streamable HTTP on your own box (e.g. Exoscale Zürich).
Why this exists
The existing options all have a catch:
Option | Problem for a sovereignty-first setup |
Zapier / viaSocket / Pipedream MCP | Hosted on US infra, per-call task billing — your invoice data transits a third party |
| Read-only; writes never implemented; pinned to one IN build |
| Single unverified v1.0.0 release |
Official IN MCP | Requested (issue #11843) but does not exist yet |
This server is standalone (no modification to Invoice Ninja), covers read + write, gates all mutations behind an explicit flag, and deploys anywhere Node runs.
The story behind it — why a chat-driven invoicing workflow, what the write-gating looks like in daily use, and Invoice Ninja REST API examples in curl and Python — is in the blog post Automate invoicing with MCP: my Invoice Ninja server (German: Buchhaltung automatisieren mit MCP).
Related MCP server: invox-mcp
Tools
Read (always on):
in_ping, in_list_clients, in_get_client, in_list_invoices, in_get_invoice,
in_list_quotes, in_list_payments, in_list_products, in_list_expenses,
in_outstanding_summary (aggregated AR / overdue totals + top debtors),
in_list_tasks, in_get_task, in_list_projects.
Write (only when INVOICE_NINJA_ALLOW_WRITES=true):
in_create_client, in_update_client, in_create_invoice, in_invoice_action
(mark_sent / mark_paid / archive / restore / delete / cancel / email),
in_create_payment, in_create_quote, in_create_product, in_create_expense,
in_create_task, in_start_task, in_stop_task, in_log_time, in_task_action
(archive / restore / delete / invoice), in_create_project.
List results are projected to key fields to keep model context lean; use the
in_get_* tools for full records.
Safe mode and a deny list. INVOICE_NINJA_SAFE_MODE=true keeps writes on but leaves out
in_invoice_action, in_quote_action and in_create_payment, and narrows in_task_action to
archive and restore: the model prepares drafts, clients, expenses, tasks and time entries, and
people send, settle, cancel and delete in Invoice Ninja. INVOICE_NINJA_DISABLED_TOOLS names
further tools to leave out, comma-separated. in_ping reports safe_mode next to writes_enabled,
and the token's company (company: {id, name}) where the instance tells.
Time tracking
Invoice Ninja tracks work time through Tasks (a task is a time entry billed at an hourly rate), optionally grouped under Projects. This server exposes the full loop:
Live timer:
in_start_taskappends an open entry;in_stop_taskcloses it. A task with an open entry is running.After the fact:
in_log_timeappends a completed session — passstart+end, orstart+duration_minutes.Seed on creation:
in_create_taskcan taketime_entriesup front.Bill it:
in_task_actionwithaction: "invoice"turns tracked time into an invoice line item.
Read tools decode the raw time_log for you and add tracked_seconds,
tracked_hms (e.g. "1h 30m") and a running flag. Internally, time_log is a
JSON string of [start_epoch, end_epoch] pairs with end = 0 meaning still
running — the server handles that encoding, you work in plain timestamps.
Note: starting/stopping/logging time are writes, so they require
INVOICE_NINJA_ALLOW_WRITES=true.
Setup
npm install
cp .env.example .env # fill in INVOICE_NINJA_URL + INVOICE_NINJA_TOKEN
npm run buildGet the token in Invoice Ninja under Settings → Account Management →
Integrations → API Tokens. INVOICE_NINJA_URL is the bare instance URL — do
not append /api/v1 (it's added for you).
Claude Desktop (stdio)
claude_desktop_config.json:
{
"mcpServers": {
"invoiceninja": {
"command": "node",
"args": ["/abs/path/to/invoiceninja-mcp/dist/index.js"],
"env": {
"INVOICE_NINJA_URL": "https://invoicing.example.ch",
"INVOICE_NINJA_TOKEN": "your-company-token",
"INVOICE_NINJA_ALLOW_WRITES": "false"
}
}
}
}Claude Code
claude mcp add invoiceninja -- node /abs/path/to/invoiceninja-mcp/dist/index.js(set the env vars in the shell or via --env flags)
Container
docker build -t invoiceninja-mcp .
docker run --rm -p 8787:8787 -e HOST=0.0.0.0 -e INVOICE_NINJA_URL=https://invoicing.example.ch \
-e INVOICE_NINJA_TOKEN=... -e INVOICE_NINJA_ALLOW_WRITES=true -e INVOICE_NINJA_SAFE_MODE=true \
-e MCP_BEARER_TOKEN=... invoiceninja-mcpThe image runs node dist/http.js as a non-root user (UID 10001), writes nothing to disk (run it with
a read-only root filesystem) and answers /healthz. CI publishes ghcr.io/tetra-2023/invoiceninja-mcp
with the tags main and sha-<7> from every merge to main, after a container smoke test; pin the digest.
Remote (streamable HTTP, self-hosted)
MCP_BEARER_TOKEN="$(openssl rand -hex 32)" npm run start:httpListens on 127.0.0.1:8787/mcp with /healthz for probes. Terminate TLS at your
proxy. Caddy example:
invoicing-mcp.example.ch {
reverse_proxy 127.0.0.1:8787
}Always set MCP_BEARER_TOKEN for remote exposure — clients send
Authorization: Bearer <token>.
Safety model
Writes are off by default. Read-only is the safe baseline.
The Invoice Ninja address and token come only from the environment; request headers never change the configuration.
No tool reads the server's filesystem (there is no document-upload tool).
Over HTTP, the server refuses to start without
MCP_BEARER_TOKENunless it listens on the loopback; the bearer is compared in constant time.Write tools carry
destructiveHintannotations so the host can prompt before executing lifecycle actions.Reminder: updating a client requires resending the full
contactsarray (with each contactid) — Invoice Ninja replaces contacts wholesale. Thein_update_clientdescription states this; honour it or you'll drop contacts.
Configuration reference
Env var | Default | Purpose |
| — (required) | Instance base URL, no |
| — (required) | Company API token |
| — | Optional |
|
| Enable mutating tools |
|
| With writes on, leave out sending, settling, cancelling, deleting and payments |
| — | Tool names never registered, comma-separated |
|
| Cap on rows per list call |
|
| Per-request timeout |
|
| HTTP transport bind |
| — | Bearer auth for HTTP transport; required unless |
Alternative: bake it into Laravel
Since Invoice Ninja is itself Laravel and laravel/mcp now exists, you could
instead expose these tools from a Laravel control plane and reuse Invoice Ninja's
own models/policies. That couples you to the IN codebase and its release cadence.
This standalone server stays decoupled and works against hosted or self-hosted
instances alike — generally the better choice unless you're already extending IN
in-process.
Roadmap
Recurring invoices + subscriptions
Per-project time & budget reporting (hours logged vs budgeted_hours)
Tax-period reporting tool (quarterly VAT)
outputSchemaon tools for structured-content clients
Origin & Acknowledgments
This repository began as a copy of halviclabs/invoiceninja-mcp at commit 6e51f1d (v0.3.0, 2026-11-04), MIT License, Copyright (c) 2026 Halvic Labs. All credit for the Invoice Ninja API mapping, the tools, the safe mode and the stateless HTTP transport belongs to that project.
This fork is disconnected from upstream. It is deployed by TETRA as a single-instance server behind an MCP gateway and differs from upstream on purpose:
configuration from the environment only (the per-request
X-Invoice-Ninja-*credential headers andINVOICE_NINJA_REQUIRE_REQUEST_CREDENTIALSare removed);no
in_upload_documenttool;bearer required off the loopback, compared in constant time;
image published to
ghcr.io/tetra-2023/invoiceninja-mcpby this repo's CI.
Upstream changes are picked up manually when needed.
License
MIT (see LICENSE).
Original author
Built by Halvic Labs — a Swiss AI-engineering workshop. More on building MCP servers: Write your first MCP server.
MIT licensed.
This server cannot be deployed
Maintenance
Related MCP Connectors
Manage Invoice Ninja clients, invoices, quotes, expenses, tasks and projects.
Free hosted MCP for invoices, estimates, clients, items and PDFs. OAuth authorization required.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- AlicenseBqualityDmaintenanceMCP server for Invoice Ninja v5 API. Enables AI assistants to manage clients, invoices, quotes, payments, and time tracking through natural language.3228 npm2MIT
- FlicenseNot gradedqualityCmaintenanceHosted MCP server that enables AI assistants to manage clients, invoices, and expenses via the Invox API, supporting actions like drafting, sending, cancelling, and marking invoices as paid, as well as logging expenses and updating client information.-
- AlicenseBqualityAmaintenanceEnables managing invoices, estimates, customers, and dashboard/account data in a self-hosted invoicing system through 23 MCP tools, while automatically handling undocumented required API fields on writes.23MIT
- AlicenseAqualityBmaintenanceEnables LLM agents and MCP clients to interact with the Blesta billing API. It provides read-only tools for searching clients, invoices, services, transactions, and payment accounts, plus optional write tools for creating invoices, managing services, recording payments, and generating customer-facing payment links.33GPL 3.0