@miragon/mcp-toolkit-core 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -0
- package/dist/engine/context-builder.d.ts +5 -0
- package/dist/engine/context-builder.d.ts.map +1 -0
- package/dist/engine/context-builder.js +22 -0
- package/dist/engine/context-builder.js.map +1 -0
- package/dist/engine/pipeline-executor.d.ts +21 -0
- package/dist/engine/pipeline-executor.d.ts.map +1 -0
- package/dist/engine/pipeline-executor.js +80 -0
- package/dist/engine/pipeline-executor.js.map +1 -0
- package/dist/framework/active-modules.d.ts +30 -0
- package/dist/framework/active-modules.d.ts.map +1 -0
- package/dist/framework/active-modules.js +44 -0
- package/dist/framework/active-modules.js.map +1 -0
- package/dist/framework/catalogue.d.ts +148 -0
- package/dist/framework/catalogue.d.ts.map +1 -0
- package/dist/framework/catalogue.js +132 -0
- package/dist/framework/catalogue.js.map +1 -0
- package/dist/framework/dashboard-store.d.ts +136 -0
- package/dist/framework/dashboard-store.d.ts.map +1 -0
- package/dist/framework/dashboard-store.js +301 -0
- package/dist/framework/dashboard-store.js.map +1 -0
- package/dist/framework/layout-schemas.d.ts +106 -0
- package/dist/framework/layout-schemas.d.ts.map +1 -0
- package/dist/framework/layout-schemas.js +67 -0
- package/dist/framework/layout-schemas.js.map +1 -0
- package/dist/framework/layout-types.d.ts +25 -0
- package/dist/framework/layout-types.d.ts.map +1 -0
- package/dist/framework/layout-types.js +7 -0
- package/dist/framework/layout-types.js.map +1 -0
- package/dist/framework/manifest.d.ts +65 -0
- package/dist/framework/manifest.d.ts.map +1 -0
- package/dist/framework/manifest.js +47 -0
- package/dist/framework/manifest.js.map +1 -0
- package/dist/framework/render-view.d.ts +53 -0
- package/dist/framework/render-view.d.ts.map +1 -0
- package/dist/framework/render-view.js +73 -0
- package/dist/framework/render-view.js.map +1 -0
- package/dist/framework/view-builders.d.ts +79 -0
- package/dist/framework/view-builders.d.ts.map +1 -0
- package/dist/framework/view-builders.js +113 -0
- package/dist/framework/view-builders.js.map +1 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +6 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/translator.d.ts +59 -0
- package/dist/i18n/translator.d.ts.map +1 -0
- package/dist/i18n/translator.js +48 -0
- package/dist/i18n/translator.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/org-gate.d.ts +22 -0
- package/dist/middleware/org-gate.d.ts.map +1 -0
- package/dist/middleware/org-gate.js +28 -0
- package/dist/middleware/org-gate.js.map +1 -0
- package/dist/middleware/role-filter.d.ts +79 -0
- package/dist/middleware/role-filter.d.ts.map +1 -0
- package/dist/middleware/role-filter.js +95 -0
- package/dist/middleware/role-filter.js.map +1 -0
- package/dist/registry/app-loader.d.ts +35 -0
- package/dist/registry/app-loader.d.ts.map +1 -0
- package/dist/registry/app-loader.js +55 -0
- package/dist/registry/app-loader.js.map +1 -0
- package/dist/registry/step-registry.d.ts +27 -0
- package/dist/registry/step-registry.d.ts.map +1 -0
- package/dist/registry/step-registry.js +53 -0
- package/dist/registry/step-registry.js.map +1 -0
- package/dist/registry/widget-registry.d.ts +15 -0
- package/dist/registry/widget-registry.d.ts.map +1 -0
- package/dist/registry/widget-registry.js +28 -0
- package/dist/registry/widget-registry.js.map +1 -0
- package/dist/rest/client.d.ts +3 -0
- package/dist/rest/client.d.ts.map +1 -0
- package/dist/rest/client.js +155 -0
- package/dist/rest/client.js.map +1 -0
- package/dist/rest/errors.d.ts +14 -0
- package/dist/rest/errors.d.ts.map +1 -0
- package/dist/rest/errors.js +21 -0
- package/dist/rest/errors.js.map +1 -0
- package/dist/rest/index.d.ts +6 -0
- package/dist/rest/index.d.ts.map +1 -0
- package/dist/rest/index.js +4 -0
- package/dist/rest/index.js.map +1 -0
- package/dist/rest/tool.d.ts +60 -0
- package/dist/rest/tool.d.ts.map +1 -0
- package/dist/rest/tool.js +81 -0
- package/dist/rest/tool.js.map +1 -0
- package/dist/rest/types.d.ts +66 -0
- package/dist/rest/types.d.ts.map +1 -0
- package/dist/rest/types.js +2 -0
- package/dist/rest/types.js.map +1 -0
- package/dist/tools/app-resource-uri.d.ts +28 -0
- package/dist/tools/app-resource-uri.d.ts.map +1 -0
- package/dist/tools/app-resource-uri.js +30 -0
- package/dist/tools/app-resource-uri.js.map +1 -0
- package/dist/tools/backend-registry.d.ts +111 -0
- package/dist/tools/backend-registry.d.ts.map +1 -0
- package/dist/tools/backend-registry.js +154 -0
- package/dist/tools/backend-registry.js.map +1 -0
- package/dist/tools/create-framework-app.d.ts +147 -0
- package/dist/tools/create-framework-app.d.ts.map +1 -0
- package/dist/tools/create-framework-app.js +111 -0
- package/dist/tools/create-framework-app.js.map +1 -0
- package/dist/tools/index.d.ts +22 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +15 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/register-catalogue-tool.d.ts +22 -0
- package/dist/tools/register-catalogue-tool.d.ts.map +1 -0
- package/dist/tools/register-catalogue-tool.js +45 -0
- package/dist/tools/register-catalogue-tool.js.map +1 -0
- package/dist/tools/register-dashboard-tools.d.ts +32 -0
- package/dist/tools/register-dashboard-tools.d.ts.map +1 -0
- package/dist/tools/register-dashboard-tools.js +149 -0
- package/dist/tools/register-dashboard-tools.js.map +1 -0
- package/dist/tools/register-framework-tools.d.ts +83 -0
- package/dist/tools/register-framework-tools.d.ts.map +1 -0
- package/dist/tools/register-framework-tools.js +154 -0
- package/dist/tools/register-framework-tools.js.map +1 -0
- package/dist/tools/register-tool.d.ts +45 -0
- package/dist/tools/register-tool.d.ts.map +1 -0
- package/dist/tools/register-tool.js +82 -0
- package/dist/tools/register-tool.js.map +1 -0
- package/dist/tools/register-widget-tool.d.ts +51 -0
- package/dist/tools/register-widget-tool.d.ts.map +1 -0
- package/dist/tools/register-widget-tool.js +45 -0
- package/dist/tools/register-widget-tool.js.map +1 -0
- package/dist/tools/tool-call-name.d.ts +53 -0
- package/dist/tools/tool-call-name.d.ts.map +1 -0
- package/dist/tools/tool-call-name.js +92 -0
- package/dist/tools/tool-call-name.js.map +1 -0
- package/dist/tools/with-tool-errors.d.ts +16 -0
- package/dist/tools/with-tool-errors.d.ts.map +1 -0
- package/dist/tools/with-tool-errors.js +28 -0
- package/dist/tools/with-tool-errors.js.map +1 -0
- package/dist/types/app.d.ts +44 -0
- package/dist/types/app.d.ts.map +1 -0
- package/dist/types/app.js +2 -0
- package/dist/types/app.js.map +1 -0
- package/dist/types/config.d.ts +15 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/context.d.ts +18 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/context.js +2 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/meta.d.ts +99 -0
- package/dist/types/meta.d.ts.map +1 -0
- package/dist/types/meta.js +66 -0
- package/dist/types/meta.js.map +1 -0
- package/dist/types/pipeline.d.ts +9 -0
- package/dist/types/pipeline.d.ts.map +1 -0
- package/dist/types/pipeline.js +2 -0
- package/dist/types/pipeline.js.map +1 -0
- package/dist/types/step.d.ts +51 -0
- package/dist/types/step.d.ts.map +1 -0
- package/dist/types/step.js +2 -0
- package/dist/types/step.js.map +1 -0
- package/dist/types/view-data.d.ts +67 -0
- package/dist/types/view-data.d.ts.map +1 -0
- package/dist/types/view-data.js +2 -0
- package/dist/types/view-data.js.map +1 -0
- package/dist/types/widget.d.ts +57 -0
- package/dist/types/widget.d.ts.map +1 -0
- package/dist/types/widget.js +2 -0
- package/dist/types/widget.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { RestError } from "./errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build a `RestClient` with the given base URL, auth mode, and default
|
|
4
|
+
* headers. The returned client handles URL-template expansion, query-string
|
|
5
|
+
* encoding, auth header stamping, JSON serialization, and error mapping
|
|
6
|
+
* (non-2xx responses throw `RestError`).
|
|
7
|
+
*
|
|
8
|
+
* Consumers typically instantiate one client per upstream backend and pass
|
|
9
|
+
* it into `createToolRegistrar` so every tool handler receives the typed
|
|
10
|
+
* client instance.
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
13
|
+
export function createRestClient(config) {
|
|
14
|
+
const baseUrl = stripTrailingSlash(config.baseUrl);
|
|
15
|
+
const authHeaders = buildAuthHeaders(config.auth ?? { mode: "none" });
|
|
16
|
+
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
17
|
+
const defaultTimeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
18
|
+
if (typeof fetchImpl !== "function") {
|
|
19
|
+
throw new Error("createRestClient: no fetch implementation available");
|
|
20
|
+
}
|
|
21
|
+
async function request(options) {
|
|
22
|
+
const url = buildUrl(baseUrl, options.path, options.pathParams, options.query);
|
|
23
|
+
const headers = mergeHeaders({ accept: "application/json" }, config.defaultHeaders, authHeaders, options.headers);
|
|
24
|
+
const init = {
|
|
25
|
+
method: options.method,
|
|
26
|
+
headers,
|
|
27
|
+
};
|
|
28
|
+
if (options.body !== undefined && options.body !== null && methodAllowsBody(options.method)) {
|
|
29
|
+
init.body = typeof options.body === "string" ? options.body : JSON.stringify(options.body);
|
|
30
|
+
if (typeof options.body !== "string" && !hasContentType(headers)) {
|
|
31
|
+
;
|
|
32
|
+
init.headers["content-type"] = "application/json";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// A hung upstream must not block the tool call (and its MCP connection)
|
|
36
|
+
// forever. Abort on timeout, and combine with the caller's signal so an
|
|
37
|
+
// explicit cancellation still works. A dedicated timeout signal lets us
|
|
38
|
+
// tell "timed out" from "caller aborted" in the catch below.
|
|
39
|
+
const timeoutMs = options.timeoutMs ?? defaultTimeoutMs;
|
|
40
|
+
const timeoutSignal = timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined;
|
|
41
|
+
const signal = combineSignals(options.signal, timeoutSignal);
|
|
42
|
+
if (signal)
|
|
43
|
+
init.signal = signal;
|
|
44
|
+
let response;
|
|
45
|
+
try {
|
|
46
|
+
response = await fetchImpl(url, init);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
if (timeoutSignal?.aborted && !options.signal?.aborted) {
|
|
50
|
+
throw new Error(`REST request to ${url} timed out after ${timeoutMs}ms`, { cause: err });
|
|
51
|
+
}
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
const body = await safeReadText(response);
|
|
56
|
+
throw new RestError(response.status, response.statusText, body, url);
|
|
57
|
+
}
|
|
58
|
+
if (response.status === 204) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
62
|
+
if (contentType.includes("application/json")) {
|
|
63
|
+
return (await response.json());
|
|
64
|
+
}
|
|
65
|
+
return (await response.text());
|
|
66
|
+
}
|
|
67
|
+
return { request, baseUrl };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Combine an optional caller signal with an optional timeout signal into the
|
|
71
|
+
* single `AbortSignal` fetch accepts. Returns `undefined` when neither is
|
|
72
|
+
* present (no abort behaviour), the sole signal when only one is, or
|
|
73
|
+
* `AbortSignal.any([...])` when both are — so whichever fires first aborts the
|
|
74
|
+
* request.
|
|
75
|
+
*/
|
|
76
|
+
function combineSignals(caller, timeout) {
|
|
77
|
+
if (caller && timeout)
|
|
78
|
+
return AbortSignal.any([caller, timeout]);
|
|
79
|
+
return caller ?? timeout;
|
|
80
|
+
}
|
|
81
|
+
function buildAuthHeaders(auth) {
|
|
82
|
+
switch (auth.mode) {
|
|
83
|
+
case "none":
|
|
84
|
+
return {};
|
|
85
|
+
case "bearer":
|
|
86
|
+
return { authorization: `Bearer ${auth.token}` };
|
|
87
|
+
case "header":
|
|
88
|
+
return { [auth.headerName.toLowerCase()]: auth.value };
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function buildUrl(baseUrl, path, pathParams, query) {
|
|
92
|
+
const expandedPath = expandPathTemplate(path, pathParams);
|
|
93
|
+
const joined = expandedPath.startsWith("/")
|
|
94
|
+
? `${baseUrl}${expandedPath}`
|
|
95
|
+
: `${baseUrl}/${expandedPath}`;
|
|
96
|
+
const queryString = encodeQuery(query);
|
|
97
|
+
return queryString ? `${joined}?${queryString}` : joined;
|
|
98
|
+
}
|
|
99
|
+
function expandPathTemplate(path, params) {
|
|
100
|
+
return path.replace(/\{([^}]+)\}/g, (_, key) => {
|
|
101
|
+
if (!params || !(key in params)) {
|
|
102
|
+
throw new Error(`Missing path parameter "${key}" for template "${path}"`);
|
|
103
|
+
}
|
|
104
|
+
return encodeURIComponent(String(params[key]));
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function encodeQuery(query) {
|
|
108
|
+
if (!query)
|
|
109
|
+
return "";
|
|
110
|
+
const params = [];
|
|
111
|
+
for (const [key, value] of Object.entries(query)) {
|
|
112
|
+
if (value === undefined || value === null)
|
|
113
|
+
continue;
|
|
114
|
+
if (Array.isArray(value)) {
|
|
115
|
+
for (const entry of value) {
|
|
116
|
+
if (entry === undefined || entry === null)
|
|
117
|
+
continue;
|
|
118
|
+
params.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(entry))}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
params.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return params.join("&");
|
|
126
|
+
}
|
|
127
|
+
function mergeHeaders(...sources) {
|
|
128
|
+
const out = {};
|
|
129
|
+
for (const source of sources) {
|
|
130
|
+
if (!source)
|
|
131
|
+
continue;
|
|
132
|
+
for (const [key, value] of Object.entries(source)) {
|
|
133
|
+
out[key.toLowerCase()] = value;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
function hasContentType(headers) {
|
|
139
|
+
return "content-type" in headers;
|
|
140
|
+
}
|
|
141
|
+
function methodAllowsBody(method) {
|
|
142
|
+
return method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE";
|
|
143
|
+
}
|
|
144
|
+
function stripTrailingSlash(url) {
|
|
145
|
+
return url.endsWith("/") ? url.slice(0, -1) : url;
|
|
146
|
+
}
|
|
147
|
+
async function safeReadText(response) {
|
|
148
|
+
try {
|
|
149
|
+
return await response.text();
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return "";
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/rest/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by `RestClient.request` on non-2xx responses.
|
|
3
|
+
*
|
|
4
|
+
* `status` is picked up by `createToolRegistrar`'s error handler and
|
|
5
|
+
* rendered as `[<status>] <message>` in the MCP tool response, so tool
|
|
6
|
+
* authors do not need to translate HTTP errors manually.
|
|
7
|
+
*/
|
|
8
|
+
export declare class RestError extends Error {
|
|
9
|
+
readonly status: number;
|
|
10
|
+
readonly statusText: string;
|
|
11
|
+
readonly body: string;
|
|
12
|
+
constructor(status: number, statusText: string, body: string, url: string);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/rest/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;gBAET,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;CAQ1E"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by `RestClient.request` on non-2xx responses.
|
|
3
|
+
*
|
|
4
|
+
* `status` is picked up by `createToolRegistrar`'s error handler and
|
|
5
|
+
* rendered as `[<status>] <message>` in the MCP tool response, so tool
|
|
6
|
+
* authors do not need to translate HTTP errors manually.
|
|
7
|
+
*/
|
|
8
|
+
export class RestError extends Error {
|
|
9
|
+
status;
|
|
10
|
+
statusText;
|
|
11
|
+
body;
|
|
12
|
+
constructor(status, statusText, body, url) {
|
|
13
|
+
const snippet = body.length > 200 ? `${body.slice(0, 200)}…` : body;
|
|
14
|
+
super(`HTTP ${status} ${statusText} for ${url}${snippet ? `: ${snippet}` : ""}`);
|
|
15
|
+
this.name = "RestError";
|
|
16
|
+
this.status = status;
|
|
17
|
+
this.statusText = statusText;
|
|
18
|
+
this.body = body;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/rest/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,MAAM,CAAQ;IACd,UAAU,CAAQ;IAClB,IAAI,CAAQ;IAErB,YAAY,MAAc,EAAE,UAAkB,EAAE,IAAY,EAAE,GAAW;QACvE,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAA;QACnE,KAAK,CAAC,QAAQ,MAAM,IAAI,UAAU,QAAQ,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAChF,IAAI,CAAC,IAAI,GAAG,WAAW,CAAA;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createRestClient } from "./client.js";
|
|
2
|
+
export { createRestTool } from "./tool.js";
|
|
3
|
+
export { RestError } from "./errors.js";
|
|
4
|
+
export type { HttpMethod, QueryValue, RestAuthConfig, RestClient, RestClientConfig, RestRequestOptions, } from "./types.js";
|
|
5
|
+
export type { RestToolConfig, RequestParts } from "./tool.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rest/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,YAAY,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,UAAU,EACV,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rest/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { ToolConfig } from "../tools/register-tool.js";
|
|
3
|
+
import type { HttpMethod, RestClient, RestRequestOptions } from "./types.js";
|
|
4
|
+
type ZodRawShape = Record<string, z.ZodTypeAny>;
|
|
5
|
+
type ToolArgs = Record<string, any>;
|
|
6
|
+
/**
|
|
7
|
+
* Subset of `RestRequestOptions` that a `buildRequest` callback may return.
|
|
8
|
+
* `method` and `path` are fixed by the tool definition.
|
|
9
|
+
*/
|
|
10
|
+
export type RequestParts = Pick<RestRequestOptions, "pathParams" | "query" | "body" | "headers">;
|
|
11
|
+
export interface RestToolConfig<TArgs extends ToolArgs = ToolArgs, TRaw = unknown, TOut = unknown> {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
category?: string;
|
|
15
|
+
method: HttpMethod;
|
|
16
|
+
/** URL template relative to the client's baseUrl, e.g. `/orders/{orderId}`. */
|
|
17
|
+
path: string;
|
|
18
|
+
inputSchema?: ZodRawShape;
|
|
19
|
+
/**
|
|
20
|
+
* Map validated args to request parts. If omitted, a method-dependent
|
|
21
|
+
* default is used: path placeholders consume matching args, the rest
|
|
22
|
+
* become `query` (GET/DELETE) or `body` (POST/PUT/PATCH).
|
|
23
|
+
*/
|
|
24
|
+
buildRequest?: (args: TArgs) => RequestParts;
|
|
25
|
+
/**
|
|
26
|
+
* Transform the raw response before handing it to the LLM. Use this to
|
|
27
|
+
* reduce field surface — the main context-hygiene lever.
|
|
28
|
+
*/
|
|
29
|
+
projection?: (raw: TRaw, args: TArgs) => TOut;
|
|
30
|
+
annotations?: {
|
|
31
|
+
readOnlyHint?: boolean;
|
|
32
|
+
destructiveHint?: boolean;
|
|
33
|
+
idempotentHint?: boolean;
|
|
34
|
+
openWorldHint?: boolean;
|
|
35
|
+
};
|
|
36
|
+
formatResult?: (result: TOut, args: TArgs) => string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Produce a `ToolConfig<RestClient>` that the standard `createToolRegistrar`
|
|
40
|
+
* can register. This keeps REST tools on the same registration path as
|
|
41
|
+
* hand-written tools — same error handling, same result formatting.
|
|
42
|
+
*
|
|
43
|
+
* Typical usage:
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* const client = createRestClient({ baseUrl, auth: { mode: "bearer", token } })
|
|
47
|
+
* const register = createToolRegistrar(server, client)
|
|
48
|
+
* register(createRestTool({
|
|
49
|
+
* name: "get_order",
|
|
50
|
+
* description: "Fetch an order by ID.",
|
|
51
|
+
* method: "GET",
|
|
52
|
+
* path: "/orders/{orderId}",
|
|
53
|
+
* inputSchema: { orderId: z.string() },
|
|
54
|
+
* projection: (raw: Order) => ({ id: raw.id, total: raw.totalAmount }),
|
|
55
|
+
* }))
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function createRestTool<TArgs extends ToolArgs = ToolArgs, TRaw = unknown, TOut = unknown>(config: RestToolConfig<TArgs, TRaw, TOut>): ToolConfig<RestClient>;
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/rest/tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAE5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAc,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAExF,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAAA;AAG/C,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AAEnC;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,EAAE,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC,CAAA;AAEhG,MAAM,WAAW,cAAc,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ,EAAE,IAAI,GAAG,OAAO,EAAE,IAAI,GAAG,OAAO;IAC/F,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,UAAU,CAAA;IAClB,+EAA+E;IAC/E,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,YAAY,CAAA;IAC5C;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,KAAK,IAAI,CAAA;IAC7C,WAAW,CAAC,EAAE;QACZ,YAAY,CAAC,EAAE,OAAO,CAAA;QACtB,eAAe,CAAC,EAAE,OAAO,CAAA;QACzB,cAAc,CAAC,EAAE,OAAO,CAAA;QACxB,aAAa,CAAC,EAAE,OAAO,CAAA;KACxB,CAAA;IACD,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,KAAK,MAAM,CAAA;CACrD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ,EAAE,IAAI,GAAG,OAAO,EAAE,IAAI,GAAG,OAAO,EAC9F,MAAM,EAAE,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,GACxC,UAAU,CAAC,UAAU,CAAC,CA8BxB"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Produce a `ToolConfig<RestClient>` that the standard `createToolRegistrar`
|
|
3
|
+
* can register. This keeps REST tools on the same registration path as
|
|
4
|
+
* hand-written tools — same error handling, same result formatting.
|
|
5
|
+
*
|
|
6
|
+
* Typical usage:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* const client = createRestClient({ baseUrl, auth: { mode: "bearer", token } })
|
|
10
|
+
* const register = createToolRegistrar(server, client)
|
|
11
|
+
* register(createRestTool({
|
|
12
|
+
* name: "get_order",
|
|
13
|
+
* description: "Fetch an order by ID.",
|
|
14
|
+
* method: "GET",
|
|
15
|
+
* path: "/orders/{orderId}",
|
|
16
|
+
* inputSchema: { orderId: z.string() },
|
|
17
|
+
* projection: (raw: Order) => ({ id: raw.id, total: raw.totalAmount }),
|
|
18
|
+
* }))
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function createRestTool(config) {
|
|
22
|
+
const placeholders = extractPathPlaceholders(config.path);
|
|
23
|
+
const method = config.method;
|
|
24
|
+
return {
|
|
25
|
+
name: config.name,
|
|
26
|
+
description: config.description,
|
|
27
|
+
category: config.category,
|
|
28
|
+
inputSchema: config.inputSchema,
|
|
29
|
+
annotations: config.annotations,
|
|
30
|
+
handler: async (client, args) => {
|
|
31
|
+
const typedArgs = args;
|
|
32
|
+
const parts = config.buildRequest
|
|
33
|
+
? config.buildRequest(typedArgs)
|
|
34
|
+
: defaultBuildRequest(method, placeholders, typedArgs);
|
|
35
|
+
const raw = await client.request({
|
|
36
|
+
method,
|
|
37
|
+
path: config.path,
|
|
38
|
+
pathParams: parts.pathParams,
|
|
39
|
+
query: parts.query,
|
|
40
|
+
body: parts.body,
|
|
41
|
+
headers: parts.headers,
|
|
42
|
+
});
|
|
43
|
+
if (raw === undefined)
|
|
44
|
+
return undefined;
|
|
45
|
+
return config.projection ? config.projection(raw, typedArgs) : raw;
|
|
46
|
+
},
|
|
47
|
+
formatResult: config.formatResult
|
|
48
|
+
? (result, args) => config.formatResult(result, args)
|
|
49
|
+
: undefined,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function extractPathPlaceholders(path) {
|
|
53
|
+
const out = new Set();
|
|
54
|
+
for (const match of path.matchAll(/\{([^}]+)\}/g)) {
|
|
55
|
+
const name = match[1];
|
|
56
|
+
if (name)
|
|
57
|
+
out.add(name);
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
function defaultBuildRequest(method, placeholders, args) {
|
|
62
|
+
const pathParams = {};
|
|
63
|
+
const rest = {};
|
|
64
|
+
for (const [key, value] of Object.entries(args)) {
|
|
65
|
+
if (placeholders.has(key)) {
|
|
66
|
+
pathParams[key] = value;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
rest[key] = value;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const hasRest = Object.keys(rest).length > 0;
|
|
73
|
+
if (method === "GET" || method === "DELETE") {
|
|
74
|
+
return {
|
|
75
|
+
pathParams,
|
|
76
|
+
query: hasRest ? rest : undefined,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return { pathParams, body: hasRest ? rest : undefined };
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/rest/tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth configuration for a REST upstream.
|
|
3
|
+
*
|
|
4
|
+
* Modes: `none`, `bearer`, and custom `header`. `oauth2` is out of scope —
|
|
5
|
+
* it requires per-user session plumbing (callback routes, token store) and
|
|
6
|
+
* is a future iteration.
|
|
7
|
+
*
|
|
8
|
+
* - `none` — no auth headers added
|
|
9
|
+
* - `bearer` — stamps `Authorization: Bearer <token>`
|
|
10
|
+
* - `header` — stamps a custom header on every request
|
|
11
|
+
*/
|
|
12
|
+
export type RestAuthConfig = {
|
|
13
|
+
mode: "none";
|
|
14
|
+
} | {
|
|
15
|
+
mode: "bearer";
|
|
16
|
+
token: string;
|
|
17
|
+
} | {
|
|
18
|
+
mode: "header";
|
|
19
|
+
headerName: string;
|
|
20
|
+
value: string;
|
|
21
|
+
};
|
|
22
|
+
export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
23
|
+
export type QueryValue = string | number | boolean | null | undefined;
|
|
24
|
+
export interface RestRequestOptions {
|
|
25
|
+
method: HttpMethod;
|
|
26
|
+
path: string;
|
|
27
|
+
pathParams?: Record<string, string | number>;
|
|
28
|
+
query?: Record<string, QueryValue | QueryValue[]>;
|
|
29
|
+
body?: unknown;
|
|
30
|
+
headers?: Record<string, string>;
|
|
31
|
+
/**
|
|
32
|
+
* Abort the request when this signal fires, in addition to the timeout. Use
|
|
33
|
+
* it to cancel a request from the caller (e.g. a tool handler that received
|
|
34
|
+
* its own abort signal).
|
|
35
|
+
*/
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
/**
|
|
38
|
+
* Override {@link RestClientConfig.timeoutMs} for this request. `0` disables
|
|
39
|
+
* the timeout for this call only.
|
|
40
|
+
*/
|
|
41
|
+
timeoutMs?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface RestClientConfig {
|
|
44
|
+
baseUrl: string;
|
|
45
|
+
auth?: RestAuthConfig;
|
|
46
|
+
defaultHeaders?: Record<string, string>;
|
|
47
|
+
/**
|
|
48
|
+
* Optional fetch implementation. Defaults to `globalThis.fetch`. Useful
|
|
49
|
+
* for tests and for runtimes that require a custom fetch.
|
|
50
|
+
*/
|
|
51
|
+
fetch?: typeof fetch;
|
|
52
|
+
/**
|
|
53
|
+
* Default per-request timeout in milliseconds. A request that doesn't settle
|
|
54
|
+
* within this window is aborted, so a hung upstream can't block a tool call
|
|
55
|
+
* (and its MCP connection) indefinitely. Defaults to `30000`. Set to `0` to
|
|
56
|
+
* disable the default timeout entirely.
|
|
57
|
+
*/
|
|
58
|
+
timeoutMs?: number;
|
|
59
|
+
}
|
|
60
|
+
export interface RestClient {
|
|
61
|
+
/** Execute a request; throws `RestError` on non-2xx responses. */
|
|
62
|
+
request<T = unknown>(options: RestRequestOptions): Promise<T>;
|
|
63
|
+
/** Exposed so tools can share the base URL (e.g. for link formatting). */
|
|
64
|
+
readonly baseUrl: string;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rest/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEzD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEpE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;AAErE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,EAAE,CAAC,CAAA;IACjD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACvC;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IACpB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,kEAAkE;IAClE,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC7D,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/rest/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface DeriveAppResourceUriInput {
|
|
2
|
+
/** Server / app name used as the resource URI authority (`ui://<appName>/...`). */
|
|
3
|
+
appName: string;
|
|
4
|
+
/** Absolute path to the bundled `mcp-app.html` served under the URI. */
|
|
5
|
+
htmlPath: string;
|
|
6
|
+
/**
|
|
7
|
+
* Resource URI used when the bundle file is missing (e.g. `dist` not built
|
|
8
|
+
* yet in a dev loop). Defaults to `ui://<appName>/mcp-app.dev.html` so a
|
|
9
|
+
* stable, obviously-non-production URI is still served. Pass a custom value
|
|
10
|
+
* only when a different placeholder is needed.
|
|
11
|
+
*/
|
|
12
|
+
devFallback?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Derives a content-hashed MCP UI resource URI for the widget bundle.
|
|
16
|
+
*
|
|
17
|
+
* MCP hosts cache the widget bundle by its resource URI; with a fixed URI a
|
|
18
|
+
* host keeps serving a stale bundle even across server restarts. Hashing the
|
|
19
|
+
* file content into the URI (`ui://<appName>/mcp-app.<hash>.html`) forces a
|
|
20
|
+
* fresh fetch whenever the bundle actually changes — and only then.
|
|
21
|
+
*
|
|
22
|
+
* When the bundle file cannot be read (commonly `dist` not built yet), it
|
|
23
|
+
* falls back to {@link DeriveAppResourceUriInput.devFallback} — a stable
|
|
24
|
+
* `ui://<appName>/mcp-app.dev.html` by default — and emits a boot warning so
|
|
25
|
+
* the missing file is visible in logs rather than silently degrading.
|
|
26
|
+
*/
|
|
27
|
+
export declare function deriveAppResourceUri(input: DeriveAppResourceUriInput): string;
|
|
28
|
+
//# sourceMappingURL=app-resource-uri.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-resource-uri.d.ts","sourceRoot":"","sources":["../../src/tools/app-resource-uri.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,yBAAyB;IACxC,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAA;IACf,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,MAAM,CAc7E"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
/**
|
|
4
|
+
* Derives a content-hashed MCP UI resource URI for the widget bundle.
|
|
5
|
+
*
|
|
6
|
+
* MCP hosts cache the widget bundle by its resource URI; with a fixed URI a
|
|
7
|
+
* host keeps serving a stale bundle even across server restarts. Hashing the
|
|
8
|
+
* file content into the URI (`ui://<appName>/mcp-app.<hash>.html`) forces a
|
|
9
|
+
* fresh fetch whenever the bundle actually changes — and only then.
|
|
10
|
+
*
|
|
11
|
+
* When the bundle file cannot be read (commonly `dist` not built yet), it
|
|
12
|
+
* falls back to {@link DeriveAppResourceUriInput.devFallback} — a stable
|
|
13
|
+
* `ui://<appName>/mcp-app.dev.html` by default — and emits a boot warning so
|
|
14
|
+
* the missing file is visible in logs rather than silently degrading.
|
|
15
|
+
*/
|
|
16
|
+
export function deriveAppResourceUri(input) {
|
|
17
|
+
const { appName, htmlPath } = input;
|
|
18
|
+
const devFallback = input.devFallback ?? `ui://${appName}/mcp-app.dev.html`;
|
|
19
|
+
try {
|
|
20
|
+
const hash = createHash("sha256").update(readFileSync(htmlPath)).digest("hex").slice(0, 10);
|
|
21
|
+
return `ui://${appName}/mcp-app.${hash}.html`;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
console.warn(`[mcp-toolkit] could not read widget bundle at "${htmlPath}" — ` +
|
|
25
|
+
`serving the dev fallback resource URI "${devFallback}". ` +
|
|
26
|
+
`Build the bundle (dist/mcp-app.html) before shipping to production.`);
|
|
27
|
+
return devFallback;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=app-resource-uri.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-resource-uri.js","sourceRoot":"","sources":["../../src/tools/app-resource-uri.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAgBtC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAgC;IACnE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;IACnC,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,QAAQ,OAAO,mBAAmB,CAAA;IAC3E,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QAC3F,OAAO,QAAQ,OAAO,YAAY,IAAI,OAAO,CAAA;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CACV,kDAAkD,QAAQ,MAAM;YAC9D,0CAA0C,WAAW,KAAK;YAC1D,qEAAqE,CACxE,CAAA;QACD,OAAO,WAAW,CAAA;IACpB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default backend-selection TTL: how long a session's sticky pick survives
|
|
3
|
+
* without being re-set. `mcp-use` exposes no session-close hook to plugins, so
|
|
4
|
+
* without eviction the per-session selection map would grow with every MCP
|
|
5
|
+
* session that ever selected a backend. 24h comfortably outlives any real
|
|
6
|
+
* session.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEFAULT_BACKEND_SESSION_TTL_MS: number;
|
|
9
|
+
/** A single addressable backend: a stable `id`, its `client`, and free-form `meta`. */
|
|
10
|
+
export interface BackendEntry<TClient, TMeta = undefined> {
|
|
11
|
+
id: string;
|
|
12
|
+
client: TClient;
|
|
13
|
+
meta?: TMeta;
|
|
14
|
+
}
|
|
15
|
+
/** A resolved backend handed to a tool handler. */
|
|
16
|
+
export interface ResolvedBackend<TClient, TMeta = undefined> {
|
|
17
|
+
id: string;
|
|
18
|
+
client: TClient;
|
|
19
|
+
meta: TMeta | undefined;
|
|
20
|
+
}
|
|
21
|
+
export interface CreateBackendRegistryOptions {
|
|
22
|
+
/** Sticky-selection TTL in ms (default: {@link DEFAULT_BACKEND_SESSION_TTL_MS}). */
|
|
23
|
+
sessionTtlMs?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Noun used in error messages and the select-instruction hint, e.g.
|
|
26
|
+
* `"engine"` → "No engine selected for this session." Defaults to
|
|
27
|
+
* `"backend"`.
|
|
28
|
+
*/
|
|
29
|
+
label?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Resolves the current MCP session id. Defaults to reading the
|
|
32
|
+
* `Mcp-Session-Id` header off the request context. Injectable for tests and
|
|
33
|
+
* for hosts that key sessions differently.
|
|
34
|
+
*/
|
|
35
|
+
getSessionId?: () => string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Clock used for TTL bookkeeping, in ms. Defaults to `Date.now`. Injectable
|
|
38
|
+
* so tests can drive eviction deterministically.
|
|
39
|
+
*/
|
|
40
|
+
now?: () => number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Thrown when a tool is invoked but no backend has been selected for the
|
|
44
|
+
* current MCP session and the registry holds more than one backend.
|
|
45
|
+
*
|
|
46
|
+
* The message lists the available ids because the error path commonly only
|
|
47
|
+
* serialises `code` + `message` (the structured `availableIds` field may not
|
|
48
|
+
* reach the model) — naming them saves the model a discovery roundtrip before
|
|
49
|
+
* it can pick one and select it.
|
|
50
|
+
*/
|
|
51
|
+
export declare class BackendNotSelectedError extends Error {
|
|
52
|
+
readonly code: "BACKEND_NOT_SELECTED";
|
|
53
|
+
readonly availableIds: string[];
|
|
54
|
+
constructor(availableIds: string[], label: string);
|
|
55
|
+
}
|
|
56
|
+
/** Thrown when an override or sticky selection names a backend that isn't registered. */
|
|
57
|
+
export declare class UnknownBackendError extends Error {
|
|
58
|
+
readonly code: "UNKNOWN_BACKEND";
|
|
59
|
+
readonly requestedId: string;
|
|
60
|
+
readonly availableIds: string[];
|
|
61
|
+
constructor(requestedId: string, availableIds: string[], label: string);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* A session-aware registry of interchangeable backends (Camunda engines, REST
|
|
65
|
+
* hosts, tenants, …). Resolves the backend for a tool call by precedence:
|
|
66
|
+
* 1. an explicit per-call `override` wins,
|
|
67
|
+
* 2. otherwise the sticky session selection,
|
|
68
|
+
* 3. otherwise, if exactly one backend is configured, that one,
|
|
69
|
+
* 4. otherwise throws {@link BackendNotSelectedError}.
|
|
70
|
+
*
|
|
71
|
+
* Sticky selections are kept per MCP session and evicted by a lazy TTL sweep
|
|
72
|
+
* (no timer): expired entries are dropped on read and on the next `select`.
|
|
73
|
+
*/
|
|
74
|
+
export interface BackendRegistry<TClient, TMeta = undefined> {
|
|
75
|
+
/** Resolve the backend for the current call (precedence: override > sticky > single default). */
|
|
76
|
+
resolve(override?: string): ResolvedBackend<TClient, TMeta>;
|
|
77
|
+
/** Pin `id` as the sticky selection for the current MCP session. */
|
|
78
|
+
select(id: string): void;
|
|
79
|
+
/** Clear the sticky selection for a given session id (no-op if none). */
|
|
80
|
+
clear(sessionId: string): void;
|
|
81
|
+
/** List every registered backend (id + meta), in registration order. */
|
|
82
|
+
list(): {
|
|
83
|
+
id: string;
|
|
84
|
+
meta: TMeta | undefined;
|
|
85
|
+
}[];
|
|
86
|
+
/**
|
|
87
|
+
* The id sticky-selected for the current session, or `undefined` when none
|
|
88
|
+
* is selected (or the selection has outlived the TTL). Unlike {@link resolve},
|
|
89
|
+
* it never falls back to a single configured default and never throws — it
|
|
90
|
+
* reports only an explicit sticky selection, which is what a "what is
|
|
91
|
+
* currently selected?" reader needs: a select-tool's `current` action, or
|
|
92
|
+
* surfacing the active pick alongside `list`.
|
|
93
|
+
*/
|
|
94
|
+
getSelected(): string | undefined;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Builds a {@link BackendRegistry} from a non-empty list of backend entries.
|
|
98
|
+
* Throws if `entries` is empty or contains duplicate ids — both are
|
|
99
|
+
* programmer errors that should fail at boot rather than at the first tool
|
|
100
|
+
* call.
|
|
101
|
+
*/
|
|
102
|
+
export declare function createBackendRegistry<TClient, TMeta = undefined>(entries: BackendEntry<TClient, TMeta>[], opts?: CreateBackendRegistryOptions): BackendRegistry<TClient, TMeta>;
|
|
103
|
+
/**
|
|
104
|
+
* Lifts a handler written against a single resolved backend into one that
|
|
105
|
+
* resolves the backend from `registry` (override > sticky > single default)
|
|
106
|
+
* before delegating. The override is read from `args[paramName]`, so a tool
|
|
107
|
+
* adds backend selection by spreading an optional `{ [paramName]: z.string() }`
|
|
108
|
+
* into its input schema and wrapping its handler in `withBackend(...)`.
|
|
109
|
+
*/
|
|
110
|
+
export declare function withBackend<TClient, TMeta, TArgs extends Record<string, unknown>, TResult>(registry: BackendRegistry<TClient, TMeta>, paramName: string, fn: (backend: ResolvedBackend<TClient, TMeta>, args: TArgs) => Promise<TResult>): (args: TArgs) => Promise<TResult>;
|
|
111
|
+
//# sourceMappingURL=backend-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend-registry.d.ts","sourceRoot":"","sources":["../../src/tools/backend-registry.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,QAAsB,CAAA;AAEjE,uFAAuF;AACvF,MAAM,WAAW,YAAY,CAAC,OAAO,EAAE,KAAK,GAAG,SAAS;IACtD,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,KAAK,CAAA;CACb;AAED,mDAAmD;AACnD,MAAM,WAAW,eAAe,CAAC,OAAO,EAAE,KAAK,GAAG,SAAS;IACzD,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,KAAK,GAAG,SAAS,CAAA;CACxB;AAkBD,MAAM,WAAW,4BAA4B;IAC3C,oFAAoF;IACpF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAA;IACvC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED;;;;;;;;GAQG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAG,sBAAsB,CAAS;IAC/C,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,CAAA;gBACnB,YAAY,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM;CAQlD;AAED,yFAAyF;AACzF,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAG,iBAAiB,CAAS;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE,CAAA;gBACnB,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM;CAMvE;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe,CAAC,OAAO,EAAE,KAAK,GAAG,SAAS;IACzD,iGAAiG;IACjG,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAC3D,oEAAoE;IACpE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,yEAAyE;IACzE,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,wEAAwE;IACxE,IAAI,IAAI;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,GAAG,SAAS,CAAA;KAAE,EAAE,CAAA;IACjD;;;;;;;OAOG;IACH,WAAW,IAAI,MAAM,GAAG,SAAS,CAAA;CAClC;AAOD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,KAAK,GAAG,SAAS,EAC9D,OAAO,EAAE,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,EACvC,IAAI,GAAE,4BAAiC,GACtC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAmFjC;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EACxF,QAAQ,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,EACzC,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,GAC9E,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAMnC"}
|