@frihet/mcp-server 2.0.1 → 2.0.2
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 +6 -6
- package/dist/canary/mcp-harness.d.ts +1 -1
- package/dist/canary/mcp-harness.js +3 -2
- package/dist/claude-profile.js +3 -1
- package/dist/client-interface.d.ts +7 -0
- package/dist/client.d.ts +7 -0
- package/dist/client.js +16 -0
- package/dist/demo-client.d.ts +14 -16
- package/dist/demo-client.js +101 -30
- package/dist/demo-fixtures.d.ts +14 -4
- package/dist/demo-fixtures.js +84 -16
- package/dist/invoice-payment-link.d.ts +189 -0
- package/dist/invoice-payment-link.js +371 -0
- package/dist/mpp-sandbox.d.ts +176 -0
- package/dist/mpp-sandbox.js +612 -0
- package/dist/openai-103/openai-expansion-103.d.ts +1192 -0
- package/dist/openai-103/openai-expansion-103.js +1628 -0
- package/dist/openai-profile.d.ts +5 -1
- package/dist/openai-profile.js +14 -2
- package/dist/openai-review-contract.js +2 -1
- package/dist/server-composition.js +34 -0
- package/dist/tool-exposure.js +2 -1
- package/dist/tools/purchaseOrders.d.ts +30 -0
- package/dist/tools/purchaseOrders.js +102 -0
- package/dist/tools/register-all.js +2 -0
- package/dist/tools/shared.d.ts +42 -0
- package/dist/tools/shared.js +46 -0
- package/docs/agent-onboarding.json +2 -2
- package/package.json +9 -9
package/dist/openai-profile.d.ts
CHANGED
|
@@ -26,6 +26,10 @@ export declare const OPENAI_OAUTH_SECURITY_SCHEMES: readonly [{
|
|
|
26
26
|
readonly type: "oauth2";
|
|
27
27
|
readonly scopes: readonly string[];
|
|
28
28
|
}];
|
|
29
|
+
export declare const OPENAI_103_READ_ONLY_CANDIDATE_TOOLS: ReadonlySet<string>;
|
|
30
|
+
export interface ApplyOpenAIProfileOptions {
|
|
31
|
+
candidateVersion?: "1.0.2" | "1.0.3";
|
|
32
|
+
}
|
|
29
33
|
export declare const OPENAI_WORKSPACE_WEBHOOK_EVENT_TOOLS: ReadonlySet<string>;
|
|
30
34
|
export declare const OPENAI_REVIEW_CONFIRM_REQUIRED_TOOLS: ReadonlySet<string>;
|
|
31
35
|
/** Strictly necessary row fields for reviewed collection/search responses. */
|
|
@@ -62,7 +66,7 @@ export declare const OPENAI_CSP: string;
|
|
|
62
66
|
* registerAllResources(server, client);
|
|
63
67
|
* ```
|
|
64
68
|
*/
|
|
65
|
-
export declare function applyOpenAIProfile(server: any): void;
|
|
69
|
+
export declare function applyOpenAIProfile(server: any, options?: ApplyOpenAIProfileOptions): void;
|
|
66
70
|
/** Number of tools excluded in OpenAI mode (for logging). */
|
|
67
71
|
export declare const OPENAI_EXCLUDED_COUNT: number;
|
|
68
72
|
/** Number of tools explicitly allowed in OpenAI mode. */
|
package/dist/openai-profile.js
CHANGED
|
@@ -429,6 +429,12 @@ function installOpenAIToolsListSecurityProjection(server) {
|
|
|
429
429
|
});
|
|
430
430
|
};
|
|
431
431
|
}
|
|
432
|
+
export const OPENAI_103_READ_ONLY_CANDIDATE_TOOLS = new Set([
|
|
433
|
+
"get_daily_operational_brief",
|
|
434
|
+
"get_business_period_summary",
|
|
435
|
+
"search_clients",
|
|
436
|
+
"search_vendors",
|
|
437
|
+
]);
|
|
432
438
|
export const OPENAI_WORKSPACE_WEBHOOK_EVENT_TOOLS = new Set([
|
|
433
439
|
"create_invoice",
|
|
434
440
|
"create_expense",
|
|
@@ -1167,15 +1173,21 @@ export const OPENAI_CSP = "default-src 'self'; " +
|
|
|
1167
1173
|
* ```
|
|
1168
1174
|
*/
|
|
1169
1175
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1170
|
-
export function applyOpenAIProfile(server) {
|
|
1176
|
+
export function applyOpenAIProfile(server, options) {
|
|
1171
1177
|
installOpenAIToolsListSecurityProjection(server);
|
|
1172
1178
|
const fieldsToRedact = PROFILE.redactOutputFields;
|
|
1179
|
+
const activeIncludeTools = new Set(PROFILE.includeTools);
|
|
1180
|
+
if (options?.candidateVersion === "1.0.3") {
|
|
1181
|
+
for (const tool of OPENAI_103_READ_ONLY_CANDIDATE_TOOLS) {
|
|
1182
|
+
activeIncludeTools.add(tool);
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1173
1185
|
/* ── Intercept registerTool ─────────────────────────────────────── */
|
|
1174
1186
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
1175
1187
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1176
1188
|
server.registerTool = (name, config, handler) => {
|
|
1177
1189
|
// 0. Keep the public ChatGPT app to the reviewed core tool surface
|
|
1178
|
-
if (!
|
|
1190
|
+
if (!activeIncludeTools.has(name))
|
|
1179
1191
|
return;
|
|
1180
1192
|
// 1. Skip excluded tools entirely
|
|
1181
1193
|
if (PROFILE.excludeTools.has(name))
|
|
@@ -657,7 +657,7 @@ export function assertOpenAIReviewContract(actual, expected) {
|
|
|
657
657
|
const outputRequired = outputSchema?.required;
|
|
658
658
|
const success = jsonObject(outputProperties?.success);
|
|
659
659
|
const result = jsonObject(outputProperties?.result);
|
|
660
|
-
const branches = result?.
|
|
660
|
+
const branches = result?.oneOf;
|
|
661
661
|
const branchObjects = Array.isArray(branches)
|
|
662
662
|
? branches.map((branch) => jsonObject(branch))
|
|
663
663
|
: [];
|
|
@@ -687,6 +687,7 @@ export function assertOpenAIReviewContract(actual, expected) {
|
|
|
687
687
|
outputRequired.length !== 3 ||
|
|
688
688
|
success?.const !== true ||
|
|
689
689
|
!result ||
|
|
690
|
+
Object.keys(result).length !== 1 ||
|
|
690
691
|
branchObjects.length !== 2 ||
|
|
691
692
|
branchObjects.some((branch) => !branch) ||
|
|
692
693
|
branchByOutcome.size !== 2 ||
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* generated public-surface contract. Transport/auth setup stays with each host;
|
|
4
4
|
* the exposed MCP operations/resources/prompts are composed here exactly once.
|
|
5
5
|
*/
|
|
6
|
+
import { z } from "zod/v4";
|
|
7
|
+
import { READ_STAMP } from "./demo-fixtures.js";
|
|
6
8
|
import { applyPublicCapabilityTruth, buildLocalDiscoveryCapability, CAPABILITY_META_KEY, } from "./capability-truth.js";
|
|
7
9
|
import { applyFiscalAliases } from "./fiscal-aliases.js";
|
|
8
10
|
import { applyClaudeCandidateProfile, CLAUDE_CANDIDATE_TOOLS, CLAUDE_GROUP_METADATA } from "./claude-profile.js";
|
|
@@ -43,6 +45,38 @@ export function registerMcpSurface(server, client, options) {
|
|
|
43
45
|
clientIsDemo = false;
|
|
44
46
|
}
|
|
45
47
|
const isDemoMode = options.demoMode === true || clientIsDemo;
|
|
48
|
+
if (isDemoMode) {
|
|
49
|
+
// Install closest to the SDK so profile projection/redaction runs first.
|
|
50
|
+
// Only trusted server/client configuration enables this boundary; neither
|
|
51
|
+
// input arguments nor response metadata can switch a live server to demo.
|
|
52
|
+
const registerTool = server.registerTool.bind(server);
|
|
53
|
+
server.registerTool = (name, config, handler) => {
|
|
54
|
+
const schema = config.outputSchema;
|
|
55
|
+
if (!(schema instanceof z.ZodObject)
|
|
56
|
+
|| !["data", "total", "limit", "offset"].every((key) => key in schema.shape)) {
|
|
57
|
+
return registerTool(name, config, handler);
|
|
58
|
+
}
|
|
59
|
+
return registerTool(name, {
|
|
60
|
+
...config,
|
|
61
|
+
outputSchema: schema.extend({
|
|
62
|
+
_demo: z.literal(true),
|
|
63
|
+
_demoNotice: z.literal(READ_STAMP._demoNotice),
|
|
64
|
+
}),
|
|
65
|
+
}, (async (args, extra) => {
|
|
66
|
+
const result = await handler(args, extra);
|
|
67
|
+
if (result.isError || !result.structuredContent)
|
|
68
|
+
return result;
|
|
69
|
+
const structuredContent = { ...result.structuredContent, ...READ_STAMP };
|
|
70
|
+
return {
|
|
71
|
+
...result,
|
|
72
|
+
structuredContent,
|
|
73
|
+
// JSON mirrors structuredContent for hosts that only read text.
|
|
74
|
+
// Keep existing summaries/hints too; no warning is silently dropped.
|
|
75
|
+
content: [{ type: "text", text: JSON.stringify(structuredContent, null, 2) }, ...result.content],
|
|
76
|
+
};
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
}
|
|
46
80
|
if (options.groupedMode) {
|
|
47
81
|
if (options.openaiMode) {
|
|
48
82
|
applyOpenAIReviewProfiles(server);
|
package/dist/tool-exposure.js
CHANGED
|
@@ -113,6 +113,7 @@ export const FILE_TO_GROUP = {
|
|
|
113
113
|
deposits: "invoicing",
|
|
114
114
|
expenses: "expenses",
|
|
115
115
|
vendors: "expenses",
|
|
116
|
+
purchaseOrders: "expenses",
|
|
116
117
|
fiscal: "fiscal",
|
|
117
118
|
igic: "fiscal",
|
|
118
119
|
impuesto_sociedades: "fiscal",
|
|
@@ -177,7 +178,7 @@ export function groupForTool(name) {
|
|
|
177
178
|
return "fiscal";
|
|
178
179
|
if (/(invoice|quote|credit_note|late_fee|recurring|deposit)/.test(n))
|
|
179
180
|
return "invoicing";
|
|
180
|
-
if (/(expense|vendor)/.test(n))
|
|
181
|
+
if (/(expense|vendor|purchase_order)/.test(n))
|
|
181
182
|
return "expenses";
|
|
182
183
|
if (/(bank|transaction)/.test(n))
|
|
183
184
|
return "banking";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Purchase-order read tools for the Frihet MCP server.
|
|
3
|
+
*
|
|
4
|
+
* READ-ONLY surface for the /v1/purchase-orders family (ADR 0027 S2, server
|
|
5
|
+
* authority shipped in Frihet-ERP #2359). The single-object read returns the
|
|
6
|
+
* stored document as it lives in the workspace; list returns the same shape
|
|
7
|
+
* paged by status and vendorId, ordered by createdAt desc.
|
|
8
|
+
*
|
|
9
|
+
* Scope semantics: list_purchase_orders and get_purchase_order both classify
|
|
10
|
+
* as `read` under the family router (functions/src/publicApi/apiKeyScopes.ts
|
|
11
|
+
* → requiredPurchaseOrderApiAccess), so a restricted API key needs at least
|
|
12
|
+
* one of `*`, `read`, `purchase-orders:*` or `purchase-orders:read`.
|
|
13
|
+
*
|
|
14
|
+
* WRITE tools (create draft, send, confirm, cancel, receive, reverse-receipt,
|
|
15
|
+
* bill) are deliberately NOT exposed here: they move money or stock and need
|
|
16
|
+
* human-authority semantics (draft → show → confirm) that this surface does not
|
|
17
|
+
* define. No write route is called from this file or from the client methods.
|
|
18
|
+
*
|
|
19
|
+
* NOT IN SCOPE for this surface (correction to a prior brief):
|
|
20
|
+
* - Physical count truth (#2355): no callable, no API route. Not designed.
|
|
21
|
+
* - Inventory balances (/v1/inventory/balances): ADR 0027 S4, not landed.
|
|
22
|
+
*/
|
|
23
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
24
|
+
import type { IFrihetClient } from "../client-interface.js";
|
|
25
|
+
/**
|
|
26
|
+
* Read tools for purchase orders. Tool names follow the canonical
|
|
27
|
+
* snake_case convention used across the catalog.
|
|
28
|
+
*/
|
|
29
|
+
export declare function registerPurchaseOrderTools(server: McpServer, client: IFrihetClient): void;
|
|
30
|
+
//# sourceMappingURL=purchaseOrders.d.ts.map
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Purchase-order read tools for the Frihet MCP server.
|
|
3
|
+
*
|
|
4
|
+
* READ-ONLY surface for the /v1/purchase-orders family (ADR 0027 S2, server
|
|
5
|
+
* authority shipped in Frihet-ERP #2359). The single-object read returns the
|
|
6
|
+
* stored document as it lives in the workspace; list returns the same shape
|
|
7
|
+
* paged by status and vendorId, ordered by createdAt desc.
|
|
8
|
+
*
|
|
9
|
+
* Scope semantics: list_purchase_orders and get_purchase_order both classify
|
|
10
|
+
* as `read` under the family router (functions/src/publicApi/apiKeyScopes.ts
|
|
11
|
+
* → requiredPurchaseOrderApiAccess), so a restricted API key needs at least
|
|
12
|
+
* one of `*`, `read`, `purchase-orders:*` or `purchase-orders:read`.
|
|
13
|
+
*
|
|
14
|
+
* WRITE tools (create draft, send, confirm, cancel, receive, reverse-receipt,
|
|
15
|
+
* bill) are deliberately NOT exposed here: they move money or stock and need
|
|
16
|
+
* human-authority semantics (draft → show → confirm) that this surface does not
|
|
17
|
+
* define. No write route is called from this file or from the client methods.
|
|
18
|
+
*
|
|
19
|
+
* NOT IN SCOPE for this surface (correction to a prior brief):
|
|
20
|
+
* - Physical count truth (#2355): no callable, no API route. Not designed.
|
|
21
|
+
* - Inventory balances (/v1/inventory/balances): ADR 0027 S4, not landed.
|
|
22
|
+
*/
|
|
23
|
+
import { z } from "zod/v4";
|
|
24
|
+
import { withToolLogging, formatPaginatedResponse, formatRecord, listContent, getContent, READ_ONLY_ANNOTATIONS, paginatedOutput, purchaseOrderItemOutput, } from "./shared.js";
|
|
25
|
+
/**
|
|
26
|
+
* Read tools for purchase orders. Tool names follow the canonical
|
|
27
|
+
* snake_case convention used across the catalog.
|
|
28
|
+
*/
|
|
29
|
+
export function registerPurchaseOrderTools(server, client) {
|
|
30
|
+
// -- list_purchase_orders --
|
|
31
|
+
server.registerTool("list_purchase_orders", {
|
|
32
|
+
title: "List Purchase Orders",
|
|
33
|
+
description: "List purchase orders in the workspace with optional filters. " +
|
|
34
|
+
"Returns one entry per PO with vendor, status, line items and totals. " +
|
|
35
|
+
"Statuses reflect the server-owned lifecycle (ADR 0027 S2): " +
|
|
36
|
+
"draft → sent → confirmed → received → billed, with cancel as a terminal branch. " +
|
|
37
|
+
"/ Lista pedidos de compra del workspace con filtros opcionales. " +
|
|
38
|
+
"Devuelve un registro por pedido con proveedor, estado, lineas y totales. " +
|
|
39
|
+
"Los estados reflejan el ciclo de vida del servidor (ADR 0027 S2): " +
|
|
40
|
+
"borrador → enviado → confirmado → recibido → facturado, con cancelado como rama terminal.",
|
|
41
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
42
|
+
inputSchema: {
|
|
43
|
+
status: z
|
|
44
|
+
.string()
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("Filter by PO status (draft, sent, confirmed, received, billed, cancelled) / " +
|
|
47
|
+
"Filtro por estado del pedido"),
|
|
48
|
+
vendorId: z
|
|
49
|
+
.string()
|
|
50
|
+
.trim()
|
|
51
|
+
.min(1)
|
|
52
|
+
.max(128)
|
|
53
|
+
.optional()
|
|
54
|
+
.describe("Filter by vendor ID / Filtro por ID de proveedor"),
|
|
55
|
+
limit: z
|
|
56
|
+
.number()
|
|
57
|
+
.int()
|
|
58
|
+
.min(1)
|
|
59
|
+
.max(100)
|
|
60
|
+
.optional()
|
|
61
|
+
.describe("Max results (1-100) / Resultados maximos"),
|
|
62
|
+
offset: z
|
|
63
|
+
.number()
|
|
64
|
+
.int()
|
|
65
|
+
.min(0)
|
|
66
|
+
.optional()
|
|
67
|
+
.describe("Offset / Desplazamiento"),
|
|
68
|
+
},
|
|
69
|
+
outputSchema: paginatedOutput(purchaseOrderItemOutput),
|
|
70
|
+
}, async ({ status, vendorId, limit, offset }) => withToolLogging("list_purchase_orders", async () => {
|
|
71
|
+
const result = await client.listPurchaseOrders({ status, vendorId, limit, offset });
|
|
72
|
+
return {
|
|
73
|
+
content: [listContent(formatPaginatedResponse("purchase_orders", result))],
|
|
74
|
+
structuredContent: result,
|
|
75
|
+
};
|
|
76
|
+
}));
|
|
77
|
+
// -- get_purchase_order --
|
|
78
|
+
server.registerTool("get_purchase_order", {
|
|
79
|
+
title: "Get Purchase Order",
|
|
80
|
+
description: "Get a single purchase order by its ID. Returns the full document: " +
|
|
81
|
+
"vendor, line items, totals, status, issue/expected dates and currency. " +
|
|
82
|
+
"/ Obtiene un pedido de compra por su ID. Devuelve el documento completo: " +
|
|
83
|
+
"proveedor, lineas, totales, estado, fechas de emision y esperada y moneda.",
|
|
84
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
85
|
+
inputSchema: {
|
|
86
|
+
id: z
|
|
87
|
+
.string()
|
|
88
|
+
.trim()
|
|
89
|
+
.min(1)
|
|
90
|
+
.max(128)
|
|
91
|
+
.describe("Purchase-order ID / ID del pedido de compra"),
|
|
92
|
+
},
|
|
93
|
+
outputSchema: purchaseOrderItemOutput,
|
|
94
|
+
}, async ({ id }) => withToolLogging("get_purchase_order", async () => {
|
|
95
|
+
const result = await client.getPurchaseOrder(id);
|
|
96
|
+
return {
|
|
97
|
+
content: [getContent(formatRecord("PurchaseOrder", result))],
|
|
98
|
+
structuredContent: result,
|
|
99
|
+
};
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=purchaseOrders.js.map
|
|
@@ -15,6 +15,7 @@ import { registerClientTools } from "./clients.js";
|
|
|
15
15
|
import { registerProductTools } from "./products.js";
|
|
16
16
|
import { registerQuoteTools } from "./quotes.js";
|
|
17
17
|
import { registerVendorTools } from "./vendors.js";
|
|
18
|
+
import { registerPurchaseOrderTools } from "./purchaseOrders.js";
|
|
18
19
|
import { registerWebhookTools } from "./webhooks.js";
|
|
19
20
|
import { registerIntelligenceTools } from "./intelligence.js";
|
|
20
21
|
import { registerCrmTools } from "./crm.js";
|
|
@@ -89,6 +90,7 @@ export function registerAllTools(server, client) {
|
|
|
89
90
|
registerProductTools(server, client);
|
|
90
91
|
registerQuoteTools(server, client);
|
|
91
92
|
registerVendorTools(server, client);
|
|
93
|
+
registerPurchaseOrderTools(server, client);
|
|
92
94
|
registerWebhookTools(server, client);
|
|
93
95
|
registerDepositTools(server, client);
|
|
94
96
|
registerEInvoiceTools(server, client);
|
package/dist/tools/shared.d.ts
CHANGED
|
@@ -247,6 +247,48 @@ export declare const vendorItemOutput: z.ZodObject<{
|
|
|
247
247
|
createdAt: z.ZodOptional<z.ZodString>;
|
|
248
248
|
updatedAt: z.ZodOptional<z.ZodString>;
|
|
249
249
|
}, z.core.$loose>;
|
|
250
|
+
/**
|
|
251
|
+
* Purchase-order output (ADR 0027 S2, server-owned lifecycle).
|
|
252
|
+
*
|
|
253
|
+
* Fields mirror the live API shape returned by /v1/purchase-orders GETs:
|
|
254
|
+
* - `status` ∈ {draft, sent, confirmed, received, billed, cancelled}
|
|
255
|
+
* - `items[].taxRate` is optional because per-line tax rates may override
|
|
256
|
+
* the document tax rate; the family router accepts it as a string-coerced
|
|
257
|
+
* number in the request, so the response can carry it.
|
|
258
|
+
* - `currency` is an ISO 4217 code (e.g. "EUR"). It is the same code the
|
|
259
|
+
* server stamps on the stored doc.
|
|
260
|
+
* - `createdAt`/`updatedAt` are ISO 8601; `issueDate`/`expectedDate` are
|
|
261
|
+
* YYYY-MM-DD.
|
|
262
|
+
*
|
|
263
|
+
* `.passthrough()` preserves receipts (`receipts[]`) and the linked expense
|
|
264
|
+
* id (`billedExpenseId`) once the order moves past `billed`, plus any
|
|
265
|
+
* additional fields the server adds in later S-stages without breaking
|
|
266
|
+
* downstream consumers.
|
|
267
|
+
*/
|
|
268
|
+
export declare const purchaseOrderItemOutput: z.ZodObject<{
|
|
269
|
+
id: z.ZodString;
|
|
270
|
+
poNumber: z.ZodOptional<z.ZodString>;
|
|
271
|
+
vendorId: z.ZodOptional<z.ZodString>;
|
|
272
|
+
vendorName: z.ZodOptional<z.ZodString>;
|
|
273
|
+
status: z.ZodOptional<z.ZodString>;
|
|
274
|
+
items: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
275
|
+
description: z.ZodString;
|
|
276
|
+
quantity: z.ZodNumber;
|
|
277
|
+
unitPrice: z.ZodNumber;
|
|
278
|
+
productId: z.ZodOptional<z.ZodString>;
|
|
279
|
+
taxRate: z.ZodOptional<z.ZodNumber>;
|
|
280
|
+
}, z.core.$loose>>>;
|
|
281
|
+
issueDate: z.ZodOptional<z.ZodString>;
|
|
282
|
+
expectedDate: z.ZodOptional<z.ZodString>;
|
|
283
|
+
taxRate: z.ZodOptional<z.ZodNumber>;
|
|
284
|
+
subtotal: z.ZodOptional<z.ZodNumber>;
|
|
285
|
+
tax: z.ZodOptional<z.ZodNumber>;
|
|
286
|
+
total: z.ZodOptional<z.ZodNumber>;
|
|
287
|
+
currency: z.ZodOptional<z.ZodString>;
|
|
288
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
289
|
+
createdAt: z.ZodOptional<z.ZodString>;
|
|
290
|
+
updatedAt: z.ZodOptional<z.ZodString>;
|
|
291
|
+
}, z.core.$loose>;
|
|
250
292
|
export declare const webhookItemOutput: z.ZodObject<{
|
|
251
293
|
id: z.ZodString;
|
|
252
294
|
userId: z.ZodOptional<z.ZodString>;
|
package/dist/tools/shared.js
CHANGED
|
@@ -555,6 +555,52 @@ export const vendorItemOutput = z.object({
|
|
|
555
555
|
createdAt: z.string().optional(),
|
|
556
556
|
updatedAt: z.string().optional(),
|
|
557
557
|
}).passthrough();
|
|
558
|
+
/**
|
|
559
|
+
* Purchase-order output (ADR 0027 S2, server-owned lifecycle).
|
|
560
|
+
*
|
|
561
|
+
* Fields mirror the live API shape returned by /v1/purchase-orders GETs:
|
|
562
|
+
* - `status` ∈ {draft, sent, confirmed, received, billed, cancelled}
|
|
563
|
+
* - `items[].taxRate` is optional because per-line tax rates may override
|
|
564
|
+
* the document tax rate; the family router accepts it as a string-coerced
|
|
565
|
+
* number in the request, so the response can carry it.
|
|
566
|
+
* - `currency` is an ISO 4217 code (e.g. "EUR"). It is the same code the
|
|
567
|
+
* server stamps on the stored doc.
|
|
568
|
+
* - `createdAt`/`updatedAt` are ISO 8601; `issueDate`/`expectedDate` are
|
|
569
|
+
* YYYY-MM-DD.
|
|
570
|
+
*
|
|
571
|
+
* `.passthrough()` preserves receipts (`receipts[]`) and the linked expense
|
|
572
|
+
* id (`billedExpenseId`) once the order moves past `billed`, plus any
|
|
573
|
+
* additional fields the server adds in later S-stages without breaking
|
|
574
|
+
* downstream consumers.
|
|
575
|
+
*/
|
|
576
|
+
export const purchaseOrderItemOutput = z.object({
|
|
577
|
+
id: z.string(),
|
|
578
|
+
poNumber: z.string().optional(),
|
|
579
|
+
vendorId: z.string().optional(),
|
|
580
|
+
vendorName: z.string().optional(),
|
|
581
|
+
status: z.string().optional(),
|
|
582
|
+
items: z
|
|
583
|
+
.array(z
|
|
584
|
+
.object({
|
|
585
|
+
description: z.string(),
|
|
586
|
+
quantity: z.number(),
|
|
587
|
+
unitPrice: z.number(),
|
|
588
|
+
productId: z.string().optional(),
|
|
589
|
+
taxRate: z.number().optional(),
|
|
590
|
+
})
|
|
591
|
+
.passthrough())
|
|
592
|
+
.optional(),
|
|
593
|
+
issueDate: z.string().optional(),
|
|
594
|
+
expectedDate: z.string().optional(),
|
|
595
|
+
taxRate: z.number().optional(),
|
|
596
|
+
subtotal: z.number().optional(),
|
|
597
|
+
tax: z.number().optional(),
|
|
598
|
+
total: z.number().optional(),
|
|
599
|
+
currency: z.string().optional(),
|
|
600
|
+
notes: z.string().optional(),
|
|
601
|
+
createdAt: z.string().optional(),
|
|
602
|
+
updatedAt: z.string().optional(),
|
|
603
|
+
}).passthrough();
|
|
558
604
|
export const webhookItemOutput = z.object({
|
|
559
605
|
id: z.string(),
|
|
560
606
|
userId: z.string().optional(),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frihet/mcp-server",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "AI-native MCP server for Frihet ERP —
|
|
3
|
+
"version": "2.0.2",
|
|
4
|
+
"description": "AI-native MCP server for Frihet ERP — 158 canonical operations for invoicing, expenses, CRM, banking, POS and ES/EU fiscal workflows, with conservative capability and side-effect metadata.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc",
|
|
12
|
-
"test": "npm run build && node --test dist/__tests__/resources-eu-catalog.test.js && node --test dist/__tests__/resources-p1-contract.test.js dist/__tests__/openai-profile.test.js dist/__tests__/openai-client-tax-id-contract.test.js dist/__tests__/tool-exposure.test.js dist/__tests__/fiscal-aliases.test.js dist/__tests__/einvoice-tools.test.js dist/__tests__/einvoice-day4-tools.test.js dist/__tests__/expenses-tools.test.js dist/__tests__/stay-tools.test.js dist/__tests__/pos-tools.test.js dist/__tests__/kitchen-tools.test.js dist/__tests__/banking-tools.test.js dist/__tests__/banking-client-contract.test.js dist/__tests__/pagination-cursor-param.test.js dist/__tests__/fiscal-tools.test.js dist/__tests__/fiscal-period-contract.test.js dist/__tests__/time-tools.test.js dist/__tests__/deposits-tools.test.js dist/__tests__/recurring-tools.test.js dist/__tests__/team-tools.test.js dist/__tests__/team-tools-real-sdk.test.js dist/__tests__/d4b-hr-payroll-onboarding-tools.test.js dist/__tests__/hr-payroll-period-contract.test.js dist/__tests__/webhook-crm-reviewed-contract.test.js dist/__tests__/audit-server-version.test.js dist/__tests__/search-tools.test.js dist/__tests__/openai-full-compose.test.js dist/__tests__/openai-review-descriptor.test.js dist/__tests__/directory-profile-policy.test.js dist/__tests__/claude-profile.test.js dist/__tests__/claude-output-privacy.test.js dist/__tests__/claude-write-route-contract.test.js dist/__tests__/contract.test.js dist/__tests__/observability-redaction.test.js dist/__tests__/security-containment-gate0.test.js dist/__tests__/intelligence-duplicate-invoice.test.js dist/__tests__/get-envelope-unwrap-regression.test.js dist/__tests__/binary-content-types.test.js dist/__tests__/api-error-remediation.test.js dist/__tests__/mutation-unwrap-and-schema-regression.test.js dist/__tests__/schema-envelope-guard.test.js dist/__tests__/paginated-strict-output.test.js dist/__tests__/paginated-metadata-contract.test.js dist/__tests__/demo-mode.test.js dist/__tests__/idempotency-key-contract.test.js dist/__tests__/retry-after-contract.test.js dist/__tests__/source-header-contract.test.js dist/__tests__/no-provisioning-credential-to-public-api.test.js dist/__tests__/truth-in-descriptions.test.js dist/__tests__/mcp-baseline-mutation.test.js dist/__tests__/forms-elicitation.test.js dist/__tests__/agent-onboarding.test.js scripts/__tests__/openai-worker-review-wire.test.mjs scripts/__tests__/sync-openapi-retry.test.mjs scripts/__tests__/conformance-provenance.test.mjs scripts/__tests__/conformance-phase0.test.mjs scripts/__tests__/published-artifact-drift.test.mjs scripts/__tests__/cross-surface-authority.test.mjs scripts/__tests__/release-workflow-contract.test.mjs scripts/__tests__/openai-wrangler-resolution.test.mjs scripts/__tests__/audit-mcp-refs-detector.test.mjs scripts/__tests__/openai-public-surface.test.mjs scripts/__tests__/claude-plugin-package.test.mjs scripts/__tests__/claude-hosted-release.test.mjs scripts/__tests__/claude-hosted-acceptance.test.mjs scripts/__tests__/claude-oauth-provider.test.mjs scripts/__tests__/audit-mcp-refs-published-sot.test.mjs scripts/__tests__/claude-bootstrap-secrets.test.mjs scripts/__tests__/no-public-leak.test.mjs",
|
|
12
|
+
"test": "npm run build && node --test dist/__tests__/resources-eu-catalog.test.js && node --test dist/__tests__/resources-p1-contract.test.js dist/__tests__/openai-profile.test.js dist/__tests__/openai-client-tax-id-contract.test.js dist/__tests__/tool-exposure.test.js dist/__tests__/fiscal-aliases.test.js dist/__tests__/einvoice-tools.test.js dist/__tests__/einvoice-day4-tools.test.js dist/__tests__/expenses-tools.test.js dist/__tests__/stay-tools.test.js dist/__tests__/pos-tools.test.js dist/__tests__/kitchen-tools.test.js dist/__tests__/banking-tools.test.js dist/__tests__/banking-client-contract.test.js dist/__tests__/pagination-cursor-param.test.js dist/__tests__/fiscal-tools.test.js dist/__tests__/fiscal-period-contract.test.js dist/__tests__/time-tools.test.js dist/__tests__/deposits-tools.test.js dist/__tests__/recurring-tools.test.js dist/__tests__/team-tools.test.js dist/__tests__/team-tools-real-sdk.test.js dist/__tests__/d4b-hr-payroll-onboarding-tools.test.js dist/__tests__/hr-payroll-period-contract.test.js dist/__tests__/webhook-crm-reviewed-contract.test.js dist/__tests__/audit-server-version.test.js dist/__tests__/search-tools.test.js dist/__tests__/openai-full-compose.test.js dist/__tests__/openai-review-descriptor.test.js dist/__tests__/directory-profile-policy.test.js dist/__tests__/claude-profile.test.js dist/__tests__/claude-output-privacy.test.js dist/__tests__/claude-write-route-contract.test.js dist/__tests__/contract.test.js dist/__tests__/observability-redaction.test.js dist/__tests__/security-containment-gate0.test.js dist/__tests__/intelligence-duplicate-invoice.test.js dist/__tests__/get-envelope-unwrap-regression.test.js dist/__tests__/binary-content-types.test.js dist/__tests__/api-error-remediation.test.js dist/__tests__/mutation-unwrap-and-schema-regression.test.js dist/__tests__/schema-envelope-guard.test.js dist/__tests__/paginated-strict-output.test.js dist/__tests__/paginated-metadata-contract.test.js dist/__tests__/purchase-orders-tools.test.js dist/__tests__/purchase-orders-client-contract.test.js dist/__tests__/demo-mode.test.js dist/__tests__/idempotency-key-contract.test.js dist/__tests__/retry-after-contract.test.js dist/__tests__/source-header-contract.test.js dist/__tests__/no-provisioning-credential-to-public-api.test.js dist/__tests__/truth-in-descriptions.test.js dist/__tests__/mcp-baseline-mutation.test.js dist/__tests__/forms-elicitation.test.js dist/__tests__/agent-onboarding.test.js scripts/__tests__/openai-worker-review-wire.test.mjs scripts/__tests__/sync-openapi-retry.test.mjs scripts/__tests__/conformance-provenance.test.mjs scripts/__tests__/conformance-phase0.test.mjs scripts/__tests__/published-artifact-drift.test.mjs scripts/__tests__/cross-surface-authority.test.mjs scripts/__tests__/release-workflow-contract.test.mjs scripts/__tests__/openai-wrangler-resolution.test.mjs scripts/__tests__/audit-mcp-refs-detector.test.mjs scripts/__tests__/openai-public-surface.test.mjs scripts/__tests__/claude-plugin-package.test.mjs scripts/__tests__/claude-hosted-release.test.mjs scripts/__tests__/claude-hosted-acceptance.test.mjs scripts/__tests__/claude-oauth-provider.test.mjs scripts/__tests__/audit-mcp-refs-published-sot.test.mjs scripts/__tests__/claude-bootstrap-secrets.test.mjs scripts/__tests__/no-public-leak.test.mjs",
|
|
13
13
|
"canary:mcp": "npm run build && node scripts/canary-mcp.mjs",
|
|
14
14
|
"canary:mcp:check": "npm run build && node scripts/canary-mcp.mjs --check",
|
|
15
15
|
"canary:mcp:snapshot": "npm run build && node scripts/canary-mcp.mjs --snapshot",
|
|
@@ -121,17 +121,17 @@
|
|
|
121
121
|
"LICENSE"
|
|
122
122
|
],
|
|
123
123
|
"dependencies": {
|
|
124
|
-
"@modelcontextprotocol/sdk": "1.
|
|
124
|
+
"@modelcontextprotocol/sdk": "1.32.2"
|
|
125
125
|
},
|
|
126
126
|
"overrides": {
|
|
127
|
-
"hono": ">=4.13.
|
|
128
|
-
"ip-address": ">=10.7.
|
|
127
|
+
"hono": ">=4.13.16 <5",
|
|
128
|
+
"ip-address": ">=10.7.6 <11",
|
|
129
129
|
"proxy-addr": ">=2.0.8",
|
|
130
|
-
"qs": ">=6.
|
|
130
|
+
"qs": ">=6.17.1 <7",
|
|
131
131
|
"@ai-sdk/provider-utils": ">=4.0.33 <5"
|
|
132
132
|
},
|
|
133
133
|
"peerDependencies": {
|
|
134
|
-
"zod": "
|
|
134
|
+
"zod": "^4.6.6"
|
|
135
135
|
},
|
|
136
136
|
"peerDependenciesMeta": {
|
|
137
137
|
"zod": {
|
|
@@ -142,6 +142,6 @@
|
|
|
142
142
|
"@types/node": "^22.0.0",
|
|
143
143
|
"typescript": "^5.7.0",
|
|
144
144
|
"ajv": "8.18.0",
|
|
145
|
-
"zod": "^
|
|
145
|
+
"zod": "^4.6.7"
|
|
146
146
|
}
|
|
147
147
|
}
|