@dojocoding/hacienda-mcp 0.7.0 → 0.9.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/CHANGELOG.md +24 -0
- package/README.md +7 -7
- package/dist/{chunk-A5SYNMZP.js → chunk-QCXIDV2U.js} +34 -67
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @dojocoding/hacienda-mcp
|
|
2
2
|
|
|
3
|
+
## 0.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 72a7670: Require positive one-to-five-digit credit days for current exact FE conditions 02/10 and reject any explicitly supplied zero term while preserving valid leading-zero lexemes. Preserve the existing REP-only 09/11 exclusion and additionally reject FEC-only 13 in current exact FE inputs, while preserving other valid FE conditions and historical read-only 13 compatibility. Add an explicitly read-only retained exact FE schema/calculator for independently bound historical 0.6–0.8 source facts; it does not provide an XML builder or grant signing/transport authority. Legacy Number APIs are unchanged. CLI/MCP participate in the coordinated linked release; no new adapter endpoint or fiscal activation is introduced.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [72a7670]
|
|
12
|
+
- @dojocoding/hacienda-shared@0.9.0
|
|
13
|
+
- @dojocoding/hacienda-sdk@0.9.0
|
|
14
|
+
|
|
15
|
+
## 0.8.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- 813e329: Correct the read-only Hacienda history contract across all four packages. Lists consume metadata arrays, combined domestic party filters and observed 200/206 range headers; details return metadata/references rather than promised XML/status. Reject unsupported date/legacy filters before authentication and propagate SDK request cancellation and MCP history-request signals (preexisting shared MCP bootstrap remains internally time-bounded, not caller-cancelled). Preserve wrapper names and exact identifier strings, with an explicit pre-1.0 minor migration for removed fictional total/status/XML fields. No automatic paging, completeness claim, live Hacienda verification or fiscal mutation changes.
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [813e329]
|
|
24
|
+
- @dojocoding/hacienda-shared@0.8.0
|
|
25
|
+
- @dojocoding/hacienda-sdk@0.8.0
|
|
26
|
+
|
|
3
27
|
## 0.7.0
|
|
4
28
|
|
|
5
29
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -135,21 +135,19 @@ Check the processing status of a document by its 50-digit clave numerica.
|
|
|
135
135
|
|
|
136
136
|
### `list_documents`
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
Read one observed metadata page, with strict combined domestic party filters. No status/XML, inferred total, next page or completeness claim.
|
|
139
139
|
|
|
140
140
|
**Parameters:**
|
|
141
141
|
|
|
142
|
-
- `limit` --
|
|
142
|
+
- `limit` -- Requested size (1–50 SDK cap, default: 50)
|
|
143
143
|
- `offset` -- Pagination offset (default: 0)
|
|
144
|
-
- `
|
|
145
|
-
- `
|
|
146
|
-
- `fechaDesde` -- Start date filter, ISO 8601 (optional)
|
|
147
|
-
- `fechaHasta` -- End date filter, ISO 8601 (optional)
|
|
144
|
+
- `emisor` -- Combined domestic issuer type + ID (optional)
|
|
145
|
+
- `receptor` -- Combined domestic receiver type + ID (optional)
|
|
148
146
|
- `profile` -- Saved profile name (default: `"default"`); requires server password environment
|
|
149
147
|
|
|
150
148
|
### `get_document`
|
|
151
149
|
|
|
152
|
-
Get
|
|
150
|
+
Get observed metadata/references by the current 50-character clave. Use `check_status` separately; this tool does not fetch original XML or status.
|
|
153
151
|
|
|
154
152
|
**Parameters:**
|
|
155
153
|
|
|
@@ -212,3 +210,5 @@ Read the [migration guide](https://github.com/DojoCodingLabs/hacienda-cr/blob/ma
|
|
|
212
210
|
If an old global `sequences.json` contains positive counters, creating a new unseeded issuer series fails closed. Stop writers, back up the old file, establish the issuer/environment that owns each series, and seed each corresponding scoped file with the last reserved number before resuming. Do not copy a mixed-company global file blindly, delete counters, or restart a production series at one. There is no automatic migration because the old file does not identify its owner.
|
|
213
211
|
|
|
214
212
|
Authenticated clients are invalidated when the resolved profile, environment, issuer configuration, certificate path, password or PIN changes. Replacing certificate bytes at the same path still requires restarting the process or clearing the cache. Configure one profile per identity/environment.
|
|
213
|
+
|
|
214
|
+
See the [history contract migration](../../docs/history-contract.md); unsupported keys are rejected before authentication.
|
|
@@ -278,7 +278,7 @@ import {
|
|
|
278
278
|
listComprobantes,
|
|
279
279
|
getComprobante
|
|
280
280
|
} from "@dojocoding/hacienda-sdk";
|
|
281
|
-
import { DOCUMENT_TYPE_NAMES } from "@dojocoding/hacienda-shared";
|
|
281
|
+
import { ComprobantesQuerySchema, DOCUMENT_TYPE_NAMES } from "@dojocoding/hacienda-shared";
|
|
282
282
|
|
|
283
283
|
// src/tools/api-client.ts
|
|
284
284
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -340,7 +340,7 @@ function registerCheckStatusTool(server) {
|
|
|
340
340
|
`Document Type: ${docTypeName}`,
|
|
341
341
|
`Taxpayer ID: ${parsed.taxpayerId}`,
|
|
342
342
|
`Date: ${parsed.dateRaw}`,
|
|
343
|
-
`Sequence: ${
|
|
343
|
+
`Sequence: ${args.clave.slice(31, 41)}`,
|
|
344
344
|
``,
|
|
345
345
|
`Status: ${status.status}`,
|
|
346
346
|
status.date ? `Response Date: ${status.date}` : null,
|
|
@@ -365,66 +365,42 @@ function registerCheckStatusTool(server) {
|
|
|
365
365
|
);
|
|
366
366
|
}
|
|
367
367
|
function registerListDocumentsTool(server) {
|
|
368
|
-
server.
|
|
368
|
+
server.registerTool(
|
|
369
369
|
"list_documents",
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
receptorIdentificacion: z2.string().optional().describe("Filter by receiver identification number"),
|
|
376
|
-
fechaDesde: z2.string().optional().describe("Filter by start date (ISO 8601)"),
|
|
377
|
-
fechaHasta: z2.string().optional().describe("Filter by end date (ISO 8601)"),
|
|
378
|
-
profile: z2.string().default("default").describe('Config profile name (default: "default")')
|
|
370
|
+
{
|
|
371
|
+
description: "Read one bounded page of observed Hacienda metadata, optionally filtered by combined domestic emisor/receptor. No date filters, status/XML, inferred totals or complete-history claim.",
|
|
372
|
+
inputSchema: ComprobantesQuerySchema.extend({
|
|
373
|
+
profile: z2.string().default("default")
|
|
374
|
+
}).strict()
|
|
379
375
|
},
|
|
380
|
-
async (
|
|
376
|
+
async ({ profile, ...query }, extra) => {
|
|
381
377
|
try {
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
emisorIdentificacion: args.emisorIdentificacion,
|
|
387
|
-
receptorIdentificacion: args.receptorIdentificacion,
|
|
388
|
-
fechaEmisionDesde: args.fechaDesde,
|
|
389
|
-
fechaEmisionHasta: args.fechaHasta
|
|
390
|
-
});
|
|
391
|
-
const lines = [
|
|
392
|
-
`Document List`,
|
|
393
|
-
``,
|
|
394
|
-
`Total: ${result.totalRegistros} documents`,
|
|
395
|
-
`Showing: ${result.comprobantes.length} (offset ${result.offset})`,
|
|
396
|
-
``
|
|
397
|
-
];
|
|
398
|
-
if (result.comprobantes.length === 0) {
|
|
399
|
-
lines.push("No documents found matching the criteria.");
|
|
400
|
-
} else {
|
|
401
|
-
for (const doc of result.comprobantes) {
|
|
402
|
-
lines.push(
|
|
403
|
-
`- ${doc.clave}`,
|
|
404
|
-
` Date: ${doc.fechaEmision} | Status: ${doc.estado}`,
|
|
405
|
-
` Emisor: ${doc.emisor.numeroIdentificacion}`,
|
|
406
|
-
``
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
378
|
+
const params = ComprobantesQuerySchema.parse(query);
|
|
379
|
+
extra.signal.throwIfAborted();
|
|
380
|
+
const httpClient = await createMcpApiClient(profile);
|
|
381
|
+
const result = await listComprobantes(httpClient, params, { signal: extra.signal });
|
|
410
382
|
return {
|
|
411
383
|
content: [
|
|
412
384
|
{
|
|
413
385
|
type: "text",
|
|
414
|
-
text:
|
|
386
|
+
text: JSON.stringify({
|
|
387
|
+
kind: "observed-history-page",
|
|
388
|
+
...result,
|
|
389
|
+
coverage: "not-established",
|
|
390
|
+
statusAndXml: "not-provided-by-history"
|
|
391
|
+
})
|
|
415
392
|
}
|
|
416
393
|
]
|
|
417
394
|
};
|
|
418
395
|
} catch (error) {
|
|
419
|
-
const message = sanitizeLogString2(error instanceof Error ? error.message : String(error));
|
|
420
396
|
return {
|
|
397
|
+
isError: true,
|
|
421
398
|
content: [
|
|
422
399
|
{
|
|
423
400
|
type: "text",
|
|
424
|
-
text: `Error listing documents: ${message}`
|
|
401
|
+
text: `Error listing documents: ${sanitizeLogString2(error instanceof Error ? error.message : String(error))}`
|
|
425
402
|
}
|
|
426
|
-
]
|
|
427
|
-
isError: true
|
|
403
|
+
]
|
|
428
404
|
};
|
|
429
405
|
}
|
|
430
406
|
}
|
|
@@ -433,50 +409,41 @@ function registerListDocumentsTool(server) {
|
|
|
433
409
|
function registerGetDocumentTool(server) {
|
|
434
410
|
server.tool(
|
|
435
411
|
"get_document",
|
|
436
|
-
"Get
|
|
412
|
+
"Get observed document metadata by its current 50-character clave. Returns observed metadata and credit/debit references only, without status or XML. Use check_status separately. Requires a configured profile (run `hacienda auth login` first).",
|
|
437
413
|
{
|
|
438
|
-
clave: z2.string().length(50).describe("The 50-
|
|
414
|
+
clave: z2.string().length(50).describe("The current 50-character clave of the document metadata to retrieve"),
|
|
439
415
|
profile: z2.string().default("default").describe('Config profile name (default: "default")')
|
|
440
416
|
},
|
|
441
|
-
async (args) => {
|
|
417
|
+
async (args, extra) => {
|
|
442
418
|
try {
|
|
419
|
+
extra.signal.throwIfAborted();
|
|
443
420
|
const parsed = parseClave(args.clave);
|
|
444
421
|
const docTypeName = DOCUMENT_TYPE_NAMES[parsed.documentType] ?? `Unknown (${parsed.documentType})`;
|
|
445
422
|
const httpClient = await createMcpApiClient(args.profile);
|
|
446
|
-
const doc = await getComprobante(httpClient, args.clave);
|
|
447
|
-
let xmlContent;
|
|
448
|
-
if (doc.comprobanteXml) {
|
|
449
|
-
try {
|
|
450
|
-
xmlContent = Buffer.from(doc.comprobanteXml, "base64").toString("utf-8");
|
|
451
|
-
} catch {
|
|
452
|
-
xmlContent = "(unable to decode XML)";
|
|
453
|
-
}
|
|
454
|
-
}
|
|
423
|
+
const doc = await getComprobante(httpClient, args.clave, { signal: extra.signal });
|
|
455
424
|
return {
|
|
456
425
|
content: [
|
|
457
426
|
{
|
|
458
427
|
type: "text",
|
|
459
428
|
text: [
|
|
460
|
-
`Document
|
|
429
|
+
`Document Metadata`,
|
|
461
430
|
``,
|
|
462
431
|
`Clave: ${doc.clave}`,
|
|
463
432
|
`Document Type: ${docTypeName}`,
|
|
464
433
|
`Taxpayer ID: ${parsed.taxpayerId}`,
|
|
465
|
-
`
|
|
466
|
-
|
|
467
|
-
|
|
434
|
+
`Document Date: ${doc.fecha}`,
|
|
435
|
+
"Metadata only; use check_status for a separate status/response observation.",
|
|
436
|
+
`Credit references: ${JSON.stringify(doc.notasCredito ?? [])}`,
|
|
437
|
+
`Debit references: ${JSON.stringify(doc.notasDebito ?? [])}`,
|
|
468
438
|
``,
|
|
469
439
|
`Emisor: ${doc.emisor.tipoIdentificacion} ${doc.emisor.numeroIdentificacion}`,
|
|
470
440
|
doc.receptor ? `Receptor: ${doc.receptor.tipoIdentificacion} ${doc.receptor.numeroIdentificacion}` : null,
|
|
471
441
|
``,
|
|
472
442
|
`Branch: ${parsed.branch}`,
|
|
473
443
|
`POS: ${parsed.pos}`,
|
|
474
|
-
`Sequence: ${
|
|
444
|
+
`Sequence: ${args.clave.slice(31, 41)}`,
|
|
475
445
|
`Situation: ${parsed.situation}`,
|
|
476
|
-
`Security Code: ${parsed.securityCode}
|
|
477
|
-
xmlContent ? `
|
|
478
|
-
--- XML ---
|
|
479
|
-
${xmlContent}` : null
|
|
446
|
+
`Security Code: ${parsed.securityCode}`
|
|
480
447
|
].filter(Boolean).join("\n")
|
|
481
448
|
}
|
|
482
449
|
]
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dojocoding/hacienda-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "MCP Server for Costa Rica electronic invoicing (AI-accessible tools)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"model-context-protocol"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@dojocoding/hacienda-sdk": "0.
|
|
32
|
-
"@dojocoding/hacienda-shared": "0.
|
|
31
|
+
"@dojocoding/hacienda-sdk": "0.9.0",
|
|
32
|
+
"@dojocoding/hacienda-shared": "0.9.0",
|
|
33
33
|
"@modelcontextprotocol/sdk": "^1.32.0",
|
|
34
34
|
"xmllint-wasm": "^5.3.0",
|
|
35
35
|
"zod": "^4.6.5"
|