beliq-mcp 0.3.1 → 0.3.3
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/README.md +21 -4
- package/dist/schema.js +2 -6
- package/dist/tools/generate.js +1 -1
- package/dist/tools/shared.js +14 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -71,9 +71,26 @@ Add to `~/.cursor/mcp.json` (or a project `.cursor/mcp.json`) using the same `mc
|
|
|
71
71
|
|
|
72
72
|
`beliq_parse_einvoice` returns the detected `format` and `profileDetected` plus the extracted `invoice` object (EN 16931 fields: number, dates, currency, seller, buyer, lines, totals, and any national extensions present).
|
|
73
73
|
|
|
74
|
-
`beliq_generate_einvoice` returns
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
`beliq_generate_einvoice` returns a short text summary (with the XML document appended for XML output) plus a structured result:
|
|
75
|
+
|
|
76
|
+
- `output` is `xml` or `pdf`, as requested, and `contentType` is the matching media type (`application/xml` or `application/pdf`).
|
|
77
|
+
- `xml` is the generated document inline, present only for XML output.
|
|
78
|
+
- `outputPath` and `bytesWritten` are set when the document was written to disk: always for a PDF, and for XML when you set `outputPath`. The call never overwrites an existing file, so pick a path that does not exist.
|
|
79
|
+
- `pdfKind` is present only for PDF output: `hybrid` (a PDF/A-3 with the XML embedded, for facturx and zugferd) or `visualization` (rendered pages with no XML inside, for xrechnung and peppol-bis, whose legal document stays the XML).
|
|
80
|
+
- `schematronVersion` is the ruleset (Schematron) revision the document was checked against.
|
|
81
|
+
- `sha256` is the lowercase-hex SHA-256 of the returned document bytes, so `sha256sum` on the file at `outputPath` reproduces it.
|
|
82
|
+
- `rulesetSha256` is one combined fingerprint of the rule artifacts the document was checked against, present when a ruleset ran.
|
|
83
|
+
- `livemode` is true for a `blq_live_` key and false for a `blq_test_` sandbox key, whose output is [marked as a specimen](https://docs.beliq.eu/api-reference/test-mode/#sandbox-markers) and is not a production invoice.
|
|
84
|
+
- `validationResult` is the verdict on the generated document: `valid`, the `schematronVersion` it ran, and `errors[]`/`warnings[]` in the same shape as validate returns. With the default `verify: true`, a document that fails validation comes back as a tool error instead of a result. With `verify: false` no ruleset runs: `valid` is false and `errors`/`warnings` are empty because nothing checked the document, not because it failed.
|
|
85
|
+
|
|
86
|
+
`beliq_convert_einvoice` returns a short text summary (with the XML document appended for an XML target) plus a structured result:
|
|
87
|
+
|
|
88
|
+
- `output` is `pdf` for a facturx or zugferd target and `xml` for the others, and `contentType` is the matching media type (`application/pdf` or `application/xml`).
|
|
89
|
+
- `xml` is the converted document inline, present only for an XML target.
|
|
90
|
+
- `outputPath` and `bytesWritten` are set when the document was written to disk: always for a PDF target, and for an XML target when you set `outputPath`. Like generate, it never overwrites an existing file.
|
|
91
|
+
- `sourceFormat` is the format the engine read, and `targetFormat` the format it produced (the `targetFormat` you asked for when the API does not name one).
|
|
92
|
+
- `profileDetected` is the profile the engine recognised on the source document, when it recognised one.
|
|
93
|
+
- `lostElementsCount` and `lostElements` count and name the source elements that had no equivalent in the target format; `0` means nothing was lost at the element level.
|
|
77
94
|
|
|
78
95
|
A PDF (Factur-X / ZUGFeRD) must be passed by `documentPath` for validate, parse, and convert, not inlined as text.
|
|
79
96
|
|
|
@@ -83,7 +100,7 @@ A PDF (Factur-X / ZUGFeRD) must be passed by `documentPath` for validate, parse,
|
|
|
83
100
|
|
|
84
101
|
## Development
|
|
85
102
|
|
|
86
|
-
This server depends on the published [`@beliq/sdk`](https://www.npmjs.com/package/@beliq/sdk), which carries the request, transport, and result-shaping logic.
|
|
103
|
+
This server depends on the published [`@beliq/sdk`](https://www.npmjs.com/package/@beliq/sdk), which carries the request, transport, and result-shaping logic. `package-lock.json` is committed, and CI and the release build install from it with `npm ci`.
|
|
87
104
|
|
|
88
105
|
- `npm install`
|
|
89
106
|
- `npm run build` - compile to `dist/`
|
package/dist/schema.js
CHANGED
|
@@ -117,11 +117,11 @@ export const generateInputShape = {
|
|
|
117
117
|
output: z
|
|
118
118
|
.enum(['xml', 'pdf'])
|
|
119
119
|
.optional()
|
|
120
|
-
.describe("'xml' (default) returns the document inline. 'pdf'
|
|
120
|
+
.describe("'xml' (default) returns the document inline. 'pdf' needs outputPath to write it to: for facturx and zugferd it is a hybrid PDF/A-3 with the XML embedded; xrechnung and peppol-bis have no hybrid form, so it is a visualization with no XML inside it, and their legal document stays the XML."),
|
|
121
121
|
facturxProfile: z
|
|
122
122
|
.enum(LIVE_PROFILES)
|
|
123
123
|
.optional()
|
|
124
|
-
.describe('Profile for a Factur-X / ZUGFeRD
|
|
124
|
+
.describe('Profile for a Factur-X / ZUGFeRD document; ignored for xrechnung and peppol-bis. extended-ctc-fr is Factur-X only: zugferd accepts basicwl, en16931 and extended.'),
|
|
125
125
|
verify: z
|
|
126
126
|
.boolean()
|
|
127
127
|
.optional()
|
|
@@ -199,7 +199,3 @@ export const convertOutputShape = {
|
|
|
199
199
|
bytesWritten: z.number().optional(),
|
|
200
200
|
xml: z.string().optional(),
|
|
201
201
|
};
|
|
202
|
-
const validateInputSchema = z.object(validateInputShape);
|
|
203
|
-
const parseInputSchema = z.object(parseInputShape);
|
|
204
|
-
const generateInputSchema = z.object(generateInputShape);
|
|
205
|
-
const convertInputSchema = z.object(convertInputShape);
|
package/dist/tools/generate.js
CHANGED
|
@@ -3,7 +3,7 @@ import { runGenerate } from './shared.js';
|
|
|
3
3
|
const description = [
|
|
4
4
|
'Generate a compliant EU electronic invoice from an EN 16931 invoice object.',
|
|
5
5
|
'Set standard to the target (xrechnung, zugferd, facturx, or peppol-bis) and pass the invoice fields.',
|
|
6
|
-
"output 'xml' (default) returns the document inline; 'pdf'
|
|
6
|
+
"output 'xml' (default) returns the document inline; 'pdf' needs outputPath to write it to, and is a hybrid PDF/A-3 with the XML embedded for facturx and zugferd, or a visualization with no embedded XML for xrechnung and peppol-bis (whose legal document stays the XML).",
|
|
7
7
|
'By default the result is validated before it is returned (verify), so a non-compliant document fails rather than coming back.',
|
|
8
8
|
'beliq produces the compliant document; transmission (Peppol, PDP, KSeF, SDI), archiving, and tax-authority reporting stay with your access point.',
|
|
9
9
|
].join(' ');
|
package/dist/tools/shared.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { BeliqApiError } from '@beliq/sdk';
|
|
2
|
+
import { BeliqApiError, isProfileAllowedForStandard, profilesForStandard, } from '@beliq/sdk';
|
|
3
3
|
import { summarizeConvert, summarizeGenerate, summarizeParse, summarizeValidation } from '../summary.js';
|
|
4
4
|
function errorResult(message) {
|
|
5
5
|
return { content: [{ type: 'text', text: message }], isError: true };
|
|
@@ -153,6 +153,15 @@ export async function runGenerate(input, deps) {
|
|
|
153
153
|
if (output === 'pdf' && !outputPath) {
|
|
154
154
|
return errorResult('A pdf output needs outputPath: the file path to write the generated PDF to.');
|
|
155
155
|
}
|
|
156
|
+
// The SDK drops facturxProfile outside the Factur-X / ZUGFeRD family. Inside
|
|
157
|
+
// it the pair is still pinned: extended-ctc-fr is Factur-X only, and the API
|
|
158
|
+
// answers it on zugferd with 422 PROFILE_STANDARD_MISMATCH. Name the legal
|
|
159
|
+
// values rather than spend a call on a pair that cannot succeed.
|
|
160
|
+
const hybrid = input.standard === 'facturx' || input.standard === 'zugferd';
|
|
161
|
+
if (hybrid && input.facturxProfile && !isProfileAllowedForStandard(input.standard, input.facturxProfile)) {
|
|
162
|
+
return errorResult(`facturxProfile '${input.facturxProfile}' is not available for ${input.standard}. ` +
|
|
163
|
+
`Use one of: ${profilesForStandard(input.standard).join(', ')}.`);
|
|
164
|
+
}
|
|
156
165
|
let result;
|
|
157
166
|
try {
|
|
158
167
|
result = await deps.client.generate({
|
|
@@ -160,6 +169,10 @@ export async function runGenerate(input, deps) {
|
|
|
160
169
|
invoice: input.invoice,
|
|
161
170
|
output,
|
|
162
171
|
facturxProfile: input.facturxProfile,
|
|
172
|
+
// XRechnung and Peppol BIS have no hybrid PDF, and the API refuses PDF
|
|
173
|
+
// for them unless the request names a visual to render. Factur-X and
|
|
174
|
+
// ZUGFeRD render theirs either way, so this is inert for them.
|
|
175
|
+
template: output === 'pdf' ? 'standard' : undefined,
|
|
163
176
|
verify: input.verify ?? true,
|
|
164
177
|
// Always seal so the tool can hand back the document sha256 and the
|
|
165
178
|
// validation verdict for the model to cite.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "beliq-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "beliq MCP server: validate, parse, generate, and convert EU e-invoices (XRechnung, ZUGFeRD, Factur-X, Peppol BIS) against authority-pinned, drift-checked rules, for MCP clients.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -56,16 +56,16 @@
|
|
|
56
56
|
"prepublishOnly": "npm run build"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@beliq/sdk": "^0.
|
|
59
|
+
"@beliq/sdk": "^0.4.0",
|
|
60
60
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
61
61
|
"zod": "^4.4.3"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@types/node": "^20.14.0",
|
|
65
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
66
|
-
"@typescript-eslint/parser": "^
|
|
65
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
66
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
67
67
|
"eslint": "^8.57.0",
|
|
68
68
|
"typescript": "^5.5.4",
|
|
69
|
-
"vitest": "^
|
|
69
|
+
"vitest": "^4.0.0"
|
|
70
70
|
}
|
|
71
71
|
}
|