smartbill-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@smartbill-mcpCreate an invoice for client ABC for 500 RON."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
smartbill-mcp
An MCP server for the SmartBill Cloud API. It lets an MCP client issue and manage Romanian invoices, proformas and payments, download document PDFs, and read VAT rates, series and stock levels.
It runs two ways:
stdio, single account, on your machine — credentials come from the environment.
HTTP, multi-tenant, hosted — credentials arrive with each request, so one deployment serves any number of SmartBill accounts.
Credentials
You need a SmartBill Cloud account with API access. The token is generated in Contul meu → Integrari → API; the username is the email you log in with. A SmartBill token is a bearer credential with full account access and no scoping — anything holding it can issue and delete real fiscal documents.
Related MCP server: oblio-mcp
Running over stdio
npm install
npm run build
cp .env.example .env # then fill it inVariable | Required | Description |
| yes | Account email. |
| yes | API token from SmartBill Cloud. |
| yes | Your company CIF, used as the default |
| no | Default invoice series, e.g. |
| no | Default proforma series. |
| no | Default receipt (chitanta) series. |
| no | Where PDFs are written. Default |
| no | Override the API base URL. |
The series defaults are optional but convenient: with them set, tools can be
called with just a document number. Without them, pass seriesName explicitly.
claude mcp add smartbill \
--env SMARTBILL_USERNAME=you@example.com \
--env SMARTBILL_TOKEN=your-api-token \
--env SMARTBILL_VAT_CODE=RO12345678 \
--env SMARTBILL_INVOICE_SERIES=FF \
-- node /absolute/path/to/smartbill-mcp/dist/index.jsThe token is read once at startup, turned into an Authorization: Basic header
inside the HTTP client, and never enters the model's context — no tool takes a
credential argument, so it cannot surface in a tool result.
Running over HTTP (multi-tenant)
npm run build
npm run start:http # or: node dist/index.js --httpVariable | Default | Description |
| — | Set to |
|
| Port to listen on. |
|
| Interface to bind. |
|
| Base path the endpoint is mounted at. |
| — | Comma-separated |
No SMARTBILL_* secrets are read in this mode — the server holds none.
GET /health answers {"status":"ok"} without credentials, for platform health
checks.
The setup page
Opening the deployment's root in a browser serves a self-service page that explains what the server does, points at the SmartBill integrations page for the three values it needs, and generates the connector URL.
The page is entirely self-contained — no external scripts, styles or fonts, no
fetch, no <form>. The URL is assembled in the browser from what the user
types, so the token never reaches the server until it is used for a real MCP
call. test/http.test.ts asserts that, so a future edit can't quietly add a
third-party subresource that could observe the field.
Non-browser callers (Accept without text/html) still get JSON at the root,
so health checks and monitoring are unaffected.
Credentials in the URL
Each caller's credentials travel as one base64url segment of
username:token:cif:
https://smartbill.example.com/mcp/<credentials>?invoiceSeries=FFGenerate the URL rather than assembling it by hand:
npm run make-url -- https://smartbill.example.com/mcp you@example.com TOKEN RO12345678 FF PF CHThe optional invoiceSeries, estimateSeries and receiptSeries query
parameters set that tenant's series defaults, matching the stdio env vars.
This is the form to use with clients that only accept a URL — including claude.ai's Add custom connector dialog, which has fields for a URL and OAuth credentials but none for custom headers.
The URL is the secret. Anyone holding it can issue and delete fiscal documents on that account, and URLs leak more readily than headers do: they land in reverse-proxy access logs, error pages and crash traces. Mitigate it:
Turn off request-path logging on whatever proxy sits in front (Traefik/Coolify). This server never logs the URL itself.
Treat the URL like a password: don't paste it into shared docs or tickets.
To revoke, regenerate the SmartBill token — that invalidates every URL built from it.
Credentials in a header
Clients that can send headers should, since the token then stays out of access logs. Send both:
Authorization: Basic base64(username:token)
X-SmartBill-Cif: RO12345678against the bare /mcp path. Query parameters for series defaults still apply.
When both a header and a URL segment are present, the header wins.
Deploying
The Dockerfile builds for the runtime Prionman expects — linux/arm64,
listening on port 80, no secrets baked into the image:
docker build --platform linux/arm64 -t smartbill-mcp .
docker run -p 8080:80 smartbill-mcpTools
Invoices
Tool | What it does |
| Issue an invoice, optionally recording a payment and emailing it. |
| Issue an invoice that copies its details from a proforma. |
| Issue a storno invoice reversing an existing one. |
| Download the invoice PDF. |
| Total, paid and unpaid amounts for an invoice. |
| Cancel an invoice, or undo the cancellation. |
| Permanently delete an invoice. |
Estimates (proforme)
Tool | What it does |
| Issue a proforma. |
| Download the proforma PDF. |
| List invoices already issued from a proforma. |
| Cancel a proforma, or undo the cancellation. |
| Permanently delete a proforma. |
Payments
Tool | What it does |
| Record a collection, optionally settling specific invoices. |
| Cancel a receipt without deleting it. |
| Delete a receipt (chitanta) by series and number. |
| Delete a non-receipt payment (card, transfer, ...). |
| Printable text of a fiscal receipt, base64-decoded for you. |
Account and catalogue
Tool | What it does |
| Document series configured on the account, with their next number. |
| VAT rates, for the |
| Stock levels on a date, optionally per warehouse or product. |
| Email an already-issued invoice or proforma. |
How the tools are documented
The descriptions are written for a model choosing between them, not just for a
human reading the list. Every tool states what it does, when to reach for it,
what it returns, and which sibling tool to use instead when it is the wrong
choice — delete_invoice points at cancel_invoice, create_invoice points at
create_invoice_from_estimate, and so on. Irreversible tools say so and ask for
confirmation; read-only ones are marked readOnlyHint and destructive ones
destructiveHint, so clients can gate them.
The server also ships instructions, which explain the domain a model has to get
right up front: how series and numbers work, the difference between an invoice, a
proforma and a payment, and the asymmetry between deleting, cancelling and
reversing.
test/documentation.test.ts enforces this — it fails the build if a tool loses
its title, gets a thin description, stops saying when to use it, drops one of the
cross-references, or grows an undocumented parameter.
Behaviour worth knowing
Errors. SmartBill reports business failures with HTTP 200 and a non-empty
errorText (and the email endpoint uses a status.code instead). Both are
turned into tool errors, so a failed call never looks like a success.
Rate limiting. SmartBill allows 3 calls per second. The client serialises requests and spaces them out, so a burst of tool calls queues instead of failing.
PDFs. Over stdio, get_invoice_pdf and get_estimate_pdf write the file to
SMARTBILL_DOWNLOAD_DIR and return the path. Over HTTP the server has no
filesystem the client can read, so they return base64 bytes instead. Either
default can be overridden per call with as: "file" | "base64".
Email fields. SmartBill expects the email subject and body base64-encoded. Pass plain text; the encoding is handled for you.
Irreversibility. Only the last document in a series can be deleted. Older
documents can be cancelled (cancel_invoice) or reversed with a storno invoice
(create_reverse_invoice). The server tells the model this in its instructions
and marks the destructive tools accordingly, but the client still decides whether
to prompt — treat write tools as needing confirmation.
Development
npm test # vitest, no network access needed
npm run typecheck
npm run dev # stdio, from sourceTests drive the real MCP server — over an in-memory transport for the tool layer
and over a real socket for the HTTP layer — with a stubbed fetch, so they cover
the tool schemas, the request bodies sent to SmartBill, the error mapping and
per-tenant credential isolation.
Notes on the API surface
SmartBill's reference lives at https://api.smartbill.ro/. The endpoints, field names and query parameters used here match the published SmartBill SDKs. Two details are worth flagging:
delete_paymentcallsDELETE /paymentwith query parameters. SmartBill also documents a/payment/v2variant; if your account rejects the call, setSMARTBILL_BASE_URLor open an issue.create_invoice_from_estimatesendsuseEstimateDetails: truewith anestimatereference and no client block, letting SmartBill copy the client and line items from the proforma.
License
MIT
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/bogdanripa/smartbill-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server