yuki-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., "@yuki-mcpshow me my administrations"
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.
yuki-mcp
A Model Context Protocol (MCP) server that connects AI agents to Yuki accounting via Yuki's SOAP API.
Built with Node.js, TypeScript, and @modelcontextprotocol/sdk.
Installation
npm install @codemill-solutions/yuki-mcpThen add it to your MCP host configuration (e.g. claude_desktop_config.json):
{
"mcpServers": {
"yuki": {
"command": "node",
"args": ["node_modules/@codemill-solutions/yuki-mcp/dist/index.js"],
"env": {
"YUKI_API_KEY": "your-api-key-here",
"YUKI_DOMAIN_ID": "your-administration-guid-here"
}
}
}
}Related MCP server: fortnox-mcp-server
Prerequisites
Node.js 20+
A Yuki account with API access enabled
Your Yuki API key (Yuki → Settings → API)
Setup
1. Install dependencies
npm install2. Configure environment variables
cp .env.example .envEdit .env:
YUKI_API_KEY=your-api-key-here
YUKI_DOMAIN_ID=your-administration-guid-here # optional at startupYUKI_DOMAIN_ID can be left empty — the server starts without it. Call get_administrations to discover the correct GUID, then pass it via the administrationId parameter on individual tools.
3. Build
npm run build4. Connect to an MCP host
Add to your MCP host configuration (e.g. claude_desktop_config.json):
{
"mcpServers": {
"yuki": {
"command": "node",
"args": ["/absolute/path/to/yuki-mcp/dist/index.js"],
"env": {
"YUKI_API_KEY": "your-api-key-here",
"YUKI_DOMAIN_ID": "your-administration-guid-here"
}
}
}
}Multi-administration support
If you manage multiple Yuki administrations (each with its own API key), you can supply a JSON file that maps every administrationId to its corresponding API key. The server then authenticates per administration automatically — no single shared key required.
Keys file format
{
"a1b2c3d4-0000-0000-0000-000000000001": "api-key-for-admin-1",
"a1b2c3d4-0000-0000-0000-000000000002": "api-key-for-admin-2"
}Path resolution (first match wins)
Priority | Path |
1 |
|
2 |
|
3 |
|
Environment variable
YUKI_API_KEYS_FILE=/path/to/your/api-keys.jsonWhen a keys file is present, YUKI_API_KEY becomes optional — the file keys are used for all administration-specific tool calls, and YUKI_API_KEY (if set) serves as the fallback for tools that don't target a specific administration (e.g. get_administrations).
If neither YUKI_API_KEY nor a keys file is found at startup, the server logs a warning but continues running — tools will return an error when called.
Reloading keys at runtime
When a new key is generated externally — for example by a sibling MCP server that drives the Yuki Integraties UI to create a fresh API key for a new administration — the new entry only lands in ~/.yuki/api-keys.json. By default the MCP server reads that file once at startup, so a freshly added key would require a server restart before it can be used for SOAP calls.
The reload_keys tool (see Available tools below) avoids this: it re-reads the keys file from disk and replaces the in-memory map in place. Sessions for keys that changed or were removed are evicted from the session cache automatically; sessions for unchanged keys stay warm so subsequent calls do not pay the re-authentication cost.
Typical flow for a sibling tool that has just minted a new key:
1. (external) write the new key to ~/.yuki/api-keys.json
2. yuki-mcp.reload_keys() → { added: [<adminId>], updated: [], removed: [], total: N }
3. yuki-mcp.get_administrations → now works for the new admin without restartAvailable tools (31)
Administrations
Tool | Description |
| List all administrations (companies) for this API key. Run this first to find the correct |
| Look up an administration's GUID by its exact name. Useful when you know the name but not the GUID. |
| Re-read the |
Relations
Tool | Key parameters | Description |
|
| Search customers and suppliers by name, code, VAT number, email, etc. Returns up to 100 results per page. |
|
| Create or update a contact. When |
Sales invoices
Tool | Key parameters | Description |
|
| Retrieve outstanding (unpaid) sales invoices. |
|
| Create and book a new sales invoice. Optionally email it to the customer. |
Purchase invoices
Tool | Key parameters | Description |
| — | Retrieve bank payments that still need a matching purchase invoice — equivalent to "Postbus → Ontbrekende facturen" in the Yuki web interface. |
|
| Retrieve outstanding (unpaid) purchase invoices. |
|
| Book an incoming purchase invoice. Accepts an optional PDF as base64. |
Transactions & bank
Tool | Key parameters | Description |
|
| Retrieve journal entries for a GL account (e.g. a bank account) in a date range. Use |
|
| Check if an outstanding item still exists and retrieve its current status. |
|
| Post a general journal entry (memoriaal). All entry amounts must sum to exactly 0. Used for bank reconciliation, corrections, and custom bookings. |
Accounting
Tool | Key parameters | Description |
|
| Retrieve all GL accounts with their balance at a given date (commercial view). Use this to find account codes before calling |
|
| Same as |
|
| Retrieve net revenue (netto-omzet) for a date range. Set |
Accounting info
Richer read-only views from the AccountingInfo.asmx service — not available through the standard Accounting.asmx.
Tool | Key parameters | Description |
| — | Retrieve the complete GL account scheme (rekeningschema): all codes with type, subtype, description, and active/inactive status. Use to validate GL codes or build account pickers. |
|
| Retrieve the fiscal period table for a year: period numbers, names, and date ranges. Use to translate transaction dates into human-readable period names for reports. |
|
| Detailed transaction listing with document type, archive folder, fiscal period ID, project code, and mutation user. More complete than |
|
| Download the source PDF for a booked transaction as base64. Use the |
|
| Retrieve opening balances (beginbalansen) per GL account for a fiscal year. |
Documents
Tool | Key parameters | Description |
|
| Upload a PDF to the Yuki archive by passing its content as a base64 string. Use |
|
| Upload a PDF from a local file path. Reads and encodes the file internally — preferred over |
| — | List all archive folders available in the administration. |
|
| List documents in a specific archive folder. Returns document IDs, file names, dates, and amounts. |
|
| Full-text search across all archived documents (file names, amounts, OCR content). |
|
| Retrieve metadata for a single archived document by its ID (name, folder, date, amount, status). |
|
| Download an archived document as a base64-encoded string. |
| — | List available GL cost categories for use as the |
Backoffice
Tool | Key parameters | Description |
|
| Retrieve backoffice workflow items — documents that could not be processed automatically and are awaiting review by the accountant. |
|
| Retrieve outstanding questions raised by the accountant that require a response before the related documents can be processed. |
Testing
Option 1 — MCP Inspector (tool-level, no LLM)
npm run inspectOpens a browser UI at http://localhost:5173 where you can call individual tools and inspect raw responses.
Option 2 — Agent test harness (with Claude)
Runs a full agentic loop: Claude reasons about the task, calls tools, and returns a final answer — exactly as an AI agent would use this MCP.
Add your Anthropic API key to .env:
ANTHROPIC_API_KEY=sk-ant-...Then run a scenario:
npm run agent # default: get_administrations
npm run agent -- --scenario outstanding-invoices
npm run agent -- --scenario search-relations --arg "Bedrijf BV"
npm run agent -- --scenario gl-accounts
npm run agent -- --scenario bank-transactions --arg "1200"
npm run agent -- --scenario full-workflowAvailable scenarios: get-administrations, search-relations, outstanding-invoices, outstanding-payables, gl-accounts, bank-transactions, full-workflow.
Architecture
src/
├── index.ts # Entry point — loads env + keys file, registers tools, starts stdio transport
├── yuki-client.ts # SOAP client: per-key session cache, envelope builder, axios HTTP, fast-xml-parser
└── tools/
├── administrations.ts # get_administrations, get_administration_id
├── relations.ts # search_relations, upsert_contact
├── invoices.ts # get_sales_invoices, get_purchase_invoices,
│ # process_sales_invoice, process_purchase_invoice
├── transactions.ts # get_transactions, get_transaction_details, process_journal
├── accounting.ts # get_gl_accounts, get_gl_accounts_fiscal, get_net_revenue
├── accounting-info.ts # get_gl_account_scheme, get_period_table,
│ # get_gl_transactions_detailed, get_transaction_document,
│ # get_start_balances, get_missing_invoices
├── documents.ts # upload_document, upload_document_from_path,
│ # get_document_folders, list_documents, search_documents,
│ # get_document, download_document, get_cost_categories
└── backoffice.ts # get_workflow, get_outstanding_questions
scripts/
└── test-agent.ts # Agent test harness (Claude + MCP client loop)Auth flow
Yuki uses a two-step authentication pattern:
Authenticate(accessKey)→ returns a temporarysessionIDAll subsequent calls include that
sessionID
YukiClient.getSessionID(adminId?) handles this transparently. When called with an administrationId, it resolves the matching API key from the loaded keys map. Session IDs are cached per API key for the lifetime of the process — Authenticate is only called once per key, not once per tool call.
Note: Parameter casing differs across Yuki's services —
sessionId(lowercase d) onSales.asmxandPurchase.asmx;sessionID(uppercase D) onAccounting.asmx,AccountingInfo.asmx,Contact.asmx, andArchive.asmx. This is handled per-tool.
XML documents
Write tools (process_sales_invoice, process_purchase_invoice, process_journal, upsert_contact) pass structured data to Yuki as an XML string inside the xmlDoc SOAP parameter. The XmlValue wrapper ensures this XML is embedded raw (not entity-encoded) in the SOAP envelope. All user-supplied values are XML-escaped via escapeXml().
Rate limits
Yuki enforces 1,000 API requests per day (upgradeable to 5,000–10,000). Each tool call is 1 request. Session IDs are cached so Authenticate is only called once per API key per server process, not once per tool call.
Design agent workflows to fetch broad lists once and reference them from the agent's context window rather than re-fetching on every step.
Troubleshooting
Error | Likely cause |
|
|
| The |
| Wrong |
| Amounts in |
| Usually a wrong XML namespace or malformed |
| The file at |
|
|
| No connectivity to |
About CodeMill Solutions
CodeMill Solutions is a Dutch software company based in the Netherlands. We build smart, scalable, and customized solutions that help organizations grow, optimize processes, and realize their digital ambitions.
Our services include:
Custom applications — portals, dashboards, business software, and fully tailored platforms that truly add value.
API integrations — connecting your application with other systems and external platforms via smart API connections.
Mobile apps — iOS and Android apps as a logical extension of your web application(s).
yuki-mcp is one of our open-source integrations, making Yuki's accounting platform accessible to AI agents through the Model Context Protocol.
📧 info@codemill.dev 🌐 codemill.dev 💼 LinkedIn 🐙 GitHub
License
MIT — see LICENSE.
This server cannot be installed
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
- 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/CodeMill-Solutions/yuki-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server