SolidInvoice MCP
Create and send invoices and quotes, manage clients, record payments, and check what's overdue in SolidInvoice, all from your AI assistant.
Barındırılan MCP Sunucusu
npx add-mcp 'https://solidinvoice.app/_mcp'Claude Code, Codex, Cursor ve daha fazlasına kurulur
Dokümantasyon
SolidInvoice ships with a built-in Model Context Protocol (MCP) server. Once you connect an AI agent to it, the agent can read your invoices, quotes, clients, and payments — and, if you grant write access, create and update them on your behalf.
Every connection is bound to a single company at consent time and authenticated with OAuth 2.1. An agent connected to Company A can never see Company B's data, even if you belong to both.
Endpoint URL
The MCP server is always served at the path /_mcp on your SolidInvoice instance.
| Deployment | URL Cloud SaaS https://solidinvoice.app/_mcp Self-hosted https://<your-solidinvoice-host>/_mcp |
|---|---|
| Cloud SaaS | https://solidinvoice.app/_mcp |
| Self-hosted | https://<your-solidinvoice-host>/_mcp |
[!-info] -info info
The transport is Streamable HTTP (the standard remote-MCP transport), not stdio. Any agent that supports remote MCP servers with OAuth can connect — no proxy or wrapper script is required.
[!-warning] -warning warning
A self-hosted instance must be reachable over HTTPS for OAuth to work. The flow involves browser redirects, so
localhostworks for local testing but a private LAN address generally will not — use a tunnel (Cloudflare Tunnel, ngrok) if you need to expose a dev instance to a hosted agent.
How authorization works
You don't paste API keys anywhere. The first time an agent connects, it walks you through a standard OAuth consent flow:
- The agent discovers SolidInvoice's OAuth endpoints from
/.well-known/oauth-authorization-serverand registers itself dynamically. - Your browser opens to the SolidInvoice consent page. Sign in if you aren't already.
- On the consent screen you choose:
- Which company the agent will act on (if you belong to more than one).
- Which scopes to grant —
mcp:readis always enabled;mcp:writeis opt-in and only shown if the agent asked for it.
- Which scopes to grant —
- Which company the agent will act on (if you belong to more than one).
- After you approve, the agent receives an access token (valid for 24 hours) and a refresh token (valid for 90 days, rotated on each use). Tokens are bound to the company and scopes you chose; nothing about that binding can be changed later without re-consenting.
You can review and revoke any connected agent at any time from Profile → Connected apps (/profile/connected-apps).
Connecting your agent
The exact steps depend on the agent. The URL is always your /_mcp endpoint; everything else is handled by OAuth.
- Claude Desktop
- Claude Code
- Cursor
- Codex CLI
- Goose
- MCP Inspector
- Other agents
In Claude Desktop, open Settings → Connectors → Add custom connector and enter:
- Name:
SolidInvoice - URL:
https://solidinvoice.app/_mcp(or your self-hosted URL)
Claude opens a browser window to complete OAuth. Approve the consent screen and the connector is ready to use in any chat.
[!-success] -success tip
After connecting, ask the agent something like "List my unpaid invoices" or "Show this month's revenue" to verify everything works.
Picking a company
If you belong to multiple companies, the consent screen shows a company picker. The choice is locked into the access token — to point the same agent at a different company, revoke it from Profile → Connected apps and reconnect.
[!-success] -success tip
You can connect the same agent to multiple companies by registering it more than once under different names — for example
solidinvoice-acmeandsolidinvoice-personal. Each registration gets its own consent and its own token, so the agent can act against either company by picking the matching connection.
Available tools
The server exposes a single, consistent toolset across every agent. Tools requiring mcp:write will only succeed if you granted write access at consent time.
Read tools (mcp:read)
| Tool | What it does list_resource List records of any resource (invoice, quote, client, contact, payment, tax, recurring invoice) with filters and pagination. get_resource Fetch a single record by ID. list_invoices_by_status List invoices filtered by status (draft, pending, paid, overdue, etc.). list_overdue_invoices List overdue invoices, optionally for a specific client. list_quotes_by_status List quotes filtered by status. list_recurring_invoices List recurring invoices, optionally filtered by status and/or client. list_payment_methods List configured payment methods for the active company. list_tax_rates List tax rates configured for the active company. list_workflow_transitions List workflow transitions currently enabled on a record. get_company_info Return id, name, and default currency for the active company. get_client_summary Totals invoiced, outstanding balance, total paid, and counts for a client. get_dashboard_stats Outstanding/overdue totals per currency, invoice counts by status, client count. get_invoice_status_distribution Count of invoices grouped by status. get_revenue_by_period Revenue from captured payments between two dates, grouped by day/week/month. get_total_outstanding Total outstanding invoiced amounts per currency, optionally filtered by client. get_total_overdue Total overdue invoiced amounts per currency, optionally filtered by client. |
|---|---|
list_resource | List records of any resource (invoice, quote, client, contact, payment, tax, recurring invoice) with filters and pagination. |
get_resource | Fetch a single record by ID. |
list_invoices_by_status | List invoices filtered by status (draft, pending, paid, overdue, etc.). |
list_overdue_invoices | List overdue invoices, optionally for a specific client. |
list_quotes_by_status | List quotes filtered by status. |
list_recurring_invoices | List recurring invoices, optionally filtered by status and/or client. |
list_payment_methods | List configured payment methods for the active company. |
list_tax_rates | List tax rates configured for the active company. |
list_workflow_transitions | List workflow transitions currently enabled on a record. |
get_company_info | Return id, name, and default currency for the active company. |
get_client_summary | Totals invoiced, outstanding balance, total paid, and counts for a client. |
get_dashboard_stats | Outstanding/overdue totals per currency, invoice counts by status, client count. |
get_invoice_status_distribution | Count of invoices grouped by status. |
get_revenue_by_period | Revenue from captured payments between two dates, grouped by day/week/month. |
get_total_outstanding | Total outstanding invoiced amounts per currency, optionally filtered by client. |
get_total_overdue | Total overdue invoiced amounts per currency, optionally filtered by client. |
Write tools (mcp:write)
| Tool | What it does create_resource Create a flat resource — client, contact, or tax. update_resource Update scalar fields on an existing client, contact, or tax. delete_resource Delete a client, contact, or tax. create_invoice Create an invoice for a client with line items, optional discount, due date, and contacts. create_quote Create a quote for a client with line items, optional discount, due date, and contacts. create_recurring_invoice Create a recurring invoice on a daily, weekly, monthly, or yearly cadence. clone_invoice Clone an existing invoice into a new draft with the same line items. clone_quote Clone an existing quote into a new draft with the same line items. convert_quote_to_invoice Convert a quote into a new invoice, copying client, line items, and totals. apply_invoice_transition Apply a workflow transition (accept, cancel, overdue, pay, reopen, archive) to an invoice. apply_quote_transition Apply a workflow transition (send, accept, decline, cancel, reopen, archive) to a quote. apply_recurring_transition Apply a workflow transition to a recurring invoice. record_payment Record an offline payment (cash by default, or another offline method) against an invoice. The invoice is marked paid once settled, and an overpayment becomes client credit. add_contact Add a contact (email + optional name) to an existing client. send_invoice_reminder Email a manual reminder for an invoice to its contacts. |
|---|---|
create_resource | Create a flat resource — client, contact, or tax. |
update_resource | Update scalar fields on an existing client, contact, or tax. |
delete_resource | Delete a client, contact, or tax. |
create_invoice | Create an invoice for a client with line items, optional discount, due date, and contacts. |
create_quote | Create a quote for a client with line items, optional discount, due date, and contacts. |
create_recurring_invoice | Create a recurring invoice on a daily, weekly, monthly, or yearly cadence. |
clone_invoice | Clone an existing invoice into a new draft with the same line items. |
clone_quote | Clone an existing quote into a new draft with the same line items. |
convert_quote_to_invoice | Convert a quote into a new invoice, copying client, line items, and totals. |
apply_invoice_transition | Apply a workflow transition (accept, cancel, overdue, pay, reopen, archive) to an invoice. |
apply_quote_transition | Apply a workflow transition (send, accept, decline, cancel, reopen, archive) to a quote. |
apply_recurring_transition | Apply a workflow transition to a recurring invoice. |
record_payment | Record an offline payment (cash by default, or another offline method) against an invoice. The invoice is marked paid once settled, and an overpayment becomes client credit. |
add_contact | Add a contact (email + optional name) to an existing client. |
send_invoice_reminder | Email a manual reminder for an invoice to its contacts. |
[!-secondary] -secondary note
The agent always operates as the user who consented, on the company chosen at consent time. Any
company/company_idan agent tries to pass in a write call is ignored — the active company is enforced server-side.
Managing connected apps
Visit /profile/connected-apps while signed in to:
- See every agent that has been authorized, the company it is bound to, and the scopes it holds.
- Revoke an agent. Revocation immediately invalidates its access and refresh tokens; the next request from that agent will fail with
401 invalid_tokenand the user will need to re-consent.
Revoking an agent does not delete its registration, so the same agent can be reconnected later without going through dynamic registration again.
Self-hosted: enabling the server
The MCP server is bundled with SolidInvoice 3.0 and enabled by default. The only one-time prerequisites are:
- OAuth signing keys. Run
bin/console mcp:keys:generateonce; keys are written to$SOLIDINVOICE_CONFIG_DIR/oauth/and survive redeployments. The single-binary launcher (solidinvoice run) does this automatically on first start. - Database migrations. Run
bin/console doctrine:migrations:migrateto create the OAuth and token tables.
For multi-node deployments, switch the MCP session store off the default on-disk backend so sessions survive across nodes:
SOLIDINVOICE_MCP_SESSION_STORE=cache
SOLIDINVOICE_MCP_SESSION_CACHE_POOL=cache.app
| Store | When to use file Default. Single-node deployments. memory Local development only — sessions reset on every worker restart. cache Multi-node deployments. Point SOLIDINVOICE_MCP_SESSION_CACHE_POOL at a Redis pool. framework Re-uses your application's Symfony session handler. |
|---|---|
file | Default. Single-node deployments. |
memory | Local development only — sessions reset on every worker restart. |
cache | Multi-node deployments. Point SOLIDINVOICE_MCP_SESSION_CACHE_POOL at a Redis pool. |
framework | Re-uses your application's Symfony session handler. |
Troubleshooting
[!-info] -info The browser opens but consent fails with "company required"
You belong to multiple companies and didn't pick one. Re-trigger the connection in the agent and select a company on the consent screen.
[!-info] -info Tools that change data return "insufficient scope"
The agent only requested — or you only granted —
mcp:read. Revoke the connection fromProfile → Connected appsand reconnect, making sure the agent requestsmcp:writeand you tick the write checkbox on the consent screen.
[!-info] -info Requests started returning
401 invalid_tokenThe token expired or was revoked. Most agents refresh automatically; if not, reconnect from the agent's MCP settings. Check
Profile → Connected appsto confirm the agent hasn't been revoked.
[!-info] -info Self-hosted: OAuth redirect fails
SolidInvoice must be reachable from the agent's browser over HTTPS at the same hostname the agent was configured with. Mixed
http/httpsor hostname mismatches between the configured URL and the redirect target will break the flow.