Skip to navigation

MCP server

Connect Claude, Codex, or another MCP client to your Lucanto workspace
View as Markdown

Lucanto ships a built-in Model Context Protocol server, so AI agents can read and act on your workspace data — invoices and other documents, expenses, contacts, projects, bank transactions — with the same scopes as the REST API.

  • Endpoint: POST https://app.lucanto.eu/api/mcp/v1
  • Transport: Streamable HTTP (stateless)
  • Auth: OAuth 2.1 sign-in (Claude), or Authorization: Bearer lct_pat_... / Bearer lct_live_...

How you connect depends on the client:

ClientConnects with
Claude: web, Desktop, mobile, CoworkOAuth sign-in
Claude CodePersonal access token
Codex: CLI, IDE extension, appPersonal access token
ChatGPTNot supported yet

Any other MCP client that speaks Streamable HTTP and can send a custom Authorization header connects the same way as Claude Code and Codex.

Once connected, ask: “List my Lucanto workspaces” — the agent calls lucanto_list_workspaces and goes from there.

Claude

Claude on the web, in Claude Desktop, on mobile and in Cowork signs you in instead of taking a token. Add Lucanto once as a custom connector. Claude Desktop adds remote servers the same way, through Connectors, not through claude_desktop_config.json.

  1. Open Customize > Connectors, click Add, and choose Add custom connector. Team and Enterprise owners add it under Organization settings > Connectors > Add > Custom > Web; members then connect from Customize > Connectors.
  2. Enter Lucanto as the Name and https://app.lucanto.eu/api/mcp/v1 as the MCP server URL, then click Continue. If Claude asks which OAuth client to use, keep Use Claude’s published identity. Lucanto has no dynamic registration endpoint, so don’t pick Register automatically.
  3. Sign in to Lucanto and approve the requested access. What you grant is capped by your workspace role, exactly like a personal access token.

Free plans allow one custom connector.

The connection appears in Lucanto under Settings > Personal API access, where you can revoke it; it expires after one year. OAuth tokens issued this way work only on the MCP endpoint, not on the REST API.

Claude Code

Claude Code sends a personal access token as a header. Create one with the scopes you want the agent to have, then add the server:

claude mcp add --transport http lucanto https://app.lucanto.eu/api/mcp/v1 \
--header "Authorization: Bearer lct_pat_xxxxxxxxxxxx"

By default the server is stored for you and the current project only. Add --scope user to use it in every project. Run claude mcp list — Lucanto should read Connected — or /mcp inside a session. A 401 means the token is invalid or revoked. While an Authorization header is set, Claude Code does not fall back to an OAuth sign-in.

To share the server with your team through .mcp.json, keep the token out of the file and let each person supply it from their own environment:

{
"mcpServers": {
"lucanto": {
"type": "http",
"url": "https://app.lucanto.eu/api/mcp/v1",
"headers": {
"Authorization": "Bearer ${LUCANTO_TOKEN}"
}
}
}
}

Codex

Codex reads the token from an environment variable, so it never lands in a config file. The CLI, the IDE extension and the Codex app share one configuration. Create a personal access token, then:

export LUCANTO_TOKEN=lct_pat_xxxxxxxxxxxx
codex mcp add lucanto --url https://app.lucanto.eu/api/mcp/v1 \
--bearer-token-env-var LUCANTO_TOKEN

This writes the server to ~/.codex/config.toml:

[mcp_servers.lucanto]
url = "https://app.lucanto.eu/api/mcp/v1"
bearer_token_env_var = "LUCANTO_TOKEN"

codex mcp list shows Lucanto with Bearer token under Auth. Set the variable in the environment that starts Codex: a desktop app launched outside your terminal may not see variables exported in your shell profile. Don’t run codex mcp login lucanto; that starts an OAuth flow Lucanto does not offer to Codex.

ChatGPT

ChatGPT can’t connect to Lucanto yet. It signs in to custom MCP servers with OAuth only and has no field for a personal access token, and Lucanto’s OAuth sign-in currently recognizes only Claude’s client identity. Use Claude or Codex for now.

Tools & scopes

The tool catalog is filtered by your token’s scopes — a read:invoices token never sees write tools. Tool execution and returned records are also limited by the user’s current workspace role, so an employee sees only its own records and a suspended membership cannot resolve the workspace.

Tools that reach a customer, update external records, or cannot be undone declare destructiveHint: true (e.g. lucanto_delete_invoice, lucanto_cancel_*, lucanto_send_*, lucanto_mark_*_paid, lucanto_correct_transaction) so client interfaces can prompt for user confirmation.

Sending tools (lucanto_send_invoice, lucanto_send_proforma, lucanto_send_credit_note, lucanto_send_quote) follow the workspace’s plan and trial send limits, and return a subscription error when a limit is reached.

