Skip to main content
Glama
mcp-server-smallinvoice

mcp-server-smallinvoice

by AIWerk

@aiwerk/mcp-server-smallinvoice

MCP server for smallinvoice.ch — Swiss SME invoicing and accounting (146 tools, OAuth2 BYOC).

Install

npx -y @aiwerk/mcp-server-smallinvoice

Related MCP server: bexio-mcp

Configure

Variable

Required

Description

SMALLINVOICE_CLIENT_ID

✅

OAuth2 client ID — smallinvoice Home → Users → API V2 → New client

SMALLINVOICE_CLIENT_SECRET

✅

OAuth2 client secret

SMALLINVOICE_REFRESH_TOKEN

✅

Initial refresh token from the OAuth bootstrap flow (rotates per call)

SMALLINVOICE_ACCESS_TOKEN

optional

Pre-loaded access token; lazily refreshed if absent or expired

SMALLINVOICE_TOKEN_FILE

optional

Path to persist rotating tokens (default: ~/.aiwerk/smallinvoice-tokens.json)

SMALLINVOICE_DRY_RUN

optional

Set to 1 to prevent write operations from reaching the API

SMALLINVOICE_NO_SNAPSHOT

optional

Set to 1 to disable pre-write entity snapshots

SMALLINVOICE_SNAPSHOT_DIR

optional

Directory for pre-write snapshots (default: ~/.aiwerk/smallinvoice-snapshots)

SMALLINVOICE_SNAPSHOT_FAIL_OPEN

optional

Set to 1 to log a warning instead of blocking when a snapshot fails

SMALLINVOICE_API_TIMEOUT_MS

optional

Request timeout in ms (default: 30000)

MCP client config example (Claude Desktop / OpenClaw)

{
  "mcpServers": {
    "smallinvoice": {
      "command": "npx",
      "args": ["-y", "@aiwerk/mcp-server-smallinvoice"],
      "env": {
        "SMALLINVOICE_CLIENT_ID": "your-client-id",
        "SMALLINVOICE_CLIENT_SECRET": "your-client-secret",
        "SMALLINVOICE_REFRESH_TOKEN": "your-initial-refresh-token"
      }
    }
  }
}

Auth setup

Requires smallinvoice Starter plan or higher (CHF 15/mo). The free tier blocks API access.

  1. In your smallinvoice account: Home → Users → API V2 → New client

    • Grant type: Authorization Code

    • Redirect URI: http://127.0.0.1:8765/callback (must be registered in the client config)

    • Copy client_id and client_secret

  2. Run the authorization URL in your browser:

    https://api.smallinvoice.com/v2/auth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&scope=profile+contact+contact_reminder+letter+configuration+catalog+invoice+offer+delivery_note+order_confirmation+project+cost_unit+working_hours+activity+effort

    Log in and approve. You receive a code.

  3. Exchange the code for tokens:

    curl -X POST https://api.smallinvoice.com/v2/auth/access-tokens \
      -H 'Content-Type: application/json' \
      -d '{"grant_type":"authorization_code","client_id":"...","client_secret":"...","code":"...","redirect_uri":"http://127.0.0.1:8765/callback"}'

    The response contains access_token and refresh_token.

  4. Set SMALLINVOICE_REFRESH_TOKEN to the returned refresh_token. The server persists new tokens automatically after each refresh.

Token file is source of truth after first refresh. Once the server performs its first token rotation, the persisted SMALLINVOICE_TOKEN_FILE takes priority over SMALLINVOICE_REFRESH_TOKEN env var. If you rotate the refresh token manually, update or delete the token file.

Tools

146 tools total across 6 groups.

Group

Count

Representative tools

auth

2

get_owner, get_profile

contacts

42

list_contacts, get_contact, create_contact, update_contact, delete_contacts; sub-resources: accounts, addresses, people, groups, letters, reminders

catalog

22

list_products, create_product, list_services, create_service; categories (product & service), units

receivables

47

list_invoices, create_invoice, download_invoice_pdf, change_invoice_status, send_invoice_by_email, record_invoice_payment; offers, order-confirmations, delivery-notes, payments, ISRs

reporting

23

list_projects, list_working_hours; efforts, activities, cost-units

