Multi-tenant Model Context Protocol server for MonetAPI v2 (Lithuanian bookkeeping at https://e.monet.lt). Anyone can deploy a single instance to Vercel; users connect their MCP client (Claude Desktop, VS Code, Cursor, Windsurf, Continue, …) using their own Monet credentials passed via headers. The server is stateless and forwards requests on behalf of the caller.
- One Vercel deployment, many users. No DB, no signup, no credential storage.
- Industry-standard MCP HTTP transport (
mcp-handler/@modelcontextprotocol/sdk). Supports the Streamable HTTP transport spec, which all current MCP clients understand. - ~45 tools covering effectively the full Monet API: items, inventory journals, customers, vendors, sales (goods / services / refunds / contracts), purchases (goods / services), invoice reads & balances, company switching, currencies / VAT / dimensions / ledger, payments (PostLedgerJournal, DeleteTrans), balances & open payments, employee timetables.
- Multi-company aware. A single Monet user can have access to multiple companies (e.g. "MB Šilenskių biuras" + "UAB Saakuru technologijos"). Pass the company ID per request via
x-monet-companyand the server switches transparently.
git clone https://github.com/MindExtension/monet-mcp
cd monet-mcp
pnpm install # or npm / yarn
vercel # link to a new Vercel project
vercel --prodNo env vars are required. Optionally set MONET_BASE_URL if you point at a non-default Monet instance.
After deployment, your endpoint is:
https://<your-project>.vercel.app/api/mcp
Add it to your MCP client with your own Monet credentials in the headers.
{
"servers": {
"monet": {
"type": "http",
"url": "https://<your-project>.vercel.app/api/mcp",
"headers": {
"x-monet-user": "your-monet-username",
"x-monet-pass": "your-monet-password",
"x-monet-company": "2ZW"
}
}
}
}{
"mcpServers": {
"monet": {
"url": "https://<your-project>.vercel.app/api/mcp",
"headers": {
"x-monet-user": "your-monet-username",
"x-monet-pass": "your-monet-password",
"x-monet-company": "2ZW"
}
}
}
}Claude Desktop's stdio integration expects a local process. To use a remote HTTP MCP, run a tiny local proxy via mcp-remote:
{
"mcpServers": {
"monet": {
"command": "npx",
"args": [
"mcp-remote",
"https://<your-project>.vercel.app/api/mcp",
"--header", "x-monet-user:your-monet-username",
"--header", "x-monet-pass:your-monet-password",
"--header", "x-monet-company:2ZW"
]
}
}
}If the client supports HTTP MCP servers + custom headers, configure the URL and three headers above. If it only supports stdio, use the mcp-remote proxy approach shown for Claude Desktop.
A single Monet user can be linked to multiple companies. Run the monet_probe tool first; it reports the active company name and the IDs of any other companies you can switch to. Use that ID as x-monet-company.
You can also call get_company_list (returns OTHER companies — the active one is NOT in the list) and get_company (returns the active company's name).
get_item, get_item_list, items_quantity, insert_item, update_item, delete_item
create_invent_journal, create_invent_journal_line_acquisition_scrap, create_invent_journal_line_transfer, create_invent_journal_line_bom, check_invent_journal, post_invent_journal
get_customer_list, insert_customer, update_customer, delete_customer
get_vendor_list, insert_vendor, update_vendor, delete_vendor
get_sales_sched_list, post_sales_sched, post_sales, post_sales_service, post_sales_refund
post_purch, post_purch_service
get_cust_invoice_list, get_vend_invoice_list, get_cust_invoice_balance, get_vend_invoice_balance,
get_sales_invoice_pdf — returns the invoice as a base64-encoded PDF wrapped in an MCP resource content block. Most clients (Claude Desktop, Cursor) display it inline or let you save it directly.
get_company_list, get_company, set_company, get_currency_codes, get_tax_item_groups, get_locations, get_item_groups, get_item_types, get_ledger_list, get_dim_list, insert_dim, get_language, set_language
post_ledger_journal, delete_trans, get_cust_open_payments, get_cust_balance, get_vend_balance, get_vend_open_payments
get_company_worker_timetable
monet_probe
- VAT groups:
PVM_0,PVM_5,PVM_9,PVM_12,PVM_21,PVM_100(Kiti atvejai),PVM_21_SAVO - AccountType (PostLedgerJournal):
0= DK,1= Klientas,2= Tiekėjas,5= Turtas,6= Bankas - SalesType (PostSales):
1= Pasiūlymas,3= Pardavimo užsakymas,4= Grąžinta prekė - MarkupAllocation (PostPurch):
0= Grynoji suma,1= Kiekis,2= Pagal eilutes - Country / DeliveryCountry: ISO Alpha-2 (
LT,GB,DE, …)
set_companyis persistent server-side. When the server switches the active company on your behalf for a tool call, it does not restore the previous one (each tool call is stateless). If you also use the Monet web UI under the same login, your view will follow whichever company was last targeted. Pin onex-monet-companyper MCP client config to avoid surprises.- Rate limit. Monet enforces ~1000 requests/hour per user. The server doesn't rate-limit you locally — your MCP client is responsible for sane usage.
- Write operations are not gated by the server. This is an MCP server; the LLM client is expected to confirm with the user before issuing writes. If you want hard local gating, run the
monet-bookkeepingClaude Code skill instead, which adds--confirmand--i-understand-this-deletesbarriers at the CLI level. - No audit log. Vercel functions are stateless; persistent audit logging would require an external store (Supabase, Postgres, R2). Add it if you need one.
pnpm install
pnpm dev
# Server now at http://localhost:3000/api/mcpTest with mcp-inspector:
npx @modelcontextprotocol/inspector \
--transport http \
--url http://localhost:3000/api/mcp \
--header "x-monet-user:demo" \
--header "x-monet-pass:demo321demo321"monet-mcp/
├── app/
│ ├── api/[transport]/route.ts # MCP handler (Vercel serverless function)
│ ├── layout.tsx
│ └── page.tsx # Landing page with config snippets
├── src/
│ ├── monet.ts # Monet API client (auth, company switch, fetch)
│ └── tools.ts # All MCP tool definitions (~45)
├── package.json
├── tsconfig.json
├── next.config.js
├── vercel.json
└── README.md
MIT (see LICENSE).