Skip to main content

MCP server

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 SaaShttps://solidinvoice.app/_mcp
Self-hostedhttps://<your-solidinvoice-host>/_mcp
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

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.

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.

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.

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_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_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 against an invoice and transition it to paid.
add_contactAdd a contact (email + optional name) to an existing client.
send_invoice_reminderEmail a manual reminder for an invoice to its contacts.
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:

.env.local
SOLIDINVOICE_MCP_SESSION_STORE=cache
SOLIDINVOICE_MCP_SESSION_CACHE_POOL=cache.app
StoreWhen to use
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โ€‹

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.

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.

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.

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.