mcp-server-acube 0.1.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/dist/client.js ADDED
@@ -0,0 +1,172 @@
1
+ /**
2
+ * @module client
3
+ *
4
+ * HTTP client for the A-Cube API with automatic JWT authentication.
5
+ *
6
+ * The client handles:
7
+ * - Login via email/password and JWT token caching (24h lifetime, 23h refresh).
8
+ * - Automatic token injection on every request.
9
+ * - Content negotiation: JSON, XML, PDF (base64), HTML.
10
+ * - Two base URLs per environment: `common` (authentication) and `govIt` (API operations).
11
+ * - Error handling with clear messages including HTTP status codes.
12
+ *
13
+ * @see https://docs.acubeapi.com/
14
+ */
15
+ /**
16
+ * Base URLs for each A-Cube environment.
17
+ *
18
+ * - `common`: Used for authentication (`POST /login`).
19
+ * - `govIt`: Used for all API operations (invoices, notifications, etc.).
20
+ */
21
+ const BASE_URLS = {
22
+ production: {
23
+ common: "https://common.api.acubeapi.com",
24
+ govIt: "https://api.acubeapi.com",
25
+ },
26
+ sandbox: {
27
+ common: "https://common-sandbox.api.acubeapi.com",
28
+ govIt: "https://api-sandbox.acubeapi.com",
29
+ },
30
+ };
31
+ /**
32
+ * A-Cube API client with automatic JWT authentication.
33
+ *
34
+ * Usage:
35
+ * ```ts
36
+ * const client = new AcubeClient({ email: "...", password: "...", environment: "sandbox" });
37
+ * const invoices = await client.get("/invoices?page=1");
38
+ * ```
39
+ *
40
+ * The client automatically handles login and token refresh. The JWT token is
41
+ * cached for 23 hours (1h safety buffer before the actual 24h expiry).
42
+ */
43
+ export class AcubeClient {
44
+ config;
45
+ token = null;
46
+ tokenExpiresAt = 0;
47
+ constructor(config) {
48
+ this.config = config;
49
+ }
50
+ /** Returns the base URL for the given service in the configured environment. */
51
+ getBaseUrl(service) {
52
+ return BASE_URLS[this.config.environment][service];
53
+ }
54
+ /**
55
+ * Authenticate with A-Cube and cache the JWT token.
56
+ *
57
+ * The token has a 24h lifetime. We cache it for 23h to avoid edge-case
58
+ * expiry during a request. As per A-Cube best practices, we minimize
59
+ * login calls by reusing the cached token.
60
+ */
61
+ async login() {
62
+ const url = `${this.getBaseUrl("common")}/login`;
63
+ const response = await fetch(url, {
64
+ method: "POST",
65
+ headers: { "Content-Type": "application/json" },
66
+ body: JSON.stringify({
67
+ email: this.config.email,
68
+ password: this.config.password,
69
+ }),
70
+ });
71
+ if (!response.ok) {
72
+ const error = await response.text();
73
+ throw new Error(`Acube login failed (${response.status}): ${error}`);
74
+ }
75
+ const data = (await response.json());
76
+ this.token = data.token;
77
+ this.tokenExpiresAt = Date.now() + 23 * 60 * 60 * 1000;
78
+ return this.token;
79
+ }
80
+ /** Returns a valid token, refreshing it if expired. */
81
+ async getToken() {
82
+ if (this.token && Date.now() < this.tokenExpiresAt) {
83
+ return this.token;
84
+ }
85
+ return this.login();
86
+ }
87
+ /**
88
+ * Make an authenticated API request.
89
+ *
90
+ * Handles:
91
+ * - Automatic Bearer token injection.
92
+ * - Content-Type negotiation based on body presence.
93
+ * - Binary responses (PDF) returned as base64 strings.
94
+ * - JSON parsing with fallback to raw text.
95
+ * - HTTP 202 treated as success (used by A-Cube for invoice submission).
96
+ *
97
+ * @param method - HTTP method (GET, POST, PUT, DELETE).
98
+ * @param path - API path (e.g., `/invoices`). Appended to the base URL.
99
+ * @param options - Request options: service, body, headers, accept type.
100
+ * @returns Object with `status`, `data` (parsed), and optionally `raw` (for binary).
101
+ */
102
+ async request(method, path, options = {}) {
103
+ const { service = "govIt", body, headers: extraHeaders = {}, accept = "application/json", } = options;
104
+ const token = await this.getToken();
105
+ const url = `${this.getBaseUrl(service)}${path}`;
106
+ const headers = {
107
+ Authorization: `Bearer ${token}`,
108
+ Accept: accept,
109
+ ...extraHeaders,
110
+ };
111
+ if (body && !headers["Content-Type"]) {
112
+ headers["Content-Type"] = "application/json";
113
+ }
114
+ const fetchOptions = {
115
+ method,
116
+ headers,
117
+ };
118
+ if (body) {
119
+ fetchOptions.body =
120
+ typeof body === "string" ? body : JSON.stringify(body);
121
+ }
122
+ const response = await fetch(url, fetchOptions);
123
+ // Binary responses (PDF): return as base64
124
+ if (accept === "application/pdf" ||
125
+ accept === "application/octet-stream") {
126
+ if (!response.ok) {
127
+ const error = await response.text();
128
+ throw new Error(`Acube API error (${response.status}): ${error}`);
129
+ }
130
+ const raw = await response.arrayBuffer();
131
+ return {
132
+ status: response.status,
133
+ data: Buffer.from(raw).toString("base64"),
134
+ raw,
135
+ };
136
+ }
137
+ // Text responses (JSON, XML, HTML)
138
+ const text = await response.text();
139
+ // HTTP 202 is success for A-Cube (invoice submission)
140
+ if (!response.ok && response.status !== 202) {
141
+ throw new Error(`Acube API error (${response.status}): ${text}`);
142
+ }
143
+ if (accept === "application/json" ||
144
+ response.headers.get("content-type")?.includes("json")) {
145
+ try {
146
+ const data = JSON.parse(text);
147
+ return { status: response.status, data };
148
+ }
149
+ catch {
150
+ return { status: response.status, data: text };
151
+ }
152
+ }
153
+ return { status: response.status, data: text };
154
+ }
155
+ /** Shorthand for `request("GET", path, options)`. */
156
+ async get(path, options) {
157
+ return this.request("GET", path, options);
158
+ }
159
+ /** Shorthand for `request("POST", path, { body, ...options })`. */
160
+ async post(path, body, options) {
161
+ return this.request("POST", path, { ...options, body });
162
+ }
163
+ /** Shorthand for `request("PUT", path, { body, ...options })`. */
164
+ async put(path, body, options) {
165
+ return this.request("PUT", path, { ...options, body });
166
+ }
167
+ /** Shorthand for `request("DELETE", path, options)`. */
168
+ async delete(path, options) {
169
+ return this.request("DELETE", path, options);
170
+ }
171
+ }
172
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * @module index
4
+ *
5
+ * Entry point for the A-Cube MCP server.
6
+ *
7
+ * Reads credentials from environment variables, initializes the
8
+ * {@link AcubeClient}, creates an MCP server with stdio transport,
9
+ * and registers all 38 tools across 8 modules.
10
+ *
11
+ * Environment variables:
12
+ * - `ACUBE_EMAIL` (required) -- A-Cube account email.
13
+ * - `ACUBE_PASSWORD` (required) -- A-Cube account password.
14
+ * - `ACUBE_ENVIRONMENT` (optional, default `"sandbox"`) -- `"sandbox"` or `"production"`.
15
+ *
16
+ * @example
17
+ * ```bash
18
+ * ACUBE_EMAIL=me@example.com ACUBE_PASSWORD=secret node dist/index.js
19
+ * ```
20
+ */
21
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
22
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
23
+ import { AcubeClient } from "./client.js";
24
+ import { registerInvoiceTools } from "./tools/invoices.js";
25
+ import { registerInvoiceExtractTools } from "./tools/invoice-extract.js";
26
+ import { registerNotificationTools } from "./tools/notifications.js";
27
+ import { registerVerifyTools } from "./tools/verify.js";
28
+ import { registerReceiptTools } from "./tools/receipts.js";
29
+ import { registerWebhookTools } from "./tools/webhooks.js";
30
+ import { registerConfigurationTools } from "./tools/configurations.js";
31
+ import { registerCassettoFiscaleTools } from "./tools/cassetto-fiscale.js";
32
+ // --- Validate required environment variables ---
33
+ const email = process.env.ACUBE_EMAIL;
34
+ const password = process.env.ACUBE_PASSWORD;
35
+ if (!email || !password) {
36
+ console.error("Error: ACUBE_EMAIL and ACUBE_PASSWORD environment variables are required.\n" +
37
+ "Configure them in your MCP client settings:\n" +
38
+ ' "env": { "ACUBE_EMAIL": "...", "ACUBE_PASSWORD": "...", "ACUBE_ENVIRONMENT": "sandbox" }');
39
+ process.exit(1);
40
+ }
41
+ const environment = (process.env.ACUBE_ENVIRONMENT === "production" ? "production" : "sandbox");
42
+ // --- Initialize API client ---
43
+ const client = new AcubeClient({ email, password, environment });
44
+ // --- Create MCP server ---
45
+ const server = new McpServer({
46
+ name: "mcp-server-acube",
47
+ version: "0.1.0",
48
+ });
49
+ // --- Register all tools ---
50
+ registerInvoiceTools(server, client);
51
+ registerInvoiceExtractTools(server, client);
52
+ registerNotificationTools(server, client);
53
+ registerVerifyTools(server, client);
54
+ registerReceiptTools(server, client);
55
+ registerWebhookTools(server, client);
56
+ registerConfigurationTools(server, client);
57
+ registerCassettoFiscaleTools(server, client);
58
+ // --- Graceful shutdown ---
59
+ process.on("SIGINT", async () => {
60
+ await server.close();
61
+ process.exit(0);
62
+ });
63
+ // --- Start server ---
64
+ const transport = new StdioServerTransport();
65
+ await server.connect(transport);
66
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAE3E,kDAAkD;AAClD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;AACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AAE5C,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;IACxB,OAAO,CAAC,KAAK,CACX,6EAA6E;QAC7E,+CAA+C;QAC/C,4FAA4F,CAC7F,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,WAAW,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAA6B,CAAC;AAE5H,gCAAgC;AAChC,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;AAEjE,4BAA4B;AAC5B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,kBAAkB;IACxB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,6BAA6B;AAC7B,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,2BAA2B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC5C,yBAAyB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC1C,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACrC,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC3C,4BAA4B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C,4BAA4B;AAC5B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;IAC9B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,uBAAuB;AACvB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pick-fields.js","sourceRoot":"","sources":["../src/pick-fields.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @module response
3
+ *
4
+ * Response formatting utilities for the A-Cube MCP server.
5
+ *
6
+ * Every tool response passes through these utilities to minimize LLM token
7
+ * consumption. Three optimizations are applied:
8
+ *
9
+ * 1. **Field selection** (`pickFields`) -- Return only the requested fields,
10
+ * with dot-notation support for nested paths (e.g., `"sender.business_name"`).
11
+ *
12
+ * 2. **Null stripping** (`stripEmpty`) -- Recursively remove `null`, `undefined`,
13
+ * and empty objects. A typical A-Cube invoice has ~60 null fields across
14
+ * sender and recipient objects; stripping them reduces token count by ~50%.
15
+ *
16
+ * 3. **Compact JSON** -- Serialize without indentation. The LLM reads compact
17
+ * JSON just as well, and whitespace tokens add up quickly on large responses.
18
+ */
19
+ /**
20
+ * Recursively pick only the specified fields from an object or array of objects.
21
+ *
22
+ * Supports dot-notation for nested paths. When multiple sub-fields of the same
23
+ * parent are requested, they are merged into a single object.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * pickFields(invoice, ["uuid", "sender.business_name", "sender.business_vat_number_code"])
28
+ * // => { uuid: "...", sender: { business_name: "...", business_vat_number_code: "..." } }
29
+ * ```
30
+ *
31
+ * When applied to an array, each element is filtered individually.
32
+ */
33
+ export declare function pickFields(data: unknown, fields: string[]): unknown;
34
+ /**
35
+ * Recursively strip `null`, `undefined`, and empty objects from data.
36
+ *
37
+ * - Null/undefined values are removed (the key is omitted from the parent).
38
+ * - Objects that become empty after stripping are also removed.
39
+ * - Arrays are preserved (elements are stripped individually; null elements
40
+ * become `undefined` in the array, which `JSON.stringify` converts to `null`).
41
+ * - Primitive values (strings, numbers, booleans) are passed through unchanged.
42
+ *
43
+ * @returns The stripped data, or `undefined` if the entire input was null/empty.
44
+ */
45
+ export declare function stripEmpty(data: unknown): unknown;
46
+ /**
47
+ * Format data for an MCP tool response.
48
+ *
49
+ * Processing order: **pick fields → strip nulls → compact JSON**.
50
+ *
51
+ * The order matters: if we stripped first, `pickFields` could create empty
52
+ * nested objects (e.g., `{ sender: {} }`) that would not be cleaned up.
53
+ * By picking first and stripping second, any empty objects left by field
54
+ * selection are properly removed.
55
+ *
56
+ * @param data - The raw API response data.
57
+ * @param fields - Optional list of fields to select (dot-notation supported).
58
+ * If omitted or empty, all fields are returned (nulls still stripped).
59
+ * @returns MCP-compatible content response with compact JSON text.
60
+ */
61
+ export declare function formatResponse(data: unknown, fields?: string[]): {
62
+ content: [{
63
+ type: "text";
64
+ text: string;
65
+ }];
66
+ };
67
+ /**
68
+ * Format an error for an MCP tool response.
69
+ *
70
+ * Extracts the error message from `Error` instances or converts to string.
71
+ * Sets `isError: true` so the MCP client can distinguish errors from results.
72
+ */
73
+ export declare function errorResponse(error: unknown): {
74
+ isError: true;
75
+ content: [{
76
+ type: "text";
77
+ text: string;
78
+ }];
79
+ };
@@ -0,0 +1,137 @@
1
+ /**
2
+ * @module response
3
+ *
4
+ * Response formatting utilities for the A-Cube MCP server.
5
+ *
6
+ * Every tool response passes through these utilities to minimize LLM token
7
+ * consumption. Three optimizations are applied:
8
+ *
9
+ * 1. **Field selection** (`pickFields`) -- Return only the requested fields,
10
+ * with dot-notation support for nested paths (e.g., `"sender.business_name"`).
11
+ *
12
+ * 2. **Null stripping** (`stripEmpty`) -- Recursively remove `null`, `undefined`,
13
+ * and empty objects. A typical A-Cube invoice has ~60 null fields across
14
+ * sender and recipient objects; stripping them reduces token count by ~50%.
15
+ *
16
+ * 3. **Compact JSON** -- Serialize without indentation. The LLM reads compact
17
+ * JSON just as well, and whitespace tokens add up quickly on large responses.
18
+ */
19
+ /**
20
+ * Recursively pick only the specified fields from an object or array of objects.
21
+ *
22
+ * Supports dot-notation for nested paths. When multiple sub-fields of the same
23
+ * parent are requested, they are merged into a single object.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * pickFields(invoice, ["uuid", "sender.business_name", "sender.business_vat_number_code"])
28
+ * // => { uuid: "...", sender: { business_name: "...", business_vat_number_code: "..." } }
29
+ * ```
30
+ *
31
+ * When applied to an array, each element is filtered individually.
32
+ */
33
+ export function pickFields(data, fields) {
34
+ if (data === null || data === undefined)
35
+ return data;
36
+ if (Array.isArray(data)) {
37
+ return data.map((item) => pickFields(item, fields));
38
+ }
39
+ if (typeof data !== "object")
40
+ return data;
41
+ const record = data;
42
+ const result = {};
43
+ for (const field of fields) {
44
+ const dotIndex = field.indexOf(".");
45
+ if (dotIndex === -1) {
46
+ if (field in record) {
47
+ result[field] = record[field];
48
+ }
49
+ }
50
+ else {
51
+ const topKey = field.slice(0, dotIndex);
52
+ const rest = field.slice(dotIndex + 1);
53
+ if (topKey in record) {
54
+ const existing = result[topKey];
55
+ if (existing && typeof existing === "object" && !Array.isArray(existing)) {
56
+ const merged = pickFields(record[topKey], [rest]);
57
+ Object.assign(existing, merged);
58
+ }
59
+ else {
60
+ result[topKey] = pickFields(record[topKey], [rest]);
61
+ }
62
+ }
63
+ }
64
+ }
65
+ return result;
66
+ }
67
+ /**
68
+ * Recursively strip `null`, `undefined`, and empty objects from data.
69
+ *
70
+ * - Null/undefined values are removed (the key is omitted from the parent).
71
+ * - Objects that become empty after stripping are also removed.
72
+ * - Arrays are preserved (elements are stripped individually; null elements
73
+ * become `undefined` in the array, which `JSON.stringify` converts to `null`).
74
+ * - Primitive values (strings, numbers, booleans) are passed through unchanged.
75
+ *
76
+ * @returns The stripped data, or `undefined` if the entire input was null/empty.
77
+ */
78
+ export function stripEmpty(data) {
79
+ if (data === null || data === undefined)
80
+ return undefined;
81
+ if (Array.isArray(data)) {
82
+ return data.map(stripEmpty);
83
+ }
84
+ if (typeof data === "object") {
85
+ const record = data;
86
+ const result = {};
87
+ for (const [key, value] of Object.entries(record)) {
88
+ const stripped = stripEmpty(value);
89
+ if (stripped !== undefined) {
90
+ result[key] = stripped;
91
+ }
92
+ }
93
+ return Object.keys(result).length > 0 ? result : undefined;
94
+ }
95
+ return data;
96
+ }
97
+ /**
98
+ * Format data for an MCP tool response.
99
+ *
100
+ * Processing order: **pick fields → strip nulls → compact JSON**.
101
+ *
102
+ * The order matters: if we stripped first, `pickFields` could create empty
103
+ * nested objects (e.g., `{ sender: {} }`) that would not be cleaned up.
104
+ * By picking first and stripping second, any empty objects left by field
105
+ * selection are properly removed.
106
+ *
107
+ * @param data - The raw API response data.
108
+ * @param fields - Optional list of fields to select (dot-notation supported).
109
+ * If omitted or empty, all fields are returned (nulls still stripped).
110
+ * @returns MCP-compatible content response with compact JSON text.
111
+ */
112
+ export function formatResponse(data, fields) {
113
+ let processed = data;
114
+ if (fields && fields.length > 0) {
115
+ processed = pickFields(processed, fields);
116
+ }
117
+ processed = stripEmpty(processed) ?? null;
118
+ return {
119
+ content: [
120
+ { type: "text", text: JSON.stringify(processed) },
121
+ ],
122
+ };
123
+ }
124
+ /**
125
+ * Format an error for an MCP tool response.
126
+ *
127
+ * Extracts the error message from `Error` instances or converts to string.
128
+ * Sets `isError: true` so the MCP client can distinguish errors from results.
129
+ */
130
+ export function errorResponse(error) {
131
+ const message = error instanceof Error ? error.message : String(error);
132
+ return {
133
+ isError: true,
134
+ content: [{ type: "text", text: message }],
135
+ };
136
+ }
137
+ //# sourceMappingURL=response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../src/response.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,UAAU,CACxB,IAAa,EACb,MAAgB;IAEhB,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAErD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,MAAM,GAAG,IAA+B,CAAC;IAC/C,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;YACpB,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;gBACpB,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YACxC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;YACvC,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;gBACrB,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;gBAChC,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACzE,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAA4B,CAAC;oBAC7E,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAClC,CAAC;qBAAM,CAAC;oBACN,MAAM,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;gBACtD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE1D,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,IAA+B,CAAC;QAC/C,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;YACnC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;YACzB,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7D,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAa,EACb,MAAiB;IAEjB,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,SAAS,GAAG,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IACD,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;IAC1C,OAAO;QACL,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE;SAC3D;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAc;IAEd,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;KACpD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @module tools/cassetto-fiscale
3
+ *
4
+ * Cassetto Fiscale (tax drawer) and rejected invoice tools.
5
+ *
6
+ * Provides 7 tools:
7
+ * - `schedule_invoice_download` -- Set up recurring daily downloads at 03:00 UTC.
8
+ * - `get_download_schedule` -- Check schedule status and last execution.
9
+ * - `update_download_schedule` -- Modify schedule options (e.g., auto-renewal).
10
+ * - `delete_download_schedule` -- Stop recurring downloads.
11
+ * - `download_invoices_once` -- Trigger a one-time bulk download by date range.
12
+ * - `count_rejected_invoices` -- Count invoices rejected during processing.
13
+ * - `recover_rejected_invoices` -- Reprocess rejected invoices for a fiscal ID.
14
+ *
15
+ * The Cassetto Fiscale is the Agenzia delle Entrate's digital archive where
16
+ * all electronic invoices (sent and received) are stored for 10 years.
17
+ *
18
+ * @see https://docs.acubeapi.com/ -- A-Cube download schedule endpoints
19
+ */
20
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
21
+ import type { AcubeClient } from "../client.js";
22
+ export declare function registerCassettoFiscaleTools(server: McpServer, client: AcubeClient): void;
@@ -0,0 +1,109 @@
1
+ import { z } from "zod";
2
+ import { formatResponse, errorResponse } from "../response.js";
3
+ export function registerCassettoFiscaleTools(server, client) {
4
+ // ── schedule_invoice_download ─────────────────────────────────────────
5
+ server.tool("schedule_invoice_download", "Schedule daily invoice download from Cassetto Fiscale (runs 03:00 UTC).", {
6
+ fiscal_id: z.string().describe("P.IVA or codice fiscale"),
7
+ options: z.record(z.unknown()).optional().describe("Schedule options (e.g. auto_renewal)"),
8
+ }, async (params) => {
9
+ try {
10
+ const result = await client.post(`/schedule/invoice-download/${encodeURIComponent(params.fiscal_id)}`, params.options);
11
+ return formatResponse(result.data);
12
+ }
13
+ catch (error) {
14
+ return errorResponse(error);
15
+ }
16
+ });
17
+ // ── get_download_schedule ─────────────────────────────────────────────
18
+ server.tool("get_download_schedule", "Check invoice download schedule status for a fiscal ID.", {
19
+ fiscal_id: z.string().describe("P.IVA or codice fiscale"),
20
+ }, async (params) => {
21
+ try {
22
+ const result = await client.get(`/schedule/invoice-download/${encodeURIComponent(params.fiscal_id)}`);
23
+ return formatResponse(result.data);
24
+ }
25
+ catch (error) {
26
+ return errorResponse(error);
27
+ }
28
+ });
29
+ // ── update_download_schedule ──────────────────────────────────────────
30
+ server.tool("update_download_schedule", "Update a Cassetto Fiscale download schedule.", {
31
+ fiscal_id: z.string().describe("P.IVA or codice fiscale"),
32
+ options: z.record(z.unknown()).describe("Fields to update"),
33
+ }, async (params) => {
34
+ try {
35
+ const result = await client.put(`/schedule/invoice-download/${encodeURIComponent(params.fiscal_id)}`, params.options);
36
+ return formatResponse(result.data);
37
+ }
38
+ catch (error) {
39
+ return errorResponse(error);
40
+ }
41
+ });
42
+ // ── delete_download_schedule ──────────────────────────────────────────
43
+ server.tool("delete_download_schedule", "Delete a Cassetto Fiscale download schedule.", {
44
+ fiscal_id: z.string().describe("P.IVA or codice fiscale"),
45
+ }, async (params) => {
46
+ try {
47
+ const result = await client.delete(`/schedule/invoice-download/${encodeURIComponent(params.fiscal_id)}`);
48
+ return formatResponse(result.data);
49
+ }
50
+ catch (error) {
51
+ return errorResponse(error);
52
+ }
53
+ });
54
+ // ── download_invoices_once ────────────────────────────────────────────
55
+ server.tool("download_invoices_once", "One-time invoice download from Cassetto Fiscale by date range.", {
56
+ fiscal_id: z.string().describe("Fiscal ID"),
57
+ from_date: z.string().describe("Start date (YYYY-MM-DD)"),
58
+ to_date: z.string().describe("End date (YYYY-MM-DD)"),
59
+ }, async (params) => {
60
+ try {
61
+ const result = await client.post("/jobs/invoice-download", {
62
+ fiscal_id: params.fiscal_id,
63
+ from_date: params.from_date,
64
+ to_date: params.to_date,
65
+ });
66
+ return formatResponse(result.data);
67
+ }
68
+ catch (error) {
69
+ return errorResponse(error);
70
+ }
71
+ });
72
+ // ── count_rejected_invoices ───────────────────────────────────────────
73
+ server.tool("count_rejected_invoices", "Count rejected invoices from Cassetto Fiscale for a fiscal ID.", {
74
+ fiscal_id: z.string().describe("Fiscal ID"),
75
+ from_date: z.string().optional().describe("Start date (YYYY-MM-DD)"),
76
+ to_date: z.string().optional().describe("End date (YYYY-MM-DD)"),
77
+ }, async (params) => {
78
+ try {
79
+ const query = new URLSearchParams();
80
+ if (params.from_date)
81
+ query.set("from_date", params.from_date);
82
+ if (params.to_date)
83
+ query.set("to_date", params.to_date);
84
+ const queryString = query.toString();
85
+ const path = `/rejected-invoices/${encodeURIComponent(params.fiscal_id)}/count` +
86
+ (queryString ? `?${queryString}` : "");
87
+ const result = await client.get(path);
88
+ return formatResponse(result.data);
89
+ }
90
+ catch (error) {
91
+ return errorResponse(error);
92
+ }
93
+ });
94
+ // ── recover_rejected_invoices ─────────────────────────────────────────
95
+ server.tool("recover_rejected_invoices", "Recover and reprocess rejected Cassetto Fiscale invoices.", {
96
+ fiscal_id: z.string().describe("Fiscal ID"),
97
+ from_date: z.string().describe("Start date (YYYY-MM-DD)"),
98
+ to_date: z.string().describe("End date (YYYY-MM-DD)"),
99
+ }, async (params) => {
100
+ try {
101
+ const result = await client.post(`/rejected-invoices/${encodeURIComponent(params.fiscal_id)}/recover`, { from_date: params.from_date, to_date: params.to_date });
102
+ return formatResponse(result.data);
103
+ }
104
+ catch (error) {
105
+ return errorResponse(error);
106
+ }
107
+ });
108
+ }
109
+ //# sourceMappingURL=cassetto-fiscale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cassetto-fiscale.js","sourceRoot":"","sources":["../../src/tools/cassetto-fiscale.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @module tools/configurations
3
+ *
4
+ * Business registry and ADE appointee tools.
5
+ *
6
+ * Provides 8 tools:
7
+ * - `list_business_registries` / `create_business_registry` /
8
+ * `get_business_registry` / `update_business_registry`
9
+ * -- Manage company profiles (anagrafiche aziendali) used for SDI invoicing.
10
+ * - `list_appointees` / `create_appointee` / `get_appointee` / `update_appointee`
11
+ * -- Manage ADE tax appointees (intermediari fiscali) authorized to operate
12
+ * with the Agenzia delle Entrate on behalf of a company.
13
+ *
14
+ * @see https://docs.acubeapi.com/ -- A-Cube configuration endpoints
15
+ */
16
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
17
+ import type { AcubeClient } from "../client.js";
18
+ export declare function registerConfigurationTools(server: McpServer, client: AcubeClient): void;