configuration

10

list_bank_accounts, create_bank_account; list_exchange_rates, create_exchange_rate

All delete_* tools are marked destructiveHint: true. All list_* / get_* / download_* tools are readOnlyHint: true.

Important notes

Refresh token rotation. Smallinvoice revokes the old refresh token the moment it issues a new one. The server uses atomic write (content fsync + atomic rename + dir fsync best-effort) to persist the new token before using it. If the process crashes after the API rotation but before persist completes, the OAuth chain is broken — re-run the bootstrap flow from step 2 above.

Cross-process refresh safety. Multiple MCP server instances sharing the same token file are protected by an O_EXCL file lock. A double-check after acquiring the lock avoids redundant refreshes when another process already rotated the token.

SMALLINVOICE_DRY_RUN=1. All write tools (create_*, update_*, delete_*, change_*, send_*, record_*) return a stub response without contacting smallinvoice:

{ "_dry_run": true, "_would_call": { "method": "POST", "path": "/receivables/invoices", "body": { ... } } }

Use this when testing against a production account.

Pre-write snapshots. Before each mutating operation, the current entity state is fetched and saved to ~/.aiwerk/smallinvoice-snapshots/. The tool result includes a _snapshot field with the file path.

  • PUT / PATCH — snapshots the entity being updated

  • DELETE — snapshots each entity being deleted (batch-aware: all IDs fetched in parallel, saved as one JSON file with partial-failure tolerance)

  • send_by_email / send_by_post — snapshots the parent document before sending ⚠️ IRREVERSIBLE: sends real email/post — pre-state snapshotted under ~/.aiwerk/smallinvoice-snapshots/

  • Sub-resource POST (e.g. record_invoice_payment, create_contact_account) — snapshots the parent entity before modifying it

Disable snapshots with SMALLINVOICE_NO_SNAPSHOT=1. By default, a snapshot failure blocks the write (fail-closed). Set SMALLINVOICE_SNAPSHOT_FAIL_OPEN=1 to downgrade to a warning and continue.

Rate limit. The actual limit is 360 requests/minute (not 1000 as stated in the public documentation). The server logs a warning to stderr when X-Rate-Limit-Remaining drops below 30.

Date formats. Use YYYY-MM-DD for date fields and YYYY-MM-DD HH:MM:SS for timestamp fields (no timezone — Europe/Zurich assumed).

License

MIT — AIWerk

Available Tools

146 tools
assign_contact_groupsC

Assigns groups to specified contact

Inputs: contact_id (required), groups_ids (required).

change_delivery_note_statusB

Changes status of specified delivery note

Inputs: delivery_note_id (required), status (required), date_time.

change_invoice_statusC

Changes status of specified invoice

Inputs: invoice_id (required), status (required), date_time.

change_letter_statusA

Changes status of specified letter

Inputs: letter_id (required), status (required), date_time.

change_offer_statusC

Changes status of specified offer

Inputs: offer_id (required), status (required), date_time.

change_order_confirmation_statusB

Changes status of specified order confirmation

Inputs: order_confirmation_id (required), status (required), date_time.

change_project_statusA

Updates status for specified project

Inputs: project_id (required), status (required).

create_bank_accountB

Creates new bank account

Inputs: description (required), iban (required), default, bank_name, +3 more.

create_contactC

Creates new contact

Inputs: relation (required), type (required), name (required), main_address (required), +22 more.

create_contact_accountB

Creates new account for specified contact

Inputs: contact_id (required), type (required), number (required), default, +2 more.

create_contact_addressB

Creates new address for specified contact

Inputs: contact_id (required), country (required), street (required), postcode (required), +6 more.

create_contact_groupB

Creates new contact group

Inputs: name (required).

create_contact_personA

Creates new person for specified contact

Inputs: contact_id (required), name (required), surname (required), gender (required), +9 more.

create_cost_unitC

Creates new cost unit

Inputs: name (required), type (required), number, description.

create_delivery_noteC

Creates new delivery note

Inputs: contact_id (required), contact_address_id (required), date (required), currency (required), +15 more.

create_effortC

Creates new effort

Inputs: entity_type (required), entity_id (required), duration (required), date (required), +4 more.

