@codemill-solutions/yuki-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +240 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/accounting.d.ts +13 -0
- package/dist/tools/accounting.d.ts.map +1 -0
- package/dist/tools/accounting.js +117 -0
- package/dist/tools/accounting.js.map +1 -0
- package/dist/tools/administrations.d.ts +14 -0
- package/dist/tools/administrations.d.ts.map +1 -0
- package/dist/tools/administrations.js +80 -0
- package/dist/tools/administrations.js.map +1 -0
- package/dist/tools/documents.d.ts +18 -0
- package/dist/tools/documents.d.ts.map +1 -0
- package/dist/tools/documents.js +269 -0
- package/dist/tools/documents.js.map +1 -0
- package/dist/tools/invoices.d.ts +22 -0
- package/dist/tools/invoices.d.ts.map +1 -0
- package/dist/tools/invoices.js +549 -0
- package/dist/tools/invoices.js.map +1 -0
- package/dist/tools/relations.d.ts +20 -0
- package/dist/tools/relations.d.ts.map +1 -0
- package/dist/tools/relations.js +271 -0
- package/dist/tools/relations.js.map +1 -0
- package/dist/tools/transactions.d.ts +19 -0
- package/dist/tools/transactions.d.ts.map +1 -0
- package/dist/tools/transactions.js +294 -0
- package/dist/tools/transactions.js.map +1 -0
- package/dist/yuki-client.d.ts +72 -0
- package/dist/yuki-client.d.ts.map +1 -0
- package/dist/yuki-client.js +227 -0
- package/dist/yuki-client.js.map +1 -0
- package/package.json +37 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 CodeMill Solutions B.V.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# yuki-mcp
|
|
2
|
+
|
|
3
|
+
A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that connects AI agents to [Yuki](https://www.yukiworks.nl) accounting via Yuki's SOAP API.
|
|
4
|
+
|
|
5
|
+
Built with Node.js, TypeScript, and [`@modelcontextprotocol/sdk`](https://github.com/modelcontextprotocol/typescript-sdk).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @codemill-solutions/yuki-mcp
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then add it to your MCP host configuration (e.g. `claude_desktop_config.json`):
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"yuki": {
|
|
21
|
+
"command": "node",
|
|
22
|
+
"args": ["node_modules/@codemill-solutions/yuki-mcp/dist/index.js"],
|
|
23
|
+
"env": {
|
|
24
|
+
"YUKI_API_KEY": "your-api-key-here",
|
|
25
|
+
"YUKI_DOMAIN_ID": "your-administration-guid-here"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Prerequisites
|
|
35
|
+
|
|
36
|
+
- Node.js 20+
|
|
37
|
+
- A Yuki account with API access enabled
|
|
38
|
+
- Your Yuki API key (Yuki → Settings → API)
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Setup
|
|
43
|
+
|
|
44
|
+
### 1. Install dependencies
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. Configure environment variables
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cp .env.example .env
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Edit `.env`:
|
|
57
|
+
|
|
58
|
+
```env
|
|
59
|
+
YUKI_API_KEY=your-api-key-here
|
|
60
|
+
YUKI_DOMAIN_ID=your-administration-guid-here # optional at startup
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`YUKI_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.
|
|
64
|
+
|
|
65
|
+
### 3. Build
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm run build
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 4. Connect to an MCP host
|
|
72
|
+
|
|
73
|
+
Add to your MCP host configuration (e.g. `claude_desktop_config.json`):
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"yuki": {
|
|
79
|
+
"command": "node",
|
|
80
|
+
"args": ["/absolute/path/to/yuki-mcp/dist/index.js"],
|
|
81
|
+
"env": {
|
|
82
|
+
"YUKI_API_KEY": "your-api-key-here",
|
|
83
|
+
"YUKI_DOMAIN_ID": "your-administration-guid-here"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Available tools
|
|
93
|
+
|
|
94
|
+
### Administrations
|
|
95
|
+
|
|
96
|
+
| Tool | Description |
|
|
97
|
+
|------|-------------|
|
|
98
|
+
| `get_administrations` | List all administrations (companies) for this API key. **Run this first** to find the correct `administrationId`. |
|
|
99
|
+
|
|
100
|
+
### Relations
|
|
101
|
+
|
|
102
|
+
| Tool | Key parameters | Description |
|
|
103
|
+
|------|----------------|-------------|
|
|
104
|
+
| `search_relations` | `searchValue`, `searchOption?`, `active?`, `pageNumber?` | Search customers and suppliers by name, code, VAT number, email, etc. Returns up to 100 results per page. |
|
|
105
|
+
| `upsert_contact` | `fullName`, `contactCode?`, `contactType?`, … | Create or update a contact. When `contactCode` matches an existing record it is updated; otherwise a new contact is created. |
|
|
106
|
+
|
|
107
|
+
### Sales invoices
|
|
108
|
+
|
|
109
|
+
| Tool | Key parameters | Description |
|
|
110
|
+
|------|----------------|-------------|
|
|
111
|
+
| `get_sales_invoices` | `dateOutstanding?`, `sortOrder?`, `includeBankTransactions?` | Retrieve outstanding (unpaid) sales invoices. |
|
|
112
|
+
| `process_sales_invoice` | `reference`, `subject`, `date`, `dueDate`, `contact`, `lines` | Create and book a new sales invoice. Optionally email it to the customer. |
|
|
113
|
+
|
|
114
|
+
### Purchase invoices
|
|
115
|
+
|
|
116
|
+
| Tool | Key parameters | Description |
|
|
117
|
+
|------|----------------|-------------|
|
|
118
|
+
| `get_purchase_invoices` | `dateOutstanding?`, `sortOrder?`, `includeBankTransactions?` | Retrieve outstanding (unpaid) purchase invoices. |
|
|
119
|
+
| `process_purchase_invoice` | `date`, `invoiceAmount`, `invoiceVatAmount`, `contact`, `lines` | Book an incoming purchase invoice. Accepts an optional PDF as base64. |
|
|
120
|
+
|
|
121
|
+
### Transactions & bank
|
|
122
|
+
|
|
123
|
+
| Tool | Key parameters | Description |
|
|
124
|
+
|------|----------------|-------------|
|
|
125
|
+
| `get_transactions` | `glAccountCode`, `startDate`, `endDate` | Retrieve journal entries for a GL account (e.g. a bank account) in a date range. Use `get_gl_accounts` to find the right code. |
|
|
126
|
+
| `get_transaction_details` | `reference` | Check if an outstanding item still exists and retrieve its current status. |
|
|
127
|
+
| `process_journal` | `subject`, `entries[]` | Post a general journal entry (memoriaal). All entry amounts must sum to exactly 0. Used for bank reconciliation, corrections, and custom bookings. |
|
|
128
|
+
|
|
129
|
+
### Accounting
|
|
130
|
+
|
|
131
|
+
| Tool | Key parameters | Description |
|
|
132
|
+
|------|----------------|-------------|
|
|
133
|
+
| `get_gl_accounts` | `date?` | Retrieve all GL accounts with their balance at a given date. Use this to find bank account codes before calling `get_transactions`. |
|
|
134
|
+
|
|
135
|
+
### Documents
|
|
136
|
+
|
|
137
|
+
| Tool | Key parameters | Description |
|
|
138
|
+
|------|----------------|-------------|
|
|
139
|
+
| `upload_document` | `fileName`, `dataBase64`, `folder?`, `amount?` | Upload a PDF to the Yuki archive by passing its content as a base64 string. Use `get_document_folders` first to find the right folder ID. |
|
|
140
|
+
| `upload_document_from_path` | `filePath`, `fileName?`, `folder?`, `amount?` | Upload a PDF from a local file path. Reads and encodes the file internally — preferred over `upload_document` when the file is available on disk. Validates that the file exists and is a valid PDF before uploading. |
|
|
141
|
+
| `get_document_folders` | — | List all archive folders available in the administration. |
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Testing
|
|
146
|
+
|
|
147
|
+
### Option 1 — MCP Inspector (tool-level, no LLM)
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npm run inspect
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Opens a browser UI at `http://localhost:5173` where you can call individual tools and inspect raw responses.
|
|
154
|
+
|
|
155
|
+
### Option 2 — Agent test harness (with Claude)
|
|
156
|
+
|
|
157
|
+
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.
|
|
158
|
+
|
|
159
|
+
Add your Anthropic API key to `.env`:
|
|
160
|
+
|
|
161
|
+
```env
|
|
162
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Then run a scenario:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npm run agent # default: get_administrations
|
|
169
|
+
npm run agent -- --scenario outstanding-invoices
|
|
170
|
+
npm run agent -- --scenario search-relations --arg "Bedrijf BV"
|
|
171
|
+
npm run agent -- --scenario gl-accounts
|
|
172
|
+
npm run agent -- --scenario bank-transactions --arg "1200"
|
|
173
|
+
npm run agent -- --scenario full-workflow
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Available scenarios: `get-administrations`, `search-relations`, `outstanding-invoices`, `outstanding-payables`, `gl-accounts`, `bank-transactions`, `full-workflow`.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Architecture
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
src/
|
|
184
|
+
├── index.ts # Entry point — loads env, registers tools, starts stdio transport
|
|
185
|
+
├── yuki-client.ts # SOAP client: envelope builder, axios HTTP, fast-xml-parser, XmlValue
|
|
186
|
+
└── tools/
|
|
187
|
+
├── administrations.ts # get_administrations
|
|
188
|
+
├── relations.ts # search_relations, upsert_contact
|
|
189
|
+
├── invoices.ts # get_sales_invoices, get_purchase_invoices,
|
|
190
|
+
│ # process_sales_invoice, process_purchase_invoice
|
|
191
|
+
├── transactions.ts # get_transactions, get_transaction_details, process_journal
|
|
192
|
+
├── accounting.ts # get_gl_accounts
|
|
193
|
+
└── documents.ts # upload_document, upload_document_from_path, get_document_folders
|
|
194
|
+
|
|
195
|
+
scripts/
|
|
196
|
+
└── test-agent.ts # Agent test harness (Claude + MCP client loop)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Auth flow
|
|
200
|
+
|
|
201
|
+
Yuki uses a two-step authentication pattern:
|
|
202
|
+
|
|
203
|
+
1. `Authenticate(accessKey)` → returns a temporary `sessionID`
|
|
204
|
+
2. All subsequent calls include that `sessionID`
|
|
205
|
+
|
|
206
|
+
`YukiClient.getSessionID()` handles this transparently and caches the session for the lifetime of the process.
|
|
207
|
+
|
|
208
|
+
> **Note:** Parameter casing differs across Yuki's services — `sessionId` (lowercase d) on `Sales.asmx` and `Purchase.asmx`; `sessionID` (uppercase D) on `Accounting.asmx`, `Contact.asmx`, and `Archive.asmx`. This is handled per-tool.
|
|
209
|
+
|
|
210
|
+
### XML documents
|
|
211
|
+
|
|
212
|
+
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()`.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Rate limits
|
|
217
|
+
|
|
218
|
+
Yuki enforces **1,000 API requests per day**. Each tool call is 1 request. The session ID is cached so `Authenticate` is only called once per server process, not once per tool call.
|
|
219
|
+
|
|
220
|
+
Design agent workflows to fetch broad lists once and reference them from the agent's context window rather than re-fetching on every step.
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Troubleshooting
|
|
225
|
+
|
|
226
|
+
| Error | Likely cause |
|
|
227
|
+
|-------|-------------|
|
|
228
|
+
| `SOAP Fault: Authentication failed` | `YUKI_API_KEY` is incorrect or API access is not enabled in Yuki Settings |
|
|
229
|
+
| `SOAP Fault: Administration not found` | Wrong `administrationId` — run `get_administrations` to get the correct GUID |
|
|
230
|
+
| `Journal entries do not balance` | Amounts in `process_journal` don't sum to 0 — check debit/credit signs |
|
|
231
|
+
| `HTTP 500 from api.yukiworks.nl` | Usually a wrong XML namespace or malformed `xmlDoc` — check the WSDL at `https://api.yukiworks.nl/ws/{Service}.asmx?wsdl` |
|
|
232
|
+
| `File does not appear to be a PDF` | The file at `filePath` does not start with the `%PDF` magic bytes — check you're pointing at a valid PDF |
|
|
233
|
+
| `File not found` | `filePath` passed to `upload_document_from_path` does not exist or is inaccessible |
|
|
234
|
+
| `Network error` | No connectivity to `api.yukiworks.nl` — requests time out after 30 seconds |
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## License
|
|
239
|
+
|
|
240
|
+
MIT — see [LICENSE](./LICENSE).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { YukiClient } from "./yuki-client.js";
|
|
5
|
+
// Read tools
|
|
6
|
+
import { registerAdministrationTools } from "./tools/administrations.js";
|
|
7
|
+
import { registerRelationTools } from "./tools/relations.js";
|
|
8
|
+
import { registerInvoiceTools } from "./tools/invoices.js";
|
|
9
|
+
import { registerTransactionTools } from "./tools/transactions.js";
|
|
10
|
+
import { registerAccountingTools } from "./tools/accounting.js";
|
|
11
|
+
// Write tools
|
|
12
|
+
import { registerInvoiceWriteTools } from "./tools/invoices.js";
|
|
13
|
+
import { registerJournalWriteTools } from "./tools/transactions.js";
|
|
14
|
+
import { registerContactWriteTools } from "./tools/relations.js";
|
|
15
|
+
import { registerDocumentTools } from "./tools/documents.js";
|
|
16
|
+
// ── Environment validation ────────────────────────────────────────────────────
|
|
17
|
+
const apiKey = process.env["YUKI_API_KEY"];
|
|
18
|
+
const domainId = process.env["YUKI_DOMAIN_ID"] ?? "";
|
|
19
|
+
if (!apiKey) {
|
|
20
|
+
// Write to stderr so the MCP host can surface the message without corrupting
|
|
21
|
+
// the stdio JSON-RPC stream used by the MCP protocol.
|
|
22
|
+
process.stderr.write("[yuki-mcp] Fatal: YUKI_API_KEY environment variable is not set.\n");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
// ── Yuki SOAP client ──────────────────────────────────────────────────────────
|
|
26
|
+
const yukiClient = new YukiClient(apiKey, domainId);
|
|
27
|
+
// ── MCP server ────────────────────────────────────────────────────────────────
|
|
28
|
+
const server = new McpServer({
|
|
29
|
+
name: "yuki-mcp",
|
|
30
|
+
version: "1.0.0",
|
|
31
|
+
});
|
|
32
|
+
// ── Read tools ────────────────────────────────────────────────────────────────
|
|
33
|
+
registerAdministrationTools(server, yukiClient);
|
|
34
|
+
registerRelationTools(server, yukiClient);
|
|
35
|
+
registerInvoiceTools(server, yukiClient);
|
|
36
|
+
registerTransactionTools(server, yukiClient);
|
|
37
|
+
registerAccountingTools(server, yukiClient);
|
|
38
|
+
// ── Write tools ───────────────────────────────────────────────────────────────
|
|
39
|
+
registerInvoiceWriteTools(server, yukiClient);
|
|
40
|
+
registerJournalWriteTools(server, yukiClient);
|
|
41
|
+
registerContactWriteTools(server, yukiClient);
|
|
42
|
+
registerDocumentTools(server, yukiClient);
|
|
43
|
+
// ── Start ─────────────────────────────────────────────────────────────────────
|
|
44
|
+
const transport = new StdioServerTransport();
|
|
45
|
+
await server.connect(transport);
|
|
46
|
+
// Log startup info to stderr only (stdout is reserved for JSON-RPC)
|
|
47
|
+
process.stderr.write(`[yuki-mcp] Server started — 14 tools registered. ` +
|
|
48
|
+
`Domain ID: ${domainId || "(none — run get_administrations to discover)"}\n`);
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,aAAa;AACb,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,cAAc;AACd,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,iFAAiF;AAEjF,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;AAErD,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,6EAA6E;IAC7E,sDAAsD;IACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mEAAmE,CACpE,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,iFAAiF;AAEjF,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAEpD,iFAAiF;AAEjF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,iFAAiF;AACjF,2BAA2B,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAChD,qBAAqB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAC1C,oBAAoB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACzC,wBAAwB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAC7C,uBAAuB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAE5C,iFAAiF;AACjF,yBAAyB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAC9C,yBAAyB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAC9C,yBAAyB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAC9C,qBAAqB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAE1C,iFAAiF;AAEjF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAEhC,oEAAoE;AACpE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mDAAmD;IACjD,cAAc,QAAQ,IAAI,8CAA8C,IAAI,CAC/E,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { YukiClient } from "../yuki-client.js";
|
|
3
|
+
/**
|
|
4
|
+
* Register tools for working with the Yuki chart of accounts.
|
|
5
|
+
*
|
|
6
|
+
* GLAccountBalance returns all GL accounts with their balance at a given date.
|
|
7
|
+
* This is the closest the Yuki SOAP API comes to a "list all GL accounts" call.
|
|
8
|
+
*
|
|
9
|
+
* Yuki service: Accounting.asmx
|
|
10
|
+
* Method: GLAccountBalance(sessionID, administrationID, transactionDate)
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerAccountingTools(server: McpServer, client: YukiClient): void;
|
|
13
|
+
//# sourceMappingURL=accounting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounting.d.ts","sourceRoot":"","sources":["../../src/tools/accounting.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,GACjB,IAAI,CA2FN"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Register tools for working with the Yuki chart of accounts.
|
|
4
|
+
*
|
|
5
|
+
* GLAccountBalance returns all GL accounts with their balance at a given date.
|
|
6
|
+
* This is the closest the Yuki SOAP API comes to a "list all GL accounts" call.
|
|
7
|
+
*
|
|
8
|
+
* Yuki service: Accounting.asmx
|
|
9
|
+
* Method: GLAccountBalance(sessionID, administrationID, transactionDate)
|
|
10
|
+
*/
|
|
11
|
+
export function registerAccountingTools(server, client) {
|
|
12
|
+
/**
|
|
13
|
+
* get_gl_accounts
|
|
14
|
+
*
|
|
15
|
+
* Retrieve all GL accounts (grootboekrekeningen) with their balance at a
|
|
16
|
+
* given date. Returns account code, name, and debit/credit balance.
|
|
17
|
+
*
|
|
18
|
+
* Use this to:
|
|
19
|
+
* - Find the GL account code for a bank account before calling get_transactions
|
|
20
|
+
* - Understand the account structure before booking a journal entry
|
|
21
|
+
* - Get a financial snapshot (balance sheet / P&L) at a specific date
|
|
22
|
+
*
|
|
23
|
+
* Rate cost: 1 request.
|
|
24
|
+
*/
|
|
25
|
+
server.registerTool("get_gl_accounts", {
|
|
26
|
+
description: "Retrieve all GL accounts (grootboekrekeningen) with their balance at a given date. " +
|
|
27
|
+
"Use this to find account codes (e.g. bank account codes) or get a financial snapshot. " +
|
|
28
|
+
"Defaults to today's date if no date is provided.",
|
|
29
|
+
inputSchema: {
|
|
30
|
+
date: z
|
|
31
|
+
.string()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Date for the balance snapshot in YYYY-MM-DD format. Defaults to today."),
|
|
34
|
+
administrationId: z
|
|
35
|
+
.string()
|
|
36
|
+
.optional()
|
|
37
|
+
.describe("Administration ID (GUID). Defaults to YUKI_DOMAIN_ID env var."),
|
|
38
|
+
},
|
|
39
|
+
}, async ({ date, administrationId }) => {
|
|
40
|
+
try {
|
|
41
|
+
const adminId = administrationId ?? client.defaultDomainId;
|
|
42
|
+
if (!adminId) {
|
|
43
|
+
throw new Error("administrationId is required (or set YUKI_DOMAIN_ID env var)");
|
|
44
|
+
}
|
|
45
|
+
const sessionID = await client.getSessionID();
|
|
46
|
+
// Default to today's date in ISO format when not specified
|
|
47
|
+
const transactionDate = date ?? new Date().toISOString().split("T")[0];
|
|
48
|
+
const result = await client.callSoap({
|
|
49
|
+
service: "Accounting.asmx",
|
|
50
|
+
method: "GLAccountBalance",
|
|
51
|
+
params: {
|
|
52
|
+
sessionID,
|
|
53
|
+
administrationID: adminId,
|
|
54
|
+
transactionDate,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
const accounts = normalizeGLAccounts(result);
|
|
58
|
+
return {
|
|
59
|
+
content: [
|
|
60
|
+
{
|
|
61
|
+
type: "text",
|
|
62
|
+
text: JSON.stringify({
|
|
63
|
+
success: true,
|
|
64
|
+
count: accounts.length,
|
|
65
|
+
balanceDate: transactionDate,
|
|
66
|
+
accounts,
|
|
67
|
+
}, null, 2),
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
74
|
+
return {
|
|
75
|
+
content: [
|
|
76
|
+
{
|
|
77
|
+
type: "text",
|
|
78
|
+
text: JSON.stringify({ success: false, error: message }, null, 2),
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
isError: true,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/** Unwrap the parsed SOAP GL account balance result into a flat array. */
|
|
87
|
+
function normalizeGLAccounts(result) {
|
|
88
|
+
if (!result)
|
|
89
|
+
return [];
|
|
90
|
+
if (Array.isArray(result))
|
|
91
|
+
return result;
|
|
92
|
+
const rec = result;
|
|
93
|
+
const wrappers = ["GLAccounts", "Accounts", "Rows"];
|
|
94
|
+
const itemTags = ["GLAccount", "Account", "Row"];
|
|
95
|
+
for (const wrapper of wrappers) {
|
|
96
|
+
const c = rec[wrapper];
|
|
97
|
+
if (!c)
|
|
98
|
+
continue;
|
|
99
|
+
if (Array.isArray(c))
|
|
100
|
+
return c;
|
|
101
|
+
const inner = c;
|
|
102
|
+
for (const tag of itemTags) {
|
|
103
|
+
if (Array.isArray(inner[tag]))
|
|
104
|
+
return inner[tag];
|
|
105
|
+
if (inner[tag])
|
|
106
|
+
return [inner[tag]];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const tag of itemTags) {
|
|
110
|
+
if (Array.isArray(rec[tag]))
|
|
111
|
+
return rec[tag];
|
|
112
|
+
if (rec[tag])
|
|
113
|
+
return [rec[tag]];
|
|
114
|
+
}
|
|
115
|
+
return [result];
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=accounting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accounting.js","sourceRoot":"","sources":["../../src/tools/accounting.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { YukiClient } from "../yuki-client.js";
|
|
3
|
+
/**
|
|
4
|
+
* Register tools related to Yuki administrations.
|
|
5
|
+
*
|
|
6
|
+
* A Yuki account can contain multiple administrations (companies/entities).
|
|
7
|
+
* Use get_administrations to discover the correct administrationID / domainID
|
|
8
|
+
* to pass to all other tools.
|
|
9
|
+
*
|
|
10
|
+
* Yuki service: Accounting.asmx
|
|
11
|
+
* Auth flow: Authenticate(accessKey) → sessionID → Administrations(sessionID)
|
|
12
|
+
*/
|
|
13
|
+
export declare function registerAdministrationTools(server: McpServer, client: YukiClient): void;
|
|
14
|
+
//# sourceMappingURL=administrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"administrations.d.ts","sourceRoot":"","sources":["../../src/tools/administrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,GACjB,IAAI,CAyDN"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register tools related to Yuki administrations.
|
|
3
|
+
*
|
|
4
|
+
* A Yuki account can contain multiple administrations (companies/entities).
|
|
5
|
+
* Use get_administrations to discover the correct administrationID / domainID
|
|
6
|
+
* to pass to all other tools.
|
|
7
|
+
*
|
|
8
|
+
* Yuki service: Accounting.asmx
|
|
9
|
+
* Auth flow: Authenticate(accessKey) → sessionID → Administrations(sessionID)
|
|
10
|
+
*/
|
|
11
|
+
export function registerAdministrationTools(server, client) {
|
|
12
|
+
/**
|
|
13
|
+
* get_administrations
|
|
14
|
+
*
|
|
15
|
+
* List all administrations accessible with the current API key.
|
|
16
|
+
* Always run this first to find the correct administrationID (GUID).
|
|
17
|
+
*
|
|
18
|
+
* Rate cost: 2 requests (1× Authenticate + 1× Administrations).
|
|
19
|
+
* On subsequent calls within the same session, Authenticate is skipped: 1 request.
|
|
20
|
+
*/
|
|
21
|
+
server.registerTool("get_administrations", {
|
|
22
|
+
description: "List all Yuki administrations (companies) accessible with the configured API key. " +
|
|
23
|
+
"Run this first to discover the correct administrationID to pass to other tools.",
|
|
24
|
+
}, async () => {
|
|
25
|
+
try {
|
|
26
|
+
// Step 1 — Authenticate and obtain (cached) sessionID
|
|
27
|
+
const sessionID = await client.getSessionID();
|
|
28
|
+
// Step 2 — Fetch administrations for this session
|
|
29
|
+
const result = await client.callSoap({
|
|
30
|
+
service: "Accounting.asmx",
|
|
31
|
+
method: "Administrations",
|
|
32
|
+
params: { sessionID },
|
|
33
|
+
});
|
|
34
|
+
const administrations = normalizeAdministrations(result);
|
|
35
|
+
return {
|
|
36
|
+
content: [
|
|
37
|
+
{
|
|
38
|
+
type: "text",
|
|
39
|
+
text: JSON.stringify({ success: true, count: administrations.length, administrations }, null, 2),
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
46
|
+
return {
|
|
47
|
+
content: [
|
|
48
|
+
{
|
|
49
|
+
type: "text",
|
|
50
|
+
text: JSON.stringify({ success: false, error: message }, null, 2),
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
isError: true,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/** Normalise the parsed SOAP result into a flat array of administration objects. */
|
|
59
|
+
function normalizeAdministrations(result) {
|
|
60
|
+
if (!result)
|
|
61
|
+
return [];
|
|
62
|
+
if (Array.isArray(result))
|
|
63
|
+
return result;
|
|
64
|
+
const rec = result;
|
|
65
|
+
// The Administrations response wraps items in <Administrations><Administration>
|
|
66
|
+
const containers = [rec["Administrations"], rec["administrations"], result];
|
|
67
|
+
for (const c of containers) {
|
|
68
|
+
if (!c)
|
|
69
|
+
continue;
|
|
70
|
+
if (Array.isArray(c))
|
|
71
|
+
return c;
|
|
72
|
+
const inner = c["Administration"];
|
|
73
|
+
if (Array.isArray(inner))
|
|
74
|
+
return inner;
|
|
75
|
+
if (inner)
|
|
76
|
+
return [inner];
|
|
77
|
+
}
|
|
78
|
+
return [result];
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=administrations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"administrations.js","sourceRoot":"","sources":["../../src/tools/administrations.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,MAAM,UAAU,2BAA2B,CACzC,MAAiB,EACjB,MAAkB;IAElB;;;;;;;;OAQG;IACH,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;QACE,WAAW,EACT,oFAAoF;YACpF,iFAAiF;KACpF,EACD,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,sDAAsD;YACtD,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;YAE9C,kDAAkD;YAClD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC;gBACnC,OAAO,EAAE,iBAAiB;gBAC1B,MAAM,EAAE,iBAAiB;gBACzB,MAAM,EAAE,EAAE,SAAS,EAAE;aACtB,CAAC,CAAC;YAEH,MAAM,eAAe,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;YAEzD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,eAAe,CAAC,MAAM,EAAE,eAAe,EAAE,EACjE,IAAI,EACJ,CAAC,CACF;qBACF;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;qBAClE;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,SAAS,wBAAwB,CAAC,MAAe;IAC/C,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IAEzC,MAAM,GAAG,GAAG,MAAiC,CAAC;IAE9C,gFAAgF;IAChF,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,GAAG,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC;IAC5E,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAI,CAA6B,CAAC,gBAAgB,CAAC,CAAC;QAC/D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACvC,IAAI,KAAK;YAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { YukiClient } from "../yuki-client.js";
|
|
3
|
+
/**
|
|
4
|
+
* Register tools for uploading documents to the Yuki archive.
|
|
5
|
+
*
|
|
6
|
+
* The Yuki Archive service stores source documents (PDFs) alongside
|
|
7
|
+
* their financial data. Attaching a PDF to a purchase invoice is
|
|
8
|
+
* strongly recommended for audit compliance.
|
|
9
|
+
*
|
|
10
|
+
* Yuki service: Archive.asmx
|
|
11
|
+
* Method: UploadDocumentWithData(sessionID, fileName, data, folder,
|
|
12
|
+
* administrationID, currency, amount,
|
|
13
|
+
* costCategory, paymentMethod, project, remarks)
|
|
14
|
+
*
|
|
15
|
+
* Note: Archive.asmx uses sessionID / administrationID (uppercase D).
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerDocumentTools(server: McpServer, client: YukiClient): void;
|
|
18
|
+
//# sourceMappingURL=documents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/tools/documents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,GACjB,IAAI,CAySN"}
|