storno-cli 1.0.5 → 1.0.6
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 +39 -2
- package/TOOLS.md +10 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +9 -5
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +13 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +10 -0
- package/dist/context.js.map +1 -0
- package/dist/http-server.d.ts +12 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +269 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +6 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -146
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +12 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +146 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/clients.d.ts.map +1 -1
- package/dist/tools/clients.js +4 -0
- package/dist/tools/clients.js.map +1 -1
- package/dist/tools/invoices.d.ts.map +1 -1
- package/dist/tools/invoices.js +98 -0
- package/dist/tools/invoices.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -91,6 +91,8 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
91
91
|
| `STORNO_COMPANY_ID` | No* | — | Default company UUID |
|
|
92
92
|
| `STORNO_EMAIL` | No | — | Email for auto-login (if no token) |
|
|
93
93
|
| `STORNO_PASSWORD` | No | — | Password for auto-login (if no token) |
|
|
94
|
+
| `STORNO_HTTP_PORT` | No | — | If set, starts Streamable HTTP transport on this port |
|
|
95
|
+
| `STORNO_HTTP_HOST` | No | `127.0.0.1` | HTTP bind address (used with `STORNO_HTTP_PORT`) |
|
|
94
96
|
|
|
95
97
|
\* You can authenticate at runtime using the `auth_login` tool instead.
|
|
96
98
|
|
|
@@ -216,12 +218,45 @@ AI: [calls invoices_list with from=2024-01-01, to=2024-01-31]
|
|
|
216
218
|
- 18 issued, 3 paid, 2 overdue
|
|
217
219
|
```
|
|
218
220
|
|
|
221
|
+
## HTTP Transport
|
|
222
|
+
|
|
223
|
+
By default, storno-cli uses **stdio transport** for local MCP clients. Set `STORNO_HTTP_PORT` to enable **Streamable HTTP transport** for remote access.
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Start HTTP server on port 3000
|
|
227
|
+
STORNO_TOKEN=your-token STORNO_COMPANY_ID=your-company-uuid \
|
|
228
|
+
STORNO_HTTP_PORT=3000 node dist/index.js
|
|
229
|
+
|
|
230
|
+
# Bind to all interfaces (for production behind a reverse proxy)
|
|
231
|
+
STORNO_HTTP_PORT=3000 STORNO_HTTP_HOST=0.0.0.0 node dist/index.js
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The server exposes a single `/mcp` endpoint supporting POST, GET, and DELETE per the MCP Streamable HTTP spec. Each client connection creates an isolated stateful session.
|
|
235
|
+
|
|
236
|
+
**Initialize a session:**
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
curl -X POST http://127.0.0.1:3000/mcp \
|
|
240
|
+
-H "Content-Type: application/json" \
|
|
241
|
+
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
|
|
242
|
+
# Response includes mcp-session-id header
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Call a tool:**
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
curl -X POST http://127.0.0.1:3000/mcp \
|
|
249
|
+
-H "Content-Type: application/json" \
|
|
250
|
+
-H "mcp-session-id: <session-id>" \
|
|
251
|
+
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"system_health","arguments":{}}}'
|
|
252
|
+
```
|
|
253
|
+
|
|
219
254
|
## Development
|
|
220
255
|
|
|
221
256
|
```bash
|
|
222
257
|
npm run dev # Watch mode (recompile on changes)
|
|
223
258
|
npm run build # Production build
|
|
224
|
-
npm run start # Start MCP server
|
|
259
|
+
npm run start # Start MCP server (stdio)
|
|
225
260
|
```
|
|
226
261
|
|
|
227
262
|
## Architecture
|
|
@@ -229,7 +264,9 @@ npm run start # Start MCP server
|
|
|
229
264
|
```
|
|
230
265
|
storno-cli/
|
|
231
266
|
├── src/
|
|
232
|
-
│ ├── index.ts #
|
|
267
|
+
│ ├── index.ts # Entry point — dispatches to stdio or HTTP transport
|
|
268
|
+
│ ├── server.ts # McpServer factory (creates server + registers all tools)
|
|
269
|
+
│ ├── http-server.ts # Streamable HTTP transport with session management
|
|
233
270
|
│ ├── config.ts # Environment configuration
|
|
234
271
|
│ ├── client.ts # HTTP client with JWT auth + auto-refresh
|
|
235
272
|
│ ├── tools/ # 40 tool domain files (237 tools total)
|
package/TOOLS.md
CHANGED
|
@@ -306,7 +306,9 @@ Create a new draft invoice. Requires a clientId and at least one line item. The
|
|
|
306
306
|
| `penaltyGraceDays` | number | No | Grace period in days before penalty starts applying |
|
|
307
307
|
| `autoApplyVatRules` | boolean | No | Auto-apply VAT rules: reverse charge for VIES-valid EU clients, OSS destination rate for non-VIES EU clients (default: false) |
|
|
308
308
|
| `vatIncluded` | boolean | No | When used with `autoApplyVatRules`, sets whether unit prices include VAT on all lines |
|
|
309
|
-
| `
|
|
309
|
+
| `paymentMethod` | enum | No | Payment method: `bank_transfer` (default), `cash`, `card`, `cheque`, `other` |
|
|
310
|
+
| `ublExtensions` | object | No | UBL extension fields for advanced e-Factura compliance. Supports: `invoicePeriod` (startDate, endDate, descriptionCode), `delivery` (actualDeliveryDate, deliveryAddress), `allowanceCharges` (array, max 20 — each with chargeIndicator, amount, taxCategoryCode, taxRate), `prepaidAmount`, `additionalDocumentReferences` (array, max 10 — each with id, documentTypeCode, documentDescription) |
|
|
311
|
+
| `lines` | array | Yes | Invoice line items (at least one required). Each line may include `ublExtensions` with: `invoicePeriod`, `allowanceCharges` (max 10), `additionalItemProperties` (max 20, name/value), `originCountry` |
|
|
310
312
|
|
|
311
313
|
### `invoices_update`
|
|
312
314
|
|
|
@@ -344,7 +346,9 @@ Update an existing draft invoice. Only invoices with status "draft" can be updat
|
|
|
344
346
|
| `penaltyGraceDays` | number | No | Grace period before penalty applies |
|
|
345
347
|
| `autoApplyVatRules` | boolean | No | Auto-apply VAT rules: reverse charge for VIES-valid EU clients, OSS destination rate for non-VIES EU clients (default: false) |
|
|
346
348
|
| `vatIncluded` | boolean | No | When used with `autoApplyVatRules`, sets whether unit prices include VAT on all lines |
|
|
347
|
-
| `
|
|
349
|
+
| `paymentMethod` | enum | No | Payment method: `bank_transfer`, `cash`, `card`, `cheque`, `other` |
|
|
350
|
+
| `ublExtensions` | object | No | UBL extension fields (same schema as invoices_create). Pass `null` to clear. |
|
|
351
|
+
| `lines` | array | No | Invoice line items. WARNING: replaces all existing lines — include every line you want to keep. Each line may include `ublExtensions`. |
|
|
348
352
|
|
|
349
353
|
### `invoices_delete`
|
|
350
354
|
|
|
@@ -734,6 +738,8 @@ Create a new client manually. Requires at least a name. If a CUI is provided and
|
|
|
734
738
|
| `defaultPaymentTermDays` | number | No | Default payment term in days |
|
|
735
739
|
| `contactPerson` | string | No | Contact person name |
|
|
736
740
|
| `notes` | string | No | Internal notes |
|
|
741
|
+
| `idNumber` | string | No | Client identification number (personal ID, passport, etc.) |
|
|
742
|
+
| `currency` | string | No | Preferred currency (ISO 4217, e.g., EUR, USD, RON) |
|
|
737
743
|
| `companyId` | string | No | Company UUID override (uses active company if not set) |
|
|
738
744
|
|
|
739
745
|
### `clients_update`
|
|
@@ -764,6 +770,8 @@ Update an existing client. Only provided fields are updated; omitted fields rema
|
|
|
764
770
|
| `defaultPaymentTermDays` | number | No | Default payment term in days |
|
|
765
771
|
| `contactPerson` | string | No | Contact person name |
|
|
766
772
|
| `notes` | string | No | Internal notes |
|
|
773
|
+
| `idNumber` | string | No | Client identification number (personal ID, passport, etc.) |
|
|
774
|
+
| `currency` | string | No | Preferred currency (ISO 4217, e.g., EUR, USD, RON) |
|
|
767
775
|
| `companyId` | string | No | Company UUID override (uses active company if not set) |
|
|
768
776
|
|
|
769
777
|
### `clients_delete`
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,CAAC;CACT;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,KAAK,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE9D,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AA0BD,wBAAsB,UAAU,CAAC,CAAC,GAAG,OAAO,EAC1C,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CA4IpC"}
|
package/dist/client.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { readFileSync } from 'node:fs';
|
|
11
11
|
import { basename } from 'node:path';
|
|
12
12
|
import { getConfig, updateConfig } from './config.js';
|
|
13
|
+
import { sessionContext } from './context.js';
|
|
13
14
|
async function refreshAccessToken() {
|
|
14
15
|
const config = getConfig();
|
|
15
16
|
if (!config.refreshToken)
|
|
@@ -49,11 +50,14 @@ export async function apiRequest(path, options = {}) {
|
|
|
49
50
|
const reqHeaders = {
|
|
50
51
|
...headers,
|
|
51
52
|
};
|
|
52
|
-
|
|
53
|
+
// Per-session token (SaaS mode) takes precedence over global config token
|
|
54
|
+
const sessionToken = sessionContext.getStore()?.token;
|
|
55
|
+
const effectiveToken = sessionToken || config.token;
|
|
56
|
+
if (!noAuth && effectiveToken) {
|
|
53
57
|
// API keys (e.g. "af_...") must be sent without "Bearer " prefix;
|
|
54
58
|
// the backend's ApiKeyAuthenticator skips Bearer-prefixed tokens.
|
|
55
|
-
const isApiKey =
|
|
56
|
-
reqHeaders['Authorization'] = isApiKey ?
|
|
59
|
+
const isApiKey = effectiveToken.startsWith('af_');
|
|
60
|
+
reqHeaders['Authorization'] = isApiKey ? effectiveToken : `Bearer ${effectiveToken}`;
|
|
57
61
|
}
|
|
58
62
|
const effectiveCompanyId = companyId || config.companyId;
|
|
59
63
|
if (effectiveCompanyId) {
|
|
@@ -95,8 +99,8 @@ export async function apiRequest(path, options = {}) {
|
|
|
95
99
|
error: `Network error: ${err instanceof Error ? err.message : String(err)}`,
|
|
96
100
|
};
|
|
97
101
|
}
|
|
98
|
-
// Auto-refresh on 401
|
|
99
|
-
if (res.status === 401 && !noAuth && config.refreshToken) {
|
|
102
|
+
// Auto-refresh on 401 (skip when using a per-session token — we don't have its refresh token)
|
|
103
|
+
if (res.status === 401 && !noAuth && !sessionToken && config.refreshToken) {
|
|
100
104
|
const refreshed = await refreshAccessToken();
|
|
101
105
|
if (refreshed) {
|
|
102
106
|
reqHeaders['Authorization'] = `Bearer ${getConfig().token}`;
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
* STORNO_COMPANY_ID — Default company UUID (used as X-Company header)
|
|
9
9
|
* STORNO_EMAIL — Email for auto-login (optional, used if no token)
|
|
10
10
|
* STORNO_PASSWORD — Password for auto-login (optional, used if no token)
|
|
11
|
+
* STORNO_HTTP_PORT — If set, starts Streamable HTTP transport on this port
|
|
12
|
+
* STORNO_HTTP_HOST — HTTP bind address (default: 127.0.0.1)
|
|
13
|
+
* STORNO_OAUTH_BASE_URL — OAuth2 base URL for SaaS protected-resource metadata
|
|
14
|
+
* STORNO_OAUTH_CLIENT_ID — OAuth2 client ID for SaaS mode
|
|
11
15
|
*/
|
|
12
16
|
export interface Config {
|
|
13
17
|
baseUrl: string;
|
|
@@ -16,6 +20,10 @@ export interface Config {
|
|
|
16
20
|
companyId: string | null;
|
|
17
21
|
email: string | null;
|
|
18
22
|
password: string | null;
|
|
23
|
+
httpPort: number | null;
|
|
24
|
+
httpHost: string;
|
|
25
|
+
oauthBaseUrl: string | null;
|
|
26
|
+
oauthClientId: string | null;
|
|
19
27
|
}
|
|
20
28
|
export declare function getConfig(): Config;
|
|
21
29
|
export declare function updateConfig(updates: Partial<Config>): void;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAID,wBAAgB,SAAS,IAAI,MAAM,CAgBlC;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAG3D"}
|
package/dist/config.js
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
* STORNO_COMPANY_ID — Default company UUID (used as X-Company header)
|
|
9
9
|
* STORNO_EMAIL — Email for auto-login (optional, used if no token)
|
|
10
10
|
* STORNO_PASSWORD — Password for auto-login (optional, used if no token)
|
|
11
|
+
* STORNO_HTTP_PORT — If set, starts Streamable HTTP transport on this port
|
|
12
|
+
* STORNO_HTTP_HOST — HTTP bind address (default: 127.0.0.1)
|
|
13
|
+
* STORNO_OAUTH_BASE_URL — OAuth2 base URL for SaaS protected-resource metadata
|
|
14
|
+
* STORNO_OAUTH_CLIENT_ID — OAuth2 client ID for SaaS mode
|
|
11
15
|
*/
|
|
12
16
|
let _config = null;
|
|
13
17
|
export function getConfig() {
|
|
@@ -19,6 +23,10 @@ export function getConfig() {
|
|
|
19
23
|
companyId: process.env.STORNO_COMPANY_ID || null,
|
|
20
24
|
email: process.env.STORNO_EMAIL || null,
|
|
21
25
|
password: process.env.STORNO_PASSWORD || null,
|
|
26
|
+
httpPort: process.env.STORNO_HTTP_PORT ? parseInt(process.env.STORNO_HTTP_PORT, 10) : null,
|
|
27
|
+
httpHost: process.env.STORNO_HTTP_HOST || '127.0.0.1',
|
|
28
|
+
oauthBaseUrl: process.env.STORNO_OAUTH_BASE_URL || null,
|
|
29
|
+
oauthClientId: process.env.STORNO_OAUTH_CLIENT_ID || null,
|
|
22
30
|
};
|
|
23
31
|
}
|
|
24
32
|
return _config;
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAeH,IAAI,OAAO,GAAkB,IAAI,CAAC;AAElC,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG;YACR,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,uBAAuB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;YACpF,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI;YACvC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,IAAI;YACtD,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,IAAI;YAChD,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI;YACvC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI;YAC7C,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI;YAC1F,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,WAAW;YACrD,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,IAAI;YACvD,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,IAAI;SAC1D,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAwB;IACnD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-session authentication context using AsyncLocalStorage.
|
|
3
|
+
*
|
|
4
|
+
* In SaaS mode each MCP session carries its own OAuth2 token.
|
|
5
|
+
* Tool handlers and apiRequest() read the token from this context
|
|
6
|
+
* instead of the global config, requiring zero changes to individual tools.
|
|
7
|
+
*/
|
|
8
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
9
|
+
export interface SessionContext {
|
|
10
|
+
token: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const sessionContext: AsyncLocalStorage<SessionContext>;
|
|
13
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,cAAc,mCAA0C,CAAC"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-session authentication context using AsyncLocalStorage.
|
|
3
|
+
*
|
|
4
|
+
* In SaaS mode each MCP session carries its own OAuth2 token.
|
|
5
|
+
* Tool handlers and apiRequest() read the token from this context
|
|
6
|
+
* instead of the global config, requiring zero changes to individual tools.
|
|
7
|
+
*/
|
|
8
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
9
|
+
export const sessionContext = new AsyncLocalStorage();
|
|
10
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAMrD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,iBAAiB,EAAkB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streamable HTTP transport for the Storno MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Implements the MCP Streamable HTTP spec using raw node:http (no new deps).
|
|
5
|
+
* Each session gets its own StreamableHTTPServerTransport + McpServer pair.
|
|
6
|
+
*
|
|
7
|
+
* Supports two modes:
|
|
8
|
+
* - Self-hosted: global token from STORNO_TOKEN, no per-session auth needed
|
|
9
|
+
* - SaaS: each client sends its own Bearer token, stored per-session
|
|
10
|
+
*/
|
|
11
|
+
export declare function startHttpServer(port: number, host: string): void;
|
|
12
|
+
//# sourceMappingURL=http-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAmNH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAgFhE"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streamable HTTP transport for the Storno MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Implements the MCP Streamable HTTP spec using raw node:http (no new deps).
|
|
5
|
+
* Each session gets its own StreamableHTTPServerTransport + McpServer pair.
|
|
6
|
+
*
|
|
7
|
+
* Supports two modes:
|
|
8
|
+
* - Self-hosted: global token from STORNO_TOKEN, no per-session auth needed
|
|
9
|
+
* - SaaS: each client sends its own Bearer token, stored per-session
|
|
10
|
+
*/
|
|
11
|
+
import { createServer } from 'node:http';
|
|
12
|
+
import { randomUUID } from 'node:crypto';
|
|
13
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
14
|
+
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
15
|
+
import { createMcpServer } from './server.js';
|
|
16
|
+
import { getConfig } from './config.js';
|
|
17
|
+
const sessions = new Map();
|
|
18
|
+
function setCorsHeaders(res) {
|
|
19
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
20
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
21
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, mcp-session-id, Authorization');
|
|
22
|
+
res.setHeader('Access-Control-Expose-Headers', 'mcp-session-id');
|
|
23
|
+
}
|
|
24
|
+
function jsonError(res, status, code, message, headers) {
|
|
25
|
+
res.writeHead(status, { 'Content-Type': 'application/json', ...headers });
|
|
26
|
+
res.end(JSON.stringify({ jsonrpc: '2.0', error: { code, message }, id: null }));
|
|
27
|
+
}
|
|
28
|
+
function readBody(req) {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const chunks = [];
|
|
31
|
+
req.on('data', (chunk) => chunks.push(chunk));
|
|
32
|
+
req.on('end', () => {
|
|
33
|
+
try {
|
|
34
|
+
resolve(JSON.parse(Buffer.concat(chunks).toString()));
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
reject(new Error('Invalid JSON'));
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
req.on('error', reject);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/** Extract Bearer token from Authorization header. */
|
|
44
|
+
function extractBearerToken(req) {
|
|
45
|
+
const auth = req.headers['authorization'];
|
|
46
|
+
if (auth && auth.startsWith('Bearer ')) {
|
|
47
|
+
return auth.slice(7);
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
/** Set req.auth so the MCP SDK passes it as extra.authInfo to tool callbacks. */
|
|
52
|
+
function setReqAuth(req, token) {
|
|
53
|
+
req.auth = {
|
|
54
|
+
token,
|
|
55
|
+
clientId: 'mcp',
|
|
56
|
+
scopes: [],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** Build the public base URL for this MCP server (used in OAuth metadata). */
|
|
60
|
+
function getPublicBaseUrl(req) {
|
|
61
|
+
// Trust X-Forwarded headers from nginx/Cloudflare
|
|
62
|
+
const proto = req.headers['x-forwarded-proto'] || 'http';
|
|
63
|
+
const host = req.headers['x-forwarded-host'] || req.headers['host'] || 'localhost';
|
|
64
|
+
return `${proto}://${host}`;
|
|
65
|
+
}
|
|
66
|
+
/** Build WWW-Authenticate header value for 401 responses. */
|
|
67
|
+
function wwwAuthenticateHeader(req) {
|
|
68
|
+
const baseUrl = getPublicBaseUrl(req);
|
|
69
|
+
return `Bearer resource_metadata="${baseUrl}/.well-known/oauth-protected-resource"`;
|
|
70
|
+
}
|
|
71
|
+
async function handlePost(req, res) {
|
|
72
|
+
const config = getConfig();
|
|
73
|
+
let body;
|
|
74
|
+
try {
|
|
75
|
+
body = await readBody(req);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
jsonError(res, 400, -32700, 'Parse error');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
82
|
+
const bearerToken = extractBearerToken(req);
|
|
83
|
+
if (sessionId && sessions.has(sessionId)) {
|
|
84
|
+
// Existing session — set req.auth from stored token and forward
|
|
85
|
+
const session = sessions.get(sessionId);
|
|
86
|
+
if (session.token) {
|
|
87
|
+
setReqAuth(req, session.token);
|
|
88
|
+
}
|
|
89
|
+
await session.transport.handleRequest(req, res, body);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (!sessionId && isInitializeRequest(body)) {
|
|
93
|
+
// Require auth if no global token is configured (SaaS mode)
|
|
94
|
+
if (!config.token && !bearerToken) {
|
|
95
|
+
jsonError(res, 401, -32001, 'Authentication required', {
|
|
96
|
+
'WWW-Authenticate': wwwAuthenticateHeader(req),
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// New session
|
|
101
|
+
const transport = new StreamableHTTPServerTransport({
|
|
102
|
+
sessionIdGenerator: () => randomUUID(),
|
|
103
|
+
onsessioninitialized: (sid) => {
|
|
104
|
+
sessions.set(sid, { transport, token: bearerToken });
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
transport.onclose = () => {
|
|
108
|
+
const sid = transport.sessionId;
|
|
109
|
+
if (sid)
|
|
110
|
+
sessions.delete(sid);
|
|
111
|
+
};
|
|
112
|
+
if (bearerToken) {
|
|
113
|
+
setReqAuth(req, bearerToken);
|
|
114
|
+
}
|
|
115
|
+
const server = createMcpServer();
|
|
116
|
+
await server.connect(transport);
|
|
117
|
+
await transport.handleRequest(req, res, body);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// Invalid — no session or not an init request
|
|
121
|
+
jsonError(res, 400, -32000, 'Bad Request: No valid session ID provided');
|
|
122
|
+
}
|
|
123
|
+
async function handleGet(req, res) {
|
|
124
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
125
|
+
if (!sessionId || !sessions.has(sessionId)) {
|
|
126
|
+
jsonError(res, 400, -32000, 'Invalid or missing session ID');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const session = sessions.get(sessionId);
|
|
130
|
+
if (session.token) {
|
|
131
|
+
setReqAuth(req, session.token);
|
|
132
|
+
}
|
|
133
|
+
await session.transport.handleRequest(req, res);
|
|
134
|
+
}
|
|
135
|
+
async function handleDelete(req, res) {
|
|
136
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
137
|
+
if (!sessionId || !sessions.has(sessionId)) {
|
|
138
|
+
jsonError(res, 400, -32000, 'Invalid or missing session ID');
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const session = sessions.get(sessionId);
|
|
142
|
+
await session.transport.handleRequest(req, res);
|
|
143
|
+
}
|
|
144
|
+
/** RFC 9728 — Protected Resource Metadata. */
|
|
145
|
+
function handleProtectedResourceMetadata(req, res) {
|
|
146
|
+
const config = getConfig();
|
|
147
|
+
if (!config.oauthBaseUrl) {
|
|
148
|
+
res.writeHead(404);
|
|
149
|
+
res.end('Not Found');
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const baseUrl = getPublicBaseUrl(req);
|
|
153
|
+
const metadata = {
|
|
154
|
+
resource: baseUrl,
|
|
155
|
+
authorization_servers: [baseUrl],
|
|
156
|
+
bearer_methods_supported: ['header'],
|
|
157
|
+
scopes_supported: [],
|
|
158
|
+
};
|
|
159
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
160
|
+
res.end(JSON.stringify(metadata));
|
|
161
|
+
}
|
|
162
|
+
/** RFC 8414 — Authorization Server Metadata. */
|
|
163
|
+
function handleAuthorizationServerMetadata(req, res) {
|
|
164
|
+
const config = getConfig();
|
|
165
|
+
if (!config.oauthBaseUrl || !config.oauthClientId) {
|
|
166
|
+
res.writeHead(404);
|
|
167
|
+
res.end('Not Found');
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const baseUrl = getPublicBaseUrl(req);
|
|
171
|
+
const metadata = {
|
|
172
|
+
issuer: baseUrl,
|
|
173
|
+
authorization_endpoint: `${config.oauthBaseUrl}/oauth/authorize`,
|
|
174
|
+
token_endpoint: `${config.baseUrl}/api/v1/oauth2/token`,
|
|
175
|
+
revocation_endpoint: `${config.baseUrl}/api/v1/oauth2/revoke`,
|
|
176
|
+
response_types_supported: ['code'],
|
|
177
|
+
grant_types_supported: ['authorization_code', 'refresh_token'],
|
|
178
|
+
code_challenge_methods_supported: ['S256'],
|
|
179
|
+
token_endpoint_auth_methods_supported: ['none'],
|
|
180
|
+
scopes_supported: [
|
|
181
|
+
'invoice.view', 'invoice.create', 'invoice.issue', 'invoice.send',
|
|
182
|
+
'client.view', 'client.create',
|
|
183
|
+
'product.view', 'product.create',
|
|
184
|
+
'payment.view', 'payment.create',
|
|
185
|
+
'webhook.view', 'webhook.manage',
|
|
186
|
+
'series.view', 'settings.view', 'report.view', 'company.view',
|
|
187
|
+
],
|
|
188
|
+
};
|
|
189
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
190
|
+
res.end(JSON.stringify(metadata));
|
|
191
|
+
}
|
|
192
|
+
export function startHttpServer(port, host) {
|
|
193
|
+
const server = createServer(async (req, res) => {
|
|
194
|
+
setCorsHeaders(res);
|
|
195
|
+
const url = new URL(req.url || '/', `http://${req.headers.host}`);
|
|
196
|
+
// OAuth2 well-known metadata endpoints (SaaS mode)
|
|
197
|
+
if (url.pathname === '/.well-known/oauth-protected-resource' || url.pathname === '/.well-known/oauth-authorization-server') {
|
|
198
|
+
if (req.method === 'OPTIONS') {
|
|
199
|
+
res.writeHead(204);
|
|
200
|
+
res.end();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (req.method === 'GET') {
|
|
204
|
+
if (url.pathname === '/.well-known/oauth-protected-resource') {
|
|
205
|
+
handleProtectedResourceMetadata(req, res);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
handleAuthorizationServerMetadata(req, res);
|
|
209
|
+
}
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
res.writeHead(405);
|
|
213
|
+
res.end('Method Not Allowed');
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
// Only handle /mcp for MCP protocol
|
|
217
|
+
if (url.pathname !== '/mcp') {
|
|
218
|
+
res.writeHead(404);
|
|
219
|
+
res.end('Not Found');
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
switch (req.method) {
|
|
224
|
+
case 'OPTIONS':
|
|
225
|
+
res.writeHead(204);
|
|
226
|
+
res.end();
|
|
227
|
+
break;
|
|
228
|
+
case 'POST':
|
|
229
|
+
await handlePost(req, res);
|
|
230
|
+
break;
|
|
231
|
+
case 'GET':
|
|
232
|
+
await handleGet(req, res);
|
|
233
|
+
break;
|
|
234
|
+
case 'DELETE':
|
|
235
|
+
await handleDelete(req, res);
|
|
236
|
+
break;
|
|
237
|
+
default:
|
|
238
|
+
res.writeHead(405);
|
|
239
|
+
res.end('Method Not Allowed');
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
console.error('Error handling request:', err);
|
|
244
|
+
if (!res.headersSent) {
|
|
245
|
+
jsonError(res, 500, -32603, 'Internal server error');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
server.listen(port, host, () => {
|
|
250
|
+
console.error(`Storno MCP HTTP server listening on http://${host}:${port}/mcp`);
|
|
251
|
+
});
|
|
252
|
+
// Graceful shutdown
|
|
253
|
+
const shutdown = async () => {
|
|
254
|
+
console.error('Shutting down HTTP server...');
|
|
255
|
+
for (const [sessionId, session] of sessions) {
|
|
256
|
+
try {
|
|
257
|
+
await session.transport.close();
|
|
258
|
+
sessions.delete(sessionId);
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
console.error(`Error closing session ${sessionId}:`, err);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
server.close(() => process.exit(0));
|
|
265
|
+
};
|
|
266
|
+
process.on('SIGINT', shutdown);
|
|
267
|
+
process.on('SIGTERM', shutdown);
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=http-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.js","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
* as AI-callable tools. Works with Claude Code, Cursor, Windsurf, and any
|
|
7
7
|
* MCP-compatible AI assistant.
|
|
8
8
|
*
|
|
9
|
+
* Transport modes:
|
|
10
|
+
* - stdio (default) — for local MCP clients (Claude Code, Cursor, etc.)
|
|
11
|
+
* - Streamable HTTP — set STORNO_HTTP_PORT to enable remote access
|
|
12
|
+
*
|
|
9
13
|
* Configuration (environment variables):
|
|
10
14
|
* STORNO_BASE_URL — API base URL (default: https://api.storno.ro)
|
|
11
15
|
* STORNO_TOKEN — JWT access token
|
|
@@ -13,25 +17,8 @@
|
|
|
13
17
|
* STORNO_COMPANY_ID — Default company UUID
|
|
14
18
|
* STORNO_EMAIL — Email for auto-login (optional)
|
|
15
19
|
* STORNO_PASSWORD — Password for auto-login (optional)
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* node dist/index.js # Start MCP server (stdio transport)
|
|
19
|
-
*
|
|
20
|
-
* MCP Integration:
|
|
21
|
-
* Add to your claude_desktop_config.json or .claude/settings.json:
|
|
22
|
-
* {
|
|
23
|
-
* "mcpServers": {
|
|
24
|
-
* "storno": {
|
|
25
|
-
* "command": "node",
|
|
26
|
-
* "args": ["/path/to/storno-cli/dist/index.js"],
|
|
27
|
-
* "env": {
|
|
28
|
-
* "STORNO_BASE_URL": "https://api.storno.ro",
|
|
29
|
-
* "STORNO_TOKEN": "your-jwt-token",
|
|
30
|
-
* "STORNO_COMPANY_ID": "your-company-uuid"
|
|
31
|
-
* }
|
|
32
|
-
* }
|
|
33
|
-
* }
|
|
34
|
-
* }
|
|
20
|
+
* STORNO_HTTP_PORT — If set, starts Streamable HTTP transport on this port
|
|
21
|
+
* STORNO_HTTP_HOST — HTTP bind address (default: 127.0.0.1)
|
|
35
22
|
*/
|
|
36
23
|
export {};
|
|
37
24
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;GAoBG"}
|