create_exchange_rateC

Creates new currency exchange rate

Inputs: currency_from (required), currency_to (required), rate (required).

create_invoiceC

Creates new invoice

Inputs: contact_id (required), contact_address_id (required), date (required), due (required), +28 more.

create_letterC

Creates new letter

Inputs: contact_id (required), contact_address_id (required), date (required), language (required), +9 more.

create_offerC

Creates new offer

Inputs: contact_id (required), contact_address_id (required), date (required), valid_until (required), +17 more.

create_order_confirmationC

Creates new order confirmation

Inputs: contact_id (required), contact_address_id (required), date (required), currency (required), +15 more.

create_productC

Creates new product

Inputs: name (required), including_vat (required), vat (required), unit_id (required), +8 more.

create_product_categoryB

Creates new product category

Inputs: name (required), accounting_account_number.

create_projectC

Creates new project

Inputs: contact_id (required), name (required), start_date (required), number, +3 more.

create_reminderC

Creates new reminder

Inputs: contact_id (required), date_time (required), title (required), interval_value (required), +2 more.

create_serviceC

Creates new service

Inputs: name (required), including_vat (required), vat (required), unit_id (required), +7 more.

create_service_categoryC

Creates new service category

Inputs: name (required), accounting_account_number.

create_working_hoursA

Creates new working hours entry

Inputs: date (required), time_start (required), time_end (required), user_id.

delete_bank_accountsA
Destructive

Deletes specified bank accounts

Inputs: accounts_ids (required).

delete_contact_accountsC
Destructive

Deletes specified accounts

Inputs: contact_id (required), accounts_ids (required).

delete_contact_addressesB
Destructive

Deletes specified addresses

Inputs: contact_id (required), addresses_ids (required).

delete_contact_groupsC
Destructive

Deletes specified groups

Inputs: groups_ids (required).

delete_contact_peopleB
Destructive

Deletes specified people

Inputs: contact_id (required), people_ids (required).

delete_contactsA
Destructive

Deletes specified contacts

Inputs: contact_ids (required).

delete_cost_unitsB
Destructive

Deletes specified cost units

Inputs: cost_unit_ids (required).

delete_delivery_notesC
Destructive

Deletes specified delivery notes

Inputs: delivery_note_ids (required).

delete_effortsB
Destructive

Deletes specified efforts

Inputs: effort_ids (required).

delete_exchange_ratesA
Destructive

Deletes specified currency exchange rates

Inputs: exchange_ids (required).

delete_invoice_paymentB
Destructive

Deletes specified invoice's payments

Inputs: invoice_id (required), payment_ids (required).

delete_invoicesC
Destructive

Deletes specified invoices

Inputs: invoice_ids (required).

delete_lettersC
Destructive

Deletes specified letters

Inputs: letter_ids (required).

delete_offersA
Destructive

Deletes specified offers

Inputs: offer_ids (required).

delete_order_confirmationsB
Destructive

Deletes specified order confirmations

Inputs: order_confirmation_ids (required).

delete_product_categoriesB
Destructive

Deletes specified product categories

Inputs: category_ids (required).

delete_productsC
Destructive

Deletes specified products

Inputs: product_ids (required).

delete_projectsB
Destructive

Deletes specified projects

Inputs: project_ids (required).

delete_remindersC
Destructive

Deletes reminders

Inputs: reminders_ids (required).

delete_service_categoriesC
Destructive

Deletes specified service categories

Inputs: category_ids (required).

delete_servicesC
Destructive

Deletes specified services

Inputs: service_ids (required).

delete_working_hoursB
Destructive

Deletes specified working hours entries

Inputs: time_ids (required).

download_delivery_note_pdfB
Read-only

Gets pdf of specified delivery note

Inputs: delivery_note_id (required).

download_invoice_pdfA
Read-only

Gets pdf of specified invoice

Inputs: invoice_id (required), options.

download_letter_pdfB
Read-only

Gets pdf of specified letter

Inputs: letter_id (required).

download_offer_pdfC
Read-only

Gets pdf of specified offer

Inputs: offer_id (required).

download_order_confirmation_pdfB
Read-only

Gets pdf of specified order confirmation

Inputs: order_confirmation_id (required).

