@lerianstudio/matcher-mcp 5.0.0-beta.8 → 5.0.0-beta.80
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 +28 -13
- package/dist/auth/request-token.js +11 -69
- package/dist/auth/request-token.js.map +1 -1
- package/dist/config.js +6 -21
- package/dist/config.js.map +1 -1
- package/dist/copilot/agent.js +5 -9
- package/dist/copilot/agent.js.map +1 -1
- package/dist/copilot/provider-anthropic.js +75 -23
- package/dist/copilot/provider-anthropic.js.map +1 -1
- package/dist/copilot/provider-openrouter.js +5 -18
- package/dist/copilot/provider-openrouter.js.map +1 -1
- package/dist/copilot/provider-shared.js +11 -0
- package/dist/copilot/provider-shared.js.map +1 -1
- package/dist/copilot/speech-provider.js +84 -0
- package/dist/copilot/speech-provider.js.map +1 -0
- package/dist/copilot/sse.js +5 -0
- package/dist/copilot/sse.js.map +1 -1
- package/dist/copilot/tools.js +14 -65
- package/dist/copilot/tools.js.map +1 -1
- package/dist/copilot/transcribe-handler.js +8 -93
- package/dist/copilot/transcribe-handler.js.map +1 -1
- package/dist/copilot/turn-request.js +76 -0
- package/dist/copilot/turn-request.js.map +1 -0
- package/dist/copilot/turns-handler.js +11 -102
- package/dist/copilot/turns-handler.js.map +1 -1
- package/dist/matcher/client.js +14 -0
- package/dist/matcher/client.js.map +1 -1
- package/dist/matcher/idempotency.js +94 -0
- package/dist/matcher/idempotency.js.map +1 -0
- package/dist/observability/otel.js +7 -29
- package/dist/observability/otel.js.map +1 -1
- package/dist/server.js +12 -81
- package/dist/server.js.map +1 -1
- package/dist/spec/curated-operations.js +111 -95
- package/dist/spec/curated-operations.js.map +1 -1
- package/dist/spec/enum-policy.js +21 -26
- package/dist/spec/enum-policy.js.map +1 -1
- package/dist/spec/openapi.yaml +841 -56
- package/dist/spec/schema-parity.js +23 -28
- package/dist/spec/schema-parity.js.map +1 -1
- package/dist/tools/context/create.js +3 -2
- package/dist/tools/context/create.js.map +1 -1
- package/dist/tools/context/index.js +137 -17
- package/dist/tools/context/index.js.map +1 -1
- package/dist/tools/context/list.js +9 -35
- package/dist/tools/context/list.js.map +1 -1
- package/dist/tools/context/setup-progress.js +3 -2
- package/dist/tools/context/setup-progress.js.map +1 -1
- package/dist/tools/context/shared.js +7 -48
- package/dist/tools/context/shared.js.map +1 -1
- package/dist/tools/context/update.js +5 -5
- package/dist/tools/context/update.js.map +1 -1
- package/dist/tools/curated-tool.js +39 -0
- package/dist/tools/curated-tool.js.map +1 -0
- package/dist/tools/dashboard/index.js +124 -19
- package/dist/tools/dashboard/index.js.map +1 -1
- package/dist/tools/dashboard/shared.js +9 -68
- package/dist/tools/dashboard/shared.js.map +1 -1
- package/dist/tools/dispute/close.js +5 -5
- package/dist/tools/dispute/close.js.map +1 -1
- package/dist/tools/dispute/index.js +34 -6
- package/dist/tools/dispute/index.js.map +1 -1
- package/dist/tools/dispute/list.js +18 -47
- package/dist/tools/dispute/list.js.map +1 -1
- package/dist/tools/dispute/shared.js +4 -43
- package/dist/tools/dispute/shared.js.map +1 -1
- package/dist/tools/dispute/submit-evidence.js +5 -5
- package/dist/tools/dispute/submit-evidence.js.map +1 -1
- package/dist/tools/exception/add-comment.js +3 -2
- package/dist/tools/exception/add-comment.js.map +1 -1
- package/dist/tools/exception/adjust-entry.js +5 -5
- package/dist/tools/exception/adjust-entry.js.map +1 -1
- package/dist/tools/exception/bulk-assign.js +3 -2
- package/dist/tools/exception/bulk-assign.js.map +1 -1
- package/dist/tools/exception/bulk-dispatch.js +12 -4
- package/dist/tools/exception/bulk-dispatch.js.map +1 -1
- package/dist/tools/exception/bulk-resolve.js +3 -2
- package/dist/tools/exception/bulk-resolve.js.map +1 -1
- package/dist/tools/exception/dispatch.js +13 -5
- package/dist/tools/exception/dispatch.js.map +1 -1
- package/dist/tools/exception/force-match.js +3 -2
- package/dist/tools/exception/force-match.js.map +1 -1
- package/dist/tools/exception/history.js +8 -24
- package/dist/tools/exception/history.js.map +1 -1
- package/dist/tools/exception/index.js +88 -18
- package/dist/tools/exception/index.js.map +1 -1
- package/dist/tools/exception/list.js +14 -57
- package/dist/tools/exception/list.js.map +1 -1
- package/dist/tools/exception/open-dispute.js +3 -2
- package/dist/tools/exception/open-dispute.js.map +1 -1
- package/dist/tools/exception/shared.js +10 -46
- package/dist/tools/exception/shared.js.map +1 -1
- package/dist/tools/fee-rule/create.js +5 -5
- package/dist/tools/fee-rule/create.js.map +1 -1
- package/dist/tools/fee-rule/index.js +50 -8
- package/dist/tools/fee-rule/index.js.map +1 -1
- package/dist/tools/fee-rule/list.js +9 -29
- package/dist/tools/fee-rule/list.js.map +1 -1
- package/dist/tools/fee-rule/shared.js +5 -47
- package/dist/tools/fee-rule/shared.js.map +1 -1
- package/dist/tools/fee-rule/update.js +5 -5
- package/dist/tools/fee-rule/update.js.map +1 -1
- package/dist/tools/fee-schedule/create.js +8 -3
- package/dist/tools/fee-schedule/create.js.map +1 -1
- package/dist/tools/fee-schedule/index.js +62 -11
- package/dist/tools/fee-schedule/index.js.map +1 -1
- package/dist/tools/fee-schedule/list.js +8 -24
- package/dist/tools/fee-schedule/list.js.map +1 -1
- package/dist/tools/fee-schedule/shared.js +5 -44
- package/dist/tools/fee-schedule/shared.js.map +1 -1
- package/dist/tools/fee-schedule/simulate.js +5 -5
- package/dist/tools/fee-schedule/simulate.js.map +1 -1
- package/dist/tools/fee-schedule/update.js +5 -5
- package/dist/tools/fee-schedule/update.js.map +1 -1
- package/dist/tools/field-map/create.js +3 -2
- package/dist/tools/field-map/create.js.map +1 -1
- package/dist/tools/field-map/index.js +65 -11
- package/dist/tools/field-map/index.js.map +1 -1
- package/dist/tools/field-map/list.js +9 -29
- package/dist/tools/field-map/list.js.map +1 -1
- package/dist/tools/field-map/shared.js +6 -42
- package/dist/tools/field-map/shared.js.map +1 -1
- package/dist/tools/field-map/update.js +3 -2
- package/dist/tools/field-map/update.js.map +1 -1
- package/dist/tools/generic/invoke.js +16 -39
- package/dist/tools/generic/invoke.js.map +1 -1
- package/dist/tools/ingestion/index.js +100 -12
- package/dist/tools/ingestion/index.js.map +1 -1
- package/dist/tools/ingestion/job-transactions-list.js +10 -40
- package/dist/tools/ingestion/job-transactions-list.js.map +1 -1
- package/dist/tools/ingestion/jobs-list.js +9 -35
- package/dist/tools/ingestion/jobs-list.js.map +1 -1
- package/dist/tools/ingestion/shared.js +4 -41
- package/dist/tools/ingestion/shared.js.map +1 -1
- package/dist/tools/ingestion/transactions-search.js +9 -44
- package/dist/tools/ingestion/transactions-search.js.map +1 -1
- package/dist/tools/ingestion/upload-begin.js +5 -2
- package/dist/tools/ingestion/upload-begin.js.map +1 -1
- package/dist/tools/ingestion/upload.js +3 -2
- package/dist/tools/ingestion/upload.js.map +1 -1
- package/dist/tools/input-fields.js +51 -0
- package/dist/tools/input-fields.js.map +1 -0
- package/dist/tools/match-rule/index.js +130 -13
- package/dist/tools/match-rule/index.js.map +1 -1
- package/dist/tools/match-rule/list.js +9 -33
- package/dist/tools/match-rule/list.js.map +1 -1
- package/dist/tools/match-rule/shared.js +16 -46
- package/dist/tools/match-rule/shared.js.map +1 -1
- package/dist/tools/match-rule/update.js +7 -11
- package/dist/tools/match-rule/update.js.map +1 -1
- package/dist/tools/matching/get.js +5 -5
- package/dist/tools/matching/get.js.map +1 -1
- package/dist/tools/matching/groups.js +6 -14
- package/dist/tools/matching/groups.js.map +1 -1
- package/dist/tools/matching/index.js +77 -5
- package/dist/tools/matching/index.js.map +1 -1
- package/dist/tools/matching/list.js +9 -32
- package/dist/tools/matching/list.js.map +1 -1
- package/dist/tools/matching/shared.js +5 -46
- package/dist/tools/matching/shared.js.map +1 -1
- package/dist/tools/query-handler.js +9 -0
- package/dist/tools/query-handler.js.map +1 -0
- package/dist/tools/report/index.js +260 -30
- package/dist/tools/report/index.js.map +1 -1
- package/dist/tools/report/shared.js +24 -98
- package/dist/tools/report/shared.js.map +1 -1
- package/dist/tools/request-fields.js +17 -0
- package/dist/tools/request-fields.js.map +1 -0
- package/dist/tools/shared-dispatch.js +38 -0
- package/dist/tools/shared-dispatch.js.map +1 -0
- package/dist/tools/source/create.js +146 -23
- package/dist/tools/source/create.js.map +1 -1
- package/dist/tools/source/index.js +101 -13
- package/dist/tools/source/index.js.map +1 -1
- package/dist/tools/source/list.js +9 -32
- package/dist/tools/source/list.js.map +1 -1
- package/dist/tools/source/shared.js +5 -42
- package/dist/tools/source/shared.js.map +1 -1
- package/dist/tools/source/update.js +16 -33
- package/dist/tools/source/update.js.map +1 -1
- package/dist/tools/workspace/usage.js +12 -40
- package/dist/tools/workspace/usage.js.map +1 -1
- package/package.json +4 -4
- package/dist/tools/context/archive.js +0 -37
- package/dist/tools/context/archive.js.map +0 -1
- package/dist/tools/context/get.js +0 -31
- package/dist/tools/context/get.js.map +0 -1
- package/dist/tools/context/next-step.js +0 -99
- package/dist/tools/context/next-step.js.map +0 -1
- package/dist/tools/context/restore.js +0 -34
- package/dist/tools/context/restore.js.map +0 -1
- package/dist/tools/dashboard/aggregates.js +0 -37
- package/dist/tools/dashboard/aggregates.js.map +0 -1
- package/dist/tools/dashboard/cash-impact.js +0 -37
- package/dist/tools/dashboard/cash-impact.js.map +0 -1
- package/dist/tools/dashboard/match-rate.js +0 -37
- package/dist/tools/dashboard/match-rate.js.map +0 -1
- package/dist/tools/dashboard/metrics.js +0 -37
- package/dist/tools/dashboard/metrics.js.map +0 -1
- package/dist/tools/dashboard/sla.js +0 -34
- package/dist/tools/dashboard/sla.js.map +0 -1
- package/dist/tools/dashboard/source-breakdown.js +0 -37
- package/dist/tools/dashboard/source-breakdown.js.map +0 -1
- package/dist/tools/dashboard/volume.js +0 -37
- package/dist/tools/dashboard/volume.js.map +0 -1
- package/dist/tools/dispute/get.js +0 -27
- package/dist/tools/dispute/get.js.map +0 -1
- package/dist/tools/exception/delete-comment.js +0 -40
- package/dist/tools/exception/delete-comment.js.map +0 -1
- package/dist/tools/exception/get.js +0 -34
- package/dist/tools/exception/get.js.map +0 -1
- package/dist/tools/exception/list-comments.js +0 -35
- package/dist/tools/exception/list-comments.js.map +0 -1
- package/dist/tools/fee-rule/delete.js +0 -27
- package/dist/tools/fee-rule/delete.js.map +0 -1
- package/dist/tools/fee-rule/get.js +0 -27
- package/dist/tools/fee-rule/get.js.map +0 -1
- package/dist/tools/fee-schedule/delete.js +0 -32
- package/dist/tools/fee-schedule/delete.js.map +0 -1
- package/dist/tools/fee-schedule/get.js +0 -30
- package/dist/tools/fee-schedule/get.js.map +0 -1
- package/dist/tools/field-map/delete.js +0 -37
- package/dist/tools/field-map/delete.js.map +0 -1
- package/dist/tools/field-map/get.js +0 -43
- package/dist/tools/field-map/get.js.map +0 -1
- package/dist/tools/ingestion/job-errors-list.js +0 -45
- package/dist/tools/ingestion/job-errors-list.js.map +0 -1
- package/dist/tools/ingestion/job-get.js +0 -42
- package/dist/tools/ingestion/job-get.js.map +0 -1
- package/dist/tools/ingestion/transaction-ignore.js +0 -51
- package/dist/tools/ingestion/transaction-ignore.js.map +0 -1
- package/dist/tools/match-rule/create.js +0 -67
- package/dist/tools/match-rule/create.js.map +0 -1
- package/dist/tools/match-rule/delete.js +0 -35
- package/dist/tools/match-rule/delete.js.map +0 -1
- package/dist/tools/match-rule/get.js +0 -32
- package/dist/tools/match-rule/get.js.map +0 -1
- package/dist/tools/match-rule/reorder.js +0 -45
- package/dist/tools/match-rule/reorder.js.map +0 -1
- package/dist/tools/matching/start.js +0 -81
- package/dist/tools/matching/start.js.map +0 -1
- package/dist/tools/report/count-exceptions.js +0 -46
- package/dist/tools/report/count-exceptions.js.map +0 -1
- package/dist/tools/report/count-matched.js +0 -47
- package/dist/tools/report/count-matched.js.map +0 -1
- package/dist/tools/report/count-transactions.js +0 -45
- package/dist/tools/report/count-transactions.js.map +0 -1
- package/dist/tools/report/count-unmatched.js +0 -45
- package/dist/tools/report/count-unmatched.js.map +0 -1
- package/dist/tools/report/export-exceptions.js +0 -48
- package/dist/tools/report/export-exceptions.js.map +0 -1
- package/dist/tools/report/export-matched.js +0 -49
- package/dist/tools/report/export-matched.js.map +0 -1
- package/dist/tools/report/export-summary.js +0 -49
- package/dist/tools/report/export-summary.js.map +0 -1
- package/dist/tools/report/export-unmatched.js +0 -49
- package/dist/tools/report/export-unmatched.js.map +0 -1
- package/dist/tools/report/export-variance.js +0 -48
- package/dist/tools/report/export-variance.js.map +0 -1
- package/dist/tools/report/matched.js +0 -48
- package/dist/tools/report/matched.js.map +0 -1
- package/dist/tools/report/summary.js +0 -43
- package/dist/tools/report/summary.js.map +0 -1
- package/dist/tools/report/unmatched.js +0 -48
- package/dist/tools/report/unmatched.js.map +0 -1
- package/dist/tools/report/variance.js +0 -48
- package/dist/tools/report/variance.js.map +0 -1
- package/dist/tools/source/archive.js +0 -46
- package/dist/tools/source/archive.js.map +0 -1
- package/dist/tools/source/get.js +0 -57
- package/dist/tools/source/get.js.map +0 -1
- package/dist/tools/source/restore.js +0 -39
- package/dist/tools/source/restore.js.map +0 -1
|
@@ -22,10 +22,11 @@ import { BodyTooLargeError, readBody } from '../transport/body-limit.js';
|
|
|
22
22
|
import { runAgentTurn } from './agent.js';
|
|
23
23
|
import { CopilotUnconfiguredError, getProvider } from './provider-factory.js';
|
|
24
24
|
import { RateLimiter } from './rate-limit.js';
|
|
25
|
-
import { createSseSink } from './sse.js';
|
|
25
|
+
import { createSseSink, finishWithError } from './sse.js';
|
|
26
26
|
import { buildSystemPrompt } from './system-prompt.js';
|
|
27
27
|
import { resolveCopilotConfig } from './tenant-config.js';
|
|
28
28
|
import { getIndex, getToolDefs } from './tools.js';
|
|
29
|
+
import { buildTurnMessages, parseAgentTurnRequest } from './turn-request.js';
|
|
29
30
|
/**
|
|
30
31
|
* Process-lifetime rate limiter shared across turns. Buckets are keyed on the
|
|
31
32
|
* key-only tenant id; a turn with no decodable tenant shares one bucket under
|
|
@@ -110,81 +111,6 @@ export async function probeMatcherAuth(client) {
|
|
|
110
111
|
}
|
|
111
112
|
return true;
|
|
112
113
|
}
|
|
113
|
-
/**
|
|
114
|
-
* The messages the agent loop receives. Browser-supplied `screenContext` is
|
|
115
|
-
* injected as a synthetic FIRST user message — the SAME (untrusted) trust tier as
|
|
116
|
-
* the operator's own input — rather than folded into the system prompt, so a
|
|
117
|
-
* crafted route/summary can never reach the higher-trust system tier. The label
|
|
118
|
-
* is a plain statement of fact, not an instruction.
|
|
119
|
-
*/
|
|
120
|
-
function buildTurnMessages(request) {
|
|
121
|
-
const { screenContext } = request;
|
|
122
|
-
if (screenContext === undefined) {
|
|
123
|
-
return request.messages;
|
|
124
|
-
}
|
|
125
|
-
const parts = [`route ${screenContext.route}`];
|
|
126
|
-
if (screenContext.contextId !== undefined) {
|
|
127
|
-
parts.push(`reconciliation context ${screenContext.contextId}`);
|
|
128
|
-
}
|
|
129
|
-
if (screenContext.summary !== undefined) {
|
|
130
|
-
parts.push(screenContext.summary);
|
|
131
|
-
}
|
|
132
|
-
return [
|
|
133
|
-
{
|
|
134
|
-
role: 'user',
|
|
135
|
-
content: `[screen context] The operator is currently viewing: ${parts.join(' — ')}.`,
|
|
136
|
-
},
|
|
137
|
-
...request.messages,
|
|
138
|
-
];
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Validate an unknown parsed body as an `AgentTurnRequest`. Returns the typed
|
|
142
|
-
* request on success, or `undefined` when the shape is wrong (non-empty
|
|
143
|
-
* `messages` of `{role,content}` with role in {user,assistant}). A malformed
|
|
144
|
-
* `screenContext` is dropped rather than rejecting the turn.
|
|
145
|
-
*/
|
|
146
|
-
function parseAgentTurnRequest(body) {
|
|
147
|
-
if (typeof body !== 'object' || body === null) {
|
|
148
|
-
return undefined;
|
|
149
|
-
}
|
|
150
|
-
const record = body;
|
|
151
|
-
const { messages } = record;
|
|
152
|
-
if (!Array.isArray(messages) || messages.length === 0) {
|
|
153
|
-
return undefined;
|
|
154
|
-
}
|
|
155
|
-
for (const message of messages) {
|
|
156
|
-
if (typeof message !== 'object' || message === null) {
|
|
157
|
-
return undefined;
|
|
158
|
-
}
|
|
159
|
-
const { role, content } = message;
|
|
160
|
-
if (role !== 'user' && role !== 'assistant') {
|
|
161
|
-
return undefined;
|
|
162
|
-
}
|
|
163
|
-
if (typeof content !== 'string') {
|
|
164
|
-
return undefined;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
const screenContext = parseScreenContext(record.screenContext);
|
|
168
|
-
return {
|
|
169
|
-
messages: messages,
|
|
170
|
-
...(screenContext !== undefined ? { screenContext } : {}),
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
/** Parse an optional `screenContext`; drops it unless it carries a string `route`. */
|
|
174
|
-
function parseScreenContext(raw) {
|
|
175
|
-
if (typeof raw !== 'object' || raw === null) {
|
|
176
|
-
return undefined;
|
|
177
|
-
}
|
|
178
|
-
const record = raw;
|
|
179
|
-
if (typeof record.route !== 'string') {
|
|
180
|
-
return undefined;
|
|
181
|
-
}
|
|
182
|
-
return {
|
|
183
|
-
route: record.route,
|
|
184
|
-
...(typeof record.contextId === 'string' ? { contextId: record.contextId } : {}),
|
|
185
|
-
...(typeof record.summary === 'string' ? { summary: record.summary } : {}),
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
114
|
/**
|
|
189
115
|
* Handle one `POST /agent/turns` request, streaming the turn over SSE. Resolves
|
|
190
116
|
* once the turn is fully written (a terminal `done` has been emitted). Does not
|
|
@@ -206,17 +132,13 @@ export async function handleAgentTurn(config, req, res, deps = {}) {
|
|
|
206
132
|
}
|
|
207
133
|
catch (err) {
|
|
208
134
|
if (err instanceof UnauthenticatedError) {
|
|
209
|
-
sink
|
|
210
|
-
sink.done('end');
|
|
211
|
-
return;
|
|
135
|
+
return finishWithError(sink, 'unauthenticated', err.message);
|
|
212
136
|
}
|
|
213
137
|
throw err;
|
|
214
138
|
}
|
|
215
139
|
const contentType = (req.headers['content-type'] ?? '').toLowerCase();
|
|
216
140
|
if (!contentType.includes('application/json')) {
|
|
217
|
-
sink
|
|
218
|
-
sink.done('end');
|
|
219
|
-
return;
|
|
141
|
+
return finishWithError(sink, 'bad_request', 'content-type must be application/json');
|
|
220
142
|
}
|
|
221
143
|
let body;
|
|
222
144
|
try {
|
|
@@ -225,20 +147,14 @@ export async function handleAgentTurn(config, req, res, deps = {}) {
|
|
|
225
147
|
}
|
|
226
148
|
catch (err) {
|
|
227
149
|
if (err instanceof BodyTooLargeError) {
|
|
228
|
-
sink
|
|
229
|
-
sink.done('end');
|
|
230
|
-
return;
|
|
150
|
+
return finishWithError(sink, 'payload_too_large', 'request body is too large');
|
|
231
151
|
}
|
|
232
152
|
// JSON parse failure or a read error — a client fault, no internal detail.
|
|
233
|
-
sink
|
|
234
|
-
sink.done('end');
|
|
235
|
-
return;
|
|
153
|
+
return finishWithError(sink, 'bad_request', 'request body is not valid JSON');
|
|
236
154
|
}
|
|
237
155
|
const request = parseAgentTurnRequest(body);
|
|
238
156
|
if (request === undefined) {
|
|
239
|
-
sink
|
|
240
|
-
sink.done('end');
|
|
241
|
-
return;
|
|
157
|
+
return finishWithError(sink, 'bad_request', 'messages must be a non-empty array of {role,content}, role one of user|assistant');
|
|
242
158
|
}
|
|
243
159
|
// Probe matcher's `Authorize` with the relayed token BEFORE any tenant-derived
|
|
244
160
|
// work AND before constructing the paid provider (M1): a JWT-shaped-but-
|
|
@@ -249,9 +165,7 @@ export async function handleAgentTurn(config, req, res, deps = {}) {
|
|
|
249
165
|
// `requireMatcherClient`. A fresh cached verdict (keyed by token hash) skips the
|
|
250
166
|
// probe entirely.
|
|
251
167
|
if (!(await probeMatcherAuth(matcherClient))) {
|
|
252
|
-
sink
|
|
253
|
-
sink.done('end');
|
|
254
|
-
return;
|
|
168
|
+
return finishWithError(sink, 'unauthenticated', PROBE_REJECTED_REMEDIATION);
|
|
255
169
|
}
|
|
256
170
|
// Resolve the per-tenant config slice from the key-only tenant id decoded off
|
|
257
171
|
// the relayed JWT (getRequestTenantId). The token is already matcher-verified by
|
|
@@ -270,9 +184,7 @@ export async function handleAgentTurn(config, req, res, deps = {}) {
|
|
|
270
184
|
// forged token is rejected as `unauthenticated` before it can touch a bucket.
|
|
271
185
|
const decision = (deps.rateLimiter ?? turnRateLimiter).check(tenantId ?? RATE_LIMIT_ANON_KEY, resolvedConfig.copilotRateLimitPerMin, resolvedConfig.copilotRateLimitBurst);
|
|
272
186
|
if (!decision.allowed) {
|
|
273
|
-
sink
|
|
274
|
-
sink.done('end');
|
|
275
|
-
return;
|
|
187
|
+
return finishWithError(sink, 'rate_limited', `too many copilot requests; retry in ${decision.retryAfterSeconds}s`);
|
|
276
188
|
}
|
|
277
189
|
let provider;
|
|
278
190
|
try {
|
|
@@ -280,9 +192,7 @@ export async function handleAgentTurn(config, req, res, deps = {}) {
|
|
|
280
192
|
}
|
|
281
193
|
catch (err) {
|
|
282
194
|
if (err instanceof CopilotUnconfiguredError) {
|
|
283
|
-
sink
|
|
284
|
-
sink.done('end');
|
|
285
|
-
return;
|
|
195
|
+
return finishWithError(sink, 'copilot_unconfigured', 'the copilot is not configured on this server');
|
|
286
196
|
}
|
|
287
197
|
throw err;
|
|
288
198
|
}
|
|
@@ -313,8 +223,7 @@ export async function handleAgentTurn(config, req, res, deps = {}) {
|
|
|
313
223
|
}
|
|
314
224
|
catch (err) {
|
|
315
225
|
// Last-resort guard: a single safe SSE error + done, never a token or stack.
|
|
316
|
-
sink
|
|
317
|
-
sink.done('end');
|
|
226
|
+
finishWithError(sink, 'internal', 'the copilot encountered an internal error');
|
|
318
227
|
// Log only the message string, never the raw error object — a provider-SDK
|
|
319
228
|
// error can carry request context (headers, config) we must not log wholesale.
|
|
320
229
|
console.error('matcher-mcp agent turn failed:', err instanceof Error ? err.message : String(err));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turns-handler.js","sourceRoot":"","sources":["../../src/copilot/turns-handler.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,EAAE;AACF,0EAA0E;AAC1E,gFAAgF;AAChF,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,iFAAiF;AACjF,kBAAkB;AAClB,iFAAiF;AACjF,kFAAkF;AAClF,mFAAmF;AACnF,EAAE;AACF,8EAA8E;AAC9E,kFAAkF;AAClF,iFAAiF;AACjF,8EAA8E;AAE9E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,eAAe,EAA2C,MAAM,sBAAsB,CAAA;AAE/F,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AACxE,OAAO,EAAE,YAAY,EAA4B,MAAM,YAAY,CAAA;AACnE,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAE7E,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"turns-handler.js","sourceRoot":"","sources":["../../src/copilot/turns-handler.ts"],"names":[],"mappings":"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"}
|
package/dist/matcher/client.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
// fetch/abort error — so error handling upstream is uniform.
|
|
15
15
|
import { loadConfig } from '../config.js';
|
|
16
16
|
import { injectTraceContext } from '../observability/otel.js';
|
|
17
|
+
import { deriveDispatchIdempotencyKey, isDispatchPath, } from './idempotency.js';
|
|
17
18
|
/** Thrown by `MatcherClient.request` on any matcher status >= 400 (or transport failure). */
|
|
18
19
|
export class MatcherApiError extends Error {
|
|
19
20
|
/** HTTP status from matcher (synthetic, e.g. 504, for transport failures). */
|
|
@@ -122,6 +123,19 @@ export function createMatcherClient(baseUrl, bearerToken) {
|
|
|
122
123
|
// NOT set content-type and must NOT JSON.stringify. Every other body
|
|
123
124
|
// (the overwhelming majority of requests) keeps the existing JSON path.
|
|
124
125
|
const isFormData = req.body instanceof FormData;
|
|
126
|
+
// A dispatch is the one request whose side effect lands outside matcher, so
|
|
127
|
+
// it is never sent unkeyed: without a key the model's retry after a relay
|
|
128
|
+
// timeout opens a second ticket. The caller's own key always wins — that is
|
|
129
|
+
// how a DELIBERATE second dispatch gets through. Every other route stays
|
|
130
|
+
// opt-in and unkeyed. FormData is excluded because a dispatch body is JSON
|
|
131
|
+
// by contract and a multipart body has no canonical digest form here.
|
|
132
|
+
const idempotencyKey = req.idempotencyKey ??
|
|
133
|
+
(req.method === 'POST' && isDispatchPath(req.path) && !isFormData
|
|
134
|
+
? deriveDispatchIdempotencyKey(req.path, req.body)
|
|
135
|
+
: undefined);
|
|
136
|
+
if (idempotencyKey !== undefined) {
|
|
137
|
+
headers['x-idempotency-key'] = idempotencyKey;
|
|
138
|
+
}
|
|
125
139
|
let outgoingBody;
|
|
126
140
|
if (isFormData) {
|
|
127
141
|
outgoingBody = req.body;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/matcher/client.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,mDAAmD;AACnD,EAAE;AACF,kFAAkF;AAClF,4EAA4E;AAC5E,gFAAgF;AAChF,2DAA2D;AAC3D,EAAE;AACF,2CAA2C;AAC3C,6EAA6E;AAC7E,+DAA+D;AAC/D,kFAAkF;AAClF,gFAAgF;AAChF,iEAAiE;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/matcher/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Idempotency keys for the requests the relay must never send twice.
|
|
2
|
+
//
|
|
3
|
+
// WHY THIS IS IN THE TRANSPORT LAYER
|
|
4
|
+
// Matcher's idempotency is opt-in on `X-Idempotency-Key`, so an unkeyed request
|
|
5
|
+
// is a request nobody can deduplicate. The relay aborts on its own
|
|
6
|
+
// `MATCHER_TIMEOUT_MS`: a dispatch that succeeds slowly at Jira/ServiceNow still
|
|
7
|
+
// hands the model a transport error, the model retries the tool, and a second
|
|
8
|
+
// ticket opens at the target — which matcher cannot undo.
|
|
9
|
+
//
|
|
10
|
+
// Dispatch reaches matcher through THREE surfaces, not one: `exception_dispatch`,
|
|
11
|
+
// `exception_bulk_dispatch`, and the generic `matcher_invoke` (which can invoke
|
|
12
|
+
// any operation in the spec, dispatch included). Keying only the curated pair
|
|
13
|
+
// would leave the generic surface duplicating tickets. `createMatcherClient` is
|
|
14
|
+
// the single seam all three route through, so the default key is stamped there
|
|
15
|
+
// and this module owns the two rules it needs: which paths are dispatch, and how
|
|
16
|
+
// their key is derived.
|
|
17
|
+
//
|
|
18
|
+
// Every other operation keeps today's unkeyed behaviour on purpose. A key makes
|
|
19
|
+
// a repeat REPLAY, which is right for a dispatch and wrong for, say, a second
|
|
20
|
+
// deliberate `createContext` with the same body.
|
|
21
|
+
import { createHash } from 'node:crypto';
|
|
22
|
+
import { z } from 'zod';
|
|
23
|
+
/** Matcher's own key contract: 1–128 chars of `A-Za-z0-9:_-`. */
|
|
24
|
+
export const IDEMPOTENCY_KEY_PATTERN = /^[A-Za-z0-9:_-]{1,128}$/;
|
|
25
|
+
/**
|
|
26
|
+
* Zod field for the optional caller-chosen key on the tools that can dispatch.
|
|
27
|
+
* Validated against matcher's contract so a malformed key fails at the tool
|
|
28
|
+
* boundary with a readable message instead of as a matcher 400.
|
|
29
|
+
*/
|
|
30
|
+
export const idempotencyKeyInputField = z
|
|
31
|
+
.string()
|
|
32
|
+
.regex(IDEMPOTENCY_KEY_PATTERN, 'idempotencyKey must be 1–128 chars of A-Z a-z 0-9 : _ -')
|
|
33
|
+
.optional()
|
|
34
|
+
.describe('Optional idempotency key. OMIT IT normally: a key derived from this ' +
|
|
35
|
+
'request is sent automatically for dispatch operations, so a retry after ' +
|
|
36
|
+
'a timeout replays the recorded answer instead of dispatching a second ' +
|
|
37
|
+
'time. Supply a distinct value ONLY to deliberately dispatch again after ' +
|
|
38
|
+
'checking the target system — for example after an MTCH-0514 (outcome ' +
|
|
39
|
+
'unconfirmed) answer.');
|
|
40
|
+
/**
|
|
41
|
+
* Is this path one of matcher's two dispatch routes —
|
|
42
|
+
* `/v1/exceptions/{id}/dispatch` and `/v1/exceptions/bulk/dispatch`?
|
|
43
|
+
*/
|
|
44
|
+
export function isDispatchPath(path) {
|
|
45
|
+
return path.startsWith('/v1/exceptions/') && path.endsWith('/dispatch');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Content-derived key for a dispatch request: `dispatch:` + sha256 hex of
|
|
49
|
+
* `path|canonicalBody` (73 chars, inside matcher's 128-char cap and charset).
|
|
50
|
+
*
|
|
51
|
+
* Determinism is the whole point — the model's retry of the same tool call with
|
|
52
|
+
* the same arguments derives the same key, so matcher replays its recorded
|
|
53
|
+
* answer (including a HELD MTCH-0514 refusal) instead of re-executing.
|
|
54
|
+
*
|
|
55
|
+
* `exceptionIds` is sorted for the digest only; the body keeps the caller's
|
|
56
|
+
* order. The same SET of ids is the same request whatever order it arrived in,
|
|
57
|
+
* and a model re-emitting the list differently must not defeat the dedup.
|
|
58
|
+
*/
|
|
59
|
+
export function deriveDispatchIdempotencyKey(path, body) {
|
|
60
|
+
return `dispatch:${createHash('sha256')
|
|
61
|
+
.update(`${path}|${JSON.stringify(canonicalizeBody(body))}`)
|
|
62
|
+
.digest('hex')}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The digest input's body form. Object keys are sorted recursively so the same
|
|
66
|
+
* fields in a different property order hash to the same key — `matcher_invoke`
|
|
67
|
+
* accepts a free-form body, so a model re-emitting equivalent JSON with another
|
|
68
|
+
* key order must not defeat the dedup. Ordinary arrays keep their order (a
|
|
69
|
+
* different element order can be a different request); `exceptionIds` is the
|
|
70
|
+
* one set-semantics exception and is value-sorted.
|
|
71
|
+
*/
|
|
72
|
+
function canonicalizeBody(body) {
|
|
73
|
+
if (body === null || typeof body !== 'object') {
|
|
74
|
+
return body ?? null;
|
|
75
|
+
}
|
|
76
|
+
if (Array.isArray(body)) {
|
|
77
|
+
return body.map(canonicalizeBody);
|
|
78
|
+
}
|
|
79
|
+
const record = body;
|
|
80
|
+
return Object.fromEntries(Object.keys(record)
|
|
81
|
+
// `JSON.stringify` omits undefined-valued properties from the wire body,
|
|
82
|
+
// so they must not reach the digest either: `{ queue: undefined }` and
|
|
83
|
+
// `{}` send the same request and must derive the same key. Explicit
|
|
84
|
+
// nulls survive (they are on the wire too).
|
|
85
|
+
.filter((key) => record[key] !== undefined)
|
|
86
|
+
.sort()
|
|
87
|
+
.map((key) => [
|
|
88
|
+
key,
|
|
89
|
+
key === 'exceptionIds' && Array.isArray(record[key])
|
|
90
|
+
? [...record[key]].map(String).sort()
|
|
91
|
+
: canonicalizeBody(record[key]),
|
|
92
|
+
]));
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=idempotency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/matcher/idempotency.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,qCAAqC;AACrC,gFAAgF;AAChF,mEAAmE;AACnE,iFAAiF;AACjF,8EAA8E;AAC9E,0DAA0D;AAC1D,EAAE;AACF,kFAAkF;AAClF,gFAAgF;AAChF,8EAA8E;AAC9E,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AACjF,wBAAwB;AACxB,EAAE;AACF,gFAAgF;AAChF,8EAA8E;AAC9E,iDAAiD;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,iEAAiE;AACjE,MAAM,CAAC,MAAM,uBAAuB,GAAG,yBAAyB,CAAA;AAEhE;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC;KACtC,MAAM,EAAE;KACR,KAAK,CACJ,uBAAuB,EACvB,yDAAyD,CAC1D;KACA,QAAQ,EAAE;KACV,QAAQ,CACP,sEAAsE;IACpE,0EAA0E;IAC1E,wEAAwE;IACxE,0EAA0E;IAC1E,uEAAuE;IACvE,sBAAsB,CACzB,CAAA;AAEH;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;AACzE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,4BAA4B,CAC1C,IAAY,EACZ,IAAa;IAEb,OAAO,YAAY,UAAU,CAAC,QAAQ,CAAC;SACpC,MAAM,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;SAC3D,MAAM,CAAC,KAAK,CAAC,EAAE,CAAA;AACpB,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,gBAAgB,CAAC,IAAa;IACrC,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,IAAI,IAAI,IAAI,CAAA;IACrB,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IACnC,CAAC;IAED,MAAM,MAAM,GAAG,IAA+B,CAAA;IAC9C,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;QACjB,yEAAyE;QACzE,uEAAuE;QACvE,oEAAoE;QACpE,4CAA4C;SAC3C,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;SAC1C,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;QACZ,GAAG;QACH,GAAG,KAAK,cAAc,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAClD,CAAC,CAAC,CAAC,GAAI,MAAM,CAAC,GAAG,CAAe,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;YACpD,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;KAClC,CAAC,CACL,CAAA;AACH,CAAC"}
|
|
@@ -1,32 +1,10 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// (
|
|
8
|
-
// so the MCP slots into the same collector config.
|
|
9
|
-
//
|
|
10
|
-
// Everything is gated on `config.enableTelemetry` (default OFF):
|
|
11
|
-
// - Disabled → `initTelemetry` is a COMPLETE no-op: no NodeSDK, no providers,
|
|
12
|
-
// no exporters, no network. `instrumentToolCall` just runs the function and
|
|
13
|
-
// `injectTraceContext` leaves the headers untouched. Dev/test and
|
|
14
|
-
// single-operator runs pay nothing.
|
|
15
|
-
// - Enabled → a NodeSDK is started with OTLP HTTP trace + metric exporters and
|
|
16
|
-
// a resource stamping `service.name` (default `matcher-mcp`) and the build
|
|
17
|
-
// version from package.json.
|
|
18
|
-
//
|
|
19
|
-
// Token-relay rule (NON-NEGOTIABLE): telemetry records ONLY the tool name, the
|
|
20
|
-
// call outcome (ok / error), and — on a matcher API failure — the matcher HTTP
|
|
21
|
-
// status. It NEVER records the caller's bearer token, raw arguments, or request
|
|
22
|
-
// headers, in any span attribute, metric attribute, event, or log.
|
|
23
|
-
//
|
|
24
|
-
// Tenant labelling (copilot loop, task 4.2.1): the copilot span tree MAY carry a
|
|
25
|
-
// `copilot.tenant` attribute — the UNVERIFIED, key-only org identifier decoded
|
|
26
|
-
// from the relayed JWT (getRequestTenantId). It is an organization label for
|
|
27
|
-
// scoping/aggregation, token-free and not a credential; matcher still owns
|
|
28
|
-
// enforcement via the relayed token. It is kept on SPANS only (per-turn), never
|
|
29
|
-
// pushed as a metric label (cardinality), and NEVER accompanies a token/secret.
|
|
1
|
+
// Optional OTLP HTTP telemetry, correlated with Matcher through W3C traceparent.
|
|
2
|
+
// Disabled means no SDK/exporters/network, direct tool execution and unchanged
|
|
3
|
+
// outbound headers. Enabled telemetry stamps service name and build version.
|
|
4
|
+
// Tool telemetry records name, outcome and failure status only: never bearer
|
|
5
|
+
// tokens, raw arguments or request headers, including in events and logs.
|
|
6
|
+
// Copilot may label spans with the UNVERIFIED organization identifier, not metrics
|
|
7
|
+
// (cardinality). This label grants no authority; Matcher validates the relayed JWT.
|
|
30
8
|
import { context, metrics, propagation, SpanStatusCode, trace, ValueType, } from '@opentelemetry/api';
|
|
31
9
|
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
|
|
32
10
|
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otel.js","sourceRoot":"","sources":["../../src/observability/otel.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"otel.js","sourceRoot":"","sources":["../../src/observability/otel.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// Task 1.1.2: instantiate an McpServer (name/version from package.json), mount
|
|
5
|
-
// the SDK's Streamable HTTP transport on a Node HTTP server (MCP_PORT, default
|
|
6
|
-
// 4019), register a placeholder `mcp_ping` tool so tools/list has content,
|
|
7
|
-
// expose a plain GET /healthz, read MATCHER_API_URL via the config module, and
|
|
8
|
-
// shut down gracefully on SIGTERM.
|
|
9
|
-
//
|
|
10
|
-
// The transport runs in the SDK's documented stateless mode — a fresh McpServer
|
|
11
|
-
// is built per request via `buildMcpServer` (see transport/http.ts). Real tools
|
|
12
|
-
// (generic invoke trio, curated fee-schedule vertical) register here in later
|
|
13
|
-
// tasks; for now only the placeholder lives in `registerTools`.
|
|
2
|
+
// Stateless MCP entry point: build a fresh server per request, share the immutable
|
|
3
|
+
// operation index, and register all tools before the HTTP transport serves them.
|
|
14
4
|
import { readFileSync } from 'node:fs';
|
|
15
5
|
import { fileURLToPath } from 'node:url';
|
|
16
6
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
@@ -69,11 +59,7 @@ function getOperationIndex() {
|
|
|
69
59
|
return operationIndexCache;
|
|
70
60
|
}
|
|
71
61
|
/**
|
|
72
|
-
* Register
|
|
73
|
-
* transport wiring) and `mcp_whoami` (proves the request-scoped token relay),
|
|
74
|
-
* plus the generic discovery pair `matcher_list_operations` /
|
|
75
|
-
* `matcher_describe_operation` over the embedded operation index. Extended by
|
|
76
|
-
* the rest of the real tool surface in tasks 1.2.3 / 1.3.x.
|
|
62
|
+
* Register liveness, credential-presence, generic discovery/invoke and curated tools.
|
|
77
63
|
*/
|
|
78
64
|
function registerTools(server) {
|
|
79
65
|
server.registerTool('mcp_ping', {
|
|
@@ -82,13 +68,8 @@ function registerTools(server) {
|
|
|
82
68
|
}, () => ({
|
|
83
69
|
content: [{ type: 'text', text: PING_REPLY }],
|
|
84
70
|
}));
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
// requireMatcherClient: an UnauthenticatedError means no credential was
|
|
88
|
-
// relayed. Any other outcome (a client, or — until task 1.3.1 — the client
|
|
89
|
-
// factory's "not implemented" throw) means the credential WAS present, since
|
|
90
|
-
// execution got past the fail-closed guard. We therefore treat only
|
|
91
|
-
// UnauthenticatedError as "absent" and never inspect the token value.
|
|
71
|
+
// Report credential presence, never its value. Only UnauthenticatedError means
|
|
72
|
+
// the credential guard rejected the request; other errors do not prove absence.
|
|
92
73
|
server.registerTool('mcp_whoami', {
|
|
93
74
|
description: 'Reports whether the caller relayed a matcher bearer credential. ' +
|
|
94
75
|
'Returns presence only — never the token value. Use it to confirm ' +
|
|
@@ -103,85 +84,35 @@ function registerTools(server) {
|
|
|
103
84
|
// The message contains no token material.
|
|
104
85
|
return { isError: true, content: [{ type: 'text', text: err.message }] };
|
|
105
86
|
}
|
|
106
|
-
//
|
|
107
|
-
// implemented) — the credential was present.
|
|
87
|
+
// Non-authentication failures do not change the credential-presence result.
|
|
108
88
|
}
|
|
109
89
|
return { content: [{ type: 'text', text: WHOAMI_AUTHENTICATED }] };
|
|
110
90
|
});
|
|
111
|
-
//
|
|
112
|
-
// index. No matcher call, no token — they describe the contract, not data.
|
|
91
|
+
// Discovery reads the boot contract, not tenant data; no Matcher request or token.
|
|
113
92
|
const index = getOperationIndex();
|
|
114
93
|
registerListOperationsTool(server, index);
|
|
115
94
|
registerDescribeOperationTool(server, index);
|
|
116
|
-
//
|
|
117
|
-
// 174 operations with the caller's relayed token (fail-closed). Shares the
|
|
118
|
-
// RFC 9457 → tool-error mapping (toToolError) with the curated surface.
|
|
95
|
+
// Invoke and curated tools share the fail-closed relay and RFC 9457 error mapping.
|
|
119
96
|
registerInvokeTool(server, index);
|
|
120
|
-
// Curated fee-schedule vertical (task 1.3.2): six typed tools (create/list/
|
|
121
|
-
// get/update/delete/simulate). They share the fail-closed relay and the
|
|
122
|
-
// toToolError mapping with the generic invoke, so both surfaces map matcher
|
|
123
|
-
// errors identically.
|
|
124
97
|
registerFeeScheduleTools(server);
|
|
125
|
-
//
|
|
126
|
-
// built in parallel and registered here to avoid concurrent server.ts edits.
|
|
127
|
-
// Every family shares the same fail-closed relay + toToolError mapping as the
|
|
128
|
-
// fee-schedule vertical and the generic invoke. None carries a tenant field.
|
|
129
|
-
// fee_rule_* (5): create/list/get/update/delete — hybrid path
|
|
130
|
-
// match_rule_* (6): create/list/get/update/delete/reorder — context-nested
|
|
131
|
-
// context_* (5): create/list/get/update/delete
|
|
132
|
-
// source_* (5): create/list/get/update/delete — context-nested
|
|
133
|
-
// match_run_* (4): start/list/get/groups — verbs over /v1/matching
|
|
98
|
+
// Tenant identity comes from the relayed credential, never a curated input field.
|
|
134
99
|
registerFeeRuleTools(server);
|
|
135
100
|
registerMatchRuleTools(server);
|
|
136
101
|
registerContextTools(server);
|
|
137
102
|
registerSourceTools(server);
|
|
138
103
|
registerMatchingTools(server);
|
|
139
|
-
// Phase 4.2 curated verticals: the remaining five families, each built in
|
|
140
|
-
// parallel and registered here to avoid concurrent server.ts edits. Every
|
|
141
|
-
// family shares the same fail-closed relay + toToolError mapping as the
|
|
142
|
-
// fee-schedule vertical and the generic invoke. None carries a tenant field.
|
|
143
|
-
// exception_* (13): list/get, history, comments (list/add/delete), action
|
|
144
|
-
// verbs (dispatch/open-dispute/force-match/adjust-entry),
|
|
145
|
-
// and bulk actions (assign/resolve/dispatch)
|
|
146
|
-
// dispute_* (4): list/get/close/submit-evidence
|
|
147
|
-
// ingestion_* (6): jobs-list/job-get/job-errors-list/job-transactions-list/
|
|
148
|
-
// transactions-search/transaction-ignore — context-nested
|
|
149
|
-
// dashboard_* (7): aggregates + cash-impact/match-rate/metrics/sla/
|
|
150
|
-
// source-breakdown/volume — context-nested reads
|
|
151
|
-
// report_* (13): matched/unmatched/variance/summary, four counts, and
|
|
152
|
-
// five base64 exports — context-nested reads
|
|
153
104
|
registerExceptionTools(server);
|
|
154
105
|
registerDisputeTools(server);
|
|
155
106
|
registerIngestionTools(server);
|
|
156
107
|
registerDashboardTools(server);
|
|
157
108
|
registerReportTools(server);
|
|
158
|
-
// F3/N3/N4/F6 follow-up: curated field-map vertical (5) — closes the
|
|
159
|
-
// setup-configuration gap context_setup_progress points at. All five
|
|
160
|
-
// operations (createFieldMap/getFieldMapBySource/listContextFieldMaps/
|
|
161
|
-
// updateFieldMap/deleteFieldMap) were previously UNCOVERED (neither curated
|
|
162
|
-
// nor generic-only).
|
|
163
109
|
registerFieldMapTools(server);
|
|
164
|
-
// Standalone-SaaS Phase 3: the tenant's own free-tier usage read. A single
|
|
165
|
-
// tool, so it is imported directly rather than behind a one-entry family
|
|
166
|
-
// barrel (the generic trio sets that precedent).
|
|
167
110
|
registerWorkspaceUsageTool(server);
|
|
168
111
|
}
|
|
169
112
|
/**
|
|
170
|
-
* Wrap
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* dispatch chokepoint that doesn't exist. There is no central dispatch in the
|
|
174
|
-
* SDK (each tool registers its own callback), so the registration boundary IS
|
|
175
|
-
* the one place that sees every tool exactly once.
|
|
176
|
-
*
|
|
177
|
-
* The wrapper preserves the original `registerTool` signature (name + config +
|
|
178
|
-
* callback). It only swaps the callback for one that opens the tool span/metrics
|
|
179
|
-
* around the real callback and forwards the same arguments verbatim. The span
|
|
180
|
-
* records ONLY the tool name + outcome (+ matcher status on failure) — never the
|
|
181
|
-
* caller's args, headers, or token (enforced inside `instrumentToolCall`).
|
|
182
|
-
*
|
|
183
|
-
* Idempotent per server: applied once before `registerTools`, so each tool is
|
|
184
|
-
* wrapped a single time (no double-counting).
|
|
113
|
+
* Wrap registrations once per freshly built server, before tools are registered.
|
|
114
|
+
* Forward callback arguments unchanged. Instrumentation records name, outcome and
|
|
115
|
+
* failure status only; it must never record arguments, headers or credentials.
|
|
185
116
|
*/
|
|
186
117
|
function instrumentRegistrations(server) {
|
|
187
118
|
const original = server.registerTool.bind(server);
|