@lovable.dev/mcp-js 0.27.1 → 0.29.0-rc.0
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 +13 -7
- package/dist/{authorize-Cs1yyLrq.d.ts → authorize-BjNE3LPr.d.ts} +1 -1
- package/dist/{authorize-BcNuNPtP.d.cts → authorize-BzZFS0zi.d.cts} +1 -1
- package/dist/{base-CReh7d3E.d.cts → base-DSH8NnPj.d.cts} +10 -3
- package/dist/{base-CReh7d3E.d.ts → base-DSH8NnPj.d.ts} +10 -3
- package/dist/cli/extract-manifest.cjs +2 -2
- package/dist/cli/extract-manifest.js +2 -2
- package/dist/{authorize-CB35c3Wg.cjs → cors-CmKzDN7k.cjs} +154 -59
- package/dist/{authorize-FOlzhxrM.js → cors-D4YbODs-.js} +150 -55
- package/dist/{forwarded-BlLF3dfc.js → forwarded-B3EBjHnA.js} +3 -3
- package/dist/{forwarded-Bhwcj22u.cjs → forwarded-BC_RHnn5.cjs} +3 -3
- package/dist/{gate-B9RSzvoI.cjs → gate-n_HX6eQ5.cjs} +6 -4
- package/dist/{gate-BeHmyGxk.js → gate-pGsVlY_4.js} +5 -3
- package/dist/index.cjs +38 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +38 -1
- package/dist/{io-BzTGjG_c.d.cts → io-BEwvgN8s.d.cts} +1 -1
- package/dist/{io--MeYrWG7.d.ts → io-CvALf9NE.d.ts} +1 -1
- package/dist/list-tools-Dkyyje7j.cjs +48 -0
- package/dist/{list-tools-Dt-mhh52.js → list-tools-ePP9tXND.js} +9 -13
- package/dist/{list-tools-Bku6XkVc.d.ts → list-tools-qIvVJeWZ.d.ts} +3 -3
- package/dist/{list-tools-Cn7tpE0V.d.cts → list-tools-zagoI477.d.cts} +3 -3
- package/dist/{logger-BkMMCFTv.cjs → logger-CN1q-KNn.cjs} +6 -6
- package/dist/{logger-rGakBvJ1.js → logger-Ctv5xUSD.js} +6 -6
- package/dist/mcp-Cs4zfvSi.js +336 -0
- package/dist/mcp-DQ1Vdv4v.cjs +341 -0
- package/dist/{package-BdaLbzEh.cjs → package-C3YVYgxp.cjs} +1 -1
- package/dist/{package-dtiombMt.js → package-DzB_5Hur.js} +1 -1
- package/dist/protocols/mcp/index.cjs +1 -1
- package/dist/protocols/mcp/index.d.cts +3 -3
- package/dist/protocols/mcp/index.d.ts +3 -3
- package/dist/protocols/mcp/index.js +1 -1
- package/dist/protocols/oauth-metadata.cjs +12 -10
- package/dist/protocols/oauth-metadata.d.cts +2 -2
- package/dist/protocols/oauth-metadata.d.ts +2 -2
- package/dist/protocols/oauth-metadata.js +6 -4
- package/dist/protocols/rest/index.cjs +2 -2
- package/dist/protocols/rest/index.d.cts +4 -4
- package/dist/protocols/rest/index.d.ts +4 -4
- package/dist/protocols/rest/index.js +2 -2
- package/dist/{rest-Cit2862S.js → rest-DSclWpIt.js} +13 -12
- package/dist/{rest-1Pf9sYNU.cjs → rest-P6XZWP42.cjs} +28 -27
- package/dist/schema-CW1jKvio.js +65 -0
- package/dist/schema-D3vClxb7.cjs +76 -0
- package/dist/stacks/supabase/index.cjs +8 -8
- package/dist/stacks/supabase/index.d.cts +1 -1
- package/dist/stacks/supabase/index.d.ts +1 -1
- package/dist/stacks/supabase/index.js +6 -6
- package/dist/stacks/supabase/vite.cjs +1 -1
- package/dist/stacks/supabase/vite.d.cts +1 -1
- package/dist/stacks/supabase/vite.d.ts +1 -1
- package/dist/stacks/supabase/vite.js +1 -1
- package/dist/stacks/tanstack/index.cjs +8 -8
- package/dist/stacks/tanstack/index.d.cts +2 -2
- package/dist/stacks/tanstack/index.d.ts +2 -2
- package/dist/stacks/tanstack/index.js +5 -5
- package/dist/stacks/tanstack/vite.cjs +8 -4
- package/dist/stacks/tanstack/vite.d.cts +11 -1
- package/dist/stacks/tanstack/vite.d.ts +11 -1
- package/dist/stacks/tanstack/vite.js +8 -4
- package/dist/tool-result-CK6hXO43.cjs +89 -0
- package/dist/tool-result-DfCk445b.js +78 -0
- package/dist/{types-C0Wgm9zp.d.cts → types-D1cgsnPu.d.cts} +15 -7
- package/dist/{types-C0Wgm9zp.d.ts → types-D1cgsnPu.d.ts} +15 -7
- package/package.json +2 -1
- package/dist/content-D5LJAHyM.js +0 -12
- package/dist/content-NCYIGgOb.cjs +0 -17
- package/dist/list-tools-DiMCRunS.cjs +0 -52
- package/dist/mcp-DiVQhHIw.js +0 -148
- package/dist/mcp-ECo1Ixk8.cjs +0 -153
|
@@ -1,28 +1,7 @@
|
|
|
1
|
-
import { i as log, n as applyLogLevelFromEnv, o as parseSafeUrl, r as describeError, s as trimTrailingSlash, t as LOG_LEVEL_ENV_VAR, u as resolveMetricsConfig } from "./logger-
|
|
2
|
-
import { t as version } from "./package-
|
|
1
|
+
import { i as log, n as applyLogLevelFromEnv, o as parseSafeUrl, r as describeError, s as trimTrailingSlash, t as LOG_LEVEL_ENV_VAR, u as resolveMetricsConfig } from "./logger-Ctv5xUSD.js";
|
|
2
|
+
import { t as version } from "./package-DzB_5Hur.js";
|
|
3
3
|
import "./metadata-path-CAkNcfyY.js";
|
|
4
|
-
import { createLocalJWKSet, decodeProtectedHeader, jwtVerify } from "jose";
|
|
5
|
-
//#region src/core/cors.ts
|
|
6
|
-
const EXPOSE_HEADERS = "WWW-Authenticate, Mcp-Session-Id, Mcp-Protocol-Version";
|
|
7
|
-
const ALLOW_HEADERS = "Authorization, Content-Type, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID";
|
|
8
|
-
/** Add permissive CORS to a built response, preserving its other headers. */
|
|
9
|
-
function withCors(response) {
|
|
10
|
-
response.headers.set("Access-Control-Allow-Origin", "*");
|
|
11
|
-
response.headers.set("Access-Control-Expose-Headers", EXPOSE_HEADERS);
|
|
12
|
-
return response;
|
|
13
|
-
}
|
|
14
|
-
function corsPreflightResponse(allowMethods) {
|
|
15
|
-
return new Response(null, {
|
|
16
|
-
status: 204,
|
|
17
|
-
headers: {
|
|
18
|
-
"Access-Control-Allow-Origin": "*",
|
|
19
|
-
"Access-Control-Allow-Methods": allowMethods,
|
|
20
|
-
"Access-Control-Allow-Headers": ALLOW_HEADERS,
|
|
21
|
-
"Access-Control-Max-Age": "86400"
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
4
|
+
import { createLocalJWKSet, decodeProtectedHeader, errors, jwtVerify } from "jose";
|
|
26
5
|
//#region src/core/http.ts
|
|
27
6
|
const JSON_HEADERS = { "Content-Type": "application/json" };
|
|
28
7
|
/** Strip the body from a built response, preserving status and headers, for HEAD. */
|
|
@@ -34,7 +13,7 @@ function headResponse(response) {
|
|
|
34
13
|
});
|
|
35
14
|
}
|
|
36
15
|
function finalizeWireResponse(request, response) {
|
|
37
|
-
return
|
|
16
|
+
return request.method === "HEAD" ? headResponse(response) : response;
|
|
38
17
|
}
|
|
39
18
|
function methodNotAllowed(allow) {
|
|
40
19
|
return new Response(JSON.stringify({ error: "method not allowed" }), {
|
|
@@ -73,6 +52,8 @@ function toLogRecord(rec) {
|
|
|
73
52
|
if (rec.tool !== null) attributes.push(strAttr("mcp.tool", rec.tool));
|
|
74
53
|
if (rec.reqBytes !== void 0) attributes.push(intAttr("mcp.request_size_bytes", rec.reqBytes));
|
|
75
54
|
if (rec.resBytes !== void 0) attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
|
|
55
|
+
if (rec.httpMethod !== void 0) attributes.push(strAttr("http.request.method", rec.httpMethod));
|
|
56
|
+
if (rec.protocol !== void 0) attributes.push(strAttr("mcp.protocol", rec.protocol));
|
|
76
57
|
attributes.push(strAttr("mcp.stack", rec.stack));
|
|
77
58
|
if (rec.endUserId !== void 0) attributes.push(strAttr("mcp.end_user_id", rec.endUserId));
|
|
78
59
|
return {
|
|
@@ -120,6 +101,8 @@ function nowUnixNano() {
|
|
|
120
101
|
function nowMs() {
|
|
121
102
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
122
103
|
}
|
|
104
|
+
const METRICS_POST_TIMEOUT_MS = 3e3;
|
|
105
|
+
let warnedNoApiKey = false;
|
|
123
106
|
const NOOP_RECORDER = { async emit() {} };
|
|
124
107
|
function createNoopRecorder() {
|
|
125
108
|
return NOOP_RECORDER;
|
|
@@ -168,12 +151,13 @@ var BaseMetricRecorder = class {
|
|
|
168
151
|
}
|
|
169
152
|
async emit(ev) {
|
|
170
153
|
await this.applyLazyLogLevel();
|
|
171
|
-
log.info("tool.invoked", {
|
|
154
|
+
if (ev.outcome !== "auth_challenge") log.info("tool.invoked", {
|
|
172
155
|
tool: ev.tool,
|
|
173
156
|
method: ev.method,
|
|
174
157
|
outcome: ev.outcome,
|
|
175
158
|
durationMs: ev.durationMs,
|
|
176
159
|
stack: this.stack,
|
|
160
|
+
...ev.protocol !== void 0 && { protocol: ev.protocol },
|
|
177
161
|
...ev.errorText !== void 0 && { errorText: ev.errorText }
|
|
178
162
|
});
|
|
179
163
|
if (!this.config.enabled) return;
|
|
@@ -181,30 +165,34 @@ var BaseMetricRecorder = class {
|
|
|
181
165
|
log.warn("metrics.disabled_no_fetch", { endpoint: this.config.endpoint });
|
|
182
166
|
return;
|
|
183
167
|
}
|
|
184
|
-
const headers = { ...this.baseHeaders };
|
|
185
|
-
if (this.usesLovableEndpoint) {
|
|
186
|
-
const key = await this.resolveApiKey();
|
|
187
|
-
if (!key) {
|
|
188
|
-
log.warn("metrics.disabled_no_api_key", {
|
|
189
|
-
envVar: this.config.apiKeyEnvVar,
|
|
190
|
-
endpoint: this.config.endpoint
|
|
191
|
-
});
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
headers.authorization = `Bearer ${key}`;
|
|
195
|
-
}
|
|
196
|
-
const { errorText: _localOnly, ...wireEvent } = ev;
|
|
197
|
-
const body = buildLogsPayload([{
|
|
198
|
-
...wireEvent,
|
|
199
|
-
timeUnixNano: nowUnixNano(),
|
|
200
|
-
stack: this.stack
|
|
201
|
-
}], this.server);
|
|
202
168
|
try {
|
|
169
|
+
const headers = { ...this.baseHeaders };
|
|
170
|
+
if (this.usesLovableEndpoint) {
|
|
171
|
+
const key = await this.resolveApiKey();
|
|
172
|
+
if (!key) {
|
|
173
|
+
if (!warnedNoApiKey) {
|
|
174
|
+
warnedNoApiKey = true;
|
|
175
|
+
log.warn("metrics.disabled_no_api_key", {
|
|
176
|
+
envVar: this.config.apiKeyEnvVar,
|
|
177
|
+
endpoint: this.config.endpoint
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
headers.authorization = `Bearer ${key}`;
|
|
183
|
+
}
|
|
184
|
+
const { errorText: _localOnly, ...wireEvent } = ev;
|
|
185
|
+
const body = buildLogsPayload([{
|
|
186
|
+
...wireEvent,
|
|
187
|
+
timeUnixNano: nowUnixNano(),
|
|
188
|
+
stack: this.stack
|
|
189
|
+
}], this.server);
|
|
203
190
|
const res = await this.doFetch(this.config.endpoint, {
|
|
204
191
|
method: "POST",
|
|
205
192
|
headers,
|
|
206
193
|
body,
|
|
207
|
-
keepalive: true
|
|
194
|
+
keepalive: true,
|
|
195
|
+
signal: AbortSignal.timeout(METRICS_POST_TIMEOUT_MS)
|
|
208
196
|
});
|
|
209
197
|
if (!res.ok) log.warn("metrics.rejected", {
|
|
210
198
|
status: res.status,
|
|
@@ -295,8 +283,8 @@ var SupabaseMetricRecorder = class extends BaseMetricRecorder {
|
|
|
295
283
|
//#endregion
|
|
296
284
|
//#region src/metrics/recorder.ts
|
|
297
285
|
/** Vend the recorder for a stack, in-flight per request. Returns a no-op when
|
|
298
|
-
* metrics are disabled (`metrics: false`); otherwise the stack-specific class,
|
|
299
|
-
*
|
|
286
|
+
* metrics are disabled (`metrics: false`); otherwise the stack-specific class, which
|
|
287
|
+
* logs `tool.invoked` for tool invocations even if the key or endpoint is unavailable. */
|
|
300
288
|
function createRecorderForRuntime(mcp, opts) {
|
|
301
289
|
const config = resolveMetricsConfig(mcp.metrics);
|
|
302
290
|
const server = {
|
|
@@ -593,6 +581,16 @@ async function fetchVerificationKeySet(jwksUri) {
|
|
|
593
581
|
throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`, "jwks");
|
|
594
582
|
}
|
|
595
583
|
}
|
|
584
|
+
function assertCompactJwsShape(token) {
|
|
585
|
+
const parts = token.split(".");
|
|
586
|
+
if (parts.length !== 3 || parts.some((part) => part.length === 0)) {
|
|
587
|
+
log.debug("oauth.verify.bad_shape", {
|
|
588
|
+
tokenLength: token.length,
|
|
589
|
+
outcome: "401 invalid_token"
|
|
590
|
+
});
|
|
591
|
+
throw new OAuthTokenError(401, "invalid_token", "Access token is not a JWT");
|
|
592
|
+
}
|
|
593
|
+
}
|
|
596
594
|
function assertAccessTokenTyp(token, allowed) {
|
|
597
595
|
let header;
|
|
598
596
|
try {
|
|
@@ -694,6 +692,8 @@ function buildMcpAuthContext(args) {
|
|
|
694
692
|
function createOAuthTokenVerifier(auth, discovery) {
|
|
695
693
|
const allowedTyps = auth.accessTokenTyp ?? DEFAULT_ACCESS_TOKEN_TYPS;
|
|
696
694
|
return async (token, request, options) => {
|
|
695
|
+
assertCompactJwsShape(token);
|
|
696
|
+
assertAccessTokenTyp(token, allowedTyps);
|
|
697
697
|
const resource = resolveProtectedResource(auth, request, options);
|
|
698
698
|
const issuer = await discovery.resolveIssuer();
|
|
699
699
|
const acceptedAudiences = resolveAcceptedAudiences(auth, resource);
|
|
@@ -705,9 +705,7 @@ function createOAuthTokenVerifier(auth, discovery) {
|
|
|
705
705
|
});
|
|
706
706
|
const jwksUri = await discovery.resolveJwksUri();
|
|
707
707
|
log.debug("oauth.jwks.fetch", { jwksUri });
|
|
708
|
-
const
|
|
709
|
-
assertAccessTokenTyp(token, allowedTyps);
|
|
710
|
-
const claims = await verifyJwtClaims(token, keySet, issuer, auth);
|
|
708
|
+
const claims = await verifyJwtClaims(token, await fetchVerificationKeySet(jwksUri), issuer, auth);
|
|
711
709
|
const audienceVia = checkAcceptedAudience(claims, acceptedAudiences, auth);
|
|
712
710
|
assertNonEmptySubject(claims);
|
|
713
711
|
const context = buildMcpAuthContext({
|
|
@@ -719,11 +717,13 @@ function createOAuthTokenVerifier(auth, discovery) {
|
|
|
719
717
|
});
|
|
720
718
|
assertOAuthClientClaim(auth, context.principal.clientId);
|
|
721
719
|
log.info("oauth.verify.ok", {
|
|
722
|
-
sub: context.principal.sub,
|
|
723
|
-
clientId: context.principal.clientId,
|
|
724
720
|
scopes: context.principal.scopes,
|
|
725
721
|
audienceVia
|
|
726
722
|
});
|
|
723
|
+
log.debug("oauth.verify.principal", {
|
|
724
|
+
sub: context.principal.sub,
|
|
725
|
+
clientId: context.principal.clientId
|
|
726
|
+
});
|
|
727
727
|
return context;
|
|
728
728
|
};
|
|
729
729
|
}
|
|
@@ -776,6 +776,22 @@ function oauthUpstreamUnreachableResponse() {
|
|
|
776
776
|
}
|
|
777
777
|
});
|
|
778
778
|
}
|
|
779
|
+
const KNOWN_HTTP_METHODS = /* @__PURE__ */ new Set([
|
|
780
|
+
"GET",
|
|
781
|
+
"HEAD",
|
|
782
|
+
"POST",
|
|
783
|
+
"PUT",
|
|
784
|
+
"DELETE",
|
|
785
|
+
"PATCH",
|
|
786
|
+
"OPTIONS",
|
|
787
|
+
"TRACE",
|
|
788
|
+
"CONNECT",
|
|
789
|
+
"QUERY"
|
|
790
|
+
]);
|
|
791
|
+
function normalizeHttpMethod(method) {
|
|
792
|
+
const upper = method.toUpperCase();
|
|
793
|
+
return KNOWN_HTTP_METHODS.has(upper) ? upper : "_OTHER";
|
|
794
|
+
}
|
|
779
795
|
function parseBearerToken(request) {
|
|
780
796
|
const header = request.headers.get("Authorization");
|
|
781
797
|
if (!header) return void 0;
|
|
@@ -838,7 +854,18 @@ function createRequestAuthorizer(mcp, options = {}) {
|
|
|
838
854
|
const startedAt = nowMs();
|
|
839
855
|
const token = parseBearerToken(request);
|
|
840
856
|
if (!token) {
|
|
841
|
-
|
|
857
|
+
const httpMethod = normalizeHttpMethod(request.method);
|
|
858
|
+
log.info("auth.no_bearer_token", {
|
|
859
|
+
httpMethod,
|
|
860
|
+
outcome: "401"
|
|
861
|
+
});
|
|
862
|
+
await recorder?.emit({
|
|
863
|
+
tool: null,
|
|
864
|
+
method: "authorize",
|
|
865
|
+
outcome: "auth_challenge",
|
|
866
|
+
httpMethod,
|
|
867
|
+
durationMs: nowMs() - startedAt
|
|
868
|
+
});
|
|
842
869
|
return {
|
|
843
870
|
ok: false,
|
|
844
871
|
response: challengeResponse(runtime.auth, request, runtime.options, 401)
|
|
@@ -896,7 +923,12 @@ function createRequestAuthorizer(mcp, options = {}) {
|
|
|
896
923
|
response: challengeResponse(runtime.auth, request, runtime.options, err.status, err.oauthError, err.message)
|
|
897
924
|
};
|
|
898
925
|
}
|
|
899
|
-
log.
|
|
926
|
+
if (err instanceof errors.JOSEError) log.info("auth.token_rejected", {
|
|
927
|
+
...describeError(err),
|
|
928
|
+
status: 401,
|
|
929
|
+
oauthError: "invalid_token"
|
|
930
|
+
});
|
|
931
|
+
else log.error("auth.unexpected_error", {
|
|
900
932
|
...describeError(err),
|
|
901
933
|
outcome: "401"
|
|
902
934
|
});
|
|
@@ -908,4 +940,67 @@ function createRequestAuthorizer(mcp, options = {}) {
|
|
|
908
940
|
} };
|
|
909
941
|
}
|
|
910
942
|
//#endregion
|
|
911
|
-
|
|
943
|
+
//#region src/core/cors.ts
|
|
944
|
+
const EXPOSE_HEADERS = "WWW-Authenticate, MCP-Protocol-Version, Mcp-Session-Id";
|
|
945
|
+
const ALLOW_HEADERS = "Authorization, Content-Type, MCP-Protocol-Version, Mcp-Method, Mcp-Name, Mcp-Session-Id, Last-Event-ID";
|
|
946
|
+
const MCP_PARAM_HEADER = /^mcp-param-[!#$%&'*+.^_`|~0-9A-Za-z-]+$/i;
|
|
947
|
+
function appendVary(headers, value) {
|
|
948
|
+
const values = new Set((headers.get("Vary") ?? "").split(",").map((entry) => entry.trim()).filter(Boolean));
|
|
949
|
+
values.add(value);
|
|
950
|
+
headers.set("Vary", [...values].join(", "));
|
|
951
|
+
}
|
|
952
|
+
function addCorsHeaders(response, allowedOrigin, variesByOrigin) {
|
|
953
|
+
if (allowedOrigin !== void 0) {
|
|
954
|
+
response.headers.set("Access-Control-Allow-Origin", allowedOrigin);
|
|
955
|
+
response.headers.set("Access-Control-Expose-Headers", EXPOSE_HEADERS);
|
|
956
|
+
}
|
|
957
|
+
if (variesByOrigin) appendVary(response.headers, "Origin");
|
|
958
|
+
return response;
|
|
959
|
+
}
|
|
960
|
+
function allowedRequestHeaders(request) {
|
|
961
|
+
const allowed = new Map(ALLOW_HEADERS.split(", ").map((header) => [header.toLowerCase(), header]));
|
|
962
|
+
for (const header of (request.headers.get("Access-Control-Request-Headers") ?? "").split(",")) {
|
|
963
|
+
const normalized = header.trim();
|
|
964
|
+
if (MCP_PARAM_HEADER.test(normalized)) allowed.set(normalized.toLowerCase(), normalized);
|
|
965
|
+
}
|
|
966
|
+
return [...allowed.values()].join(", ");
|
|
967
|
+
}
|
|
968
|
+
function evaluateCors(request, allowedOrigins) {
|
|
969
|
+
const origin = request.headers.get("Origin");
|
|
970
|
+
const allowAny = allowedOrigins === "any";
|
|
971
|
+
let allowedOrigin;
|
|
972
|
+
if (allowAny) allowedOrigin = "*";
|
|
973
|
+
else if (origin === null) allowedOrigin = void 0;
|
|
974
|
+
else if (origin === new URL(request.url).origin || allowedOrigins?.includes(origin)) allowedOrigin = origin;
|
|
975
|
+
else allowedOrigin = null;
|
|
976
|
+
if (allowedOrigin === null) {
|
|
977
|
+
const response = Response.json({ error: "origin not allowed" }, {
|
|
978
|
+
status: 403,
|
|
979
|
+
headers: { "Cache-Control": "no-store" }
|
|
980
|
+
});
|
|
981
|
+
appendVary(response.headers, "Origin");
|
|
982
|
+
return {
|
|
983
|
+
ok: false,
|
|
984
|
+
response
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
return {
|
|
988
|
+
ok: true,
|
|
989
|
+
withHeaders: (response) => addCorsHeaders(response, allowedOrigin, !allowAny),
|
|
990
|
+
preflight: (allowMethods) => {
|
|
991
|
+
const requestedHeaders = request.headers.get("Access-Control-Request-Headers");
|
|
992
|
+
const response = new Response(null, {
|
|
993
|
+
status: 204,
|
|
994
|
+
headers: {
|
|
995
|
+
"Access-Control-Allow-Methods": allowMethods,
|
|
996
|
+
"Access-Control-Allow-Headers": allowedRequestHeaders(request),
|
|
997
|
+
"Access-Control-Max-Age": "86400"
|
|
998
|
+
}
|
|
999
|
+
});
|
|
1000
|
+
if (requestedHeaders) appendVary(response.headers, "Access-Control-Request-Headers");
|
|
1001
|
+
return addCorsHeaders(response, allowedOrigin, !allowAny);
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
}
|
|
1005
|
+
//#endregion
|
|
1006
|
+
export { oauthConfigurationErrorResponse as a, createRecorderForRuntime as c, JSON_HEADERS as d, finalizeWireResponse as f, getOAuthRuntime as i, createNoopRecorder as l, assertRestResourceBinding as n, assertResourcePathShape as o, methodNotAllowed as p, createRequestAuthorizer as r, resolveProtectedResource as s, evaluateCors as t, nowMs as u };
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
* proxy which *overwrites* the header (Lovable's web-proxy does), never by a
|
|
16
16
|
* bare SDK consumer.
|
|
17
17
|
* - `X-Forwarded-Proto` only selects http/https, so it is gated separately:
|
|
18
|
-
* Supabase
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* Supabase's gateway stamps it (that stack always trusts it), and Lovable's
|
|
19
|
+
* preview proxy overwrites it before the TanStack dev server, so the TanStack
|
|
20
|
+
* Vite plugin emits the flag by default.
|
|
21
21
|
*/
|
|
22
22
|
function applyForwardedOrigin(request, options) {
|
|
23
23
|
const proto = options.trustForwardedProto ? firstForwardedValue(request, "x-forwarded-proto") : void 0;
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
* proxy which *overwrites* the header (Lovable's web-proxy does), never by a
|
|
16
16
|
* bare SDK consumer.
|
|
17
17
|
* - `X-Forwarded-Proto` only selects http/https, so it is gated separately:
|
|
18
|
-
* Supabase
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* Supabase's gateway stamps it (that stack always trusts it), and Lovable's
|
|
19
|
+
* preview proxy overwrites it before the TanStack dev server, so the TanStack
|
|
20
|
+
* Vite plugin emits the flag by default.
|
|
21
21
|
*/
|
|
22
22
|
function applyForwardedOrigin(request, options) {
|
|
23
23
|
const proto = options.trustForwardedProto ? firstForwardedValue(request, "x-forwarded-proto") : void 0;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_cors = require("./cors-CmKzDN7k.cjs");
|
|
2
2
|
//#region src/protocols/gate.ts
|
|
3
3
|
function createGatedHandler(gate) {
|
|
4
4
|
const allow = [...gate.methods, "OPTIONS"].join(", ");
|
|
@@ -8,9 +8,11 @@ function createGatedHandler(gate) {
|
|
|
8
8
|
if (!gate.methods.includes(request.method)) return gate.methodNotAllowed(allow);
|
|
9
9
|
return gate.handle(request, authResult, recorder, ...extra);
|
|
10
10
|
};
|
|
11
|
-
return async (request, recorder =
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
return async (request, recorder = require_cors.createNoopRecorder(), ...extra) => {
|
|
12
|
+
const cors = require_cors.evaluateCors(request, gate.allowedOrigins);
|
|
13
|
+
if (!cors.ok) return require_cors.finalizeWireResponse(request, cors.response);
|
|
14
|
+
if (request.method === "OPTIONS") return cors.preflight(allow);
|
|
15
|
+
const final = require_cors.finalizeWireResponse(request, cors.withHeaders(await respond(request, recorder, ...extra)));
|
|
14
16
|
if (!final.headers.has("Cache-Control")) final.headers.set("Cache-Control", "no-store");
|
|
15
17
|
return final;
|
|
16
18
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { f as finalizeWireResponse, l as createNoopRecorder, t as evaluateCors } from "./cors-D4YbODs-.js";
|
|
2
2
|
//#region src/protocols/gate.ts
|
|
3
3
|
function createGatedHandler(gate) {
|
|
4
4
|
const allow = [...gate.methods, "OPTIONS"].join(", ");
|
|
@@ -9,8 +9,10 @@ function createGatedHandler(gate) {
|
|
|
9
9
|
return gate.handle(request, authResult, recorder, ...extra);
|
|
10
10
|
};
|
|
11
11
|
return async (request, recorder = createNoopRecorder(), ...extra) => {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const cors = evaluateCors(request, gate.allowedOrigins);
|
|
13
|
+
if (!cors.ok) return finalizeWireResponse(request, cors.response);
|
|
14
|
+
if (request.method === "OPTIONS") return cors.preflight(allow);
|
|
15
|
+
const final = finalizeWireResponse(request, cors.withHeaders(await respond(request, recorder, ...extra)));
|
|
14
16
|
if (!final.headers.has("Cache-Control")) final.headers.set("Cache-Control", "no-store");
|
|
15
17
|
return final;
|
|
16
18
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_logger = require("./logger-
|
|
2
|
+
const require_logger = require("./logger-CN1q-KNn.cjs");
|
|
3
|
+
const require_schema = require("./schema-D3vClxb7.cjs");
|
|
3
4
|
const require_errors = require("./errors-CN6Da8iz.cjs");
|
|
4
5
|
//#region src/core/define.ts
|
|
5
6
|
function assertUniqueNames(mcp) {
|
|
@@ -79,6 +80,39 @@ function freezeAuth(auth) {
|
|
|
79
80
|
if (auth.accessTokenTyp) Object.freeze(auth.accessTokenTyp);
|
|
80
81
|
Object.freeze(auth);
|
|
81
82
|
}
|
|
83
|
+
function assertAllowedOrigins(allowedOrigins) {
|
|
84
|
+
if (allowedOrigins === void 0 || allowedOrigins === "any") return;
|
|
85
|
+
if (!Array.isArray(allowedOrigins)) throw new Error(`@lovable.dev/mcp-js: allowedOrigins must be "any" or an array of exact origins`);
|
|
86
|
+
for (const origin of allowedOrigins) {
|
|
87
|
+
if (typeof origin !== "string") throw new Error(`@lovable.dev/mcp-js: allowedOrigins must contain strings`);
|
|
88
|
+
let parsed;
|
|
89
|
+
try {
|
|
90
|
+
parsed = new URL(origin);
|
|
91
|
+
} catch {
|
|
92
|
+
throw new Error(`@lovable.dev/mcp-js: allowedOrigins must contain valid exact origins`);
|
|
93
|
+
}
|
|
94
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || parsed.origin !== origin) throw new Error(`@lovable.dev/mcp-js: allowedOrigins entry "${origin}" must be an exact http(s) origin without a path, query, fragment, or trailing slash`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function assertToolSchemas(mcp) {
|
|
98
|
+
for (const tool of mcp.tools) for (const [name, definition, strategy] of [[
|
|
99
|
+
"inputSchema",
|
|
100
|
+
tool.inputSchema,
|
|
101
|
+
"input"
|
|
102
|
+
], [
|
|
103
|
+
"outputSchema",
|
|
104
|
+
tool.outputSchema,
|
|
105
|
+
"output"
|
|
106
|
+
]]) {
|
|
107
|
+
if (!definition) continue;
|
|
108
|
+
try {
|
|
109
|
+
require_schema.jsonSchemaFromDefinition(definition, strategy);
|
|
110
|
+
} catch (error) {
|
|
111
|
+
const detail = error instanceof Error ? `: ${error.message}` : "";
|
|
112
|
+
throw new Error(`@lovable.dev/mcp-js: tool "${tool.name}" ${name} cannot be represented as JSON Schema${detail}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
82
116
|
/**
|
|
83
117
|
* Declare a single MCP tool. Import the result into your MCP definition's
|
|
84
118
|
* `tools` array — `defineMcp({ tools: [echoTool, ...] })`.
|
|
@@ -101,8 +135,11 @@ function defineMcp(def) {
|
|
|
101
135
|
assertNonEmptyString("version", def.version);
|
|
102
136
|
assertUniqueNames(def);
|
|
103
137
|
if (def.auth) assertOAuthConfig(def.auth);
|
|
138
|
+
assertAllowedOrigins(def.allowedOrigins);
|
|
139
|
+
assertToolSchemas(def);
|
|
104
140
|
require_logger.resolveMetricsConfig(def.metrics);
|
|
105
141
|
freezeAuth(def.auth);
|
|
142
|
+
if (Array.isArray(def.allowedOrigins)) Object.freeze(def.allowedOrigins);
|
|
106
143
|
Object.freeze(def.tools);
|
|
107
144
|
for (const tool of def.tools) Object.freeze(tool);
|
|
108
145
|
return def;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as McpAuthConfig, S as JwtClaims, _ as
|
|
1
|
+
import { C as MetricsOptions, E as McpAuthConfig, S as MetricsConfig, T as JwtClaims, _ as ToolDefinition, a as EmbeddedResource, b as ZodRawShape, c as JsonValue, d as McpDefinitionInput, f as ResourceLink, g as ToolContent, h as ToolAnnotations, i as EmbeddedBlobResource, l as McpAllowedOrigins, m as TextContent, n as ContentAnnotations, o as EmbeddedTextResource, p as ResourceLinkIcon, r as ContentBlock, s as ImageContent, t as AudioContent, u as McpDefinition, v as ToolHandlerResult, w as ToolContext, x as ZodSchema, y as ZodOutputSchema } from "./types-D1cgsnPu.cjs";
|
|
2
2
|
//#region src/core/define.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Declare a single MCP tool. Import the result into your MCP definition's
|
|
@@ -8,7 +8,7 @@ import { C as McpAuthConfig, S as JwtClaims, _ as ZodRawShape, a as EmbeddedReso
|
|
|
8
8
|
* full `z.object(...)` — the MCP SDK builds the object wrapper internally
|
|
9
9
|
* and the raw shape is what the JSON-RPC `tools/list` payload exposes.
|
|
10
10
|
*/
|
|
11
|
-
declare function defineTool<TInput extends ZodRawShape | undefined = undefined, TOutput extends
|
|
11
|
+
declare function defineTool<TInput extends ZodRawShape | undefined = undefined, TOutput extends ZodOutputSchema | undefined = undefined>(def: ToolDefinition<TInput, TOutput>): ToolDefinition<TInput, TOutput>;
|
|
12
12
|
/**
|
|
13
13
|
* Declare the MCP server. `export default` the result from your MCP
|
|
14
14
|
* entrypoint (default `lib/mcp/index.ts`); the Vite plugin reads it to
|
|
@@ -71,4 +71,4 @@ type LogLevel = "silent" | "error" | "warn" | "info" | "debug";
|
|
|
71
71
|
*/
|
|
72
72
|
declare function setLogLevel(level: LogLevel): LogLevel;
|
|
73
73
|
//#endregion
|
|
74
|
-
export { type AudioContent, type ContentAnnotations, type ContentBlock, type EmbeddedBlobResource, type EmbeddedResource, type EmbeddedTextResource, type ImageContent, type IssuerOAuthOptions, type JwtClaims, type LogLevel, type McpDefinitionInput, type MetricsConfig, type MetricsOptions, type ResourceLink, type ResourceLinkIcon, type TextContent, type ToolAnnotations, type ToolContent, ToolContext, type ToolDefinition, ToolError, type ToolHandlerResult, type ZodRawShape, type ZodSchema, auth, defineMcp, defineTool, setLogLevel };
|
|
74
|
+
export { type AudioContent, type ContentAnnotations, type ContentBlock, type EmbeddedBlobResource, type EmbeddedResource, type EmbeddedTextResource, type ImageContent, type IssuerOAuthOptions, type JsonValue, type JwtClaims, type LogLevel, type McpAllowedOrigins, type McpDefinitionInput, type MetricsConfig, type MetricsOptions, type ResourceLink, type ResourceLinkIcon, type TextContent, type ToolAnnotations, type ToolContent, ToolContext, type ToolDefinition, ToolError, type ToolHandlerResult, type ZodOutputSchema, type ZodRawShape, type ZodSchema, auth, defineMcp, defineTool, setLogLevel };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as McpAuthConfig, S as JwtClaims, _ as
|
|
1
|
+
import { C as MetricsOptions, E as McpAuthConfig, S as MetricsConfig, T as JwtClaims, _ as ToolDefinition, a as EmbeddedResource, b as ZodRawShape, c as JsonValue, d as McpDefinitionInput, f as ResourceLink, g as ToolContent, h as ToolAnnotations, i as EmbeddedBlobResource, l as McpAllowedOrigins, m as TextContent, n as ContentAnnotations, o as EmbeddedTextResource, p as ResourceLinkIcon, r as ContentBlock, s as ImageContent, t as AudioContent, u as McpDefinition, v as ToolHandlerResult, w as ToolContext, x as ZodSchema, y as ZodOutputSchema } from "./types-D1cgsnPu.js";
|
|
2
2
|
//#region src/core/define.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Declare a single MCP tool. Import the result into your MCP definition's
|
|
@@ -8,7 +8,7 @@ import { C as McpAuthConfig, S as JwtClaims, _ as ZodRawShape, a as EmbeddedReso
|
|
|
8
8
|
* full `z.object(...)` — the MCP SDK builds the object wrapper internally
|
|
9
9
|
* and the raw shape is what the JSON-RPC `tools/list` payload exposes.
|
|
10
10
|
*/
|
|
11
|
-
declare function defineTool<TInput extends ZodRawShape | undefined = undefined, TOutput extends
|
|
11
|
+
declare function defineTool<TInput extends ZodRawShape | undefined = undefined, TOutput extends ZodOutputSchema | undefined = undefined>(def: ToolDefinition<TInput, TOutput>): ToolDefinition<TInput, TOutput>;
|
|
12
12
|
/**
|
|
13
13
|
* Declare the MCP server. `export default` the result from your MCP
|
|
14
14
|
* entrypoint (default `lib/mcp/index.ts`); the Vite plugin reads it to
|
|
@@ -71,4 +71,4 @@ type LogLevel = "silent" | "error" | "warn" | "info" | "debug";
|
|
|
71
71
|
*/
|
|
72
72
|
declare function setLogLevel(level: LogLevel): LogLevel;
|
|
73
73
|
//#endregion
|
|
74
|
-
export { type AudioContent, type ContentAnnotations, type ContentBlock, type EmbeddedBlobResource, type EmbeddedResource, type EmbeddedTextResource, type ImageContent, type IssuerOAuthOptions, type JwtClaims, type LogLevel, type McpDefinitionInput, type MetricsConfig, type MetricsOptions, type ResourceLink, type ResourceLinkIcon, type TextContent, type ToolAnnotations, type ToolContent, ToolContext, type ToolDefinition, ToolError, type ToolHandlerResult, type ZodRawShape, type ZodSchema, auth, defineMcp, defineTool, setLogLevel };
|
|
74
|
+
export { type AudioContent, type ContentAnnotations, type ContentBlock, type EmbeddedBlobResource, type EmbeddedResource, type EmbeddedTextResource, type ImageContent, type IssuerOAuthOptions, type JsonValue, type JwtClaims, type LogLevel, type McpAllowedOrigins, type McpDefinitionInput, type MetricsConfig, type MetricsOptions, type ResourceLink, type ResourceLinkIcon, type TextContent, type ToolAnnotations, type ToolContent, ToolContext, type ToolDefinition, ToolError, type ToolHandlerResult, type ZodOutputSchema, type ZodRawShape, type ZodSchema, auth, defineMcp, defineTool, setLogLevel };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { a as setLogLevel, o as parseSafeUrl, s as trimTrailingSlash, u as resolveMetricsConfig } from "./logger-
|
|
1
|
+
import { a as setLogLevel, o as parseSafeUrl, s as trimTrailingSlash, u as resolveMetricsConfig } from "./logger-Ctv5xUSD.js";
|
|
2
|
+
import { t as jsonSchemaFromDefinition } from "./schema-CW1jKvio.js";
|
|
2
3
|
import { i as ToolContext, t as ToolError } from "./errors-DSe96Ffd.js";
|
|
3
4
|
//#region src/core/define.ts
|
|
4
5
|
function assertUniqueNames(mcp) {
|
|
@@ -78,6 +79,39 @@ function freezeAuth(auth) {
|
|
|
78
79
|
if (auth.accessTokenTyp) Object.freeze(auth.accessTokenTyp);
|
|
79
80
|
Object.freeze(auth);
|
|
80
81
|
}
|
|
82
|
+
function assertAllowedOrigins(allowedOrigins) {
|
|
83
|
+
if (allowedOrigins === void 0 || allowedOrigins === "any") return;
|
|
84
|
+
if (!Array.isArray(allowedOrigins)) throw new Error(`@lovable.dev/mcp-js: allowedOrigins must be "any" or an array of exact origins`);
|
|
85
|
+
for (const origin of allowedOrigins) {
|
|
86
|
+
if (typeof origin !== "string") throw new Error(`@lovable.dev/mcp-js: allowedOrigins must contain strings`);
|
|
87
|
+
let parsed;
|
|
88
|
+
try {
|
|
89
|
+
parsed = new URL(origin);
|
|
90
|
+
} catch {
|
|
91
|
+
throw new Error(`@lovable.dev/mcp-js: allowedOrigins must contain valid exact origins`);
|
|
92
|
+
}
|
|
93
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || parsed.origin !== origin) throw new Error(`@lovable.dev/mcp-js: allowedOrigins entry "${origin}" must be an exact http(s) origin without a path, query, fragment, or trailing slash`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function assertToolSchemas(mcp) {
|
|
97
|
+
for (const tool of mcp.tools) for (const [name, definition, strategy] of [[
|
|
98
|
+
"inputSchema",
|
|
99
|
+
tool.inputSchema,
|
|
100
|
+
"input"
|
|
101
|
+
], [
|
|
102
|
+
"outputSchema",
|
|
103
|
+
tool.outputSchema,
|
|
104
|
+
"output"
|
|
105
|
+
]]) {
|
|
106
|
+
if (!definition) continue;
|
|
107
|
+
try {
|
|
108
|
+
jsonSchemaFromDefinition(definition, strategy);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
const detail = error instanceof Error ? `: ${error.message}` : "";
|
|
111
|
+
throw new Error(`@lovable.dev/mcp-js: tool "${tool.name}" ${name} cannot be represented as JSON Schema${detail}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
81
115
|
/**
|
|
82
116
|
* Declare a single MCP tool. Import the result into your MCP definition's
|
|
83
117
|
* `tools` array — `defineMcp({ tools: [echoTool, ...] })`.
|
|
@@ -100,8 +134,11 @@ function defineMcp(def) {
|
|
|
100
134
|
assertNonEmptyString("version", def.version);
|
|
101
135
|
assertUniqueNames(def);
|
|
102
136
|
if (def.auth) assertOAuthConfig(def.auth);
|
|
137
|
+
assertAllowedOrigins(def.allowedOrigins);
|
|
138
|
+
assertToolSchemas(def);
|
|
103
139
|
resolveMetricsConfig(def.metrics);
|
|
104
140
|
freezeAuth(def.auth);
|
|
141
|
+
if (Array.isArray(def.allowedOrigins)) Object.freeze(def.allowedOrigins);
|
|
105
142
|
Object.freeze(def.tools);
|
|
106
143
|
for (const tool of def.tools) Object.freeze(tool);
|
|
107
144
|
return def;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const require_schema = require("./schema-D3vClxb7.cjs");
|
|
2
|
+
const require_cors = require("./cors-CmKzDN7k.cjs");
|
|
3
|
+
const require_gate = require("./gate-n_HX6eQ5.cjs");
|
|
4
|
+
//#region src/protocols/rest/list-tools.ts
|
|
5
|
+
function schemaToJsonSchema(definition, pipeStrategy) {
|
|
6
|
+
if (!definition) return null;
|
|
7
|
+
return require_schema.jsonSchemaFromDefinition(definition, pipeStrategy);
|
|
8
|
+
}
|
|
9
|
+
function buildMcpListing(mcp) {
|
|
10
|
+
return {
|
|
11
|
+
server: {
|
|
12
|
+
name: mcp.name,
|
|
13
|
+
version: mcp.version,
|
|
14
|
+
title: mcp.title
|
|
15
|
+
},
|
|
16
|
+
tools: mcp.tools.map((tool) => ({
|
|
17
|
+
name: tool.name,
|
|
18
|
+
title: tool.title,
|
|
19
|
+
description: tool.description,
|
|
20
|
+
annotations: tool.annotations,
|
|
21
|
+
inputSchema: schemaToJsonSchema(tool.inputSchema, "input"),
|
|
22
|
+
outputSchema: schemaToJsonSchema(tool.outputSchema, "output")
|
|
23
|
+
}))
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function createListToolsHandler(mcp, options = {}) {
|
|
27
|
+
require_cors.assertRestResourceBinding(mcp, options);
|
|
28
|
+
return require_gate.createGatedHandler({
|
|
29
|
+
authorizer: require_cors.createRequestAuthorizer(mcp, options),
|
|
30
|
+
allowedOrigins: mcp.allowedOrigins,
|
|
31
|
+
methods: ["GET", "HEAD"],
|
|
32
|
+
methodNotAllowed: require_cors.methodNotAllowed,
|
|
33
|
+
handle: async () => Response.json(buildMcpListing(mcp))
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
Object.defineProperty(exports, "buildMcpListing", {
|
|
38
|
+
enumerable: true,
|
|
39
|
+
get: function() {
|
|
40
|
+
return buildMcpListing;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
Object.defineProperty(exports, "createListToolsHandler", {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
get: function() {
|
|
46
|
+
return createListToolsHandler;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { toJsonSchemaCompat } from "@modelcontextprotocol/sdk/server/zod-json-schema-compat.js";
|
|
1
|
+
import { t as jsonSchemaFromDefinition } from "./schema-CW1jKvio.js";
|
|
2
|
+
import { n as assertRestResourceBinding, p as methodNotAllowed, r as createRequestAuthorizer } from "./cors-D4YbODs-.js";
|
|
3
|
+
import { t as createGatedHandler } from "./gate-pGsVlY_4.js";
|
|
5
4
|
//#region src/protocols/rest/list-tools.ts
|
|
6
|
-
function
|
|
7
|
-
if (!
|
|
8
|
-
|
|
9
|
-
return toJsonSchemaCompat(objectFromShape(shape));
|
|
10
|
-
} catch {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
5
|
+
function schemaToJsonSchema(definition, pipeStrategy) {
|
|
6
|
+
if (!definition) return null;
|
|
7
|
+
return jsonSchemaFromDefinition(definition, pipeStrategy);
|
|
13
8
|
}
|
|
14
9
|
function buildMcpListing(mcp) {
|
|
15
10
|
return {
|
|
@@ -23,8 +18,8 @@ function buildMcpListing(mcp) {
|
|
|
23
18
|
title: tool.title,
|
|
24
19
|
description: tool.description,
|
|
25
20
|
annotations: tool.annotations,
|
|
26
|
-
inputSchema:
|
|
27
|
-
outputSchema:
|
|
21
|
+
inputSchema: schemaToJsonSchema(tool.inputSchema, "input"),
|
|
22
|
+
outputSchema: schemaToJsonSchema(tool.outputSchema, "output")
|
|
28
23
|
}))
|
|
29
24
|
};
|
|
30
25
|
}
|
|
@@ -32,6 +27,7 @@ function createListToolsHandler(mcp, options = {}) {
|
|
|
32
27
|
assertRestResourceBinding(mcp, options);
|
|
33
28
|
return createGatedHandler({
|
|
34
29
|
authorizer: createRequestAuthorizer(mcp, options),
|
|
30
|
+
allowedOrigins: mcp.allowedOrigins,
|
|
35
31
|
methods: ["GET", "HEAD"],
|
|
36
32
|
methodNotAllowed,
|
|
37
33
|
handle: async () => Response.json(buildMcpListing(mcp))
|