get_activityA
Read-only

Returns data of specified activity entry

Inputs: activity_id (required), with.

get_bank_accountB
Read-only

Returns data of specified bank account

Inputs: account_id (required), with.

get_contactC
Read-only

Returns data of specified contact

Inputs: contact_id (required), with.

get_contact_accountC
Read-only

Returns data of specified account

Inputs: contact_id (required), account_id (required), with.

get_contact_addressB
Read-only

Returns data of specified address

Inputs: contact_id (required), address_id (required), with.

get_contact_groupB
Read-only

Returns data of specified contact group

Inputs: group_id (required), with.

get_contact_personB
Read-only

Returns data of specified person

Inputs: contact_id (required), person_id (required), with.

get_cost_unitB
Read-only

Returns data of specified cost unit

Inputs: cost_unit_id (required).

get_delivery_noteA
Read-only

Returns data of specified delivery note

Inputs: delivery_note_id (required), with.

get_delivery_note_previewB
Read-only

Gets preview of specified delivery note

Inputs: delivery_note_id (required), page, size.

get_effortB
Read-only

Returns data of specified effort

Inputs: effort_id (required), with.

get_exchange_rateB
Read-only

Returns data of specified currency exchange rate

Inputs: exchange_id (required).

get_invoiceB
Read-only

Returns data of specified invoice

Inputs: invoice_id (required), with.

get_invoice_paymentA
Read-only

Returns data of specified invoice's payment

Inputs: invoice_id (required), payment_id (required), with.

get_invoice_previewB
Read-only

Gets preview of specified invoice

Inputs: invoice_id (required), page, size.

get_isrB
Read-only

Returns data of specified ISR

Inputs: isr_id (required), with.

get_letterB
Read-only

Returns data of specified letter

Inputs: letter_id (required), with.

get_letter_previewB
Read-only

Gets preview of specified letter

Inputs: letter_id (required), page, size.

get_offerB
Read-only

Returns data of specified offer

Inputs: offer_id (required), with.

get_offer_previewB
Read-only

Gets preview of specified offer

Inputs: offer_id (required), page, size.

get_order_confirmationB
Read-only

Returns data of specified order confirmation

Inputs: order_confirmation_id (required), with.

get_order_confirmation_previewB
Read-only

Gets preview of specified order confirmation

Inputs: order_confirmation_id (required), page, size.

get_ownerA
Read-only

Returns data of authenticated resource owner

Inputs: no named parameters.

get_productA
Read-only

Returns data of specified product

Inputs: product_id (required), with.

get_product_categoryA
Read-only

Returns data of specified product category

Inputs: category_id (required), with.

get_profileA
Read-only

Returns data of authenticated user's profile

Inputs: no named parameters.

get_projectB
Read-only

Returns data of specified project

Inputs: project_id (required), with.

get_reminderA
Read-only

Returns data of specified reminder

Inputs: reminder_id (required), with.

get_serviceB
Read-only

Returns data of specified service

Inputs: service_id (required), with.

get_service_categoryB
Read-only

Returns data of specified service category

Inputs: category_id (required), with.

get_unitC
Read-only

Returns data of specified unit

Inputs: unit_id (required), with.

get_working_hoursB
Read-only

Returns data of specified working hours entry

Inputs: time_id (required), with.

list_activitiesB
Read-only

Returns list of activities entries

Inputs: with, q, filter, limit, +1 more.

list_bank_accountsA
Read-only

Returns list of bank accounts

Inputs: with, q, filter, limit, +1 more.

list_contact_accountsB
Read-only

Returns list of accounts for specified contact

Inputs: contact_id (required), with, q, filter, +2 more.

list_contact_addressesB
Read-only

Returns list of addresses for specified contact

Inputs: contact_id (required), with, q, filter, +2 more.

list_contact_groupsC
Read-only

Returns list of contact groups

Inputs: with, q, filter, limit, +1 more.

list_contact_peopleB
Read-only

Returns list of people for specified contact

Inputs: contact_id (required), with, q, filter, +2 more.

list_contactsC
Read-only

Returns list of contacts

Inputs: with, q, filter, limit, +1 more.

list_cost_unitsB
Read-only

Returns list of cost units

