SolidInvoice MCP
Create and send invoices and quotes, manage clients, record payments, and check what's overdue in SolidInvoice, all from your AI assistant.
Máy chủ MCP được lưu trữ
npx add-mcp 'https://solidinvoice.app/_mcp'Cài vào Claude Code, Codex, Cursor và nhiều công cụ khác
Tài liệu
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.