@tailormade/billit-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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tailormade
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,41 @@
1
+ # Billit MCP Server
2
+
3
+ MCP server for the [Billit](https://billit.be) invoicing API.
4
+
5
+ ## Tools
6
+
7
+ | Category | Tools |
8
+ |----------|-------|
9
+ | Orders | billit_list_orders, billit_get_order, billit_create_order, billit_update_order, billit_confirm_order, billit_delete_order, billit_register_payment, billit_send_order |
10
+ | Parties | billit_list_parties, billit_get_party, billit_create_party, billit_update_party |
11
+ | Products | billit_list_products, billit_get_product, billit_create_product |
12
+ | Peppol | billit_peppol_list_inbox, billit_peppol_confirm_inbox, billit_peppol_refuse_inbox, billit_peppol_send_order, billit_peppol_lookup_participant, billit_peppol_register, billit_peppol_unregister |
13
+ | Documents | billit_list_documents, billit_get_document, billit_upload_document, billit_download_file |
14
+ | Financial | billit_list_financial_transactions, billit_import_financial_transactions, billit_list_reports, billit_get_report, billit_get_account_info, billit_search_company, billit_list_typecodes, billit_list_accountant_feeds, billit_confirm_accountant_feed, billit_download_accountant_file |
15
+ | ToProcess | billit_submit_for_processing, billit_cancel_processing |
16
+
17
+ ## Setup
18
+
19
+ ```json
20
+ {
21
+ "mcpServers": {
22
+ "billit": {
23
+ "command": "node",
24
+ "args": ["dist/index.js"],
25
+ "env": {
26
+ "BILLIT_API_KEY": "your-api-key",
27
+ "BILLIT_PARTY_ID": "12345",
28
+ "BILLIT_CONTEXT_PARTY_ID": "67890"
29
+ }
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ ## Environment variables
36
+
37
+ | Variable | Required | Description |
38
+ |----------|----------|-------------|
39
+ | BILLIT_API_KEY | Yes | API key from Billit account |
40
+ | BILLIT_PARTY_ID | Yes | Your Billit party ID |
41
+ | BILLIT_CONTEXT_PARTY_ID | No | Context party ID (for accountants acting on behalf) |
@@ -0,0 +1,13 @@
1
+ export interface BillitConfig {
2
+ apiKey: string;
3
+ partyId: number;
4
+ contextPartyId?: number;
5
+ baseUrl?: string;
6
+ }
7
+ export declare class BillitClient {
8
+ readonly baseUrl: string;
9
+ private readonly headers;
10
+ constructor(config: BillitConfig);
11
+ request<T>(method: string, path: string, body?: unknown, partyIdOverride?: number): Promise<T>;
12
+ }
13
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,YAAY;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;gBAErC,MAAM,EAAE,YAAY;IAc1B,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAerG"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BillitClient = void 0;
4
+ class BillitClient {
5
+ baseUrl;
6
+ headers;
7
+ constructor(config) {
8
+ this.baseUrl = config.baseUrl ?? "https://api.billit.be";
9
+ this.headers = {
10
+ "Content-Type": "application/json",
11
+ "ApiKey": config.apiKey,
12
+ };
13
+ if (config.partyId) {
14
+ this.headers["PartyID"] = String(config.partyId);
15
+ }
16
+ if (config.contextPartyId) {
17
+ this.headers["ContextPartyID"] = String(config.contextPartyId);
18
+ }
19
+ }
20
+ async request(method, path, body, partyIdOverride) {
21
+ const headers = { ...this.headers };
22
+ if (partyIdOverride)
23
+ headers["PartyID"] = String(partyIdOverride);
24
+ const res = await fetch(`${this.baseUrl}${path}`, {
25
+ method,
26
+ headers,
27
+ body: body ? JSON.stringify(body) : undefined,
28
+ });
29
+ if (!res.ok) {
30
+ const text = await res.text().catch(() => "");
31
+ throw new Error(`Billit ${res.status} ${method} ${path}: ${text}`);
32
+ }
33
+ if (res.status === 204)
34
+ return undefined;
35
+ return res.json();
36
+ }
37
+ }
38
+ exports.BillitClient = BillitClient;
39
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":";;;AAOA,MAAa,YAAY;IACd,OAAO,CAAS;IACR,OAAO,CAAyB;IAEjD,YAAY,MAAoB;QAC9B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,uBAAuB,CAAC;QACzD,IAAI,CAAC,OAAO,GAAG;YACb,cAAc,EAAE,kBAAkB;YAClC,QAAQ,EAAE,MAAM,CAAC,MAAM;SACxB,CAAC;QACF,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;YAC1B,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAI,MAAc,EAAE,IAAY,EAAE,IAAc,EAAE,eAAwB;QACrF,MAAM,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,eAAe;YAAE,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;YAChD,MAAM;YACN,OAAO;YACP,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC9C,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,MAAM,IAAI,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,SAAc,CAAC;QAC9C,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;IAClC,CAAC;CACF;AAjCD,oCAiCC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
5
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
6
+ const client_js_1 = require("./api/client.js");
7
+ const orders_js_1 = require("./tools/orders.js");
8
+ const parties_js_1 = require("./tools/parties.js");
9
+ const products_js_1 = require("./tools/products.js");
10
+ const peppol_js_1 = require("./tools/peppol.js");
11
+ const documents_js_1 = require("./tools/documents.js");
12
+ const financial_js_1 = require("./tools/financial.js");
13
+ const toprocess_js_1 = require("./tools/toprocess.js");
14
+ function getRequiredEnv(name) {
15
+ const value = process.env[name];
16
+ if (!value)
17
+ throw new Error(`Missing required environment variable: ${name}`);
18
+ return value;
19
+ }
20
+ async function main() {
21
+ const apiKey = getRequiredEnv("BILLIT_API_KEY");
22
+ const partyId = process.env["BILLIT_PARTY_ID"] ? parseInt(process.env["BILLIT_PARTY_ID"], 10) : 0;
23
+ const contextPartyId = process.env["BILLIT_CONTEXT_PARTY_ID"]
24
+ ? parseInt(process.env["BILLIT_CONTEXT_PARTY_ID"], 10)
25
+ : undefined;
26
+ const client = new client_js_1.BillitClient({ apiKey, partyId, contextPartyId });
27
+ const server = new mcp_js_1.McpServer({ name: "billit-mcp", version: "1.0.0" });
28
+ (0, orders_js_1.registerOrderTools)(server, client);
29
+ (0, parties_js_1.registerPartyTools)(server, client);
30
+ (0, products_js_1.registerProductTools)(server, client);
31
+ (0, peppol_js_1.registerPeppolTools)(server, client);
32
+ (0, documents_js_1.registerDocumentTools)(server, client);
33
+ (0, financial_js_1.registerFinancialTools)(server, client);
34
+ (0, toprocess_js_1.registerToProcessTools)(server, client);
35
+ const transport = new stdio_js_1.StdioServerTransport();
36
+ await server.connect(transport);
37
+ }
38
+ main().catch((err) => { console.error(err); process.exit(1); });
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,oEAAoE;AACpE,wEAAiF;AACjF,+CAA+C;AAC/C,iDAAuD;AACvD,mDAAwD;AACxD,qDAA2D;AAC3D,iDAAwD;AACxD,uDAA6D;AAC7D,uDAA8D;AAC9D,uDAA8D;AAE9D,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,IAAI,EAAE,CAAC,CAAC;IAC9E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClG,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC;QAC3D,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,EAAE,EAAE,CAAC;QACtD,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,MAAM,GAAG,IAAI,wBAAY,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;IAErE,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAEvE,IAAA,8BAAkB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,IAAA,+BAAkB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,IAAA,kCAAoB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,IAAA,+BAAmB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,IAAA,oCAAqB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,IAAA,qCAAsB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,IAAA,qCAAsB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEvC,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BillitClient } from "../api/client.js";
3
+ export declare function registerDocumentTools(server: McpServer, client: BillitClient): void;
4
+ //# 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;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAShD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QAoE5E"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerDocumentTools = registerDocumentTools;
4
+ const zod_1 = require("zod");
5
+ function respond(text) {
6
+ return { content: [{ type: "text", text }] };
7
+ }
8
+ const companyId = zod_1.z.coerce.number().optional()
9
+ .describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
10
+ function registerDocumentTools(server, client) {
11
+ server.tool("billit_list_documents", "List documents stored in Billit. Returns document metadata including DocumentID, FileName, and associated order. Supports OData $filter, $orderby, full-text search.\n\nEXAMPLES:\n- orderby='CreationDate desc'\n- filter=\"OrderID eq 12345\"", {
12
+ filter: zod_1.z.string().optional().describe("OData $filter expression. Examples: \"OrderID eq 12345\", \"FileName eq 'invoice.pdf'\""),
13
+ orderby: zod_1.z.string().optional().describe("OData $orderby expression. Examples: 'CreationDate desc', 'FileName asc'"),
14
+ search: zod_1.z.string().optional().describe("Full-text search on document name or content. Sent as 'fullTextSearch' query param."),
15
+ top: zod_1.z.coerce.number().optional().describe("Max results per page (max: 120)"),
16
+ skip: zod_1.z.coerce.number().optional().describe("Items to skip for pagination (default: 0)"),
17
+ company_id: companyId,
18
+ }, async ({ filter, orderby, search, top, skip, company_id }) => {
19
+ const params = new URLSearchParams();
20
+ if (filter)
21
+ params.set("$filter", filter);
22
+ if (orderby)
23
+ params.set("$orderby", orderby);
24
+ if (search)
25
+ params.set("fullTextSearch", search);
26
+ if (top)
27
+ params.set("$top", String(top));
28
+ if (skip)
29
+ params.set("$skip", String(skip));
30
+ const qs = params.toString();
31
+ const data = await client.request("GET", `/v1/documents${qs ? `?${qs}` : ""}`, undefined, company_id);
32
+ return respond(JSON.stringify(data, null, 2));
33
+ });
34
+ server.tool("billit_get_document", "Get metadata and content of a specific document. Returns document details including a fileID (UUID) that can be used with billit_download_file to get the actual file content.", {
35
+ document_id: zod_1.z.coerce.number().describe("Numeric document ID from billit_list_documents result"),
36
+ company_id: companyId,
37
+ }, async ({ document_id, company_id }) => {
38
+ const data = await client.request("GET", `/v1/documents/${document_id}`, undefined, company_id);
39
+ return respond(JSON.stringify(data, null, 2));
40
+ });
41
+ server.tool("billit_upload_document", "Upload a document to Billit (e.g. an incoming invoice PDF for processing). Returns the created DocumentID. Next step: billit_submit_for_processing to have Billit parse the document.\n\nNOTE: file_base64 must be a base64-encoded string of the file content. EXAMPLE: for a PDF, encode the raw bytes as base64. Max file size depends on Billit account settings.", {
42
+ file_base64: zod_1.z.string().describe("Base64-encoded file content"),
43
+ file_name: zod_1.z.string().describe("File name including extension (e.g. 'invoice-2026-001.pdf')"),
44
+ content_type: zod_1.z.string().optional().describe("MIME type (default: 'application/pdf'). Other common values: 'image/jpeg', 'image/png'"),
45
+ company_id: companyId,
46
+ }, async ({ file_base64, file_name, content_type, company_id }) => {
47
+ const body = {
48
+ FileBase64: file_base64, FileName: file_name, ContentType: content_type ?? "application/pdf",
49
+ };
50
+ const data = await client.request("POST", "/v1/documents", body, company_id);
51
+ return respond(JSON.stringify(data, null, 2));
52
+ });
53
+ server.tool("billit_download_file", "Download a file by its UUID. File UUIDs are found in order responses (PDF of the invoice), document responses, or accountant feed items. Returns base64-encoded file content.\n\nCRITICAL: This endpoint uses a UUID (string like 'a1b2c3d4-...'), NOT a numeric ID. The fileID comes from order/document response fields, not from the DocumentID. Do not confuse DocumentID (numeric) with fileID (UUID).", {
54
+ file_id: zod_1.z.string().describe("File UUID (e.g. 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'). Found in order or document response fields. This is NOT the numeric DocumentID."),
55
+ company_id: companyId,
56
+ }, async ({ file_id, company_id }) => {
57
+ const data = await client.request("GET", `/v1/files/${file_id}`, undefined, company_id);
58
+ return respond(JSON.stringify(data, null, 2));
59
+ });
60
+ }
61
+ //# sourceMappingURL=documents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/tools/documents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BillitClient } from "../api/client.js";
3
+ export declare function registerFinancialTools(server: McpServer, client: BillitClient): void;
4
+ //# sourceMappingURL=financial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"financial.d.ts","sourceRoot":"","sources":["../../src/tools/financial.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAShD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QAoL7E"}
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerFinancialTools = registerFinancialTools;
4
+ const zod_1 = require("zod");
5
+ function respond(text) {
6
+ return { content: [{ type: "text", text }] };
7
+ }
8
+ const companyId = zod_1.z.coerce.number().optional()
9
+ .describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
10
+ function registerFinancialTools(server, client) {
11
+ // ── billit_get_account_info ───────────────────────────────────────
12
+ server.tool("billit_get_account_info", "Get account and company information for the authenticated Billit API key. Returns a Companies array with PartyID, Name, VATNumber, and other details for each company associated with the API key.\n\nSTARTUP PROTOCOL: If BILLIT_PARTY_ID env is 0 or unknown, call this tool FIRST before any other Billit tool. Store the Companies array in memory (name → PartyID mapping). Then choose the correct company_id for all subsequent Billit tool calls based on conversation context.\n\nEXAMPLE: after calling this, you know 'JaRa Productions bv' = PartyID 208029 and 'TAILORMADE 2018,SL' = PartyID 663845. When user asks about invoices for JaRa, pass company_id=208029 to billit_list_orders.", {}, async () => {
13
+ const data = await client.request("GET", "/v1/account/accountInformation");
14
+ return respond(JSON.stringify(data, null, 2));
15
+ });
16
+ // ── billit_search_company ─────────────────────────────────────────
17
+ server.tool("billit_search_company", "Search for a Belgian company by name or VAT/KBO number in the official company database. Returns official company name, address, and enterprise number. Use before billit_create_party to auto-fill correct company data.\n\nEXAMPLE: billit_search_company with keywords='BE0123456789' or keywords='Acme NV' returns official KBO data. Use this to avoid typos when creating parties.", {
18
+ keywords: zod_1.z.string()
19
+ .describe("Company name, VAT number (BE0123456789), or KBO enterprise number to search"),
20
+ }, async ({ keywords }) => {
21
+ const data = await client.request("GET", `/v1/misc/companysearch/${encodeURIComponent(keywords)}`);
22
+ return respond(JSON.stringify(data, null, 2));
23
+ });
24
+ // ── billit_list_typecodes ─────────────────────────────────────────
25
+ server.tool("billit_list_typecodes", "List valid type codes for a given category. Use to get valid values for VAT rates, units of measure, languages, etc.\n\nEXAMPLE type code types: 'VATRate' for VAT percentages, 'Unit' for units of measure, 'Language' for supported languages.", {
26
+ type_code_type: zod_1.z.string()
27
+ .describe("Type code category to list (e.g. 'VATRate', 'Unit', 'Language', 'Currency')"),
28
+ }, async ({ type_code_type }) => {
29
+ const data = await client.request("GET", `/v1/misc/typecodes/${encodeURIComponent(type_code_type)}`);
30
+ return respond(JSON.stringify(data, null, 2));
31
+ });
32
+ // ── billit_list_financial_transactions ─────────────────────────────
33
+ server.tool("billit_list_financial_transactions", "List financial transactions in Billit (bank transactions, payments). Use to reconcile payments with orders. Supports full-text search, OData $filter and $orderby.\n\nEXAMPLES:\n- Recent first: orderby='ValueDate desc'\n- Date range: filter=\"ValueDate ge datetime'2026-01-01T00:00:00' and ValueDate le datetime'2026-03-31T23:59:59'\"\n- By counterparty: filter=\"NameCounterParty eq 'Mehmet'\"\n- Combined: orderby='ValueDate desc', filter=\"ValueDate ge datetime'2026-01-01T00:00:00'\"\n\nNOTE: max page size is 120. Date filter requires datetime'' syntax.", {
34
+ search: zod_1.z.string().optional()
35
+ .describe("Full-text search on transaction description, reference, or amount"),
36
+ filter: zod_1.z.string().optional()
37
+ .describe("OData $filter expression. Date syntax requires datetime'': \"ValueDate ge datetime'2026-01-01T00:00:00'\". Other examples: \"NameCounterParty eq 'Mehmet Eryilmaz'\", \"TotalAmount ge 500\""),
38
+ orderby: zod_1.z.string().optional()
39
+ .describe("OData $orderby expression. Examples: 'ValueDate desc', 'TotalAmount desc', 'ValueDate asc'"),
40
+ top: zod_1.z.coerce.number().optional()
41
+ .describe("Max results per page (max: 120)"),
42
+ skip: zod_1.z.coerce.number().optional()
43
+ .describe("Items to skip for pagination (default: 0)"),
44
+ company_id: companyId,
45
+ }, async ({ search, filter, orderby, top, skip, company_id }) => {
46
+ const params = new URLSearchParams();
47
+ if (search)
48
+ params.set("fullTextSearch", search);
49
+ if (filter)
50
+ params.set("$filter", filter);
51
+ if (orderby)
52
+ params.set("$orderby", orderby);
53
+ if (top)
54
+ params.set("$top", String(top));
55
+ if (skip)
56
+ params.set("$skip", String(skip));
57
+ const qs = params.toString();
58
+ const data = await client.request("GET", `/v1/financialTransactions${qs ? `?${qs}` : ""}`, undefined, company_id);
59
+ return respond(JSON.stringify(data, null, 2));
60
+ });
61
+ // ── billit_import_financial_transactions ───────────────────────────
62
+ server.tool("billit_import_financial_transactions", "Import bank transactions from a CODA or MT940 bank statement file. Use to bulk-import bank transactions for payment reconciliation.\n\nNOTE: Supported formats are CODA (Belgian bank format) and MT940 (SWIFT bank format). file_base64 must be base64-encoded file content.", {
63
+ file_base64: zod_1.z.string()
64
+ .describe("Base64-encoded CODA or MT940 bank statement file content"),
65
+ file_name: zod_1.z.string()
66
+ .describe("File name (e.g. 'statement-2026-01.coda' or 'statement.mt940')"),
67
+ content_type: zod_1.z.string()
68
+ .describe("MIME type of the file"),
69
+ company_id: companyId,
70
+ }, async ({ file_base64, file_name, content_type, company_id }) => {
71
+ const body = { FileBase64: file_base64, FileName: file_name, ContentType: content_type };
72
+ const data = await client.request("POST", "/v1/financialTransactions/commands/import", body, company_id);
73
+ return respond(JSON.stringify(data, null, 2));
74
+ });
75
+ // ── billit_list_reports ───────────────────────────────────────────
76
+ server.tool("billit_list_reports", "List available reports in Billit (VAT reports, sales reports, etc.). Returns report metadata. Supports OData $orderby. Use billit_get_report to retrieve the actual report data.", {
77
+ orderby: zod_1.z.string().optional()
78
+ .describe("OData $orderby expression. Example: 'Name asc'"),
79
+ top: zod_1.z.coerce.number().optional()
80
+ .describe("Max results per page (max: 120)"),
81
+ skip: zod_1.z.coerce.number().optional()
82
+ .describe("Items to skip for pagination (default: 0)"),
83
+ company_id: companyId,
84
+ }, async ({ orderby, top, skip, company_id }) => {
85
+ const params = new URLSearchParams();
86
+ if (orderby)
87
+ params.set("$orderby", orderby);
88
+ if (top)
89
+ params.set("$top", String(top));
90
+ if (skip)
91
+ params.set("$skip", String(skip));
92
+ const qs = params.toString();
93
+ const data = await client.request("GET", `/v1/reports${qs ? `?${qs}` : ""}`, undefined, company_id);
94
+ return respond(JSON.stringify(data, null, 2));
95
+ });
96
+ // ── billit_get_report ─────────────────────────────────────────────
97
+ server.tool("billit_get_report", "Get the data of a specific Billit report. Use billit_list_reports to find report IDs.", {
98
+ report_id: zod_1.z.number()
99
+ .describe("Numeric report ID from billit_list_reports result"),
100
+ company_id: companyId,
101
+ }, async ({ report_id, company_id }) => {
102
+ const data = await client.request("GET", `/v1/reports/${report_id}`, undefined, company_id);
103
+ return respond(JSON.stringify(data, null, 2));
104
+ });
105
+ // ── billit_list_accountant_feeds ──────────────────────────────────
106
+ server.tool("billit_list_accountant_feeds", "List all accountant feeds and their pending items. Feeds contain newly exported orders and documents for accountant processing. Poll at most once per minute. Next steps: billit_download_accountant_file to download items, billit_confirm_accountant_feed to confirm processed items.\n\nWARNING: Do not poll more than once per minute — this is a rate-limited endpoint. After downloading feed items, always confirm them with billit_confirm_accountant_feed to remove them from the feed.", { company_id: companyId }, async ({ company_id }) => {
107
+ const data = await client.request("GET", "/v1/accountant/feeds", undefined, company_id);
108
+ return respond(JSON.stringify(data, null, 2));
109
+ });
110
+ // ── billit_register_accountant_feed ───────────────────────────────
111
+ server.tool("billit_register_accountant_feed", "Register a new accountant feed. All newly exported orders and documents will appear in this feed for the accountant to download. One-time setup per accountant integration.", { company_id: companyId }, async ({ company_id }) => {
112
+ const data = await client.request("POST", "/v1/accountant/feeds", undefined, company_id);
113
+ return respond(JSON.stringify(data ?? { success: true }, null, 2));
114
+ });
115
+ // ── billit_confirm_accountant_feed ────────────────────────────────
116
+ server.tool("billit_confirm_accountant_feed", "Confirm that feed items have been successfully downloaded. This removes them from the feed list. Always call this after processing items from billit_list_accountant_feeds.\n\nCRITICAL: Always confirm downloaded items — without confirmation, the same items will reappear on the next poll. Pass the feed item IDs from the billit_list_accountant_feeds response.", {
117
+ feed_item_ids: zod_1.z.array(zod_1.z.string())
118
+ .describe("Array of feed item ID strings to confirm as downloaded. Get these from billit_list_accountant_feeds response."),
119
+ company_id: companyId,
120
+ }, async ({ feed_item_ids, company_id }) => {
121
+ const data = await client.request("POST", "/v1/accountant/feeds/confirm", { FeedItemIds: feed_item_ids }, company_id);
122
+ return respond(JSON.stringify(data ?? { success: true }, null, 2));
123
+ });
124
+ // ── billit_download_accountant_file ───────────────────────────────
125
+ server.tool("billit_download_accountant_file", "Download a file from an accountant feed (e.g. a CODA file or exported invoice). Returns base64-encoded file content.", {
126
+ file_id: zod_1.z.string()
127
+ .describe("File ID from an accountant feed item"),
128
+ company_id: companyId,
129
+ }, async ({ file_id, company_id }) => {
130
+ const data = await client.request("GET", `/v1/accountant/files/${file_id}`, undefined, company_id);
131
+ return respond(JSON.stringify(data, null, 2));
132
+ });
133
+ }
134
+ //# sourceMappingURL=financial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"financial.js","sourceRoot":"","sources":["../../src/tools/financial.ts"],"names":[],"mappings":";;AAWA,wDAoLC;AA9LD,6BAAwB;AAGxB,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,SAAS,GAAG,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC3C,QAAQ,CAAC,iKAAiK,CAAC,CAAC;AAE/K,SAAgB,sBAAsB,CAAC,MAAiB,EAAE,MAAoB;IAC5E,qEAAqE;IACrE,MAAM,CAAC,IAAI,CACT,yBAAyB,EACzB,0qBAA0qB,EAC1qB,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,gCAAgC,CAAC,CAAC;QAC3E,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;IAEF,qEAAqE;IACrE,MAAM,CAAC,IAAI,CACT,uBAAuB,EACvB,0XAA0X,EAC1X;QACE,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;aACjB,QAAQ,CAAC,6EAA6E,CAAC;KAC3F,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,0BAA0B,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACnG,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;IAEF,qEAAqE;IACrE,MAAM,CAAC,IAAI,CACT,uBAAuB,EACvB,kPAAkP,EAClP;QACE,cAAc,EAAE,OAAC,CAAC,MAAM,EAAE;aACvB,QAAQ,CAAC,6EAA6E,CAAC;KAC3F,EACD,KAAK,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE;QAC3B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,sBAAsB,kBAAkB,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QACrG,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;IAEF,sEAAsE;IACtE,MAAM,CAAC,IAAI,CACT,oCAAoC,EACpC,+iBAA+iB,EAC/iB;QACE,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;aAC1B,QAAQ,CAAC,mEAAmE,CAAC;QAChF,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;aAC1B,QAAQ,CAAC,8LAA8L,CAAC;QAC3M,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;aAC3B,QAAQ,CAAC,4FAA4F,CAAC;QACzG,GAAG,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;aAC9B,QAAQ,CAAC,iCAAiC,CAAC;QAC9C,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;aAC/B,QAAQ,CAAC,2CAA2C,CAAC;QACxD,UAAU,EAAE,SAAS;KACtB,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE;QAC3D,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;QACjD,IAAI,MAAM;YAAE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC1C,IAAI,OAAO;YAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC7C,IAAI,GAAG;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACzC,IAAI,IAAI;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5C,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,4BAA4B,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAClH,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;IAEF,sEAAsE;IACtE,MAAM,CAAC,IAAI,CACT,sCAAsC,EACtC,+QAA+Q,EAC/Q;QACE,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE;aACpB,QAAQ,CAAC,0DAA0D,CAAC;QACvE,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE;aAClB,QAAQ,CAAC,gEAAgE,CAAC;QAC7E,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE;aACrB,QAAQ,CAAC,uBAAuB,CAAC;QACpC,UAAU,EAAE,SAAS;KACtB,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,EAAE;QAC7D,MAAM,IAAI,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC;QACzF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,2CAA2C,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACzG,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;IAEF,qEAAqE;IACrE,MAAM,CAAC,IAAI,CACT,qBAAqB,EACrB,kLAAkL,EAClL;QACE,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;aAC3B,QAAQ,CAAC,gDAAgD,CAAC;QAC7D,GAAG,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;aAC9B,QAAQ,CAAC,iCAAiC,CAAC;QAC9C,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;aAC/B,QAAQ,CAAC,2CAA2C,CAAC;QACxD,UAAU,EAAE,SAAS;KACtB,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE;QAC3C,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,IAAI,OAAO;YAAE,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC7C,IAAI,GAAG;YAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACzC,IAAI,IAAI;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5C,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACpG,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;IAEF,qEAAqE;IACrE,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,uFAAuF,EACvF;QACE,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE;aAClB,QAAQ,CAAC,mDAAmD,CAAC;QAChE,UAAU,EAAE,SAAS;KACtB,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,eAAe,SAAS,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAC5F,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;IAEF,qEAAqE;IACrE,MAAM,CAAC,IAAI,CACT,8BAA8B,EAC9B,keAAke,EACle,EAAE,UAAU,EAAE,SAAS,EAAE,EACzB,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;QACvB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,sBAAsB,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACxF,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;IAEF,qEAAqE;IACrE,MAAM,CAAC,IAAI,CACT,iCAAiC,EACjC,6KAA6K,EAC7K,EAAE,UAAU,EAAE,SAAS,EAAE,EACzB,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;QACvB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,sBAAsB,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACzF,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC,CACF,CAAC;IAEF,qEAAqE;IACrE,MAAM,CAAC,IAAI,CACT,gCAAgC,EAChC,wWAAwW,EACxW;QACE,aAAa,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC;aAC/B,QAAQ,CAAC,+GAA+G,CAAC;QAC5H,UAAU,EAAE,SAAS;KACtB,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,EAAE,EAAE;QACtC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,8BAA8B,EAAE,EAAE,WAAW,EAAE,aAAa,EAAE,EAAE,UAAU,CAAC,CAAC;QACtH,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC,CACF,CAAC;IAEF,qEAAqE;IACrE,MAAM,CAAC,IAAI,CACT,iCAAiC,EACjC,sHAAsH,EACtH;QACE,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE;aAChB,QAAQ,CAAC,sCAAsC,CAAC;QACnD,UAAU,EAAE,SAAS;KACtB,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE;QAChC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,wBAAwB,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACnG,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BillitClient } from "../api/client.js";
3
+ export declare function registerOrderTools(server: McpServer, client: BillitClient): void;
4
+ //# sourceMappingURL=orders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orders.d.ts","sourceRoot":"","sources":["../../src/tools/orders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAWhD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QA0MzE"}
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerOrderTools = registerOrderTools;
4
+ const zod_1 = require("zod");
5
+ function respond(text) {
6
+ return { content: [{ type: "text", text }] };
7
+ }
8
+ const companyId = zod_1.z.coerce.number().optional()
9
+ .describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
10
+ const coerceBool = zod_1.z.union([zod_1.z.boolean(), zod_1.z.string().transform(v => v === "true")]).optional();
11
+ function registerOrderTools(server, client) {
12
+ server.tool("billit_list_orders", "List orders from Billit. Returns paginated array of orders (invoices, credit notes, offers). Use direction='Income' for outgoing (sales) orders, direction='Cost' for incoming (purchase) orders. Supports OData filtering and full-text search. Next steps: billit_get_order for full details including order lines, billit_confirm_order to approve, billit_register_payment when paid.\n\nWARNING: OrderDirection 'Income' means money coming IN (= outgoing invoices you send to customers). OrderDirection 'Cost' means money going OUT (= incoming invoices from suppliers). This is counter-intuitive. NOTE: fullTextSearch is a separate query param — do NOT put it in the OData $filter. OData date filter syntax: LastModified ge datetime'2026-01-01T00:00:00'", {
13
+ direction: zod_1.z.enum(["Income", "Cost"]).optional()
14
+ .describe("Filter by order direction: 'Income' = outgoing sales invoices (money coming in), 'Cost' = incoming purchase invoices (money going out)"),
15
+ order_type: zod_1.z.enum(["Invoice", "CreditNote", "Offer"]).optional()
16
+ .describe("Filter by type: 'Invoice', 'CreditNote', or 'Offer'"),
17
+ modified_after: zod_1.z.string().optional()
18
+ .describe("ISO date string — only orders modified after this date. Used in OData filter: LastModified ge datetime'YYYY-MM-DDTHH:MM:SS'"),
19
+ approval_status: zod_1.z.enum(["none", "approved", "rejected"]).optional()
20
+ .describe("Filter by approval status: 'none' (pending), 'approved', 'rejected'"),
21
+ paid: coerceBool.describe("Filter by payment status: true = paid, false = unpaid"),
22
+ search: zod_1.z.string().optional()
23
+ .describe("Full-text search across order fields (order number, customer name, reference). Sent as separate 'fullTextSearch' query param, NOT in OData filter."),
24
+ orderby: zod_1.z.string().optional()
25
+ .describe("OData $orderby expression. Examples: 'OrderDate desc', 'TotalAmountInclVat desc', 'LastModified desc'"),
26
+ top: zod_1.z.coerce.number().optional()
27
+ .describe("Max results per page (max: 120)"),
28
+ skip: zod_1.z.coerce.number().optional()
29
+ .describe("Items to skip for pagination (default: 0)"),
30
+ company_id: companyId,
31
+ }, async ({ direction, order_type, modified_after, approval_status, paid, search, orderby, top, skip, company_id }) => {
32
+ const filters = [];
33
+ if (direction)
34
+ filters.push(`OrderDirection eq '${direction}'`);
35
+ if (order_type)
36
+ filters.push(`OrderType eq '${order_type}'`);
37
+ if (modified_after)
38
+ filters.push(`LastModified ge datetime'${modified_after}'`);
39
+ if (approval_status)
40
+ filters.push(`ApprovalStatus eq '${approval_status}'`);
41
+ if (paid !== undefined)
42
+ filters.push(`Paid eq ${paid}`);
43
+ const params = new URLSearchParams();
44
+ if (filters.length)
45
+ params.set("$filter", filters.join(" and "));
46
+ if (search)
47
+ params.set("fullTextSearch", search);
48
+ if (orderby)
49
+ params.set("$orderby", orderby);
50
+ if (top)
51
+ params.set("$top", String(top));
52
+ if (skip)
53
+ params.set("$skip", String(skip));
54
+ const qs = params.toString();
55
+ const data = await client.request("GET", `/v1/orders${qs ? `?${qs}` : ""}`, undefined, company_id);
56
+ return respond(JSON.stringify(data, null, 2));
57
+ });
58
+ server.tool("billit_get_order", "Get full details of an order including all order lines, customer/supplier info, totals (excl/incl VAT), payment status, and booking entries. Use this after billit_list_orders to get line items. Next steps: billit_update_order (mark paid/sent), billit_register_payment, billit_confirm_order, billit_send_order.", {
59
+ order_id: zod_1.z.coerce.number().describe("Numeric order ID from billit_list_orders result"),
60
+ company_id: companyId,
61
+ }, async ({ order_id, company_id }) => {
62
+ const data = await client.request("GET", `/v1/orders/${order_id}`, undefined, company_id);
63
+ return respond(JSON.stringify(data, null, 2));
64
+ });
65
+ server.tool("billit_create_order", "Create a new order (invoice or credit note) in Billit. For outgoing sales invoices use order_direction='Income'. For incoming purchase invoices use order_direction='Cost'. Returns the created order ID. Next steps: billit_confirm_order to set ApprovalStatus=approved, billit_send_order to email/Peppol.\n\nNOTE: 'lines' parameter must be a JSON string containing an array: '[{\"description\":\"Service\",\"quantity\":1,\"unit_price_excl\":100,\"vat_percentage\":21}]'. EXAMPLE: to create a sales invoice for customer BE0123456789, use order_direction='Income', order_type='Invoice'.", {
66
+ order_type: zod_1.z.enum(["Invoice", "CreditNote"]).describe("'Invoice' or 'CreditNote'"),
67
+ order_direction: zod_1.z.enum(["Income", "Cost"]).describe("'Income' = outgoing sales invoice (you send to customer), 'Cost' = incoming purchase invoice (from supplier)"),
68
+ order_date: zod_1.z.string().describe("Invoice date (YYYY-MM-DD)"),
69
+ customer_name: zod_1.z.string().describe("Customer/supplier company name"),
70
+ customer_vat: zod_1.z.string().optional().describe("VAT number (e.g. BE0123456789)"),
71
+ customer_email: zod_1.z.string().optional().describe("Customer email address"),
72
+ customer_language: zod_1.z.enum(["NL", "FR", "EN", "DE"]).optional().describe("Language code: NL, FR, EN, DE"),
73
+ customer_street: zod_1.z.string().optional().describe("Street name"),
74
+ customer_street_number: zod_1.z.string().optional().describe("Street number"),
75
+ customer_city: zod_1.z.string().optional().describe("City name"),
76
+ customer_zipcode: zod_1.z.string().optional().describe("Postal code"),
77
+ customer_country: zod_1.z.string().optional().describe("Country code (default: BE)"),
78
+ order_title: zod_1.z.string().optional().describe("Invoice title/subject"),
79
+ reference: zod_1.z.string().optional().describe("PO number or external reference"),
80
+ payment_reference: zod_1.z.string().optional().describe("Structured payment reference (e.g. +++084/2613/66074+++)"),
81
+ currency: zod_1.z.string().optional().describe("Currency code (default: EUR)"),
82
+ lines: zod_1.z.string().describe("JSON string array of order lines: [{\"description\": \"...\", \"quantity\": 1, \"unit_price_excl\": 100.0, \"vat_percentage\": 21}]"),
83
+ company_id: companyId,
84
+ }, async (params) => {
85
+ const parsedLines = JSON.parse(params.lines);
86
+ const body = {
87
+ OrderType: params.order_type,
88
+ OrderDirection: params.order_direction,
89
+ OrderDate: params.order_date,
90
+ Customer: {
91
+ Name: params.customer_name,
92
+ PartyType: params.order_direction === "Income" ? "Customer" : "Supplier",
93
+ ...(params.customer_vat && { VATNumber: params.customer_vat }),
94
+ ...(params.customer_email && { Email: params.customer_email }),
95
+ ...(params.customer_language && { Language: params.customer_language }),
96
+ Addresses: (params.customer_street || params.customer_city) ? [{
97
+ AddressType: "InvoiceAddress",
98
+ ...(params.customer_street && { Street: params.customer_street }),
99
+ ...(params.customer_street_number && { StreetNumber: params.customer_street_number }),
100
+ ...(params.customer_city && { City: params.customer_city }),
101
+ ...(params.customer_zipcode && { Zipcode: params.customer_zipcode }),
102
+ CountryCode: params.customer_country ?? "BE",
103
+ }] : undefined,
104
+ },
105
+ OrderLines: parsedLines.map((l) => ({
106
+ Description: l.description, Quantity: l.quantity, UnitPriceExcl: l.unit_price_excl, VATPercentage: l.vat_percentage,
107
+ ...(l.reference && { Reference: l.reference }),
108
+ })),
109
+ ...(params.order_title && { OrderTitle: params.order_title }),
110
+ ...(params.reference && { Reference: params.reference }),
111
+ ...(params.payment_reference && { PaymentReference: params.payment_reference }),
112
+ ...(params.currency && { Currency: params.currency }),
113
+ };
114
+ const data = await client.request("POST", "/v1/orders", body, params.company_id);
115
+ return respond(JSON.stringify(data, null, 2));
116
+ });
117
+ server.tool("billit_update_order", "Update a limited set of fields on an existing order: payment status, send status, approval status, internal info, account code, export flags. Only include fields you want to change — absent fields are not modified.\n\nNOTE: Only fields present in the request are updated. To mark an order as paid, provide both paid=true and paid_date. To approve use billit_confirm_order (shortcut) or set approval_status='approved' here.", {
118
+ order_id: zod_1.z.coerce.number().describe("Numeric order ID to update"),
119
+ paid: coerceBool.describe("Set to true to mark order as paid"),
120
+ paid_date: zod_1.z.string().optional().describe("Date payment was received (YYYY-MM-DD), required when setting paid=true"),
121
+ is_sent: coerceBool.describe("Mark order as sent to customer"),
122
+ approval_status: zod_1.z.enum(["none", "approved", "rejected"]).optional().describe("'none', 'approved', or 'rejected' — controls Billit processing"),
123
+ internal_info: zod_1.z.string().optional().describe("Internal note/memo not visible to customer"),
124
+ account_code: zod_1.z.string().optional().describe("Accounting code for bookkeeping export"),
125
+ invoiced: coerceBool.describe("Mark as invoiced (for offers)"),
126
+ exported_to_connector: coerceBool.describe("Mark as exported to external accounting connector"),
127
+ company_id: companyId,
128
+ }, async ({ order_id, paid, paid_date, is_sent, approval_status, internal_info, account_code, invoiced, exported_to_connector, company_id }) => {
129
+ const body = {};
130
+ if (paid !== undefined)
131
+ body.Paid = paid;
132
+ if (paid_date !== undefined)
133
+ body.PaidDate = paid_date;
134
+ if (is_sent !== undefined)
135
+ body.IsSent = is_sent;
136
+ if (approval_status !== undefined)
137
+ body.ApprovalStatus = approval_status;
138
+ if (internal_info !== undefined)
139
+ body.InternalInfo = internal_info;
140
+ if (account_code !== undefined)
141
+ body.AccountCode = account_code;
142
+ if (invoiced !== undefined)
143
+ body.Invoiced = invoiced;
144
+ if (exported_to_connector !== undefined)
145
+ body.ExportedToConnector = exported_to_connector;
146
+ const data = await client.request("PATCH", `/v1/orders/${order_id}`, body, company_id);
147
+ return respond(JSON.stringify(data, null, 2));
148
+ });
149
+ server.tool("billit_confirm_order", "Shortcut to approve an order for Billit processing. Sets ApprovalStatus to 'approved'. Required before Billit will process/send the invoice. Equivalent to billit_update_order with approval_status='approved'.", {
150
+ order_id: zod_1.z.coerce.number().describe("Numeric order ID to approve"),
151
+ company_id: companyId,
152
+ }, async ({ order_id, company_id }) => {
153
+ const data = await client.request("PATCH", `/v1/orders/${order_id}`, { ApprovalStatus: "approved" }, company_id);
154
+ return respond(JSON.stringify(data, null, 2));
155
+ });
156
+ server.tool("billit_delete_order", "Delete an order. Use with caution — this is permanent. Typically only applicable for draft or rejected orders.", {
157
+ order_id: zod_1.z.coerce.number().describe("Numeric order ID to delete"),
158
+ company_id: companyId,
159
+ }, async ({ order_id, company_id }) => {
160
+ await client.request("DELETE", `/v1/orders/${order_id}`, undefined, company_id);
161
+ return respond(`Order ${order_id} deleted.`);
162
+ });
163
+ server.tool("billit_register_payment", "Register a payment for an order. Use after confirming receipt of payment. Multiple payments can be registered (partial payments). Next step: billit_update_order with paid=true when fully paid.", {
164
+ order_id: zod_1.z.coerce.number().describe("Numeric order ID"),
165
+ amount: zod_1.z.coerce.number().describe("Payment amount as decimal (e.g. 121.00)"),
166
+ payment_date: zod_1.z.string().describe("Date payment was received (YYYY-MM-DD)"),
167
+ payment_reference: zod_1.z.string().optional().describe("Payment reference or bank transaction ID"),
168
+ company_id: companyId,
169
+ }, async ({ order_id, amount, payment_date, payment_reference, company_id }) => {
170
+ const body = { Amount: amount, PaymentDate: payment_date };
171
+ if (payment_reference)
172
+ body.PaymentReference = payment_reference;
173
+ const data = await client.request("POST", `/v1/orders/${order_id}/payments`, body, company_id);
174
+ return respond(JSON.stringify(data, null, 2));
175
+ });
176
+ server.tool("billit_send_order", "Send one or more orders to the customer via email or Peppol (depending on customer configuration). Returns immediately — delivery is async. Prerequisites: order must be confirmed (ApprovalStatus=approved). Use billit_peppol_lookup_participant first to check if customer is on Peppol.\n\nNOTE: Sending method (email vs Peppol) is determined by Billit based on customer configuration. To force Peppol, use billit_peppol_send_order instead. CRITICAL: order must have ApprovalStatus='approved' before sending — use billit_confirm_order first.", {
177
+ order_ids: zod_1.z.array(zod_1.z.number()).describe("Array of numeric order IDs to send (can send multiple at once)"),
178
+ company_id: companyId,
179
+ }, async ({ order_ids, company_id }) => {
180
+ const data = await client.request("POST", "/v1/orders/commands/send", { OrderIDs: order_ids }, company_id);
181
+ return respond(JSON.stringify(data ?? { sent: order_ids }, null, 2));
182
+ });
183
+ }
184
+ //# sourceMappingURL=orders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orders.js","sourceRoot":"","sources":["../../src/tools/orders.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BillitClient } from "../api/client.js";
3
+ export declare function registerPartyTools(server: McpServer, client: BillitClient): void;
4
+ //# sourceMappingURL=parties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parties.d.ts","sourceRoot":"","sources":["../../src/tools/parties.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAShD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QAuHzE"}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerPartyTools = registerPartyTools;
4
+ const zod_1 = require("zod");
5
+ function respond(text) {
6
+ return { content: [{ type: "text", text }] };
7
+ }
8
+ const companyId = zod_1.z.coerce.number().optional()
9
+ .describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
10
+ function registerPartyTools(server, client) {
11
+ server.tool("billit_list_parties", "List parties (customers and/or suppliers) in Billit. Returns array with PartyID, CommercialName, VATNumber, Email, PartyType. Supports OData $filter, $orderby, full-text search. Next steps: billit_get_party for full details, billit_create_order to create an invoice for a party.\n\nEXAMPLES:\n- filter=\"PartyType eq 'Customer'\"\n- filter=\"DisplayName eq 'Acme NV'\"\n- orderby='CommercialName asc'\n\nNOTE: fullTextSearch is a separate param — do NOT put it in OData $filter.", {
12
+ party_type: zod_1.z.enum(["Customer", "Supplier", "Both"]).optional().describe("Shortcut filter by party type. Equivalent to filter=\"PartyType eq '...'\"."),
13
+ filter: zod_1.z.string().optional().describe("OData $filter expression. Examples: \"DisplayName eq 'Acme NV'\", \"PartyType eq 'Customer'\""),
14
+ orderby: zod_1.z.string().optional().describe("OData $orderby expression. Examples: 'CommercialName asc', 'DisplayName desc'"),
15
+ search: zod_1.z.string().optional().describe("Full-text search on name, VAT number, email. Sent as separate 'fullTextSearch' query param."),
16
+ top: zod_1.z.coerce.number().optional().describe("Max results per page (max: 120)"),
17
+ skip: zod_1.z.coerce.number().optional().describe("Items to skip for pagination (default: 0)"),
18
+ company_id: companyId,
19
+ }, async ({ party_type, filter, orderby, search, top, skip, company_id }) => {
20
+ const filters = [];
21
+ if (party_type)
22
+ filters.push(`PartyType eq '${party_type}'`);
23
+ if (filter)
24
+ filters.push(filter);
25
+ const params = new URLSearchParams();
26
+ if (filters.length)
27
+ params.set("$filter", filters.join(" and "));
28
+ if (orderby)
29
+ params.set("$orderby", orderby);
30
+ if (search)
31
+ params.set("fullTextSearch", search);
32
+ if (top)
33
+ params.set("$top", String(top));
34
+ if (skip)
35
+ params.set("$skip", String(skip));
36
+ const qs = params.toString();
37
+ const data = await client.request("GET", `/v1/parties${qs ? `?${qs}` : ""}`, undefined, company_id);
38
+ return respond(JSON.stringify(data, null, 2));
39
+ });
40
+ server.tool("billit_get_party", "Get full details of a party including all addresses, identifiers (GLN, VAT), IBAN/BIC, language, and contact info. Use PartyID from billit_list_parties.", {
41
+ party_id: zod_1.z.coerce.number().describe("Numeric party ID from billit_list_parties result"),
42
+ company_id: companyId,
43
+ }, async ({ party_id, company_id }) => {
44
+ const data = await client.request("GET", `/v1/parties/${party_id}`, undefined, company_id);
45
+ return respond(JSON.stringify(data, null, 2));
46
+ });
47
+ server.tool("billit_create_party", "Create a new customer or supplier party in Billit. Use billit_search_company first to auto-fill company details from KBO/VAT lookup. Returns the created PartyID. Next steps: billit_create_order to create an invoice for this party.\n\nNOTE: Use billit_search_company with the company VAT/KBO number to look up official company data (name, address) before creating. This avoids typos and ensures correct data.", {
48
+ commercial_name: zod_1.z.string().describe("Company or person name (required)"),
49
+ party_type: zod_1.z.enum(["Customer", "Supplier", "Both"]).optional().describe("'Customer', 'Supplier', or 'Both' (default: Customer)"),
50
+ vat_number: zod_1.z.string().optional().describe("VAT number in BE format: BE0123456789"),
51
+ enterprise_number: zod_1.z.string().optional().describe("KBO enterprise number (9 digits)"),
52
+ email: zod_1.z.string().optional().describe("Primary email address"),
53
+ phone: zod_1.z.string().optional().describe("Phone number"),
54
+ language: zod_1.z.enum(["NL", "FR", "EN", "DE"]).optional().describe("Communication language: NL, FR, EN, or DE"),
55
+ iban: zod_1.z.string().optional().describe("IBAN bank account number"),
56
+ bic: zod_1.z.string().optional().describe("BIC/SWIFT code"),
57
+ street: zod_1.z.string().optional().describe("Street name"),
58
+ street_number: zod_1.z.string().optional().describe("Street number"),
59
+ box: zod_1.z.string().optional().describe("Box/apartment number"),
60
+ zipcode: zod_1.z.string().optional().describe("Postal code"),
61
+ city: zod_1.z.string().optional().describe("City name"),
62
+ country_code: zod_1.z.string().optional().describe("ISO country code (default: BE)"),
63
+ address_type: zod_1.z.enum(["InvoiceAddress", "DeliveryAddress"]).optional().describe("Address type: 'InvoiceAddress' (default) or 'DeliveryAddress'"),
64
+ company_id: companyId,
65
+ }, async (params) => {
66
+ const body = {
67
+ CommercialName: params.commercial_name,
68
+ PartyType: params.party_type ?? "Customer",
69
+ ...(params.vat_number && { VATNumber: params.vat_number }),
70
+ ...(params.enterprise_number && { EnterpriseNumber: params.enterprise_number }),
71
+ ...(params.email && { Email: params.email }),
72
+ ...(params.phone && { Phone: params.phone }),
73
+ ...(params.language && { Language: params.language }),
74
+ ...(params.iban && { IBAN: params.iban }),
75
+ ...(params.bic && { BIC: params.bic }),
76
+ };
77
+ if (params.street || params.city) {
78
+ body.Addresses = [{
79
+ AddressType: params.address_type ?? "InvoiceAddress",
80
+ ...(params.street && { Street: params.street }),
81
+ ...(params.street_number && { StreetNumber: params.street_number }),
82
+ ...(params.box && { Box: params.box }),
83
+ ...(params.zipcode && { Zipcode: params.zipcode }),
84
+ ...(params.city && { City: params.city }),
85
+ CountryCode: params.country_code ?? "BE",
86
+ }];
87
+ }
88
+ const data = await client.request("POST", "/v1/parties", body, params.company_id);
89
+ return respond(JSON.stringify(data, null, 2));
90
+ });
91
+ server.tool("billit_update_party", "Update party details. Only fields provided in the request are modified — absent fields remain unchanged.", {
92
+ party_id: zod_1.z.coerce.number().describe("Numeric party ID to update"),
93
+ commercial_name: zod_1.z.string().optional().describe("Updated company or person name"),
94
+ vat_number: zod_1.z.string().optional().describe("Updated VAT number"),
95
+ email: zod_1.z.string().optional().describe("Updated email address"),
96
+ phone: zod_1.z.string().optional().describe("Updated phone number"),
97
+ language: zod_1.z.enum(["NL", "FR", "EN", "DE"]).optional().describe("Updated language: NL, FR, EN, or DE"),
98
+ iban: zod_1.z.string().optional().describe("Updated IBAN"),
99
+ bic: zod_1.z.string().optional().describe("Updated BIC/SWIFT"),
100
+ company_id: companyId,
101
+ }, async ({ party_id, commercial_name, vat_number, email, phone, language, iban, bic, company_id }) => {
102
+ const body = {};
103
+ if (commercial_name !== undefined)
104
+ body.CommercialName = commercial_name;
105
+ if (vat_number !== undefined)
106
+ body.VATNumber = vat_number;
107
+ if (email !== undefined)
108
+ body.Email = email;
109
+ if (phone !== undefined)
110
+ body.Phone = phone;
111
+ if (language !== undefined)
112
+ body.Language = language;
113
+ if (iban !== undefined)
114
+ body.IBAN = iban;
115
+ if (bic !== undefined)
116
+ body.BIC = bic;
117
+ const data = await client.request("PATCH", `/v1/parties/${party_id}`, body, company_id);
118
+ return respond(JSON.stringify(data, null, 2));
119
+ });
120
+ }
121
+ //# sourceMappingURL=parties.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parties.js","sourceRoot":"","sources":["../../src/tools/parties.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BillitClient } from "../api/client.js";
3
+ export declare function registerPeppolTools(server: McpServer, client: BillitClient): void;
4
+ //# sourceMappingURL=peppol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peppol.d.ts","sourceRoot":"","sources":["../../src/tools/peppol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAShD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QA2F1E"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerPeppolTools = registerPeppolTools;
4
+ const zod_1 = require("zod");
5
+ function respond(text) {
6
+ return { content: [{ type: "text", text }] };
7
+ }
8
+ const companyId = zod_1.z.coerce.number().optional()
9
+ .describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
10
+ function registerPeppolTools(server, client) {
11
+ server.tool("billit_peppol_list_inbox", "List incoming Peppol messages (e-invoices received from suppliers via the Peppol network). Returns inbox items with inboxItemId, sender, document type, and date. Supports OData $orderby. Next steps: billit_peppol_confirm_inbox to accept, billit_peppol_refuse_inbox to reject.", {
12
+ orderby: zod_1.z.string().optional().describe("OData $orderby expression. Example: 'ReceivedDate desc'"),
13
+ top: zod_1.z.coerce.number().optional().describe("Max results per page (max: 120)"),
14
+ skip: zod_1.z.coerce.number().optional().describe("Items to skip for pagination (default: 0)"),
15
+ company_id: companyId,
16
+ }, async ({ orderby, top, skip, company_id }) => {
17
+ const params = new URLSearchParams();
18
+ if (orderby)
19
+ params.set("$orderby", orderby);
20
+ if (top)
21
+ params.set("$top", String(top));
22
+ if (skip)
23
+ params.set("$skip", String(skip));
24
+ const qs = params.toString();
25
+ const data = await client.request("GET", `/v1/peppol/inbox${qs ? `?${qs}` : ""}`, undefined, company_id);
26
+ return respond(JSON.stringify(data, null, 2));
27
+ });
28
+ server.tool("billit_peppol_confirm_inbox", "Accept an incoming Peppol message. Marks the item as processed and accepted. Use after reviewing an incoming e-invoice.", {
29
+ inbox_item_id: zod_1.z.string().describe("Inbox item ID from billit_peppol_list_inbox result"),
30
+ company_id: companyId,
31
+ }, async ({ inbox_item_id, company_id }) => {
32
+ const data = await client.request("POST", `/v1/peppol/inbox/${inbox_item_id}/confirm`, undefined, company_id);
33
+ return respond(JSON.stringify(data ?? { success: true }, null, 2));
34
+ });
35
+ server.tool("billit_peppol_refuse_inbox", "Refuse/reject an incoming Peppol message. Use when an incoming e-invoice is incorrect or unexpected.", {
36
+ inbox_item_id: zod_1.z.string().describe("Inbox item ID from billit_peppol_list_inbox result"),
37
+ company_id: companyId,
38
+ }, async ({ inbox_item_id, company_id }) => {
39
+ const data = await client.request("POST", `/v1/peppol/inbox/${inbox_item_id}/refuse`, undefined, company_id);
40
+ return respond(JSON.stringify(data ?? { success: true }, null, 2));
41
+ });
42
+ server.tool("billit_peppol_send_order", "Send a specific order directly via the Peppol e-invoicing network. Use billit_peppol_lookup_participant first to verify the customer is a Peppol participant. Prerequisites: order must be confirmed (ApprovalStatus=approved).\n\nCRITICAL: The customer must be registered on Peppol before you can send. Use billit_peppol_lookup_participant with their VAT/CBE number first. If they are not on Peppol, use billit_send_order (which falls back to email) instead.", {
43
+ order_id: zod_1.z.coerce.number().describe("Numeric order ID to send via Peppol"),
44
+ company_id: companyId,
45
+ }, async ({ order_id, company_id }) => {
46
+ const data = await client.request("POST", "/v1/peppol/sendOrder", { OrderID: order_id }, company_id);
47
+ return respond(JSON.stringify(data ?? { success: true }, null, 2));
48
+ });
49
+ server.tool("billit_peppol_lookup_participant", "Check if a company is registered as a Peppol participant. Returns participant information including endpoint and supported document types. Use before billit_peppol_send_order to verify the customer is reachable.", {
50
+ vat_or_cbe: zod_1.z.string().describe("Company VAT number (e.g. BE0123456789) or CBE/KBO enterprise number to look up on Peppol"),
51
+ }, async ({ vat_or_cbe }) => {
52
+ const data = await client.request("GET", `/v1/peppol/participantInformation/${vat_or_cbe}`);
53
+ return respond(JSON.stringify(data, null, 2));
54
+ });
55
+ server.tool("billit_peppol_register", "Register the current Billit party as a Peppol participant. Enables receiving e-invoices via Peppol and sending outgoing invoices via the network. One-time setup operation.", { company_id: companyId }, async ({ company_id }) => {
56
+ const data = await client.request("POST", "/v1/peppol/participants", undefined, company_id);
57
+ return respond(JSON.stringify(data ?? { success: true }, null, 2));
58
+ });
59
+ server.tool("billit_peppol_unregister", "Unregister the current Billit party from the Peppol network. After this, the party can no longer receive or send via Peppol. Use with caution.\n\nWARNING: Unregistering from Peppol is immediate and affects all incoming e-invoices. Confirm with the user before calling this.", { company_id: companyId }, async ({ company_id }) => {
60
+ const data = await client.request("DELETE", "/v1/peppol/participants", undefined, company_id);
61
+ return respond(JSON.stringify(data ?? { success: true }, null, 2));
62
+ });
63
+ }
64
+ //# sourceMappingURL=peppol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peppol.js","sourceRoot":"","sources":["../../src/tools/peppol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BillitClient } from "../api/client.js";
3
+ export declare function registerProductTools(server: McpServer, client: BillitClient): void;
4
+ //# sourceMappingURL=products.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../src/tools/products.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAShD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QA2D3E"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerProductTools = registerProductTools;
4
+ const zod_1 = require("zod");
5
+ function respond(text) {
6
+ return { content: [{ type: "text", text }] };
7
+ }
8
+ const companyId = zod_1.z.coerce.number().optional()
9
+ .describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
10
+ function registerProductTools(server, client) {
11
+ server.tool("billit_list_products", "List products/services in the Billit product catalog. Returns ProductID, Description, Reference, UnitPrice, VATPercentage, Unit. Supports OData $filter, $orderby, full-text search. Next step: billit_create_order using product descriptions and prices.\n\nEXAMPLES:\n- orderby='Description asc'\n- filter=\"VATPercentage eq 21\"", {
12
+ filter: zod_1.z.string().optional().describe("OData $filter expression. Examples: \"VATPercentage eq 21\", \"Reference eq 'SKU-001'\""),
13
+ orderby: zod_1.z.string().optional().describe("OData $orderby expression. Examples: 'Description asc', 'UnitPrice desc'"),
14
+ search: zod_1.z.string().optional().describe("Full-text search on product description or reference code. Sent as 'fullTextSearch' query param."),
15
+ top: zod_1.z.coerce.number().optional().describe("Max results per page (max: 120)"),
16
+ skip: zod_1.z.coerce.number().optional().describe("Items to skip for pagination (default: 0)"),
17
+ company_id: companyId,
18
+ }, async ({ filter, orderby, search, top, skip, company_id }) => {
19
+ const params = new URLSearchParams();
20
+ if (filter)
21
+ params.set("$filter", filter);
22
+ if (orderby)
23
+ params.set("$orderby", orderby);
24
+ if (search)
25
+ params.set("fullTextSearch", search);
26
+ if (top)
27
+ params.set("$top", String(top));
28
+ if (skip)
29
+ params.set("$skip", String(skip));
30
+ const qs = params.toString();
31
+ const data = await client.request("GET", `/v1/products${qs ? `?${qs}` : ""}`, undefined, company_id);
32
+ return respond(JSON.stringify(data, null, 2));
33
+ });
34
+ server.tool("billit_get_product", "Get full details of a single product including price, VAT percentage, and unit. Use ProductID from billit_list_products.", {
35
+ product_id: zod_1.z.coerce.number().describe("Numeric product ID from billit_list_products result"),
36
+ company_id: companyId,
37
+ }, async ({ product_id, company_id }) => {
38
+ const data = await client.request("GET", `/v1/products/${product_id}`, undefined, company_id);
39
+ return respond(JSON.stringify(data, null, 2));
40
+ });
41
+ server.tool("billit_create_product", "Create a new product in the Billit catalog, or update an existing product if one with the same reference already exists. Use to maintain a reusable product list for order lines.\n\nNOTE: If a product with the same 'reference' already exists, this acts as an upsert (update). Use a unique reference code to distinguish products.", {
42
+ description: zod_1.z.string().describe("Product or service description (required)"),
43
+ reference: zod_1.z.string().optional().describe("Unique product reference/SKU code. If a product with this reference exists, it will be updated."),
44
+ unit_price: zod_1.z.coerce.number().optional().describe("Default unit price (excl. VAT) as decimal"),
45
+ vat_percentage: zod_1.z.coerce.number().optional().describe("VAT percentage as number (e.g. 21 for 21%, 0 for VAT exempt)"),
46
+ unit: zod_1.z.string().optional().describe("Unit of measure (e.g. 'piece', 'hour', 'kg')"),
47
+ company_id: companyId,
48
+ }, async ({ description, reference, unit_price, vat_percentage, unit, company_id }) => {
49
+ const body = { Description: description };
50
+ if (reference !== undefined)
51
+ body.Reference = reference;
52
+ if (unit_price !== undefined)
53
+ body.UnitPrice = unit_price;
54
+ if (vat_percentage !== undefined)
55
+ body.VATPercentage = vat_percentage;
56
+ if (unit !== undefined)
57
+ body.Unit = unit;
58
+ const data = await client.request("POST", "/v1/products", body, company_id);
59
+ return respond(JSON.stringify(data, null, 2));
60
+ });
61
+ }
62
+ //# sourceMappingURL=products.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"products.js","sourceRoot":"","sources":["../../src/tools/products.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BillitClient } from "../api/client.js";
3
+ export declare function registerToProcessTools(server: McpServer, client: BillitClient): void;
4
+ //# sourceMappingURL=toprocess.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toprocess.d.ts","sourceRoot":"","sources":["../../src/tools/toprocess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAShD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QA+B7E"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerToProcessTools = registerToProcessTools;
4
+ const zod_1 = require("zod");
5
+ function respond(text) {
6
+ return { content: [{ type: "text", text }] };
7
+ }
8
+ const companyId = zod_1.z.coerce.number().optional()
9
+ .describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
10
+ function registerToProcessTools(server, client) {
11
+ server.tool("billit_submit_for_processing", "Submit a file (e.g. incoming invoice PDF) to Billit for automated processing. Billit will parse the document and create a corresponding order. Returns an uploadID that can be used to cancel. Use for processing incoming supplier invoices without manual data entry.\n\nNOTE: file_base64 must be base64-encoded file content. The processing is async — Billit will parse the document and create an order in the background. Use billit_list_orders with direction='Cost' after processing to find the created order.", {
12
+ file_base64: zod_1.z.string().describe("Base64-encoded file content of the document to process"),
13
+ file_name: zod_1.z.string().describe("File name including extension (e.g. 'supplier-invoice-001.pdf')"),
14
+ content_type: zod_1.z.string().optional().describe("MIME type (default: 'application/pdf'). Billit processes PDF and common image formats."),
15
+ company_id: companyId,
16
+ }, async ({ file_base64, file_name, content_type, company_id }) => {
17
+ const body = {
18
+ FileBase64: file_base64, FileName: file_name, ContentType: content_type ?? "application/pdf",
19
+ };
20
+ const data = await client.request("POST", "/v1/toProcess", body, company_id);
21
+ return respond(JSON.stringify(data, null, 2));
22
+ });
23
+ server.tool("billit_cancel_processing", "Cancel a pending processing upload. Use if a wrong file was submitted. Only works while the upload is still pending — cannot cancel already-processed documents.", {
24
+ upload_id: zod_1.z.string().describe("Upload ID returned by billit_submit_for_processing"),
25
+ company_id: companyId,
26
+ }, async ({ upload_id, company_id }) => {
27
+ const data = await client.request("DELETE", `/v1/toProcess/${upload_id}`, undefined, company_id);
28
+ return respond(JSON.stringify(data ?? { success: true }, null, 2));
29
+ });
30
+ }
31
+ //# sourceMappingURL=toprocess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toprocess.js","sourceRoot":"","sources":["../../src/tools/toprocess.ts"],"names":[],"mappings":";;AAWA,wDA+BC;AAzCD,6BAAwB;AAGxB,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,MAAM,SAAS,GAAG,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC3C,QAAQ,CAAC,iKAAiK,CAAC,CAAC;AAE/K,SAAgB,sBAAsB,CAAC,MAAiB,EAAE,MAAoB;IAC5E,MAAM,CAAC,IAAI,CACT,8BAA8B,EAC9B,4fAA4f,EAC5f;QACE,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wDAAwD,CAAC;QAC1F,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iEAAiE,CAAC;QACjG,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wFAAwF,CAAC;QACtI,UAAU,EAAE,SAAS;KACtB,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,EAAE;QAC7D,MAAM,IAAI,GAA4B;YACpC,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,IAAI,iBAAiB;SAC7F,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QAC7E,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,0BAA0B,EAC1B,kKAAkK,EAClK;QACE,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oDAAoD,CAAC;QACpF,UAAU,EAAE,SAAS;KACtB,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,iBAAiB,SAAS,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACjG,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@tailormade/billit-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for the Billit invoicing API — orders, parties, products, Peppol, documents and more.",
5
+ "main": "dist/index.js",
6
+ "bin": { "billit-mcp": "dist/index.js" },
7
+ "files": ["dist"],
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "dev": "tsx src/index.ts",
11
+ "start": "node dist/index.js",
12
+ "lint": "tsc --noEmit",
13
+ "typecheck": "tsc --noEmit",
14
+ "check-coverage": "tsx scripts/check-coverage.ts",
15
+ "prepare": "npm run build"
16
+ },
17
+ "keywords": ["mcp", "billit", "invoicing", "peppol", "e-invoice", "model-context-protocol", "ai", "claude", "tailormade"],
18
+ "author": "Tailormade",
19
+ "license": "MIT",
20
+ "engines": { "node": ">=20.0.0" },
21
+ "dependencies": {
22
+ "@modelcontextprotocol/sdk": "^1.5.0",
23
+ "zod": "^4.3.6"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^22.0.0",
27
+ "tsx": "^4.19.0",
28
+ "typescript": "^5.7.0"
29
+ }
30
+ }