Inputs: q, filter, limit, offset.

list_delivery_notesB
Read-only

Returns list of delivery notes

Inputs: with, q, filter, limit, +1 more.

list_effortsC
Read-only

Returns list of efforts

Inputs: with, q, filter, limit, +1 more.

list_exchange_ratesB
Read-only

Returns list of currency exchange rates

Inputs: q, filter, limit, offset.

list_invoice_paymentsA
Read-only

Returns list of payments for specified invoice

Inputs: invoice_id (required), with, q, filter, +2 more.

list_invoicesB
Read-only

Returns list of invoices

Inputs: with, q, filter, limit, +1 more.

list_isrsC
Read-only

Returns list of ISRs

Inputs: with, q, filter, limit, +1 more.

list_lettersB
Read-only

Returns list of letters

Inputs: with, q, filter, limit, +1 more.

list_offersB
Read-only

Returns list of offers

Inputs: with, q, filter, limit, +1 more.

list_order_confirmationsB
Read-only

Returns list of order confirmations

Inputs: with, q, filter, limit, +1 more.

list_product_categoriesB
Read-only

Returns list of product categories

Inputs: with, q, filter, limit, +1 more.

list_productsC
Read-only

Returns list of products

Inputs: with, q, filter, limit, +1 more.

list_projectsB
Read-only

Returns list of projects

Inputs: with, q, filter, limit, +1 more.

list_remindersC
Read-only

Returns list of reminders

Inputs: with, q, filter, limit, +1 more.

list_service_categoriesB
Read-only

Returns list of service categories

Inputs: with, q, filter, limit, +1 more.

list_servicesC
Read-only

Returns list of services

Inputs: with, q, filter, limit, +1 more.

list_unitsB
Read-only

Returns list of units

Inputs: with, q, filter, limit, +1 more.

list_working_hoursB
Read-only

Returns list of working hours entries

Inputs: with, q, filter, limit, +1 more.

record_invoice_paymentA

Creates new payment for specified invoice

Inputs: invoice_id (required), type (required), amount (required), date (required), +2 more.

remove_contact_groupsB

Removes groups from specified contact

Inputs: contact_id (required), groups_ids (required).

send_delivery_note_by_emailA

Sends specified delivery note by email (SENDS REAL EMAIL — irreversible)

Inputs: delivery_note_id (required), subject (required), body (required), recipients (required), +1 more.

send_delivery_note_by_postA

Sends specified delivery note by post (SENDS BY POST — irreversible)

Inputs: delivery_note_id (required), palette (required), print (required), speed (required).

send_invoice_by_emailA

Sends specified invoice by email (SENDS REAL EMAIL — irreversible)

Inputs: invoice_id (required), subject (required), body (required), recipients (required), +2 more.

send_invoice_by_postA

Sends specified invoice by post (SENDS BY POST — irreversible)

Inputs: invoice_id (required), palette (required), print (required), speed (required).

send_letter_by_emailB

Sends specified letter by email (SENDS REAL EMAIL — irreversible)

Inputs: letter_id (required), subject (required), body (required), recipients (required), +1 more.

send_letter_by_postA

Sends specified letter by post (SENDS BY POST — irreversible)

Inputs: letter_id (required), palette (required), print (required), speed (required).

send_offer_by_emailA

Sends specified offer by email (SENDS REAL EMAIL — irreversible)

Inputs: offer_id (required), subject (required), body (required), recipients (required), +1 more.

send_offer_by_postA

Sends specified offer by post (SENDS BY POST — irreversible)

Inputs: offer_id (required), palette (required), print (required), speed (required).

send_order_confirmation_by_emailA

Sends specified order confirmation by email (SENDS REAL EMAIL — irreversible)

Inputs: order_confirmation_id (required), subject (required), body (required), recipients (required), +1 more.

send_order_confirmation_by_postA

Sends specified order confirmation by post (SENDS BY POST — irreversible)

Inputs: order_confirmation_id (required), palette (required), print (required), speed (required).

update_bank_accountB

Updates specified bank account

Inputs: account_id (required), default, description, bank_name, +4 more.

update_contactC

Updates specified contact

Inputs: contact_id (required), number, relation, type, +22 more.

