@lerianstudio/matcher-mcp 1.0.0-beta.5
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/LICENSE +202 -0
- package/README.md +281 -0
- package/dist/auth/request-token.js +117 -0
- package/dist/auth/request-token.js.map +1 -0
- package/dist/config.js +95 -0
- package/dist/config.js.map +1 -0
- package/dist/matcher/client.js +168 -0
- package/dist/matcher/client.js.map +1 -0
- package/dist/observability/otel.js +223 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/server.js +245 -0
- package/dist/server.js.map +1 -0
- package/dist/spec/curated-operations.js +145 -0
- package/dist/spec/curated-operations.js.map +1 -0
- package/dist/spec/index.js +155 -0
- package/dist/spec/index.js.map +1 -0
- package/dist/spec/load.js +76 -0
- package/dist/spec/load.js.map +1 -0
- package/dist/spec/openapi.yaml +15217 -0
- package/dist/tools/context/create.js +100 -0
- package/dist/tools/context/create.js.map +1 -0
- package/dist/tools/context/get.js +31 -0
- package/dist/tools/context/get.js.map +1 -0
- package/dist/tools/context/index.js +21 -0
- package/dist/tools/context/index.js.map +1 -0
- package/dist/tools/context/list.js +78 -0
- package/dist/tools/context/list.js.map +1 -0
- package/dist/tools/context/shared.js +61 -0
- package/dist/tools/context/shared.js.map +1 -0
- package/dist/tools/context/update.js +105 -0
- package/dist/tools/context/update.js.map +1 -0
- package/dist/tools/dashboard/aggregates.js +34 -0
- package/dist/tools/dashboard/aggregates.js.map +1 -0
- package/dist/tools/dashboard/cash-impact.js +36 -0
- package/dist/tools/dashboard/cash-impact.js.map +1 -0
- package/dist/tools/dashboard/index.js +27 -0
- package/dist/tools/dashboard/index.js.map +1 -0
- package/dist/tools/dashboard/match-rate.js +35 -0
- package/dist/tools/dashboard/match-rate.js.map +1 -0
- package/dist/tools/dashboard/metrics.js +36 -0
- package/dist/tools/dashboard/metrics.js.map +1 -0
- package/dist/tools/dashboard/shared.js +122 -0
- package/dist/tools/dashboard/shared.js.map +1 -0
- package/dist/tools/dashboard/sla.js +33 -0
- package/dist/tools/dashboard/sla.js.map +1 -0
- package/dist/tools/dashboard/source-breakdown.js +36 -0
- package/dist/tools/dashboard/source-breakdown.js.map +1 -0
- package/dist/tools/dashboard/volume.js +35 -0
- package/dist/tools/dashboard/volume.js.map +1 -0
- package/dist/tools/dispute/close.js +49 -0
- package/dist/tools/dispute/close.js.map +1 -0
- package/dist/tools/dispute/get.js +27 -0
- package/dist/tools/dispute/get.js.map +1 -0
- package/dist/tools/dispute/index.js +17 -0
- package/dist/tools/dispute/index.js.map +1 -0
- package/dist/tools/dispute/list.js +137 -0
- package/dist/tools/dispute/list.js.map +1 -0
- package/dist/tools/dispute/shared.js +66 -0
- package/dist/tools/dispute/shared.js.map +1 -0
- package/dist/tools/dispute/submit-evidence.js +58 -0
- package/dist/tools/dispute/submit-evidence.js.map +1 -0
- package/dist/tools/exception/add-comment.js +50 -0
- package/dist/tools/exception/add-comment.js.map +1 -0
- package/dist/tools/exception/adjust-entry.js +71 -0
- package/dist/tools/exception/adjust-entry.js.map +1 -0
- package/dist/tools/exception/bulk-assign.js +47 -0
- package/dist/tools/exception/bulk-assign.js.map +1 -0
- package/dist/tools/exception/bulk-dispatch.js +69 -0
- package/dist/tools/exception/bulk-dispatch.js.map +1 -0
- package/dist/tools/exception/bulk-resolve.js +64 -0
- package/dist/tools/exception/bulk-resolve.js.map +1 -0
- package/dist/tools/exception/delete-comment.js +40 -0
- package/dist/tools/exception/delete-comment.js.map +1 -0
- package/dist/tools/exception/dispatch.js +64 -0
- package/dist/tools/exception/dispatch.js.map +1 -0
- package/dist/tools/exception/force-match.js +55 -0
- package/dist/tools/exception/force-match.js.map +1 -0
- package/dist/tools/exception/get.js +34 -0
- package/dist/tools/exception/get.js.map +1 -0
- package/dist/tools/exception/history.js +61 -0
- package/dist/tools/exception/history.js.map +1 -0
- package/dist/tools/exception/index.js +39 -0
- package/dist/tools/exception/index.js.map +1 -0
- package/dist/tools/exception/list-comments.js +35 -0
- package/dist/tools/exception/list-comments.js.map +1 -0
- package/dist/tools/exception/list.js +169 -0
- package/dist/tools/exception/list.js.map +1 -0
- package/dist/tools/exception/open-dispute.js +53 -0
- package/dist/tools/exception/open-dispute.js.map +1 -0
- package/dist/tools/exception/shared.js +98 -0
- package/dist/tools/exception/shared.js.map +1 -0
- package/dist/tools/fee-rule/create.js +106 -0
- package/dist/tools/fee-rule/create.js.map +1 -0
- package/dist/tools/fee-rule/delete.js +27 -0
- package/dist/tools/fee-rule/delete.js.map +1 -0
- package/dist/tools/fee-rule/get.js +27 -0
- package/dist/tools/fee-rule/get.js.map +1 -0
- package/dist/tools/fee-rule/index.js +21 -0
- package/dist/tools/fee-rule/index.js.map +1 -0
- package/dist/tools/fee-rule/list.js +64 -0
- package/dist/tools/fee-rule/list.js.map +1 -0
- package/dist/tools/fee-rule/shared.js +67 -0
- package/dist/tools/fee-rule/shared.js.map +1 -0
- package/dist/tools/fee-rule/update.js +70 -0
- package/dist/tools/fee-rule/update.js.map +1 -0
- package/dist/tools/fee-schedule/create.js +105 -0
- package/dist/tools/fee-schedule/create.js.map +1 -0
- package/dist/tools/fee-schedule/delete.js +32 -0
- package/dist/tools/fee-schedule/delete.js.map +1 -0
- package/dist/tools/fee-schedule/get.js +30 -0
- package/dist/tools/fee-schedule/get.js.map +1 -0
- package/dist/tools/fee-schedule/index.js +22 -0
- package/dist/tools/fee-schedule/index.js.map +1 -0
- package/dist/tools/fee-schedule/list.js +56 -0
- package/dist/tools/fee-schedule/list.js.map +1 -0
- package/dist/tools/fee-schedule/shared.js +58 -0
- package/dist/tools/fee-schedule/shared.js.map +1 -0
- package/dist/tools/fee-schedule/simulate.js +54 -0
- package/dist/tools/fee-schedule/simulate.js.map +1 -0
- package/dist/tools/fee-schedule/update.js +69 -0
- package/dist/tools/fee-schedule/update.js.map +1 -0
- package/dist/tools/generic/describe-operation.js +157 -0
- package/dist/tools/generic/describe-operation.js.map +1 -0
- package/dist/tools/generic/invoke.js +343 -0
- package/dist/tools/generic/invoke.js.map +1 -0
- package/dist/tools/generic/list-operations.js +73 -0
- package/dist/tools/generic/list-operations.js.map +1 -0
- package/dist/tools/ingestion/index.js +29 -0
- package/dist/tools/ingestion/index.js.map +1 -0
- package/dist/tools/ingestion/job-errors-list.js +45 -0
- package/dist/tools/ingestion/job-errors-list.js.map +1 -0
- package/dist/tools/ingestion/job-get.js +42 -0
- package/dist/tools/ingestion/job-get.js.map +1 -0
- package/dist/tools/ingestion/job-transactions-list.js +93 -0
- package/dist/tools/ingestion/job-transactions-list.js.map +1 -0
- package/dist/tools/ingestion/jobs-list.js +89 -0
- package/dist/tools/ingestion/jobs-list.js.map +1 -0
- package/dist/tools/ingestion/shared.js +84 -0
- package/dist/tools/ingestion/shared.js.map +1 -0
- package/dist/tools/ingestion/transaction-ignore.js +51 -0
- package/dist/tools/ingestion/transaction-ignore.js.map +1 -0
- package/dist/tools/ingestion/transactions-search.js +143 -0
- package/dist/tools/ingestion/transactions-search.js.map +1 -0
- package/dist/tools/match-rule/create.js +64 -0
- package/dist/tools/match-rule/create.js.map +1 -0
- package/dist/tools/match-rule/delete.js +35 -0
- package/dist/tools/match-rule/delete.js.map +1 -0
- package/dist/tools/match-rule/get.js +32 -0
- package/dist/tools/match-rule/get.js.map +1 -0
- package/dist/tools/match-rule/index.js +22 -0
- package/dist/tools/match-rule/index.js.map +1 -0
- package/dist/tools/match-rule/list.js +72 -0
- package/dist/tools/match-rule/list.js.map +1 -0
- package/dist/tools/match-rule/reorder.js +45 -0
- package/dist/tools/match-rule/reorder.js.map +1 -0
- package/dist/tools/match-rule/shared.js +71 -0
- package/dist/tools/match-rule/shared.js.map +1 -0
- package/dist/tools/match-rule/update.js +68 -0
- package/dist/tools/match-rule/update.js.map +1 -0
- package/dist/tools/matching/get.js +48 -0
- package/dist/tools/matching/get.js.map +1 -0
- package/dist/tools/matching/groups.js +98 -0
- package/dist/tools/matching/groups.js.map +1 -0
- package/dist/tools/matching/index.js +19 -0
- package/dist/tools/matching/index.js.map +1 -0
- package/dist/tools/matching/list.js +76 -0
- package/dist/tools/matching/list.js.map +1 -0
- package/dist/tools/matching/shared.js +77 -0
- package/dist/tools/matching/shared.js.map +1 -0
- package/dist/tools/matching/start.js +55 -0
- package/dist/tools/matching/start.js.map +1 -0
- package/dist/tools/report/count-exceptions.js +45 -0
- package/dist/tools/report/count-exceptions.js.map +1 -0
- package/dist/tools/report/count-matched.js +46 -0
- package/dist/tools/report/count-matched.js.map +1 -0
- package/dist/tools/report/count-transactions.js +44 -0
- package/dist/tools/report/count-transactions.js.map +1 -0
- package/dist/tools/report/count-unmatched.js +44 -0
- package/dist/tools/report/count-unmatched.js.map +1 -0
- package/dist/tools/report/export-exceptions.js +46 -0
- package/dist/tools/report/export-exceptions.js.map +1 -0
- package/dist/tools/report/export-matched.js +47 -0
- package/dist/tools/report/export-matched.js.map +1 -0
- package/dist/tools/report/export-summary.js +47 -0
- package/dist/tools/report/export-summary.js.map +1 -0
- package/dist/tools/report/export-unmatched.js +47 -0
- package/dist/tools/report/export-unmatched.js.map +1 -0
- package/dist/tools/report/export-variance.js +46 -0
- package/dist/tools/report/export-variance.js.map +1 -0
- package/dist/tools/report/index.js +40 -0
- package/dist/tools/report/index.js.map +1 -0
- package/dist/tools/report/matched.js +44 -0
- package/dist/tools/report/matched.js.map +1 -0
- package/dist/tools/report/shared.js +176 -0
- package/dist/tools/report/shared.js.map +1 -0
- package/dist/tools/report/summary.js +41 -0
- package/dist/tools/report/summary.js.map +1 -0
- package/dist/tools/report/unmatched.js +44 -0
- package/dist/tools/report/unmatched.js.map +1 -0
- package/dist/tools/report/variance.js +44 -0
- package/dist/tools/report/variance.js.map +1 -0
- package/dist/tools/source/create.js +84 -0
- package/dist/tools/source/create.js.map +1 -0
- package/dist/tools/source/get.js +41 -0
- package/dist/tools/source/get.js.map +1 -0
- package/dist/tools/source/index.js +22 -0
- package/dist/tools/source/index.js.map +1 -0
- package/dist/tools/source/list.js +72 -0
- package/dist/tools/source/list.js.map +1 -0
- package/dist/tools/source/shared.js +63 -0
- package/dist/tools/source/shared.js.map +1 -0
- package/dist/tools/source/update.js +73 -0
- package/dist/tools/source/update.js.map +1 -0
- package/dist/tools/tool-error.js +74 -0
- package/dist/tools/tool-error.js.map +1 -0
- package/dist/transport/body-limit.js +82 -0
- package/dist/transport/body-limit.js.map +1 -0
- package/dist/transport/http.js +154 -0
- package/dist/transport/http.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// `fee_rule_list` — curated GET /v1/contexts/{contextId}/fee-rules.
|
|
2
|
+
//
|
|
3
|
+
// Cursor-paginated list of a context's fee rules. `contextId` is a required path
|
|
4
|
+
// param (routing, not a tenant field). limit/cursor pass through untouched and
|
|
5
|
+
// matcher's { items, nextCursor, ... } envelope is returned as-is — no
|
|
6
|
+
// auto-pagination (the model re-calls with the returned cursor). The list is
|
|
7
|
+
// implicitly tenant-scoped by the relayed token; no tenant field is accepted.
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { contextFeeRulesPath, dispatchFeeRule } from './shared.js';
|
|
10
|
+
/** Zod raw shape for `fee_rule_list` input — contextId path + pagination knobs. */
|
|
11
|
+
export const listFeeRulesInputShape = {
|
|
12
|
+
contextId: z
|
|
13
|
+
.string()
|
|
14
|
+
.min(1)
|
|
15
|
+
.describe('The reconciliation context id (UUID) whose fee rules to list. A routing ' +
|
|
16
|
+
"path param matcher validates against your token's tenant. NOT a tenant " +
|
|
17
|
+
'field.'),
|
|
18
|
+
limit: z
|
|
19
|
+
.number()
|
|
20
|
+
.int()
|
|
21
|
+
.min(1)
|
|
22
|
+
.max(200)
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Maximum number of records to return (1–200, default 20).'),
|
|
25
|
+
cursor: z
|
|
26
|
+
.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Opaque pagination cursor from a prior response. Re-call with the ' +
|
|
29
|
+
'returned nextCursor to page forward (there is no auto-pagination).'),
|
|
30
|
+
};
|
|
31
|
+
/** Build the list query, omitting unset knobs so the request stays minimal. */
|
|
32
|
+
function buildListQuery(args) {
|
|
33
|
+
const query = {};
|
|
34
|
+
if (args.limit !== undefined) {
|
|
35
|
+
query.limit = args.limit;
|
|
36
|
+
}
|
|
37
|
+
if (args.cursor !== undefined) {
|
|
38
|
+
query.cursor = args.cursor;
|
|
39
|
+
}
|
|
40
|
+
return Object.keys(query).length > 0 ? query : undefined;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Register `fee_rule_list`. Substitutes `contextId` into the context-nested path,
|
|
44
|
+
* passes limit/cursor through, and returns matcher's pagination envelope
|
|
45
|
+
* verbatim; a matcher error surfaces via the shared toToolError.
|
|
46
|
+
*/
|
|
47
|
+
export function registerFeeRuleListTool(server) {
|
|
48
|
+
server.registerTool('fee_rule_list', {
|
|
49
|
+
description: 'List the fee rules for a reconciliation context (cursor-paginated). ' +
|
|
50
|
+
'Provide contextId (path); optionally limit (1–200) and/or cursor. The ' +
|
|
51
|
+
'response carries { items, nextCursor } — paginate by re-calling with the ' +
|
|
52
|
+
'returned nextCursor. No tenant field is accepted; the tenant is derived ' +
|
|
53
|
+
'from your bearer token.',
|
|
54
|
+
inputSchema: listFeeRulesInputShape,
|
|
55
|
+
}, async (args, extra) => {
|
|
56
|
+
const query = buildListQuery(args);
|
|
57
|
+
return dispatchFeeRule({
|
|
58
|
+
method: 'GET',
|
|
59
|
+
path: contextFeeRulesPath(args.contextId),
|
|
60
|
+
...(query !== undefined ? { query } : {}),
|
|
61
|
+
}, extra);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/tools/fee-rule/list.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,iFAAiF;AACjF,+EAA+E;AAC/E,uEAAuE;AACvE,6EAA6E;AAC7E,8EAA8E;AAE9E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElE,mFAAmF;AACnF,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CACP,0EAA0E;QACxE,yEAAyE;QACzE,QAAQ,CACX;IACH,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,0DAA0D,CAAC;IACvE,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,mEAAmE;QACjE,oEAAoE,CACvE;CACJ,CAAA;AAOD,+EAA+E;AAC/E,SAAS,cAAc,CAAC,IAAuB;IAC7C,MAAM,KAAK,GAAoC,EAAE,CAAA;IACjD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;IAC1B,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;AAC1D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAiB;IACvD,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,WAAW,EACT,sEAAsE;YACtE,wEAAwE;YACxE,2EAA2E;YAC3E,0EAA0E;YAC1E,yBAAyB;QAC3B,WAAW,EAAE,sBAAsB;KACpC,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACpB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA;QAClC,OAAO,eAAe,CACpB;YACE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC;YACzC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C,EACD,KAAK,CACN,CAAA;IACH,CAAC,CACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Shared plumbing for the curated fee-rule tools.
|
|
2
|
+
//
|
|
3
|
+
// Fee rules use a HYBRID path shape (verified against docs/openapi/openapi.yaml):
|
|
4
|
+
// - create + list are CONTEXT-NESTED: POST/GET /v1/contexts/{contextId}/fee-rules
|
|
5
|
+
// - get + update(PATCH) + delete are FLAT: GET/PATCH/DELETE /v1/fee-rules/{feeRuleId}
|
|
6
|
+
// This module exports both path helpers plus the single dispatch that every
|
|
7
|
+
// fee-rule tool funnels through.
|
|
8
|
+
//
|
|
9
|
+
// Every fee-rule tool follows the same relay shape: fail-closed auth via
|
|
10
|
+
// requireMatcherClient, dispatch one assembled MatcherRequest, then return
|
|
11
|
+
// matcher's JSON on success or the SHARED toToolError on a MatcherApiError. This
|
|
12
|
+
// factors that boilerplate exactly once so the five tools stay thin (just "build
|
|
13
|
+
// the request") and so curated + generic surfaces map matcher errors through the
|
|
14
|
+
// identical path (toToolError).
|
|
15
|
+
//
|
|
16
|
+
// Security: the bearer token is never read here directly — requireMatcherClient
|
|
17
|
+
// owns the request-scoped relay and fails closed when no usable credential was
|
|
18
|
+
// provided. No tenant identifier is ever read or injected (matcher derives
|
|
19
|
+
// tenant from the relayed JWT); no fee-rule tool input carries one. `contextId`
|
|
20
|
+
// is a routing path param matcher validates ownership of, NOT a tenant field.
|
|
21
|
+
import { requireMatcherClient, UnauthenticatedError, } from '../../auth/request-token.js';
|
|
22
|
+
import { isMatcherApiError, toToolError } from '../tool-error.js';
|
|
23
|
+
/** Context-nested collection path for fee rules (create + list). */
|
|
24
|
+
export function contextFeeRulesPath(contextId) {
|
|
25
|
+
return `/v1/contexts/${encodeURIComponent(contextId)}/fee-rules`;
|
|
26
|
+
}
|
|
27
|
+
/** Flat single-rule path (get + update + delete), URL-encoding the id. */
|
|
28
|
+
export function feeRulePath(feeRuleId) {
|
|
29
|
+
return `/v1/fee-rules/${encodeURIComponent(feeRuleId)}`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Run one assembled request through the relay: fail-closed auth, dispatch, and
|
|
33
|
+
* RFC 9457 → tool-error mapping — identical to the generic invoke's dispatch so
|
|
34
|
+
* both surfaces produce the same structured error shape.
|
|
35
|
+
*
|
|
36
|
+
* `clientFor` is injectable for tests; production callers pass nothing and get
|
|
37
|
+
* the request-scoped, fail-closed `requireMatcherClient`.
|
|
38
|
+
*/
|
|
39
|
+
export async function dispatchFeeRule(request, extra, clientFor = requireMatcherClient) {
|
|
40
|
+
let client;
|
|
41
|
+
try {
|
|
42
|
+
// Fail-closed on a missing / empty / non-Bearer credential.
|
|
43
|
+
client = clientFor(extra);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
if (err instanceof UnauthenticatedError) {
|
|
47
|
+
return { isError: true, content: [{ type: 'text', text: err.message }] };
|
|
48
|
+
}
|
|
49
|
+
throw err;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const result = await client.request(request);
|
|
53
|
+
// Success → matcher's JSON returned as-is (incl. pagination envelopes and
|
|
54
|
+
// 204 → null for delete).
|
|
55
|
+
return { content: [{ type: 'text', text: JSON.stringify(result ?? null) }] };
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
// RFC 9457 problem → the SHARED structured tool error (status/title/detail/
|
|
59
|
+
// code preserved). A non-matcher error is a bug, not a matcher failure, and
|
|
60
|
+
// is re-thrown rather than masqueraded as one.
|
|
61
|
+
if (isMatcherApiError(err)) {
|
|
62
|
+
return toToolError(err);
|
|
63
|
+
}
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/tools/fee-rule/shared.ts"],"names":[],"mappings":"AAAA,kDAAkD;AAClD,EAAE;AACF,kFAAkF;AAClF,oFAAoF;AACpF,wFAAwF;AACxF,4EAA4E;AAC5E,iCAAiC;AACjC,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,iFAAiF;AACjF,iFAAiF;AACjF,iFAAiF;AACjF,gCAAgC;AAChC,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,2EAA2E;AAC3E,gFAAgF;AAChF,8EAA8E;AAI9E,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GAErB,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEjE,oEAAoE;AACpE,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACnD,OAAO,gBAAgB,kBAAkB,CAAC,SAAS,CAAC,YAAY,CAAA;AAClE,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC3C,OAAO,iBAAiB,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAA;AACzD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAuB,EACvB,KAAmC,EACnC,YAAyD,oBAAoB;IAE7E,IAAI,MAAqB,CAAA;IACzB,IAAI,CAAC;QACH,4DAA4D;QAC5D,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,oBAAoB,EAAE,CAAC;YACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,CAAA;QAC1E,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC5C,0EAA0E;QAC1E,0BAA0B;QAC1B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,CAAC,EAAE,CAAA;IAC9E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4EAA4E;QAC5E,4EAA4E;QAC5E,+CAA+C;QAC/C,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,WAAW,CAAC,GAAG,CAAC,CAAA;QACzB,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// `fee_rule_update` — curated PATCH /v1/fee-rules/{feeRuleId}.
|
|
2
|
+
//
|
|
3
|
+
// Partial update of a fee rule's fields via the FLAT path, mirroring the spec's
|
|
4
|
+
// UpdateFeeRuleRequest. All body fields are optional (PATCH semantics). The flat
|
|
5
|
+
// update path takes no contextId — feeRuleId alone identifies the rule. The spec
|
|
6
|
+
// DOES allow re-pointing the rule at a different fee schedule via feeScheduleId,
|
|
7
|
+
// so it is a settable field here; providing `predicates` replaces the existing
|
|
8
|
+
// predicate set. No tenant field is accepted (matcher scopes to the relayed
|
|
9
|
+
// token's tenant).
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { FEE_RULE_SIDES, feeRulePredicateShape } from './create.js';
|
|
12
|
+
import { dispatchFeeRule, feeRulePath } from './shared.js';
|
|
13
|
+
/** Zod raw shape for `fee_rule_update` input — id (path) + optional fields. */
|
|
14
|
+
export const updateFeeRuleInputShape = {
|
|
15
|
+
feeRuleId: z.string().min(1).describe('The fee rule id (UUID) to update.'),
|
|
16
|
+
side: z
|
|
17
|
+
.enum(FEE_RULE_SIDES)
|
|
18
|
+
.optional()
|
|
19
|
+
.describe('Side the rule applies to. LEFT and RIGHT target one reconciliation side; ' +
|
|
20
|
+
'ANY matches transactions on either side.'),
|
|
21
|
+
feeScheduleId: z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('UUID of the fee schedule this rule applies when its predicates match. ' +
|
|
25
|
+
'Changing it requires read access to the new schedule.'),
|
|
26
|
+
name: z.string().optional().describe('New human-readable name of the fee rule.'),
|
|
27
|
+
priority: z
|
|
28
|
+
.number()
|
|
29
|
+
.int()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe('Evaluation priority; lower numbers are evaluated first. Must remain ' +
|
|
32
|
+
'unique within the context (LEFT, RIGHT, and ANY share one priority space).'),
|
|
33
|
+
predicates: z
|
|
34
|
+
.array(feeRulePredicateShape)
|
|
35
|
+
.optional()
|
|
36
|
+
.describe('Predicates (ANDed together) a transaction must satisfy. When provided, ' +
|
|
37
|
+
'replaces the existing predicate set entirely.'),
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Build the PATCH body from the input minus the path-only `feeRuleId`. Only the
|
|
41
|
+
* fields the caller actually set are sent — matcher treats absent fields as
|
|
42
|
+
* unchanged.
|
|
43
|
+
*/
|
|
44
|
+
export function buildUpdateBody(args) {
|
|
45
|
+
const { feeRuleId: _feeRuleId, ...body } = args;
|
|
46
|
+
void _feeRuleId;
|
|
47
|
+
return body;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Register `fee_rule_update`. Splits the id (path) from the body fields and
|
|
51
|
+
* dispatches a PATCH through the shared fail-closed relay; a matcher error
|
|
52
|
+
* surfaces via the shared toToolError.
|
|
53
|
+
*/
|
|
54
|
+
export function registerFeeRuleUpdateTool(server) {
|
|
55
|
+
server.registerTool('fee_rule_update', {
|
|
56
|
+
description: 'Update fields of a fee rule by id (UUID) via the flat path. All fields ' +
|
|
57
|
+
'are optional (PATCH): side (LEFT|RIGHT|ANY), feeScheduleId (UUID), name, ' +
|
|
58
|
+
'priority (unique within the context), predicates[] (replaces the set ' +
|
|
59
|
+
'when provided). No tenant field is accepted. Returns the updated rule, ' +
|
|
60
|
+
'or a structured RFC 9457 error.',
|
|
61
|
+
inputSchema: updateFeeRuleInputShape,
|
|
62
|
+
}, async (args, extra) => {
|
|
63
|
+
return dispatchFeeRule({
|
|
64
|
+
method: 'PATCH',
|
|
65
|
+
path: feeRulePath(args.feeRuleId),
|
|
66
|
+
body: buildUpdateBody(args),
|
|
67
|
+
}, extra);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/tools/fee-rule/update.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,EAAE;AACF,gFAAgF;AAChF,iFAAiF;AACjF,iFAAiF;AACjF,iFAAiF;AACjF,+EAA+E;AAC/E,4EAA4E;AAC5E,mBAAmB;AAEnB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE1D,+EAA+E;AAC/E,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;IAC1E,IAAI,EAAE,CAAC;SACJ,IAAI,CAAC,cAAc,CAAC;SACpB,QAAQ,EAAE;SACV,QAAQ,CACP,2EAA2E;QACzE,0CAA0C,CAC7C;IACH,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,wEAAwE;QACtE,uDAAuD,CAC1D;IACH,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;IAChF,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,QAAQ,CACP,sEAAsE;QACpE,4EAA4E,CAC/E;IACH,UAAU,EAAE,CAAC;SACV,KAAK,CAAC,qBAAqB,CAAC;SAC5B,QAAQ,EAAE;SACV,QAAQ,CACP,yEAAyE;QACvE,+CAA+C,CAClD;CACJ,CAAA;AAOD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAwB;IAExB,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAA;IAC/C,KAAK,UAAU,CAAA;IACf,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAiB;IACzD,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EACT,yEAAyE;YACzE,2EAA2E;YAC3E,uEAAuE;YACvE,yEAAyE;YACzE,iCAAiC;QACnC,WAAW,EAAE,uBAAuB;KACrC,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACpB,OAAO,eAAe,CACpB;YACE,MAAM,EAAE,OAAO;YACf,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC;YACjC,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC;SAC5B,EACD,KAAK,CACN,CAAA;IACH,CAAC,CACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// `fee_schedule_create` — curated POST /v1/fee-schedules.
|
|
2
|
+
//
|
|
3
|
+
// A typed, richly-described front door to creating a fee schedule, mirroring the
|
|
4
|
+
// spec's CreateFeeScheduleRequest. The Zod schema models the required scalars
|
|
5
|
+
// and the documented enums (applicationOrder, roundingMode) so an operator-
|
|
6
|
+
// driving LLM gets the shape and the units up front; the `items[]` array is
|
|
7
|
+
// modeled as a typed-but-permissive structure (per task 1.3.2) — matcher's
|
|
8
|
+
// server-side validation + the returned RFC 9457 problem are the authoritative
|
|
9
|
+
// check, so we do not duplicate the full item validation here.
|
|
10
|
+
//
|
|
11
|
+
// No tenant field exists in the schema: the schedule is created for the tenant
|
|
12
|
+
// of the relayed bearer token, never a tenant supplied as input.
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { dispatchFeeSchedule, FEE_SCHEDULES_PATH } from './shared.js';
|
|
15
|
+
/** How fee items combine when applied to a base amount. */
|
|
16
|
+
export const APPLICATION_ORDERS = ['PARALLEL', 'CASCADING'];
|
|
17
|
+
/** Rounding strategies matcher supports for fee amounts. */
|
|
18
|
+
export const ROUNDING_MODES = [
|
|
19
|
+
'HALF_UP',
|
|
20
|
+
'BANKERS',
|
|
21
|
+
'FLOOR',
|
|
22
|
+
'CEIL',
|
|
23
|
+
'TRUNCATE',
|
|
24
|
+
];
|
|
25
|
+
/** Shape of a single fee item's structure (FLAT / PERCENTAGE / TIERED). */
|
|
26
|
+
export const FEE_STRUCTURE_TYPES = ['FLAT', 'PERCENTAGE', 'TIERED'];
|
|
27
|
+
/**
|
|
28
|
+
* One fee item. Typed-but-permissive: the named fields mirror the spec's
|
|
29
|
+
* CreateFeeScheduleItemRequest, but `structure` is left as an open record
|
|
30
|
+
* (its shape depends on structureType) and unknown keys are allowed so matcher
|
|
31
|
+
* remains the authoritative validator.
|
|
32
|
+
*/
|
|
33
|
+
export const feeScheduleItemShape = z
|
|
34
|
+
.object({
|
|
35
|
+
name: z
|
|
36
|
+
.string()
|
|
37
|
+
.describe('Human-readable name of the fee item, e.g. "interchange".'),
|
|
38
|
+
priority: z
|
|
39
|
+
.number()
|
|
40
|
+
.int()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Application order within the schedule (relevant for CASCADING ' +
|
|
43
|
+
'applicationOrder); lower runs first.'),
|
|
44
|
+
structureType: z
|
|
45
|
+
.enum(FEE_STRUCTURE_TYPES)
|
|
46
|
+
.describe('Shape of the fee structure. FLAT is a fixed amount; PERCENTAGE is a ' +
|
|
47
|
+
'rate of the base; TIERED applies different rates per amount tier.'),
|
|
48
|
+
structure: z
|
|
49
|
+
.record(z.string(), z.unknown())
|
|
50
|
+
.describe('Type-specific structure object. FLAT: {"amount":"1.50"}. PERCENTAGE: ' +
|
|
51
|
+
'{"rate":"0.029"} where rate is a 0..1 fraction (0.029 = 2.9%), not a ' +
|
|
52
|
+
'percent value. TIERED: {"tiers":[{"rate":"0.01","upTo":"1000"},...]} ' +
|
|
53
|
+
'with the same 0..1 fraction semantics per tier rate.'),
|
|
54
|
+
})
|
|
55
|
+
.describe('A single fee item making up the schedule.');
|
|
56
|
+
/** Zod raw shape for `fee_schedule_create` input — mirrors CreateFeeScheduleRequest. */
|
|
57
|
+
export const createFeeScheduleInputShape = {
|
|
58
|
+
name: z
|
|
59
|
+
.string()
|
|
60
|
+
.min(1)
|
|
61
|
+
.max(100)
|
|
62
|
+
.describe('Human-readable name of the fee schedule (1–100 chars).'),
|
|
63
|
+
currency: z
|
|
64
|
+
.string()
|
|
65
|
+
.describe("ISO 4217 currency code the schedule's amounts are denominated in, e.g. " +
|
|
66
|
+
'"USD". Validated server-side.'),
|
|
67
|
+
applicationOrder: z
|
|
68
|
+
.enum(APPLICATION_ORDERS)
|
|
69
|
+
.describe('How items combine. PARALLEL applies every item to the same gross base; ' +
|
|
70
|
+
'CASCADING applies each item to the net remaining after prior items.'),
|
|
71
|
+
roundingScale: z
|
|
72
|
+
.number()
|
|
73
|
+
.int()
|
|
74
|
+
.describe('Number of decimal places fee amounts are rounded to, e.g. 2.'),
|
|
75
|
+
roundingMode: z
|
|
76
|
+
.enum(ROUNDING_MODES)
|
|
77
|
+
.describe('Rounding strategy. HALF_UP rounds halves away from zero; BANKERS rounds ' +
|
|
78
|
+
'halves to the nearest even digit; FLOOR rounds down; CEIL rounds up; ' +
|
|
79
|
+
'TRUNCATE drops extra digits.'),
|
|
80
|
+
items: z
|
|
81
|
+
.array(feeScheduleItemShape)
|
|
82
|
+
.min(1)
|
|
83
|
+
.max(100)
|
|
84
|
+
.describe('Fee items that make up the schedule; at least one is required (max 100). ' +
|
|
85
|
+
"Each item's structure is validated server-side against its structureType."),
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Register `fee_schedule_create`. Builds the POST request body from the typed
|
|
89
|
+
* input and dispatches it through the shared fail-closed relay; a matcher error
|
|
90
|
+
* surfaces via the shared toToolError (same shape as matcher_invoke).
|
|
91
|
+
*/
|
|
92
|
+
export function registerFeeScheduleCreateTool(server) {
|
|
93
|
+
server.registerTool('fee_schedule_create', {
|
|
94
|
+
description: 'Create a fee schedule for transaction fee calculation. The schedule is ' +
|
|
95
|
+
"created for your token's tenant (no tenant field is accepted). Provide " +
|
|
96
|
+
'name, currency (ISO 4217), applicationOrder (PARALLEL|CASCADING), ' +
|
|
97
|
+
'roundingScale (decimal places), roundingMode (HALF_UP|BANKERS|FLOOR|' +
|
|
98
|
+
'CEIL|TRUNCATE), and items[] (≥1). Returns the created schedule, or a ' +
|
|
99
|
+
'structured RFC 9457 error.',
|
|
100
|
+
inputSchema: createFeeScheduleInputShape,
|
|
101
|
+
}, async (args, extra) => {
|
|
102
|
+
return dispatchFeeSchedule({ method: 'POST', path: FEE_SCHEDULES_PATH, body: args }, extra);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/tools/fee-schedule/create.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,iFAAiF;AACjF,8EAA8E;AAC9E,4EAA4E;AAC5E,4EAA4E;AAC5E,2EAA2E;AAC3E,+EAA+E;AAC/E,+DAA+D;AAC/D,EAAE;AACF,+EAA+E;AAC/E,iEAAiE;AAEjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAErE,2DAA2D;AAC3D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,EAAE,WAAW,CAAU,CAAA;AAEpE,4DAA4D;AAC5D,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,SAAS;IACT,SAAS;IACT,OAAO;IACP,MAAM;IACN,UAAU;CACF,CAAA;AAEV,2EAA2E;AAC3E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAU,CAAA;AAE5E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,CAAC;IACN,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,CAAC,0DAA0D,CAAC;IACvE,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,QAAQ,CACP,gEAAgE;QAC9D,sCAAsC,CACzC;IACH,aAAa,EAAE,CAAC;SACb,IAAI,CAAC,mBAAmB,CAAC;SACzB,QAAQ,CACP,sEAAsE;QACpE,mEAAmE,CACtE;IACH,SAAS,EAAE,CAAC;SACT,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;SAC/B,QAAQ,CACP,uEAAuE;QACrE,uEAAuE;QACvE,uEAAuE;QACvE,sDAAsD,CACzD;CACJ,CAAC;KACD,QAAQ,CAAC,2CAA2C,CAAC,CAAA;AAExD,wFAAwF;AACxF,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,CAAC,wDAAwD,CAAC;IACrE,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,CACP,yEAAyE;QACvE,+BAA+B,CAClC;IACH,gBAAgB,EAAE,CAAC;SAChB,IAAI,CAAC,kBAAkB,CAAC;SACxB,QAAQ,CACP,yEAAyE;QACvE,qEAAqE,CACxE;IACH,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,CAAC,8DAA8D,CAAC;IAC3E,YAAY,EAAE,CAAC;SACZ,IAAI,CAAC,cAAc,CAAC;SACpB,QAAQ,CACP,0EAA0E;QACxE,uEAAuE;QACvE,8BAA8B,CACjC;IACH,KAAK,EAAE,CAAC;SACL,KAAK,CAAC,oBAAoB,CAAC;SAC3B,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,CACP,2EAA2E;QACzE,2EAA2E,CAC9E;CACJ,CAAA;AAOD;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAAC,MAAiB;IAC7D,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;QACE,WAAW,EACT,yEAAyE;YACzE,yEAAyE;YACzE,oEAAoE;YACpE,sEAAsE;YACtE,uEAAuE;YACvE,4BAA4B;QAC9B,WAAW,EAAE,2BAA2B;KACzC,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACpB,OAAO,mBAAmB,CACxB,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,IAAI,EAAE,EACxD,KAAK,CACN,CAAA;IACH,CAAC,CACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// `fee_schedule_delete` — curated DELETE /v1/fee-schedules/{scheduleId}.
|
|
2
|
+
//
|
|
3
|
+
// Removes a fee schedule by id. Matcher rejects with 409 while fee rules still
|
|
4
|
+
// reference the schedule — that problem surfaces verbatim through the shared
|
|
5
|
+
// toToolError. A successful delete returns 204 (no content), which the relay
|
|
6
|
+
// renders as null. scheduleId is a UUID path param; no tenant field is accepted.
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { dispatchFeeSchedule, feeSchedulePath } from './shared.js';
|
|
9
|
+
/** Zod raw shape for `fee_schedule_delete` input — just the schedule id. */
|
|
10
|
+
export const deleteFeeScheduleInputShape = {
|
|
11
|
+
scheduleId: z
|
|
12
|
+
.string()
|
|
13
|
+
.min(1)
|
|
14
|
+
.describe('The fee schedule id (UUID) to delete.'),
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Register `fee_schedule_delete`. Substitutes the id into the path and dispatches
|
|
18
|
+
* a DELETE through the shared fail-closed relay; a 409 (still referenced) or any
|
|
19
|
+
* other matcher error surfaces via the shared toToolError.
|
|
20
|
+
*/
|
|
21
|
+
export function registerFeeScheduleDeleteTool(server) {
|
|
22
|
+
server.registerTool('fee_schedule_delete', {
|
|
23
|
+
description: 'Delete a fee schedule by id (UUID). Rejected with 409 while fee rules ' +
|
|
24
|
+
'still reference it — detach those first. The schedule must belong to ' +
|
|
25
|
+
"your token's tenant (no tenant field is accepted). Returns no content on " +
|
|
26
|
+
'success, or a structured RFC 9457 error.',
|
|
27
|
+
inputSchema: deleteFeeScheduleInputShape,
|
|
28
|
+
}, async (args, extra) => {
|
|
29
|
+
return dispatchFeeSchedule({ method: 'DELETE', path: feeSchedulePath(args.scheduleId) }, extra);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../src/tools/fee-schedule/delete.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,+EAA+E;AAC/E,6EAA6E;AAC7E,6EAA6E;AAC7E,iFAAiF;AAEjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElE,4EAA4E;AAC5E,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,uCAAuC,CAAC;CACrD,CAAA;AAOD;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAAC,MAAiB;IAC7D,MAAM,CAAC,YAAY,CACjB,qBAAqB,EACrB;QACE,WAAW,EACT,wEAAwE;YACxE,uEAAuE;YACvE,2EAA2E;YAC3E,0CAA0C;QAC5C,WAAW,EAAE,2BAA2B;KACzC,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACpB,OAAO,mBAAmB,CACxB,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EAC5D,KAAK,CACN,CAAA;IACH,CAAC,CACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// `fee_schedule_get` — curated GET /v1/fee-schedules/{scheduleId}.
|
|
2
|
+
//
|
|
3
|
+
// Reads one fee schedule by id. scheduleId is the only input (a UUID path
|
|
4
|
+
// param). The schedule must belong to the relayed token's tenant — matcher
|
|
5
|
+
// enforces that; no tenant field is accepted.
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { dispatchFeeSchedule, feeSchedulePath } from './shared.js';
|
|
8
|
+
/** Zod raw shape for `fee_schedule_get` input — just the schedule id. */
|
|
9
|
+
export const getFeeScheduleInputShape = {
|
|
10
|
+
scheduleId: z
|
|
11
|
+
.string()
|
|
12
|
+
.min(1)
|
|
13
|
+
.describe('The fee schedule id (UUID) to fetch.'),
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Register `fee_schedule_get`. Substitutes the id into the path and dispatches a
|
|
17
|
+
* GET through the shared fail-closed relay; a matcher error (e.g. 404) surfaces
|
|
18
|
+
* via the shared toToolError.
|
|
19
|
+
*/
|
|
20
|
+
export function registerFeeScheduleGetTool(server) {
|
|
21
|
+
server.registerTool('fee_schedule_get', {
|
|
22
|
+
description: 'Fetch a single fee schedule by id (UUID). The schedule must belong to ' +
|
|
23
|
+
"your token's tenant. Returns the schedule, or a structured RFC 9457 " +
|
|
24
|
+
'error (e.g. 404 if it does not exist or is not yours).',
|
|
25
|
+
inputSchema: getFeeScheduleInputShape,
|
|
26
|
+
}, async (args, extra) => {
|
|
27
|
+
return dispatchFeeSchedule({ method: 'GET', path: feeSchedulePath(args.scheduleId) }, extra);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=get.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get.js","sourceRoot":"","sources":["../../../src/tools/fee-schedule/get.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,8CAA8C;AAE9C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElE,yEAAyE;AACzE,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,sCAAsC,CAAC;CACpD,CAAA;AAOD;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAiB;IAC1D,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;QACE,WAAW,EACT,wEAAwE;YACxE,sEAAsE;YACtE,wDAAwD;QAC1D,WAAW,EAAE,wBAAwB;KACtC,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACpB,OAAO,mBAAmB,CACxB,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,EACzD,KAAK,CACN,CAAA;IACH,CAAC,CACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Curated fee-schedule vertical (task 1.3.2): six typed tools over the matcher
|
|
2
|
+
// fee-schedule resource — create, list, get, update, delete, simulate — proving
|
|
3
|
+
// the typed pattern coexists with the generic invoke on one client + one token
|
|
4
|
+
// relay. Each tool shares the fail-closed relay (shared.ts) and the RFC 9457 →
|
|
5
|
+
// tool-error mapping (toToolError) with the generic surface, so curated and
|
|
6
|
+
// generic map matcher errors identically. No tool carries a tenant field.
|
|
7
|
+
import { registerFeeScheduleCreateTool } from './create.js';
|
|
8
|
+
import { registerFeeScheduleDeleteTool } from './delete.js';
|
|
9
|
+
import { registerFeeScheduleGetTool } from './get.js';
|
|
10
|
+
import { registerFeeScheduleListTool } from './list.js';
|
|
11
|
+
import { registerFeeScheduleSimulateTool } from './simulate.js';
|
|
12
|
+
import { registerFeeScheduleUpdateTool } from './update.js';
|
|
13
|
+
/** Register all six curated fee-schedule tools on the given server. */
|
|
14
|
+
export function registerFeeScheduleTools(server) {
|
|
15
|
+
registerFeeScheduleCreateTool(server);
|
|
16
|
+
registerFeeScheduleListTool(server);
|
|
17
|
+
registerFeeScheduleGetTool(server);
|
|
18
|
+
registerFeeScheduleUpdateTool(server);
|
|
19
|
+
registerFeeScheduleDeleteTool(server);
|
|
20
|
+
registerFeeScheduleSimulateTool(server);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/fee-schedule/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,0EAA0E;AAI1E,OAAO,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAA;AACrD,OAAO,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAA;AACvD,OAAO,EAAE,+BAA+B,EAAE,MAAM,eAAe,CAAA;AAC/D,OAAO,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAA;AAE3D,uEAAuE;AACvE,MAAM,UAAU,wBAAwB,CAAC,MAAiB;IACxD,6BAA6B,CAAC,MAAM,CAAC,CAAA;IACrC,2BAA2B,CAAC,MAAM,CAAC,CAAA;IACnC,0BAA0B,CAAC,MAAM,CAAC,CAAA;IAClC,6BAA6B,CAAC,MAAM,CAAC,CAAA;IACrC,6BAA6B,CAAC,MAAM,CAAC,CAAA;IACrC,+BAA+B,CAAC,MAAM,CAAC,CAAA;AACzC,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// `fee_schedule_list` — curated GET /v1/fee-schedules.
|
|
2
|
+
//
|
|
3
|
+
// Cursor-paginated list of the tenant's fee schedules. limit/cursor pass through
|
|
4
|
+
// untouched and matcher's { items, nextCursor, ... } envelope is returned as-is
|
|
5
|
+
// — no auto-pagination (the model re-calls with the returned cursor). The list
|
|
6
|
+
// is implicitly tenant-scoped by the relayed token; no tenant field is accepted.
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import { dispatchFeeSchedule, FEE_SCHEDULES_PATH } from './shared.js';
|
|
9
|
+
/** Zod raw shape for `fee_schedule_list` input — pagination knobs only. */
|
|
10
|
+
export const listFeeSchedulesInputShape = {
|
|
11
|
+
limit: z
|
|
12
|
+
.number()
|
|
13
|
+
.int()
|
|
14
|
+
.min(1)
|
|
15
|
+
.max(200)
|
|
16
|
+
.optional()
|
|
17
|
+
.describe('Maximum number of records to return (1–200, default 20).'),
|
|
18
|
+
cursor: z
|
|
19
|
+
.string()
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Opaque pagination cursor from a prior response. Re-call with the ' +
|
|
22
|
+
"returned nextCursor to page forward (there is no auto-pagination)."),
|
|
23
|
+
};
|
|
24
|
+
/** Build the list query, omitting unset knobs so the request stays minimal. */
|
|
25
|
+
function buildListQuery(args) {
|
|
26
|
+
const query = {};
|
|
27
|
+
if (args.limit !== undefined) {
|
|
28
|
+
query.limit = args.limit;
|
|
29
|
+
}
|
|
30
|
+
if (args.cursor !== undefined) {
|
|
31
|
+
query.cursor = args.cursor;
|
|
32
|
+
}
|
|
33
|
+
return Object.keys(query).length > 0 ? query : undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Register `fee_schedule_list`. Passes limit/cursor through and returns matcher's
|
|
37
|
+
* pagination envelope verbatim; a matcher error surfaces via the shared
|
|
38
|
+
* toToolError.
|
|
39
|
+
*/
|
|
40
|
+
export function registerFeeScheduleListTool(server) {
|
|
41
|
+
server.registerTool('fee_schedule_list', {
|
|
42
|
+
description: "List the fee schedules for your token's tenant (cursor-paginated). Pass " +
|
|
43
|
+
'limit (1–200) and/or cursor; the response carries { items, nextCursor } ' +
|
|
44
|
+
'— paginate by re-calling with the returned nextCursor. No tenant field ' +
|
|
45
|
+
'is accepted; the tenant is derived from your bearer token.',
|
|
46
|
+
inputSchema: listFeeSchedulesInputShape,
|
|
47
|
+
}, async (args, extra) => {
|
|
48
|
+
const query = buildListQuery(args);
|
|
49
|
+
return dispatchFeeSchedule({
|
|
50
|
+
method: 'GET',
|
|
51
|
+
path: FEE_SCHEDULES_PATH,
|
|
52
|
+
...(query !== undefined ? { query } : {}),
|
|
53
|
+
}, extra);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/tools/fee-schedule/list.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AAEjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAErE,2EAA2E;AAC3E,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,0DAA0D,CAAC;IACvE,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,mEAAmE;QACjE,oEAAoE,CACvE;CACJ,CAAA;AAOD,+EAA+E;AAC/E,SAAS,cAAc,CAAC,IAA2B;IACjD,MAAM,KAAK,GAAoC,EAAE,CAAA;IACjD,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;IAC1B,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;IAC5B,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;AAC1D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAiB;IAC3D,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,WAAW,EACT,0EAA0E;YAC1E,0EAA0E;YAC1E,yEAAyE;YACzE,4DAA4D;QAC9D,WAAW,EAAE,0BAA0B;KACxC,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACpB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA;QAClC,OAAO,mBAAmB,CACxB;YACE,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,kBAAkB;YACxB,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC1C,EACD,KAAK,CACN,CAAA;IACH,CAAC,CACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Shared plumbing for the curated fee-schedule tools.
|
|
2
|
+
//
|
|
3
|
+
// Every fee-schedule tool follows the same relay shape: fail-closed auth via
|
|
4
|
+
// requireMatcherClient, dispatch one assembled MatcherRequest, then return
|
|
5
|
+
// matcher's JSON on success or the SHARED toToolError on a MatcherApiError. This
|
|
6
|
+
// module factors that boilerplate exactly once so the six tools stay thin (just
|
|
7
|
+
// "build the request") and so curated + generic surfaces map matcher errors
|
|
8
|
+
// through the identical path (toToolError) — the whole point of task 1.3.2.
|
|
9
|
+
//
|
|
10
|
+
// Security: the bearer token is never read here directly — requireMatcherClient
|
|
11
|
+
// owns the request-scoped relay and fails closed when no usable credential was
|
|
12
|
+
// provided. No tenant identifier is ever read or injected (matcher derives
|
|
13
|
+
// tenant from the relayed JWT); no fee-schedule tool input carries one.
|
|
14
|
+
import { requireMatcherClient, UnauthenticatedError, } from '../../auth/request-token.js';
|
|
15
|
+
import { isMatcherApiError, toToolError } from '../tool-error.js';
|
|
16
|
+
/** Base path for the fee-schedule resource (tenant-scoped; tenant from the token). */
|
|
17
|
+
export const FEE_SCHEDULES_PATH = '/v1/fee-schedules';
|
|
18
|
+
/** Build the single-schedule sub-path, URL-encoding the id so reserved chars are safe. */
|
|
19
|
+
export function feeSchedulePath(scheduleId) {
|
|
20
|
+
return `${FEE_SCHEDULES_PATH}/${encodeURIComponent(scheduleId)}`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Run one assembled request through the relay: fail-closed auth, dispatch, and
|
|
24
|
+
* RFC 9457 → tool-error mapping — identical to the generic invoke's dispatch so
|
|
25
|
+
* both surfaces produce the same structured error shape.
|
|
26
|
+
*
|
|
27
|
+
* `clientFor` is injectable for tests; production callers pass nothing and get
|
|
28
|
+
* the request-scoped, fail-closed `requireMatcherClient`.
|
|
29
|
+
*/
|
|
30
|
+
export async function dispatchFeeSchedule(request, extra, clientFor = requireMatcherClient) {
|
|
31
|
+
let client;
|
|
32
|
+
try {
|
|
33
|
+
// Fail-closed on a missing / empty / non-Bearer credential.
|
|
34
|
+
client = clientFor(extra);
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err instanceof UnauthenticatedError) {
|
|
38
|
+
return { isError: true, content: [{ type: 'text', text: err.message }] };
|
|
39
|
+
}
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const result = await client.request(request);
|
|
44
|
+
// Success → matcher's JSON returned as-is (incl. pagination envelopes and
|
|
45
|
+
// 204 → null for delete).
|
|
46
|
+
return { content: [{ type: 'text', text: JSON.stringify(result ?? null) }] };
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
// RFC 9457 problem → the SHARED structured tool error (status/title/detail/
|
|
50
|
+
// code preserved). A non-matcher error is a bug, not a matcher failure, and
|
|
51
|
+
// is re-thrown rather than masqueraded as one.
|
|
52
|
+
if (isMatcherApiError(err)) {
|
|
53
|
+
return toToolError(err);
|
|
54
|
+
}
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../src/tools/fee-schedule/shared.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,iFAAiF;AACjF,gFAAgF;AAChF,4EAA4E;AAC5E,4EAA4E;AAC5E,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,2EAA2E;AAC3E,wEAAwE;AAIxE,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GAErB,MAAM,6BAA6B,CAAA;AAEpC,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEjE,sFAAsF;AACtF,MAAM,CAAC,MAAM,kBAAkB,GAAG,mBAAmB,CAAA;AAErD,0FAA0F;AAC1F,MAAM,UAAU,eAAe,CAAC,UAAkB;IAChD,OAAO,GAAG,kBAAkB,IAAI,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAA;AAClE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAAuB,EACvB,KAAmC,EACnC,YAAyD,oBAAoB;IAE7E,IAAI,MAAqB,CAAA;IACzB,IAAI,CAAC;QACH,4DAA4D;QAC5D,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,oBAAoB,EAAE,CAAC;YACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,CAAA;QAC1E,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC5C,0EAA0E;QAC1E,0BAA0B;QAC1B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,CAAC,EAAE,CAAA;IAC9E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,4EAA4E;QAC5E,4EAA4E;QAC5E,+CAA+C;QAC/C,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,WAAW,CAAC,GAAG,CAAC,CAAA;QACzB,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// `fee_schedule_simulate` — curated POST /v1/fee-schedules/{scheduleId}/simulate.
|
|
2
|
+
//
|
|
3
|
+
// Calculates the fees a given gross amount would incur under a specific fee
|
|
4
|
+
// schedule, without persisting anything. Mirrors the spec's SimulateFeeRequest
|
|
5
|
+
// (grossAmount + currency, both required). Amounts are decimal STRINGS to avoid
|
|
6
|
+
// float precision loss. scheduleId is a UUID path param; no tenant field is
|
|
7
|
+
// accepted (matcher scopes to the relayed token's tenant).
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { dispatchFeeSchedule, feeSchedulePath } from './shared.js';
|
|
10
|
+
/** Zod raw shape for `fee_schedule_simulate` input — id (path) + body fields. */
|
|
11
|
+
export const simulateFeeScheduleInputShape = {
|
|
12
|
+
scheduleId: z
|
|
13
|
+
.string()
|
|
14
|
+
.min(1)
|
|
15
|
+
.describe('The fee schedule id (UUID) to simulate against.'),
|
|
16
|
+
grossAmount: z
|
|
17
|
+
.string()
|
|
18
|
+
.describe('Gross amount to simulate fees against, as a decimal STRING in the given ' +
|
|
19
|
+
'currency, e.g. "100.00" (a string, not a number, to preserve precision).'),
|
|
20
|
+
currency: z
|
|
21
|
+
.string()
|
|
22
|
+
.describe('ISO 4217 currency code of the gross amount, e.g. "USD".'),
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Build the simulate POST body from the input minus the path-only `scheduleId`.
|
|
26
|
+
*/
|
|
27
|
+
export function buildSimulateBody(args) {
|
|
28
|
+
const { scheduleId: _scheduleId, ...body } = args;
|
|
29
|
+
void _scheduleId;
|
|
30
|
+
return body;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Register `fee_schedule_simulate`. Splits the id (path) from the body, dispatches
|
|
34
|
+
* a POST to the schedule's /simulate sub-path through the shared fail-closed
|
|
35
|
+
* relay, and returns the { grossAmount, netAmount, totalFee, currency, items }
|
|
36
|
+
* breakdown; a matcher error surfaces via the shared toToolError.
|
|
37
|
+
*/
|
|
38
|
+
export function registerFeeScheduleSimulateTool(server) {
|
|
39
|
+
server.registerTool('fee_schedule_simulate', {
|
|
40
|
+
description: 'Simulate fee calculation for a gross amount under a specific fee ' +
|
|
41
|
+
'schedule (by id, UUID) — a dry run, nothing is persisted. Provide ' +
|
|
42
|
+
'grossAmount (decimal string, e.g. "100.00") and currency (ISO 4217). ' +
|
|
43
|
+
'Returns the per-item breakdown plus totalFee and netAmount. No tenant ' +
|
|
44
|
+
'field is accepted. Errors surface as structured RFC 9457 problems.',
|
|
45
|
+
inputSchema: simulateFeeScheduleInputShape,
|
|
46
|
+
}, async (args, extra) => {
|
|
47
|
+
return dispatchFeeSchedule({
|
|
48
|
+
method: 'POST',
|
|
49
|
+
path: `${feeSchedulePath(args.scheduleId)}/simulate`,
|
|
50
|
+
body: buildSimulateBody(args),
|
|
51
|
+
}, extra);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=simulate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simulate.js","sourceRoot":"","sources":["../../../src/tools/fee-schedule/simulate.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,EAAE;AACF,4EAA4E;AAC5E,+EAA+E;AAC/E,gFAAgF;AAChF,4EAA4E;AAC5E,2DAA2D;AAE3D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElE,iFAAiF;AACjF,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,UAAU,EAAE,CAAC;SACV,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,CAAC,iDAAiD,CAAC;IAC9D,WAAW,EAAE,CAAC;SACX,MAAM,EAAE;SACR,QAAQ,CACP,0EAA0E;QACxE,0EAA0E,CAC7E;IACH,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,CAAC,yDAAyD,CAAC;CACvE,CAAA;AAOD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAA8B;IAE9B,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAA;IACjD,KAAK,WAAW,CAAA;IAChB,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,+BAA+B,CAAC,MAAiB;IAC/D,MAAM,CAAC,YAAY,CACjB,uBAAuB,EACvB;QACE,WAAW,EACT,mEAAmE;YACnE,oEAAoE;YACpE,uEAAuE;YACvE,wEAAwE;YACxE,oEAAoE;QACtE,WAAW,EAAE,6BAA6B;KAC3C,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACpB,OAAO,mBAAmB,CACxB;YACE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,GAAG,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW;YACpD,IAAI,EAAE,iBAAiB,CAAC,IAAI,CAAC;SAC9B,EACD,KAAK,CACN,CAAA;IACH,CAAC,CACF,CAAA;AACH,CAAC"}
|