Skip to main content
Glama
Invoice Ninja MCP Server

Invoice Ninja MCP Server

by TETRA-2023

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

a-wiseguy/invoiceninja-mcp (Python)

Read-only; writes never implemented; pinned to one IN build

invoice-ninja-mcp-server (npm)

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_task appends an open entry; in_stop_task closes it. A task with an open entry is running.

  • After the fact: in_log_time appends a completed session — pass start + end, or start + duration_minutes.

  • Seed on creation: in_create_task can take time_entries up front.

  • Bill it: in_task_action with action: "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 build

Get 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-mcp

The 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:http

Listens 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_TOKEN unless it listens on the loopback; the bearer is compared in constant time.

  • Write tools carry destructiveHint annotations so the host can prompt before executing lifecycle actions.

  • Reminder: updating a client requires resending the full contacts array (with each contact id) — Invoice Ninja replaces contacts wholesale. The in_update_client description states this; honour it or you'll drop contacts.

Configuration reference

Env var

Default

Purpose

INVOICE_NINJA_URL

— (required)

Instance base URL, no /api/v1 (an internal http:// address is fine)

INVOICE_NINJA_TOKEN

— (required)

Company API token

INVOICE_NINJA_SECRET

—

Optional X-Api-Secret

INVOICE_NINJA_ALLOW_WRITES

false

Enable mutating tools

INVOICE_NINJA_SAFE_MODE

false

With writes on, leave out sending, settling, cancelling, deleting and payments

INVOICE_NINJA_DISABLED_TOOLS

—

Tool names never registered, comma-separated

INVOICE_NINJA_MAX_PER_PAGE

100

Cap on rows per list call

INVOICE_NINJA_TIMEOUT_MS

30000

Per-request timeout

PORT / HOST

8787 / 127.0.0.1

HTTP transport bind

MCP_BEARER_TOKEN

—

Bearer auth for HTTP transport; required unless HOST is a loopback address

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)

  • outputSchema on 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 and INVOICE_NINJA_REQUIRE_REQUEST_CREDENTIALS are removed);

  • no in_upload_document tool;

  • bearer required off the loopback, compared in constant time;

  • image published to ghcr.io/tetra-2023/invoiceninja-mcp by 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.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    MCP server for Invoice Ninja v5 API. Enables AI assistants to manage clients, invoices, quotes, payments, and time tracking through natural language.
    32
    28 npm
    2
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Hosted 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.
    -
  • A
    license
    B
    quality
    A
    maintenance
    Enables 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.
    23
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables 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.
    33
    GPL 3.0