update_contact_accountC

Updates specified account

Inputs: contact_id (required), account_id (required), default, type, +3 more.

update_contact_addressB

Updates specified address

Inputs: contact_id (required), address_id (required), default, country, +7 more.

update_contact_groupC

Updates specified group

Inputs: group_id (required), name.

update_contact_personC

Updates specified person

Inputs: contact_id (required), person_id (required), default, name, +10 more.

update_cost_unitC

Updates specified cost unit

Inputs: cost_unit_id (required), number, name, description, +1 more.

update_delivery_noteB

Updates specified delivery note

Inputs: delivery_note_id (required), number, contact_id, contact_address_id, +16 more.

update_effortC

Updates specified effort

Inputs: effort_id (required), duration, date, activity_id, +3 more.

update_exchange_rateB

Updates specified currency exchange rate

Inputs: exchange_id (required), currency_from, currency_to, rate.

update_invoiceB

Updates specified invoice

Inputs: invoice_id (required), number, contact_id, contact_address_id, +29 more.

update_invoice_paymentB

Updates specified invoice's payment

Inputs: invoice_id (required), payment_id (required), notes.

update_letterC

Updates specified letter

Inputs: letter_id (required), contact_id, contact_address_id, contact_prepage_address_id, +10 more.

update_offerC

Updates specified offer

Inputs: offer_id (required), number, contact_id, contact_address_id, +18 more.

update_order_confirmationC

Updates specified order confirmation

Inputs: order_confirmation_id (required), number, contact_id, contact_address_id, +16 more.

update_productB

Updates specified product

Inputs: product_id (required), number, name, description, +9 more.

update_product_categoryC

Updates specified product category

Inputs: category_id (required), name, accounting_account_number.

update_projectC

Updates specified project

Inputs: project_id (required), number, contact_id, name, +4 more.

update_reminderB

Updates specified reminder

Inputs: reminder_id (required), contact_id, date_time, title, +3 more.

update_serviceC

Updates specified service

Inputs: service_id (required), number, name, description, +8 more.

update_service_categoryB

Updates specified service category

Inputs: category_id (required), name, accounting_account_number.

update_working_hoursB

Updates specified working hours entry

Inputs: time_id (required), user_id, date, time_start, +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    C2.9/5.0

    Scored across 146 tools

    Disambiguation4/5

    Most tools are cleanly separated by resource prefix (e.g., list_invoices, create_product), making selection straightforward. Minor ambiguity exists between get_owner and get_profile, and between activities/efforts/working_hours, which could confuse agents in time-tracking contexts.

    Naming Consistency4/5

    The naming pattern is highly consistent: list_/create_/get_/update_/delete_ plus standardized document actions like download_*_pdf, get_*_preview, and send_*_by_email. Small deviations such as record_invoice_payment and singular delete_invoice_payment break the pattern slightly but do not undermine overall predictability.

    Tool Count1/5

    At 146 tools, this is an extreme overload for an MCP server, far beyond the 25+ threshold and even the 50+ extreme case. Even though the domain is broad, the enormous surface area will overwhelm agents and create selection overhead, suggesting the need for consolidation or dynamic tool discovery.

    Completeness4/5

    The server covers the core invoicing/ERP lifecycle well, with full CRUD on contacts, products, invoices, offers, delivery notes, and projects, plus domain-specific actions like PDF generation and sending. Missing mutability for units, ISRs, and activities are notable but minor gaps that do not block primary workflows.

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      C
      maintenance
      MCP server for the bexio API, enabling interaction with contacts, sales, accounting, projects, and more through 35 tools. Supports both PAT and OAuth authentication with read-only mode and tool group filtering.
      35
      23 npm
      4
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      An MCP server that acts as a secure, multi-tenant proxy to the InvoiceShelf API, enabling AI assistants to manage invoices, estimates, customers, payments, expenses, and more with 109 tools and TOON compression for efficient token usage.
      GPL 3.0
    • A
      license
      B
      quality
      B
      maintenance
      MCP server for VoxFactura enabling AI assistants to query business data (invoices, expenses, project margins, clients, VAT) and create draft quotes or mark invoices paid via a scoped API, with no direct client sends.
      25
      MIT