@useyona/einvoice-mcp 0.0.0-stage → 0.1.1

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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +201 -2
  3. package/bin/cli.js +2 -0
  4. package/dist/cli.d.ts +24 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +73 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/http.d.ts +16 -0
  9. package/dist/http.d.ts.map +1 -0
  10. package/dist/http.js +41 -0
  11. package/dist/http.js.map +1 -0
  12. package/dist/idempotency.d.ts +16 -0
  13. package/dist/idempotency.d.ts.map +1 -0
  14. package/dist/idempotency.js +31 -0
  15. package/dist/idempotency.js.map +1 -0
  16. package/dist/index.d.ts +12 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +22 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/prompts.d.ts +5 -0
  21. package/dist/prompts.d.ts.map +1 -0
  22. package/dist/prompts.js +72 -0
  23. package/dist/prompts.js.map +1 -0
  24. package/dist/resources.d.ts +16 -0
  25. package/dist/resources.d.ts.map +1 -0
  26. package/dist/resources.js +65 -0
  27. package/dist/resources.js.map +1 -0
  28. package/dist/result.d.ts +42 -0
  29. package/dist/result.d.ts.map +1 -0
  30. package/dist/result.js +83 -0
  31. package/dist/result.js.map +1 -0
  32. package/dist/server.d.ts +26 -0
  33. package/dist/server.d.ts.map +1 -0
  34. package/dist/server.js +68 -0
  35. package/dist/server.js.map +1 -0
  36. package/dist/tools/index.d.ts +34 -0
  37. package/dist/tools/index.d.ts.map +1 -0
  38. package/dist/tools/index.js +284 -0
  39. package/dist/tools/index.js.map +1 -0
  40. package/dist/tools/schemas.d.ts +877 -0
  41. package/dist/tools/schemas.d.ts.map +1 -0
  42. package/dist/tools/schemas.js +192 -0
  43. package/dist/tools/schemas.js.map +1 -0
  44. package/dist/version.d.ts +5 -0
  45. package/dist/version.d.ts.map +1 -0
  46. package/dist/version.js +8 -0
  47. package/dist/version.js.map +1 -0
  48. package/package.json +82 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Elyonar
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 CHANGED
@@ -1,3 +1,202 @@
1
- # Temporary Holding Version
1
+ # @useyona/einvoice-mcp
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The [Model Context Protocol](https://modelcontextprotocol.io) server for the Yona e-invoicing API. It lets an AI
4
+ assistant (Claude, Cursor, VS Code, Muse and any MCP client) create buyers and invoices, validate them, report them to
5
+ the tax authority and follow their status, with the same API key an integration uses.
6
+
7
+ It runs on your machine over stdio (`npx @useyona/einvoice-mcp`). A hosted endpoint is coming soon.
8
+
9
+ ## Before you start
10
+
11
+ - Node.js 20 or later.
12
+ - A Yona API key from the dashboard (API keys). Start with a **sandbox** key (`sk_test_…`): sandbox submissions go to
13
+ the tax authority's test environment and spend sandbox credits only. The key's capabilities decide which tools
14
+ succeed; the `full_integration` preset is the usual choice.
15
+
16
+ ## Install and configure
17
+
18
+ The server reads its configuration from the environment:
19
+
20
+ | Variable | Required | Meaning |
21
+ |---|---|---|
22
+ | `YONA_API_KEY` | yes | Your API key, `sk_test_…` (sandbox) or `sk_live_…` (live). A missing or malformed key stops the server with a message. |
23
+ | `YONA_ALLOW_LIVE` | no | `true` to allow a live key. Without it a live key is refused at start. |
24
+ | `YONA_BASE_URL` | no | Another API host, for testing against a local gateway. Leave it unset. |
25
+
26
+ Keep the key out of shared files: put it in your client's secret or environment settings where it offers one.
27
+
28
+ ### Claude Desktop
29
+
30
+ `claude_desktop_config.json` (Settings → Developer → Edit Config):
31
+
32
+ ```json
33
+ {
34
+ "mcpServers": {
35
+ "yona": {
36
+ "command": "npx",
37
+ "args": ["-y", "@useyona/einvoice-mcp"],
38
+ "env": { "YONA_API_KEY": "sk_test_…" }
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ Restart Claude Desktop after saving.
45
+
46
+ ### Claude Code
47
+
48
+ ```bash
49
+ claude mcp add yona --env YONA_API_KEY=sk_test_… -- npx -y @useyona/einvoice-mcp
50
+ ```
51
+
52
+ ### Cursor
53
+
54
+ `~/.cursor/mcp.json` (all projects) or `.cursor/mcp.json` (one project):
55
+
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "yona": {
60
+ "command": "npx",
61
+ "args": ["-y", "@useyona/einvoice-mcp"],
62
+ "env": { "YONA_API_KEY": "sk_test_…" }
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ ### VS Code
69
+
70
+ `.vscode/mcp.json`; VS Code asks for the key once and stores it as a secret:
71
+
72
+ ```json
73
+ {
74
+ "inputs": [
75
+ { "type": "promptString", "id": "yona-api-key", "description": "Yona API key", "password": true }
76
+ ],
77
+ "servers": {
78
+ "yona": {
79
+ "type": "stdio",
80
+ "command": "npx",
81
+ "args": ["-y", "@useyona/einvoice-mcp"],
82
+ "env": { "YONA_API_KEY": "${input:yona-api-key}" }
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ ### Muse Code
89
+
90
+ `~/.config/muse/settings.json`:
91
+
92
+ ```json
93
+ {
94
+ "mcp_servers": {
95
+ "yona": {
96
+ "command": "npx",
97
+ "args": ["-y", "@useyona/einvoice-mcp"],
98
+ "env": { "YONA_API_KEY": "sk_test_…" }
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ ### Hosted (coming soon)
105
+
106
+ A hosted endpoint will serve the same tools over streamable HTTP, with nothing to install:
107
+
108
+ - URL: `https://gp.useyona.com/mcp`
109
+ - Header: `Authorization: Bearer sk_test_…`
110
+
111
+ ```bash
112
+ # Claude Code, once the endpoint is live
113
+ claude mcp add --transport http yona https://gp.useyona.com/mcp --header "Authorization: Bearer sk_test_…"
114
+ ```
115
+
116
+ It is not live yet; use the local server until this section says otherwise.
117
+
118
+ ## Tools
119
+
120
+ | Tool | What it does | Kind |
121
+ |---|---|---|
122
+ | `get_organization` | The key's organisation: profile and readiness to report invoices | read |
123
+ | `lookup_tin` | Looks up a tax id with the tax authority | charged |
124
+ | `search_buyers` | Lists saved buyers, by text or verification status | read |
125
+ | `get_buyer` | One buyer | read |
126
+ | `create_buyer` | Saves a buyer | write, charged |
127
+ | `search_items` | Lists saved goods and services | read |
128
+ | `create_item` | Saves a good or service | write |
129
+ | `list_invoices` | Lists invoices, by status, payment status, buyer, date or text | read |
130
+ | `get_invoice` | One invoice | read |
131
+ | `create_invoice` | Creates a **draft** invoice | write, charged |
132
+ | `update_invoice` | Changes a draft | write |
133
+ | `validate_invoice` | Checks a draft or a document with the tax authority's rules, storing nothing | charged |
134
+ | `finalise_invoice` | Freezes a draft for submission | write |
135
+ | `submit_invoice` | Reports an invoice to the tax authority | **destructive**, charged |
136
+ | `get_submission_status` | Where a report stands: accepted, rejected, parked and why | read |
137
+ | `cancel_invoice` | Cancels an issued invoice | **destructive** |
138
+ | `issue_credit_note` | Credits a reported invoice in full, by lines or by amount | **destructive**, charged |
139
+ | `get_download_link` | A short-lived link to the invoice PDF | charged |
140
+ | `create_share_link` | A revocable public link to view an invoice | write |
141
+ | `list_received_invoices` | Invoices other businesses issued to you | read |
142
+ | `get_received_invoice` | One received invoice | read |
143
+ | `get_balance` | The credit balance for the key's mode | read |
144
+ | `list_webhook_deliveries` | Webhook deliveries to your endpoints, to debug an integration | read |
145
+
146
+ **Resources:** `yona://reference/tax-categories`, `yona://reference/units`, `yona://reference/hs-codes` (search with
147
+ `?q=laptop`), `yona://organization`.
148
+
149
+ **Prompts:** `draft_invoice` (a validated draft from a plain description), `explain_rejection` (why the tax authority
150
+ did not accept an invoice, in plain words).
151
+
152
+ A typical session: *"Invoice Acme Ltd for 2 laptops at ₦850,000 each"* → `search_buyers` → `create_invoice` →
153
+ `validate_invoice` → you review → `finalise_invoice` → `submit_invoice` (after you approve) → `get_submission_status`.
154
+
155
+ ## Safety
156
+
157
+ - **Mode in every result.** Each tool result carries `"mode": "sandbox"` or `"live"`, so the assistant always knows
158
+ whether an action is real.
159
+ - **Live is opt-in.** A live key is refused at start unless `YONA_ALLOW_LIVE=true`. In live mode a submission is a
160
+ legal filing and spends real credits.
161
+ - **Destructive tools need `confirm: true`.** `submit_invoice`, `cancel_invoice` and `issue_credit_note` are annotated
162
+ as destructive and refuse to run without `confirm: true` in their input, so a client that ignores annotations still
163
+ cannot submit by accident. The assistant is told to set it only after you approve the exact action.
164
+ - **Charged calls are not marked read-only**, so clients that auto-approve read-only tools still ask before spending
165
+ credits.
166
+ - **No double charges on retries.** Writes carry an `Idempotency-Key` derived from the MCP call (its request id, the
167
+ tool and its arguments): a client that retries the same call gets the first result and is charged once.
168
+ - **No secrets in output.** No tool, resource or error returns the key or a token. Errors carry the API's
169
+ `errorCode`, message, `requestId` and field-level reasons only.
170
+
171
+ ## Embedding the server
172
+
173
+ The package exports the server for hosts that run their own transport:
174
+
175
+ ```ts
176
+ import { EInvoice } from '@useyona/einvoice-js';
177
+ import { createYonaMcpServer, handleStreamableHttp } from '@useyona/einvoice-mcp';
178
+
179
+ // Any transport:
180
+ const server = createYonaMcpServer({ client: new EInvoice({ apiKey }), allowLive: false });
181
+
182
+ // Streamable HTTP, stateless, JSON responses (no SSE, no session), one server per request:
183
+ app.post('/mcp', (req, res) => handleStreamableHttp(req, res, { client: clientFor(req), parsedBody: req.body }));
184
+ ```
185
+
186
+ `handleStreamableHttp` answers `POST` only (`GET` and `DELETE` are 405: there is no session) and 403 for a live client
187
+ without `allowLive`. Build the client per request from the caller's credentials.
188
+
189
+ ## Development
190
+
191
+ ```bash
192
+ npm install
193
+ npm run lint # types, src and tests
194
+ npm test # jest with coverage
195
+ npm run build # dist/
196
+ ```
197
+
198
+ `npm run live-check` drives the built server against a local Yona e2e stack (see `scripts/live-check.mjs`).
199
+
200
+ ## License
201
+
202
+ MIT
package/bin/cli.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/cli.js').main();
package/dist/cli.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import { EInvoice } from '@useyona/einvoice-js';
2
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ /** A configuration problem the binary reports and exits on. Its message never contains the key. */
4
+ export declare class CliConfigError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ /** The binary's configuration, from the environment. */
8
+ export interface CliConfig {
9
+ client: EInvoice;
10
+ allowLive: boolean;
11
+ }
12
+ /**
13
+ * Reads `YONA_API_KEY` (required), `YONA_ALLOW_LIVE` (`true` to allow a live key) and
14
+ * `YONA_BASE_URL` (an override for testing against another gateway).
15
+ */
16
+ export declare function configFromEnv(env: NodeJS.ProcessEnv): CliConfig;
17
+ /** Builds the server from the environment; throws {@link CliConfigError} for a bad configuration. */
18
+ export declare function serverFromEnv(env: NodeJS.ProcessEnv): {
19
+ server: McpServer;
20
+ mode: string;
21
+ };
22
+ /** The `einvoice-mcp` binary: the server over stdio. Diagnostics go to stderr; stdout is the protocol. */
23
+ export declare function main(env?: NodeJS.ProcessEnv): Promise<void>;
24
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAoC,MAAM,sBAAsB,CAAC;AACjF,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAIvE,mGAAmG;AACnG,qBAAa,cAAe,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI9B;AAED,wDAAwD;AACxD,MAAM,WAAW,SAAS;IACtB,MAAM,EAAE,QAAQ,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,CAsB/D;AAED,qGAAqG;AACrG,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAQvF;AAED,0GAA0G;AAC1G,wBAAsB,IAAI,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAW9E"}
package/dist/cli.js ADDED
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CliConfigError = void 0;
4
+ exports.configFromEnv = configFromEnv;
5
+ exports.serverFromEnv = serverFromEnv;
6
+ exports.main = main;
7
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
8
+ const einvoice_js_1 = require("@useyona/einvoice-js");
9
+ const server_1 = require("./server");
10
+ const version_1 = require("./version");
11
+ /** A configuration problem the binary reports and exits on. Its message never contains the key. */
12
+ class CliConfigError extends Error {
13
+ constructor(message) {
14
+ super(message);
15
+ this.name = 'CliConfigError';
16
+ }
17
+ }
18
+ exports.CliConfigError = CliConfigError;
19
+ /**
20
+ * Reads `YONA_API_KEY` (required), `YONA_ALLOW_LIVE` (`true` to allow a live key) and
21
+ * `YONA_BASE_URL` (an override for testing against another gateway).
22
+ */
23
+ function configFromEnv(env) {
24
+ const apiKey = env.YONA_API_KEY?.trim();
25
+ if (!apiKey) {
26
+ throw new CliConfigError('YONA_API_KEY is not set. Create an API key in the Yona dashboard (API keys) and pass it in the ' +
27
+ 'environment of this server, e.g. "env": { "YONA_API_KEY": "sk_test_…" } in your MCP client configuration.');
28
+ }
29
+ try {
30
+ (0, einvoice_js_1.modeOfApiKey)(apiKey);
31
+ }
32
+ catch (error) {
33
+ // The SDK's message describes the expected shape and never echoes the key.
34
+ throw new CliConfigError(`YONA_API_KEY: ${error.message}`);
35
+ }
36
+ const allowLive = env.YONA_ALLOW_LIVE === 'true';
37
+ try {
38
+ const client = new einvoice_js_1.EInvoice({ apiKey, ...(env.YONA_BASE_URL ? { baseUrl: env.YONA_BASE_URL } : {}) });
39
+ return { client, allowLive };
40
+ }
41
+ catch (error) {
42
+ if (error instanceof einvoice_js_1.EInvoiceConfigError)
43
+ throw new CliConfigError(error.message);
44
+ throw error;
45
+ }
46
+ }
47
+ /** Builds the server from the environment; throws {@link CliConfigError} for a bad configuration. */
48
+ function serverFromEnv(env) {
49
+ const { client, allowLive } = configFromEnv(env);
50
+ try {
51
+ return { server: (0, server_1.createYonaMcpServer)({ client, allowLive }), mode: client.mode };
52
+ }
53
+ catch (error) {
54
+ if (error instanceof server_1.LiveModeRefusedError)
55
+ throw new CliConfigError(error.message);
56
+ throw error;
57
+ }
58
+ }
59
+ /** The `einvoice-mcp` binary: the server over stdio. Diagnostics go to stderr; stdout is the protocol. */
60
+ async function main(env = process.env) {
61
+ let built;
62
+ try {
63
+ built = serverFromEnv(env);
64
+ }
65
+ catch (error) {
66
+ process.stderr.write(`einvoice-mcp: ${error.message}\n`);
67
+ process.exitCode = 1;
68
+ return;
69
+ }
70
+ await built.server.connect(new stdio_js_1.StdioServerTransport());
71
+ process.stderr.write(`einvoice-mcp ${version_1.VERSION}: Yona e-invoicing, ${built.mode} mode, on stdio\n`);
72
+ }
73
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAwBA,sCAsBC;AAGD,sCAQC;AAGD,oBAWC;AAvED,wEAA+E;AAC/E,sDAAiF;AAEjF,qCAAmE;AACnE,uCAAkC;AAElC,mGAAmG;AACnG,MAAa,cAAe,SAAQ,KAAK;IACrC,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IACjC,CAAC;CACJ;AALD,wCAKC;AAQD;;;GAGG;AACH,SAAgB,aAAa,CAAC,GAAsB;IAChD,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,MAAM,IAAI,cAAc,CACpB,iGAAiG;YAC7F,2GAA2G,CAClH,CAAC;IACN,CAAC;IACD,IAAI,CAAC;QACD,IAAA,0BAAY,EAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,2EAA2E;QAC3E,MAAM,IAAI,cAAc,CAAC,iBAAkB,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,KAAK,MAAM,CAAC;IACjD,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,sBAAQ,CAAC,EAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAC,OAAO,EAAE,GAAG,CAAC,aAAa,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAC,CAAC,CAAC;QAClG,OAAO,EAAC,MAAM,EAAE,SAAS,EAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,iCAAmB;YAAE,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAClF,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC;AAED,qGAAqG;AACrG,SAAgB,aAAa,CAAC,GAAsB;IAChD,MAAM,EAAC,MAAM,EAAE,SAAS,EAAC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,CAAC;QACD,OAAO,EAAC,MAAM,EAAE,IAAA,4BAAmB,EAAC,EAAC,MAAM,EAAE,SAAS,EAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAC,CAAC;IACjF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,6BAAoB;YAAE,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnF,MAAM,KAAK,CAAC;IAChB,CAAC;AACL,CAAC;AAED,0GAA0G;AACnG,KAAK,UAAU,IAAI,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC3D,IAAI,KAAK,CAAC;IACV,IAAI,CAAC;QACD,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAkB,KAAe,CAAC,OAAO,IAAI,CAAC,CAAC;QACpE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACX,CAAC;IACD,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,+BAAoB,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,iBAAO,uBAAuB,KAAK,CAAC,IAAI,mBAAmB,CAAC,CAAC;AACtG,CAAC"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { YonaMcpServerOptions } from './server';
3
+ /** Options of {@link handleStreamableHttp}. */
4
+ export interface StreamableHttpOptions extends YonaMcpServerOptions {
5
+ /** The request body when the host framework already parsed it (Express/NestJS `req.body`). */
6
+ parsedBody?: unknown;
7
+ }
8
+ /**
9
+ * Answers one MCP request over streamable HTTP, stateless, with JSON responses (no SSE, no
10
+ * session): a fresh server and transport per request, closed when the response closes. This is
11
+ * how a host (the hosted Yona MCP service) mounts the server on `POST /mcp`; build `client` per
12
+ * request with the caller's credentials. GET and DELETE answer 405 (there is no session to stream
13
+ * or end); a live client without `allowLive` answers 403.
14
+ */
15
+ export declare function handleStreamableHttp(req: IncomingMessage, res: ServerResponse, options: StreamableHttpOptions): Promise<void>;
16
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAE,cAAc,EAAC,MAAM,WAAW,CAAC;AAG/D,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,UAAU,CAAC;AAEnD,+CAA+C;AAC/C,MAAM,WAAW,qBAAsB,SAAQ,oBAAoB;IAC/D,8FAA8F;IAC9F,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAOD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBnI"}
package/dist/http.js ADDED
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleStreamableHttp = handleStreamableHttp;
4
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
5
+ const server_1 = require("./server");
6
+ function jsonRpcError(res, status, code, message, headers = {}) {
7
+ res.writeHead(status, { 'content-type': 'application/json', ...headers });
8
+ res.end(JSON.stringify({ jsonrpc: '2.0', error: { code, message }, id: null }));
9
+ }
10
+ /**
11
+ * Answers one MCP request over streamable HTTP, stateless, with JSON responses (no SSE, no
12
+ * session): a fresh server and transport per request, closed when the response closes. This is
13
+ * how a host (the hosted Yona MCP service) mounts the server on `POST /mcp`; build `client` per
14
+ * request with the caller's credentials. GET and DELETE answer 405 (there is no session to stream
15
+ * or end); a live client without `allowLive` answers 403.
16
+ */
17
+ async function handleStreamableHttp(req, res, options) {
18
+ if (req.method !== 'POST') {
19
+ jsonRpcError(res, 405, -32000, 'Method not allowed: this MCP endpoint is stateless and answers POST only.', { allow: 'POST' });
20
+ return;
21
+ }
22
+ let server;
23
+ try {
24
+ server = (0, server_1.createYonaMcpServer)({ client: options.client, allowLive: options.allowLive });
25
+ }
26
+ catch (error) {
27
+ if (error instanceof server_1.LiveModeRefusedError) {
28
+ jsonRpcError(res, 403, -32001, error.message);
29
+ return;
30
+ }
31
+ throw error;
32
+ }
33
+ const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({ sessionIdGenerator: undefined, enableJsonResponse: true });
34
+ res.on('close', () => {
35
+ void transport.close();
36
+ void server.close();
37
+ });
38
+ await server.connect(transport);
39
+ await transport.handleRequest(req, res, options.parsedBody);
40
+ }
41
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":";;AAuBA,oDAsBC;AA5CD,0FAAiG;AACjG,qCAAmE;AASnE,SAAS,YAAY,CAAC,GAAmB,EAAE,MAAc,EAAE,IAAY,EAAE,OAAe,EAAE,UAAkC,EAAE;IAC1H,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAC,cAAc,EAAE,kBAAkB,EAAE,GAAG,OAAO,EAAC,CAAC,CAAC;IACxE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAC,IAAI,EAAE,OAAO,EAAC,EAAE,EAAE,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;GAMG;AACI,KAAK,UAAU,oBAAoB,CAAC,GAAoB,EAAE,GAAmB,EAAE,OAA8B;IAChH,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACxB,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,2EAA2E,EAAE,EAAC,KAAK,EAAE,MAAM,EAAC,CAAC,CAAC;QAC7H,OAAO;IACX,CAAC;IACD,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACD,MAAM,GAAG,IAAA,4BAAmB,EAAC,EAAC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAC,CAAC,CAAC;IACzF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,KAAK,YAAY,6BAAoB,EAAE,CAAC;YACxC,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC9C,OAAO;QACX,CAAC;QACD,MAAM,KAAK,CAAC;IAChB,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,iDAA6B,CAAC,EAAC,kBAAkB,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,EAAC,CAAC,CAAC;IAC/G,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACjB,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,16 @@
1
+ /** What identifies one tool call: the MCP request id and, when the transport has one, the session. */
2
+ export interface CallIdentity {
3
+ requestId: string | number;
4
+ sessionId?: string;
5
+ }
6
+ /**
7
+ * The `Idempotency-Key` of a write, derived from the tool call: the MCP request id (plus the session
8
+ * id when there is one), the tool name and its arguments. A client that retries the same call (same
9
+ * request id, same arguments) sends the same key, so the API answers the first result and charges
10
+ * once. The arguments are part of the key because request ids restart at 1 in every stateless HTTP
11
+ * request and in every new stdio process: two different calls must never share a key.
12
+ *
13
+ * The result is `mcp_` + 40 hex characters, inside the API's `[A-Za-z0-9_-]{8,128}`.
14
+ */
15
+ export declare function deriveIdempotencyKey(tool: string, call: CallIdentity, args: unknown): string;
16
+ //# sourceMappingURL=idempotency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../src/idempotency.ts"],"names":[],"mappings":"AAEA,sGAAsG;AACtG,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAeD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAG5F"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deriveIdempotencyKey = deriveIdempotencyKey;
4
+ const node_crypto_1 = require("node:crypto");
5
+ /** Sorts object keys so equal arguments always serialise the same way. */
6
+ function canonical(value) {
7
+ if (Array.isArray(value))
8
+ return value.map(canonical);
9
+ if (value && typeof value === 'object') {
10
+ const out = {};
11
+ for (const key of Object.keys(value).sort()) {
12
+ out[key] = canonical(value[key]);
13
+ }
14
+ return out;
15
+ }
16
+ return value;
17
+ }
18
+ /**
19
+ * The `Idempotency-Key` of a write, derived from the tool call: the MCP request id (plus the session
20
+ * id when there is one), the tool name and its arguments. A client that retries the same call (same
21
+ * request id, same arguments) sends the same key, so the API answers the first result and charges
22
+ * once. The arguments are part of the key because request ids restart at 1 in every stateless HTTP
23
+ * request and in every new stdio process: two different calls must never share a key.
24
+ *
25
+ * The result is `mcp_` + 40 hex characters, inside the API's `[A-Za-z0-9_-]{8,128}`.
26
+ */
27
+ function deriveIdempotencyKey(tool, call, args) {
28
+ const material = JSON.stringify([tool, call.sessionId ?? null, String(call.requestId), canonical(args)]);
29
+ return `mcp_${(0, node_crypto_1.createHash)('sha256').update(material).digest('hex').slice(0, 40)}`;
30
+ }
31
+ //# sourceMappingURL=idempotency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../src/idempotency.ts"],"names":[],"mappings":";;AA8BA,oDAGC;AAjCD,6CAAuC;AAQvC,0EAA0E;AAC1E,SAAS,SAAS,CAAC,KAAc;IAC7B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAgC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACrE,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAE,KAAiC,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,GAAG,CAAC;IACf,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,oBAAoB,CAAC,IAAY,EAAE,IAAkB,EAAE,IAAa;IAChF,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzG,OAAO,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AACrF,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { createYonaMcpServer, LiveModeRefusedError } from './server';
2
+ export type { YonaMcpServerOptions } from './server';
3
+ export { handleStreamableHttp } from './http';
4
+ export type { StreamableHttpOptions } from './http';
5
+ export { TOOLS } from './tools';
6
+ export type { ToolDefinition, ToolContext, ToolOutput } from './tools';
7
+ export { RESOURCE_URIS } from './resources';
8
+ export { PROMPT_NAMES } from './prompts';
9
+ export { deriveIdempotencyKey } from './idempotency';
10
+ export { redact } from './result';
11
+ export { VERSION, SERVER_NAME } from './version';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAE,oBAAoB,EAAC,MAAM,UAAU,CAAC;AACnE,YAAY,EAAC,oBAAoB,EAAC,MAAM,UAAU,CAAC;AACnD,OAAO,EAAC,oBAAoB,EAAC,MAAM,QAAQ,CAAC;AAC5C,YAAY,EAAC,qBAAqB,EAAC,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAC,KAAK,EAAC,MAAM,SAAS,CAAC;AAC9B,YAAY,EAAC,cAAc,EAAE,WAAW,EAAE,UAAU,EAAC,MAAM,SAAS,CAAC;AACrE,OAAO,EAAC,aAAa,EAAC,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAC,YAAY,EAAC,MAAM,WAAW,CAAC;AACvC,OAAO,EAAC,oBAAoB,EAAC,MAAM,eAAe,CAAC;AACnD,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC;AAChC,OAAO,EAAC,OAAO,EAAE,WAAW,EAAC,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SERVER_NAME = exports.VERSION = exports.redact = exports.deriveIdempotencyKey = exports.PROMPT_NAMES = exports.RESOURCE_URIS = exports.TOOLS = exports.handleStreamableHttp = exports.LiveModeRefusedError = exports.createYonaMcpServer = void 0;
4
+ var server_1 = require("./server");
5
+ Object.defineProperty(exports, "createYonaMcpServer", { enumerable: true, get: function () { return server_1.createYonaMcpServer; } });
6
+ Object.defineProperty(exports, "LiveModeRefusedError", { enumerable: true, get: function () { return server_1.LiveModeRefusedError; } });
7
+ var http_1 = require("./http");
8
+ Object.defineProperty(exports, "handleStreamableHttp", { enumerable: true, get: function () { return http_1.handleStreamableHttp; } });
9
+ var tools_1 = require("./tools");
10
+ Object.defineProperty(exports, "TOOLS", { enumerable: true, get: function () { return tools_1.TOOLS; } });
11
+ var resources_1 = require("./resources");
12
+ Object.defineProperty(exports, "RESOURCE_URIS", { enumerable: true, get: function () { return resources_1.RESOURCE_URIS; } });
13
+ var prompts_1 = require("./prompts");
14
+ Object.defineProperty(exports, "PROMPT_NAMES", { enumerable: true, get: function () { return prompts_1.PROMPT_NAMES; } });
15
+ var idempotency_1 = require("./idempotency");
16
+ Object.defineProperty(exports, "deriveIdempotencyKey", { enumerable: true, get: function () { return idempotency_1.deriveIdempotencyKey; } });
17
+ var result_1 = require("./result");
18
+ Object.defineProperty(exports, "redact", { enumerable: true, get: function () { return result_1.redact; } });
19
+ var version_1 = require("./version");
20
+ Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () { return version_1.VERSION; } });
21
+ Object.defineProperty(exports, "SERVER_NAME", { enumerable: true, get: function () { return version_1.SERVER_NAME; } });
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAAmE;AAA3D,6GAAA,mBAAmB,OAAA;AAAE,8GAAA,oBAAoB,OAAA;AAEjD,+BAA4C;AAApC,4GAAA,oBAAoB,OAAA;AAE5B,iCAA8B;AAAtB,8FAAA,KAAK,OAAA;AAEb,yCAA0C;AAAlC,0GAAA,aAAa,OAAA;AACrB,qCAAuC;AAA/B,uGAAA,YAAY,OAAA;AACpB,6CAAmD;AAA3C,mHAAA,oBAAoB,OAAA;AAC5B,mCAAgC;AAAxB,gGAAA,MAAM,OAAA;AACd,qCAA+C;AAAvC,kGAAA,OAAO,OAAA;AAAE,sGAAA,WAAW,OAAA"}
@@ -0,0 +1,5 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { EInvoice } from '@useyona/einvoice-js';
3
+ export declare const PROMPT_NAMES: readonly ["draft_invoice", "explain_rejection"];
4
+ export declare function registerPrompts(server: McpServer, client: EInvoice): void;
5
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AACvE,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAGnD,eAAO,MAAM,YAAY,iDAAkD,CAAC;AAE5E,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAyEzE"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PROMPT_NAMES = void 0;
4
+ exports.registerPrompts = registerPrompts;
5
+ const zod_1 = require("zod");
6
+ const result_1 = require("./result");
7
+ exports.PROMPT_NAMES = ['draft_invoice', 'explain_rejection'];
8
+ function registerPrompts(server, client) {
9
+ server.registerPrompt('draft_invoice', {
10
+ title: 'Draft an invoice',
11
+ description: 'Turns a plain description ("2 laptops at ₦850,000 each for Acme Ltd") into a validated draft invoice.',
12
+ argsSchema: { description: zod_1.z.string().describe('What was sold, to whom, for how much.') },
13
+ }, ({ description }) => ({
14
+ messages: [
15
+ {
16
+ role: 'user',
17
+ content: {
18
+ type: 'text',
19
+ text: [
20
+ `Draft an e-invoice in Yona (${client.mode} mode) from this description:`,
21
+ '',
22
+ description,
23
+ '',
24
+ 'Steps:',
25
+ '1. Find the buyer with search_buyers. If there is none, ask me before create_buyer (it is charged); use lookup_tin when the tax id is uncertain.',
26
+ '2. Find matching items with search_items; otherwise write each line with description, unitCode (yona://reference/units), unitPrice in major units and taxCategory (yona://reference/tax-categories, e.g. STANDARD_VAT).',
27
+ '3. Call create_invoice with invoiceKind (B2B, B2C, B2G or G2B), today’s invoiceDate, the currency and the lines. It stays a draft.',
28
+ '4. Call validate_invoice with the new invoiceId and fix what it reports with update_invoice.',
29
+ '5. Show me the draft (buyer, lines, totals, tax). Do NOT call finalise_invoice or submit_invoice unless I explicitly ask.',
30
+ ].join('\n'),
31
+ },
32
+ },
33
+ ],
34
+ }));
35
+ server.registerPrompt('explain_rejection', {
36
+ title: 'Explain a rejection',
37
+ description: 'Explains in plain words why the tax authority rejected or parked an invoice, and what to do next.',
38
+ argsSchema: { invoiceId: zod_1.z.string().describe('The invoice id.') },
39
+ }, async ({ invoiceId }, extra) => {
40
+ let status;
41
+ try {
42
+ status = JSON.stringify((0, result_1.compact)(await client.submissions.getStatus(invoiceId, { signal: extra.signal })), null, 2);
43
+ }
44
+ catch (error) {
45
+ const e = error;
46
+ status = `(could not read the status: ${e.errorCode ?? ''} ${e.message ?? String(error)}; call get_submission_status)`;
47
+ }
48
+ return {
49
+ messages: [
50
+ {
51
+ role: 'user',
52
+ content: {
53
+ type: 'text',
54
+ text: (0, result_1.redact)([
55
+ `Explain in plain words, for a business owner, why invoice ${invoiceId} was not accepted by the tax authority, and what to do next.`,
56
+ '',
57
+ 'Its submission status as Yona last recorded it:',
58
+ status,
59
+ '',
60
+ 'Read authorityState, parkReason and the submissions’ errors. Know that:',
61
+ '- "parked" means Yona holds the invoice until something outside it changes; the parkReason says what.',
62
+ '- A message that the buyer’s access points are offline usually means the BUYER’s tax id is not registered for e-invoicing, not an outage: check the buyer with lookup_tin.',
63
+ '- A validation rejection names the field: fix the draft (a reported invoice is corrected with a credit note, never edited).',
64
+ 'Do not resubmit, cancel or credit anything without my explicit approval.',
65
+ ].join('\n')),
66
+ },
67
+ },
68
+ ],
69
+ };
70
+ });
71
+ }
72
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":";;;AAOA,0CAyEC;AAhFD,6BAAsB;AAGtB,qCAAyC;AAE5B,QAAA,YAAY,GAAG,CAAC,eAAe,EAAE,mBAAmB,CAAU,CAAC;AAE5E,SAAgB,eAAe,CAAC,MAAiB,EAAE,MAAgB;IAC/D,MAAM,CAAC,cAAc,CACjB,eAAe,EACf;QACI,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,uGAAuG;QACpH,UAAU,EAAE,EAAC,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC,EAAC;KAC1F,EACD,CAAC,EAAC,WAAW,EAAC,EAAE,EAAE,CAAC,CAAC;QAChB,QAAQ,EAAE;YACN;gBACI,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACL,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;wBACF,+BAA+B,MAAM,CAAC,IAAI,+BAA+B;wBACzE,EAAE;wBACF,WAAW;wBACX,EAAE;wBACF,QAAQ;wBACR,kJAAkJ;wBAClJ,yNAAyN;wBACzN,oIAAoI;wBACpI,8FAA8F;wBAC9F,2HAA2H;qBAC9H,CAAC,IAAI,CAAC,IAAI,CAAC;iBACf;aACJ;SACJ;KACJ,CAAC,CACL,CAAC;IAEF,MAAM,CAAC,cAAc,CACjB,mBAAmB,EACnB;QACI,KAAK,EAAE,qBAAqB;QAC5B,WAAW,EAAE,mGAAmG;QAChH,UAAU,EAAE,EAAC,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAC;KAClE,EACD,KAAK,EAAE,EAAC,SAAS,EAAC,EAAE,KAAK,EAAE,EAAE;QACzB,IAAI,MAAc,CAAC;QACnB,IAAI,CAAC;YACD,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAA,gBAAO,EAAC,MAAM,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,SAAS,EAAE,EAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACrH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,KAA+C,CAAC;YAC1D,MAAM,GAAG,+BAA+B,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,+BAA+B,CAAC;QAC3H,CAAC;QACD,OAAO;YACH,QAAQ,EAAE;gBACN;oBACI,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE;wBACL,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAA,eAAM,EACR;4BACI,6DAA6D,SAAS,8DAA8D;4BACpI,EAAE;4BACF,iDAAiD;4BACjD,MAAM;4BACN,EAAE;4BACF,yEAAyE;4BACzE,uGAAuG;4BACvG,4KAA4K;4BAC5K,6HAA6H;4BAC7H,0EAA0E;yBAC7E,CAAC,IAAI,CAAC,IAAI,CAAC,CACf;qBACJ;iBACJ;aACJ;SACJ,CAAC;IACN,CAAC,CACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { EInvoice } from '@useyona/einvoice-js';
3
+ /** The resource URIs this server serves. */
4
+ export declare const RESOURCE_URIS: {
5
+ readonly taxCategories: "yona://reference/tax-categories";
6
+ readonly units: "yona://reference/units";
7
+ readonly hsCodes: "yona://reference/hs-codes";
8
+ readonly organization: "yona://organization";
9
+ };
10
+ /** The jurisdiction's code-list type behind each reference resource (`reference.getResource`). */
11
+ export declare const CODE_LIST_OF: {
12
+ readonly "yona://reference/tax-categories": "tax-categories";
13
+ readonly "yona://reference/units": "invoice-quantity-codes";
14
+ };
15
+ export declare function registerResources(server: McpServer, client: EInvoice): void;
16
+ //# sourceMappingURL=resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AAIvE,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAInD,4CAA4C;AAC5C,eAAO,MAAM,aAAa;;;;;CAKhB,CAAC;AAEX,kGAAkG;AAClG,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAuBX,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAkD3E"}