Every list tool paginates with cursor / next_cursor (25 per page, 100 max).

AreaToolsScope
Workspaceslucanto_list_workspaces, lucanto_get_workspacenone
Invoiceslucanto_list_invoices, lucanto_get_invoice, lucanto_get_invoice_pdf_urlread:invoices
lucanto_create_invoice, lucanto_update_invoicewrite:invoices
lucanto_issue_invoice, lucanto_mark_invoice_sent, lucanto_cancel_invoice, lucanto_lock_invoice, lucanto_reopen_invoice, lucanto_mark_invoice_paid, lucanto_send_invoice, lucanto_delete_invoicemanage:invoices
Quoteslucanto_list_quotes, lucanto_get_quoteread:quotes
lucanto_create_quote, lucanto_update_quotewrite:quotes
lucanto_mark_quote_sent, lucanto_accept_quote, lucanto_reject_quote, lucanto_lock_quote, lucanto_reopen_quote, lucanto_send_quotemanage:quotes
Proformaslucanto_list_proformas, lucanto_get_proformaread:proformas
lucanto_create_proforma, lucanto_update_proformawrite:proformas
lucanto_issue_proforma, lucanto_mark_proforma_sent, lucanto_cancel_proforma, lucanto_lock_proforma, lucanto_reopen_proforma, lucanto_mark_proforma_paid, lucanto_send_proformamanage:proformas
Credit noteslucanto_list_credit_notes, lucanto_get_credit_noteread:credit_notes
lucanto_create_credit_note, lucanto_update_credit_notewrite:credit_notes
lucanto_issue_credit_note, lucanto_mark_credit_note_sent, lucanto_lock_credit_note, lucanto_reopen_credit_note, lucanto_send_credit_notemanage:credit_notes
Sales orderslucanto_list_sales_orders, lucanto_get_sales_orderread:sales_orders
Expenseslucanto_list_expenses, lucanto_get_expense, lucanto_get_expense_extraction_proposal, lucanto_get_expense_extraction_statusread:expenses
lucanto_create_expense, lucanto_update_expense, lucanto_prepare_expense_uploads, lucanto_upload_expense_documents, lucanto_open_expense_uploadwrite:expenses
lucanto_apply_expense_extraction_proposal, lucanto_dismiss_expense_extraction_proposalmanage:expenses
Projectslucanto_list_projects, lucanto_get_projectread:projects
lucanto_create_project, lucanto_update_projectwrite:projects
Contactslucanto_list_contacts, lucanto_get_contactread:contacts
lucanto_create_contact, lucanto_update_contactwrite:contacts
lucanto_lookup_companyread:contacts
Document settings & Profilelucanto_get_document_settings, lucanto_get_company_register_checkread:document_settings
lucanto_update_document_settings, lucanto_dismiss_company_register_check, lucanto_update_company_profilewrite:document_settings
Bank accountslucanto_list_bank_accounts, lucanto_get_bank_account, lucanto_list_bank_statements, lucanto_get_bank_statement, lucanto_list_bank_statement_entries, lucanto_get_bank_sync_historyread:bank_accounts
lucanto_import_bank_statement, lucanto_update_bank_statement, lucanto_update_bank_statement_entry, lucanto_import_bank_statement_entries, lucanto_skip_bank_statement_entries, lucanto_unskip_bank_statement_entries, lucanto_preview_bank_statement_csv, lucanto_import_bank_statement_csv, lucanto_request_bank_history_backfillmanage:bank_accounts
Transactionslucanto_list_transactions, lucanto_get_transaction, lucanto_suggest_transaction_matchesread:transactions
lucanto_match_transaction, lucanto_unmatch_transactionwrite:transactions (plus write on the matched record’s type)
lucanto_correct_transactionmanage:transactions
Loanslucanto_list_loans, lucanto_get_loan, lucanto_get_loan_scheduleread:loans

lucanto_lookup_company searches a public register before creating a contact:

  • SK, CZ, VN, FR, CH, DE, GB by registration number or name (ORSR, ARES, VN register, Recherche d’entreprises, Swiss UID register, OpenRegister, Companies House).
  • RO by CUI (ANAF); PL by NIP, REGON, or KRS (GUS REGON).
  • Other EU countries (except Spain) by full VAT ID through EU VIES (marked "source": "vies").

Lookups return the same records as GET /registry/lookup. A “register unavailable” answer (502) never means “no such company”. Lookups count against the workspace’s daily allowance: 100 on Free, 300 during a trial, 1,000 on paid plans. Once spent, the tool reports registry_lookup_limit until the daily reset.

lucanto_get_invoice_pdf_url names the file .isdoc.pdf when the invoice is served as an ISDOC.PDF.

Start with a narrowly-scoped token. Give an agent read:* to explore, and only grant write/manage scopes once you trust the workflow.