SolidInvoice MCP

Create and send invoices and quotes, manage clients, record payments, and check what's overdue in SolidInvoice, all from your AI assistant.

호스팅형 MCP 서버

npx add-mcp 'https://solidinvoice.app/_mcp'

Claude Code, Codex, Cursor 등에 설치됩니다

문서

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.

DeploymentURL Cloud SaaS https://solidinvoice.app/_mcp Self-hosted https://<your-solidinvoice-host>/_mcp
Cloud SaaShttps://solidinvoice.app/_mcp
Self-hostedhttps://<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 localhost works 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:

  1. The agent discovers SolidInvoice's OAuth endpoints from /.well-known/oauth-authorization-server and registers itself dynamically.
  2. Your browser opens to the SolidInvoice consent page. Sign in if you aren't already.
  3. 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:read is always enabled; mcp:write is opt-in and only shown if the agent asked for it.
  4. 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-acme and solidinvoice-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)

ToolWhat 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_resourceList records of any resource (invoice, quote, client, contact, payment, tax, recurring invoice) with filters and pagination.
get_resourceFetch a single record by ID.
list_invoices_by_statusList invoices filtered by status (draft, pending, paid, overdue, etc.).
list_overdue_invoicesList overdue invoices, optionally for a specific client.
list_quotes_by_statusList quotes filtered by status.
list_recurring_invoicesList recurring invoices, optionally filtered by status and/or client.
list_payment_methodsList configured payment methods for the active company.
list_tax_ratesList tax rates configured for the active company.
list_workflow_transitionsList workflow transitions currently enabled on a record.
get_company_infoReturn id, name, and default currency for the active company.
get_client_summaryTotals invoiced, outstanding balance, total paid, and counts for a client.
get_dashboard_statsOutstanding/overdue totals per currency, invoice counts by status, client count.
get_invoice_status_distributionCount of invoices grouped by status.
get_revenue_by_periodRevenue from captured payments between two dates, grouped by day/week/month.
get_total_outstandingTotal outstanding invoiced amounts per currency, optionally filtered by client.
get_total_overdueTotal overdue invoiced amounts per currency, optionally filtered by client.

Write tools (mcp:write)

ToolWhat 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_resourceCreate a flat resource — client, contact, or tax.
update_resourceUpdate scalar fields on an existing client, contact, or tax.
delete_resourceDelete a client, contact, or tax.
create_invoiceCreate an invoice for a client with line items, optional discount, due date, and contacts.
create_quoteCreate a quote for a client with line items, optional discount, due date, and contacts.
create_recurring_invoiceCreate a recurring invoice on a daily, weekly, monthly, or yearly cadence.
clone_invoiceClone an existing invoice into a new draft with the same line items.
clone_quoteClone an existing quote into a new draft with the same line items.
convert_quote_to_invoiceConvert a quote into a new invoice, copying client, line items, and totals.
apply_invoice_transitionApply a workflow transition (accept, cancel, overdue, pay, reopen, archive) to an invoice.
apply_quote_transitionApply a workflow transition (send, accept, decline, cancel, reopen, archive) to a quote.
apply_recurring_transitionApply a workflow transition to a recurring invoice.
record_paymentRecord 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_contactAdd a contact (email + optional name) to an existing client.
send_invoice_reminderEmail 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_id an 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_token and 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:generate once; 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:migrate to 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
StoreWhen 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.
fileDefault. Single-node deployments.
memoryLocal development only — sessions reset on every worker restart.
cacheMulti-node deployments. Point SOLIDINVOICE_MCP_SESSION_CACHE_POOL at a Redis pool.
frameworkRe-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 from Profile → Connected apps and reconnect, making sure the agent requests mcp:write and you tick the write checkbox on the consent screen.

[!-info] -info Requests started returning 401 invalid_token

The token expired or was revoked. Most agents refresh automatically; if not, reconnect from the agent's MCP settings. Check Profile → Connected apps to 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 / https or hostname mismatches between the configured URL and the redirect target will break the flow.