@lovable.dev/mcp-js 2.0.0 → 2.0.2-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 +12 -2
- package/dist/cli/extract-manifest.cjs +5 -150
- package/dist/cli/extract-manifest.js +5 -150
- package/dist/{cors-Bb8_NLEB.js → cors-BLtFfCwv.js} +1 -1
- package/dist/{cors-aOILwe5U.cjs → cors-DiBSnA0M.cjs} +1 -1
- package/dist/io-CKGFa7_M.cjs +155 -0
- package/dist/io-ufHBQyKg.js +152 -0
- package/dist/{mcp-B1hj8ZPg.js → mcp-BQeQCXB4.js} +1 -1
- package/dist/{mcp-Bbl8sdkl.cjs → mcp-LfeCqruq.cjs} +1 -1
- package/dist/{package-RqZMyBY1.cjs → package-BGn-LvT3.cjs} +1 -1
- package/dist/{package-CZERyrAn.js → package-Bu8wLlvG.js} +1 -1
- package/dist/protocols/mcp/index.cjs +1 -1
- package/dist/protocols/mcp/index.js +1 -1
- package/dist/protocols/oauth-metadata.cjs +1 -1
- package/dist/protocols/oauth-metadata.js +1 -1
- package/dist/stacks/supabase/index.cjs +2 -2
- package/dist/stacks/supabase/index.js +2 -2
- package/dist/stacks/supabase/vite.cjs +1 -1
- package/dist/stacks/supabase/vite.js +1 -1
- package/dist/stacks/tanstack/index.cjs +2 -2
- package/dist/stacks/tanstack/index.js +2 -2
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -228,9 +228,19 @@ The request-derived `resource` default trusts the incoming `Host` to name this s
|
|
|
228
228
|
|
|
229
229
|
Use `auth.oauth.issuer(...)`, set `resource` or `acceptedAudiences` to anchor the accepted audience, and optionally set `jwksUri` and `requiredScopes`. For Supabase project auth, set `acceptedAudiences: "authenticated"`, keep app/business checks in app code, and forward `ctx.getToken()` to Supabase for RLS-backed data access.
|
|
230
230
|
|
|
231
|
+
## Security posture
|
|
232
|
+
|
|
233
|
+
For anyone evaluating an app that exposes an MCP server with this package:
|
|
234
|
+
|
|
235
|
+
- **Verification runs in the app runtime.** When `defineMcp({ auth })` configures OAuth, the emitted TanStack route or Supabase Edge Function verifies the bearer before dispatching a tool. Clients call the app's published endpoint; the SDK does not relay MCP calls through a shared Lovable MCP protocol gateway, although a Lovable-hosted TanStack app still receives ordinary web traffic through Lovable's hosting proxy. The SDK may fetch issuer metadata and JWKS. When default usage telemetry is emitted, it sends the operational fields described below, including the verified token `sub`; it never sends the bearer, full claims, tool arguments, or tool results.
|
|
236
|
+
- **No protocol sessions.** Every HTTP request gets a fresh MCP server, auth context, and tool callback closure. The endpoint never mints a session ID or retains MCP protocol or auth session state across requests. Durable application state belongs in the app's own storage.
|
|
237
|
+
- **Audience validation is explicit.** A populated token `aud` must exactly match `resource` or `acceptedAudiences`. For issuer compatibility, the default also accepts a matching `resource` claim when `aud` is absent or an empty array; set `acceptResourceClaim: false` to require a matching `aud` (strict RFC 9068).
|
|
238
|
+
- **The deployment controls the SDK version.** TanStack resolves the app's declared dependency through its package manager and lockfile. The generated Supabase function exact-pins the SDK release that emitted it. Updating or regenerating the dependency and redeploying is how an app adopts a newer SDK.
|
|
239
|
+
- **Controls are divided between layers.** When OAuth is configured, the SDK owns bearer verification; it also owns origin policy (`allowedOrigins`) and redacts unexpected errors. `ToolError` and returned `isError` results are intentionally caller-visible. Per-tool authorization, data access (including RLS), rate limiting, and WAF belong to the app and its host.
|
|
240
|
+
|
|
231
241
|
## Debug logging
|
|
232
242
|
|
|
233
|
-
The runtime logs operational events (tool invocations, auth outcomes, warnings, errors) at `info` by default. Raise the level to `debug` to trace OAuth discovery, JWKS resolution, and token verification when a deployed MCP server returns `401`/`500` and you need to see why. Logs go to `console` (so they land in your platform's function logs) and **never include the bearer token
|
|
243
|
+
The runtime logs operational events (tool invocations, auth outcomes, warnings, errors) at `info` by default. Raise the level to `debug` to trace OAuth discovery, JWKS resolution, and token verification when a deployed MCP server returns `401`/`500` and you need to see why. Logs go to `console` (so they land in your platform's function logs) and **never include the bearer token or full claims**. Depending on the log level, operational fields include the JWT header `alg`/`kid`, `issuer`, `jwks_uri`, token scopes, and `jose` error codes. The default `info` level excludes end-user identifiers; the token `sub`/`client_id` appears only at `debug`, as the `oauth.verify.principal` event.
|
|
234
244
|
|
|
235
245
|
Enable it either way:
|
|
236
246
|
|
|
@@ -251,7 +261,7 @@ A `500` on an OAuth-protected route is always one of two causes, logged at `erro
|
|
|
251
261
|
|
|
252
262
|
## Usage metrics
|
|
253
263
|
|
|
254
|
-
Each MCP server records per-invocation telemetry — tool name, JSON-RPC method, outcome, and
|
|
264
|
+
Each MCP server records per-invocation telemetry — tool name, JSON-RPC method, outcome, latency, request and response sizes when available, and the verified token `sub` for authenticated calls — as **OTLP/HTTP JSON logs**, one awaited POST per record, bounded by a 3-second timeout; a failed or slow POST is logged (`metrics.failed`) and swallowed, never failing the request. Outcomes cover tool results (`ok`, `tool_error`, `handler_error`, `transport_error`), the authorization gate — `auth_challenge` for an unauthenticated request answered with the `401` challenge (so probe traffic produces records), and the `auth_*` discovery/JWKS failure outcomes — and `origin_rejected` for a request refused `403` by the origin policy. Tool-call records also carry the protocol era (`mcp.protocol`: `2026-07-28` or `legacy`); records emitted before protocol classification (auth challenges, transport errors, origin rejections) have no protocol attribute. The bearer token, full claims, tool arguments, and response payloads are never captured. Emission is **on by default** and self-disables at runtime when `LOVABLE_API_KEY` is absent: records are dropped and one `metrics.disabled_no_api_key` warning is logged per process, so a local `vite dev` stays quiet. With `metrics: false` the recorder never runs — on Deno and Cloudflare Workers that also means `LOVABLE_MCP_LOG_LEVEL` is never applied (use `setLogLevel()` instead).
|
|
255
265
|
|
|
256
266
|
Configure it on the MCP definition:
|
|
257
267
|
|
|
@@ -1,155 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_schema = require("../schema-D3vClxb7.cjs");
|
|
3
|
-
const require_package = require("../package-RqZMyBY1.cjs");
|
|
4
|
-
const require_fs_errors = require("../fs-errors-CWNzOV75.cjs");
|
|
5
|
-
let node_fs = require("node:fs");
|
|
6
|
-
let node_path = require("node:path");
|
|
7
|
-
let vite = require("vite");
|
|
8
|
-
let node_crypto = require("node:crypto");
|
|
9
|
-
//#region src/manifest/listing.ts
|
|
10
|
-
function schemaToJsonSchema(definition, pipeStrategy) {
|
|
11
|
-
if (!definition) return null;
|
|
12
|
-
return require_schema.jsonSchemaFromDefinition(definition, pipeStrategy);
|
|
13
|
-
}
|
|
14
|
-
function buildMcpListing(mcp) {
|
|
15
|
-
return {
|
|
16
|
-
server: {
|
|
17
|
-
name: mcp.name,
|
|
18
|
-
version: mcp.version,
|
|
19
|
-
title: mcp.title
|
|
20
|
-
},
|
|
21
|
-
tools: mcp.tools.map((tool) => ({
|
|
22
|
-
name: tool.name,
|
|
23
|
-
title: tool.title,
|
|
24
|
-
description: tool.description,
|
|
25
|
-
annotations: tool.annotations,
|
|
26
|
-
inputSchema: schemaToJsonSchema(tool.inputSchema, "input"),
|
|
27
|
-
outputSchema: schemaToJsonSchema(tool.outputSchema, "output")
|
|
28
|
-
}))
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
const MANIFEST_RELATIVE_PATH = ".lovable/mcp/manifest.json";
|
|
32
|
-
function manifestAuth(auth) {
|
|
33
|
-
if (!auth) return { type: "none" };
|
|
34
|
-
const oauth = {
|
|
35
|
-
type: "oauth",
|
|
36
|
-
issuer: auth.issuer
|
|
37
|
-
};
|
|
38
|
-
if (auth.resource !== void 0) oauth.resource = auth.resource;
|
|
39
|
-
if (auth.resourceName !== void 0) oauth.resource_name = auth.resourceName;
|
|
40
|
-
if (auth.resourceDocumentation !== void 0) oauth.resource_documentation = auth.resourceDocumentation;
|
|
41
|
-
if (auth.protectedResourceMetadataUrl !== void 0) oauth.protected_resource_metadata_url = auth.protectedResourceMetadataUrl;
|
|
42
|
-
if (auth.requireOAuthClientClaim !== void 0) oauth.require_oauth_client_claim = auth.requireOAuthClientClaim;
|
|
43
|
-
if (auth.acceptResourceClaim !== void 0) oauth.accept_resource_claim = auth.acceptResourceClaim;
|
|
44
|
-
if (auth.acceptedAudiences !== void 0) oauth.accepted_audiences = auth.acceptedAudiences;
|
|
45
|
-
if (auth.requiredScopes !== void 0) oauth.required_scopes = auth.requiredScopes;
|
|
46
|
-
if (auth.jwksUri !== void 0) oauth.jwks_uri = auth.jwksUri;
|
|
47
|
-
if (auth.algorithms !== void 0) oauth.algorithms = auth.algorithms;
|
|
48
|
-
if (auth.clockToleranceSeconds !== void 0) oauth.clock_tolerance_seconds = auth.clockToleranceSeconds;
|
|
49
|
-
return oauth;
|
|
50
|
-
}
|
|
51
|
-
function isToolShape(tool) {
|
|
52
|
-
if (typeof tool !== "object" || tool === null) return false;
|
|
53
|
-
const t = tool;
|
|
54
|
-
return typeof t.name === "string" && typeof t.title === "string" && typeof t.description === "string";
|
|
55
|
-
}
|
|
56
|
-
function isAuthShape(auth) {
|
|
57
|
-
if (auth === void 0) return true;
|
|
58
|
-
if (typeof auth !== "object" || auth === null) return false;
|
|
59
|
-
const a = auth;
|
|
60
|
-
return a.type === "oauth" && typeof a.issuer === "string" && a.issuer.length > 0;
|
|
61
|
-
}
|
|
62
|
-
function manifestFromDefinition(definition, urlPath, source = "the MCP entry") {
|
|
63
|
-
const def = definition;
|
|
64
|
-
if (!(!!def && typeof def === "object" && typeof def.name === "string" && typeof def.title === "string" && typeof def.version === "string" && Array.isArray(def.tools) && def.tools.every(isToolShape) && isAuthShape(def.auth))) throw new Error(`@lovable.dev/mcp-js: ${source} must \`export default defineMcp(...)\` (got ${definition == null ? "no default export" : typeof definition}).`);
|
|
65
|
-
return {
|
|
66
|
-
version: 1,
|
|
67
|
-
sdk_version: require_package.version,
|
|
68
|
-
path: urlPath,
|
|
69
|
-
auth: manifestAuth(def.auth),
|
|
70
|
-
mcp: buildMcpListing(def)
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
//#endregion
|
|
74
|
-
//#region src/manifest/ssr-loader.ts
|
|
75
|
-
async function produceViaSsr(projectRoot, alias, entryAbs, urlPath) {
|
|
76
|
-
const server = await (0, vite.createServer)({
|
|
77
|
-
configFile: false,
|
|
78
|
-
root: projectRoot,
|
|
79
|
-
logLevel: "silent",
|
|
80
|
-
server: {
|
|
81
|
-
middlewareMode: true,
|
|
82
|
-
hmr: false,
|
|
83
|
-
watch: null
|
|
84
|
-
},
|
|
85
|
-
optimizeDeps: { noDiscovery: true },
|
|
86
|
-
resolve: { alias }
|
|
87
|
-
});
|
|
88
|
-
try {
|
|
89
|
-
return manifestFromDefinition((await server.ssrLoadModule(entryAbs)).default, urlPath, entryAbs);
|
|
90
|
-
} finally {
|
|
91
|
-
await server.close();
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
//#endregion
|
|
95
|
-
//#region src/manifest/io.ts
|
|
96
|
-
const MCP_PLUGIN_NAME_PREFIX = "@lovable.dev/mcp-js";
|
|
97
|
-
function writeManifestIfChanged(file, manifest) {
|
|
98
|
-
const content = JSON.stringify(manifest, null, 2) + "\n";
|
|
99
|
-
let existing;
|
|
100
|
-
try {
|
|
101
|
-
existing = (0, node_fs.readFileSync)(file, "utf8");
|
|
102
|
-
} catch (err) {
|
|
103
|
-
if (!require_fs_errors.isFileMissing(err)) throw err;
|
|
104
|
-
}
|
|
105
|
-
if (existing === content) return;
|
|
106
|
-
(0, node_fs.mkdirSync)((0, node_path.dirname)(file), { recursive: true });
|
|
107
|
-
const tmp = `${file}.${(0, node_crypto.randomUUID)()}.tmp`;
|
|
108
|
-
try {
|
|
109
|
-
(0, node_fs.writeFileSync)(tmp, content, "utf8");
|
|
110
|
-
(0, node_fs.renameSync)(tmp, file);
|
|
111
|
-
} catch (err) {
|
|
112
|
-
try {
|
|
113
|
-
(0, node_fs.unlinkSync)(tmp);
|
|
114
|
-
} catch {}
|
|
115
|
-
throw err;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
function removeManifest(file) {
|
|
119
|
-
try {
|
|
120
|
-
(0, node_fs.unlinkSync)(file);
|
|
121
|
-
} catch (err) {
|
|
122
|
-
if (!require_fs_errors.isFileMissing(err)) throw err;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
async function syncManifest(manifestFile, entryAbs, urlPath, produce) {
|
|
126
|
-
let entryExists = true;
|
|
127
|
-
try {
|
|
128
|
-
(0, node_fs.lstatSync)(entryAbs);
|
|
129
|
-
} catch (err) {
|
|
130
|
-
if (!require_fs_errors.isFileMissing(err)) throw err;
|
|
131
|
-
entryExists = false;
|
|
132
|
-
}
|
|
133
|
-
if (!entryExists) {
|
|
134
|
-
removeManifest(manifestFile);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
writeManifestIfChanged(manifestFile, await produce(entryAbs, urlPath));
|
|
138
|
-
}
|
|
139
|
-
async function runExtract(projectRoot) {
|
|
140
|
-
const resolved = await (0, vite.resolveConfig)({
|
|
141
|
-
root: projectRoot,
|
|
142
|
-
logLevel: "silent"
|
|
143
|
-
}, "serve");
|
|
144
|
-
const alias = resolved.resolve?.alias ?? [];
|
|
145
|
-
const pluginApi = resolved.plugins.find((p) => typeof p.name === "string" && p.name.startsWith(MCP_PLUGIN_NAME_PREFIX))?.api;
|
|
146
|
-
const entryAbs = pluginApi?.mcpEntry ?? (0, node_path.resolve)(projectRoot, "src/lib/mcp/index.ts");
|
|
147
|
-
const urlPath = pluginApi?.urlPath ?? "/mcp";
|
|
148
|
-
await syncManifest((0, node_path.resolve)(projectRoot, MANIFEST_RELATIVE_PATH), entryAbs, urlPath, (entry, path) => produceViaSsr(projectRoot, alias, entry, path));
|
|
149
|
-
}
|
|
150
|
-
//#endregion
|
|
151
2
|
//#region src/cli/extract-manifest.ts
|
|
152
|
-
|
|
3
|
+
const projectRoot = process.argv[2] ?? process.cwd();
|
|
4
|
+
import("zod/v3").catch((err) => {
|
|
5
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6
|
+
throw new Error(`@lovable.dev/mcp-js requires zod ^3.25 or ^4.0 to extract MCP schemas. Verify the project's zod dependency and package resolution, then try again. Underlying error: ${message}`);
|
|
7
|
+
}).then(() => Promise.resolve().then(() => require("../io-CKGFa7_M.cjs"))).then(({ runExtract }) => runExtract(projectRoot)).catch((err) => {
|
|
153
8
|
console.error(err instanceof Error ? err.message : String(err));
|
|
154
9
|
process.exit(1);
|
|
155
10
|
});
|
|
@@ -1,155 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { t as jsonSchemaFromDefinition } from "../schema-CW1jKvio.js";
|
|
3
|
-
import { t as version } from "../package-CZERyrAn.js";
|
|
4
|
-
import { t as isFileMissing } from "../fs-errors-PA2t1TIp.js";
|
|
5
|
-
import { lstatSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
6
|
-
import { dirname, resolve } from "node:path";
|
|
7
|
-
import { createServer, resolveConfig } from "vite";
|
|
8
|
-
import { randomUUID } from "node:crypto";
|
|
9
|
-
//#region src/manifest/listing.ts
|
|
10
|
-
function schemaToJsonSchema(definition, pipeStrategy) {
|
|
11
|
-
if (!definition) return null;
|
|
12
|
-
return jsonSchemaFromDefinition(definition, pipeStrategy);
|
|
13
|
-
}
|
|
14
|
-
function buildMcpListing(mcp) {
|
|
15
|
-
return {
|
|
16
|
-
server: {
|
|
17
|
-
name: mcp.name,
|
|
18
|
-
version: mcp.version,
|
|
19
|
-
title: mcp.title
|
|
20
|
-
},
|
|
21
|
-
tools: mcp.tools.map((tool) => ({
|
|
22
|
-
name: tool.name,
|
|
23
|
-
title: tool.title,
|
|
24
|
-
description: tool.description,
|
|
25
|
-
annotations: tool.annotations,
|
|
26
|
-
inputSchema: schemaToJsonSchema(tool.inputSchema, "input"),
|
|
27
|
-
outputSchema: schemaToJsonSchema(tool.outputSchema, "output")
|
|
28
|
-
}))
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
const MANIFEST_RELATIVE_PATH = ".lovable/mcp/manifest.json";
|
|
32
|
-
function manifestAuth(auth) {
|
|
33
|
-
if (!auth) return { type: "none" };
|
|
34
|
-
const oauth = {
|
|
35
|
-
type: "oauth",
|
|
36
|
-
issuer: auth.issuer
|
|
37
|
-
};
|
|
38
|
-
if (auth.resource !== void 0) oauth.resource = auth.resource;
|
|
39
|
-
if (auth.resourceName !== void 0) oauth.resource_name = auth.resourceName;
|
|
40
|
-
if (auth.resourceDocumentation !== void 0) oauth.resource_documentation = auth.resourceDocumentation;
|
|
41
|
-
if (auth.protectedResourceMetadataUrl !== void 0) oauth.protected_resource_metadata_url = auth.protectedResourceMetadataUrl;
|
|
42
|
-
if (auth.requireOAuthClientClaim !== void 0) oauth.require_oauth_client_claim = auth.requireOAuthClientClaim;
|
|
43
|
-
if (auth.acceptResourceClaim !== void 0) oauth.accept_resource_claim = auth.acceptResourceClaim;
|
|
44
|
-
if (auth.acceptedAudiences !== void 0) oauth.accepted_audiences = auth.acceptedAudiences;
|
|
45
|
-
if (auth.requiredScopes !== void 0) oauth.required_scopes = auth.requiredScopes;
|
|
46
|
-
if (auth.jwksUri !== void 0) oauth.jwks_uri = auth.jwksUri;
|
|
47
|
-
if (auth.algorithms !== void 0) oauth.algorithms = auth.algorithms;
|
|
48
|
-
if (auth.clockToleranceSeconds !== void 0) oauth.clock_tolerance_seconds = auth.clockToleranceSeconds;
|
|
49
|
-
return oauth;
|
|
50
|
-
}
|
|
51
|
-
function isToolShape(tool) {
|
|
52
|
-
if (typeof tool !== "object" || tool === null) return false;
|
|
53
|
-
const t = tool;
|
|
54
|
-
return typeof t.name === "string" && typeof t.title === "string" && typeof t.description === "string";
|
|
55
|
-
}
|
|
56
|
-
function isAuthShape(auth) {
|
|
57
|
-
if (auth === void 0) return true;
|
|
58
|
-
if (typeof auth !== "object" || auth === null) return false;
|
|
59
|
-
const a = auth;
|
|
60
|
-
return a.type === "oauth" && typeof a.issuer === "string" && a.issuer.length > 0;
|
|
61
|
-
}
|
|
62
|
-
function manifestFromDefinition(definition, urlPath, source = "the MCP entry") {
|
|
63
|
-
const def = definition;
|
|
64
|
-
if (!(!!def && typeof def === "object" && typeof def.name === "string" && typeof def.title === "string" && typeof def.version === "string" && Array.isArray(def.tools) && def.tools.every(isToolShape) && isAuthShape(def.auth))) throw new Error(`@lovable.dev/mcp-js: ${source} must \`export default defineMcp(...)\` (got ${definition == null ? "no default export" : typeof definition}).`);
|
|
65
|
-
return {
|
|
66
|
-
version: 1,
|
|
67
|
-
sdk_version: version,
|
|
68
|
-
path: urlPath,
|
|
69
|
-
auth: manifestAuth(def.auth),
|
|
70
|
-
mcp: buildMcpListing(def)
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
//#endregion
|
|
74
|
-
//#region src/manifest/ssr-loader.ts
|
|
75
|
-
async function produceViaSsr(projectRoot, alias, entryAbs, urlPath) {
|
|
76
|
-
const server = await createServer({
|
|
77
|
-
configFile: false,
|
|
78
|
-
root: projectRoot,
|
|
79
|
-
logLevel: "silent",
|
|
80
|
-
server: {
|
|
81
|
-
middlewareMode: true,
|
|
82
|
-
hmr: false,
|
|
83
|
-
watch: null
|
|
84
|
-
},
|
|
85
|
-
optimizeDeps: { noDiscovery: true },
|
|
86
|
-
resolve: { alias }
|
|
87
|
-
});
|
|
88
|
-
try {
|
|
89
|
-
return manifestFromDefinition((await server.ssrLoadModule(entryAbs)).default, urlPath, entryAbs);
|
|
90
|
-
} finally {
|
|
91
|
-
await server.close();
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
//#endregion
|
|
95
|
-
//#region src/manifest/io.ts
|
|
96
|
-
const MCP_PLUGIN_NAME_PREFIX = "@lovable.dev/mcp-js";
|
|
97
|
-
function writeManifestIfChanged(file, manifest) {
|
|
98
|
-
const content = JSON.stringify(manifest, null, 2) + "\n";
|
|
99
|
-
let existing;
|
|
100
|
-
try {
|
|
101
|
-
existing = readFileSync(file, "utf8");
|
|
102
|
-
} catch (err) {
|
|
103
|
-
if (!isFileMissing(err)) throw err;
|
|
104
|
-
}
|
|
105
|
-
if (existing === content) return;
|
|
106
|
-
mkdirSync(dirname(file), { recursive: true });
|
|
107
|
-
const tmp = `${file}.${randomUUID()}.tmp`;
|
|
108
|
-
try {
|
|
109
|
-
writeFileSync(tmp, content, "utf8");
|
|
110
|
-
renameSync(tmp, file);
|
|
111
|
-
} catch (err) {
|
|
112
|
-
try {
|
|
113
|
-
unlinkSync(tmp);
|
|
114
|
-
} catch {}
|
|
115
|
-
throw err;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
function removeManifest(file) {
|
|
119
|
-
try {
|
|
120
|
-
unlinkSync(file);
|
|
121
|
-
} catch (err) {
|
|
122
|
-
if (!isFileMissing(err)) throw err;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
async function syncManifest(manifestFile, entryAbs, urlPath, produce) {
|
|
126
|
-
let entryExists = true;
|
|
127
|
-
try {
|
|
128
|
-
lstatSync(entryAbs);
|
|
129
|
-
} catch (err) {
|
|
130
|
-
if (!isFileMissing(err)) throw err;
|
|
131
|
-
entryExists = false;
|
|
132
|
-
}
|
|
133
|
-
if (!entryExists) {
|
|
134
|
-
removeManifest(manifestFile);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
writeManifestIfChanged(manifestFile, await produce(entryAbs, urlPath));
|
|
138
|
-
}
|
|
139
|
-
async function runExtract(projectRoot) {
|
|
140
|
-
const resolved = await resolveConfig({
|
|
141
|
-
root: projectRoot,
|
|
142
|
-
logLevel: "silent"
|
|
143
|
-
}, "serve");
|
|
144
|
-
const alias = resolved.resolve?.alias ?? [];
|
|
145
|
-
const pluginApi = resolved.plugins.find((p) => typeof p.name === "string" && p.name.startsWith(MCP_PLUGIN_NAME_PREFIX))?.api;
|
|
146
|
-
const entryAbs = pluginApi?.mcpEntry ?? resolve(projectRoot, "src/lib/mcp/index.ts");
|
|
147
|
-
const urlPath = pluginApi?.urlPath ?? "/mcp";
|
|
148
|
-
await syncManifest(resolve(projectRoot, MANIFEST_RELATIVE_PATH), entryAbs, urlPath, (entry, path) => produceViaSsr(projectRoot, alias, entry, path));
|
|
149
|
-
}
|
|
150
|
-
//#endregion
|
|
151
2
|
//#region src/cli/extract-manifest.ts
|
|
152
|
-
|
|
3
|
+
const projectRoot = process.argv[2] ?? process.cwd();
|
|
4
|
+
import("zod/v3").catch((err) => {
|
|
5
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6
|
+
throw new Error(`@lovable.dev/mcp-js requires zod ^3.25 or ^4.0 to extract MCP schemas. Verify the project's zod dependency and package resolution, then try again. Underlying error: ${message}`);
|
|
7
|
+
}).then(() => import("../io-ufHBQyKg.js")).then(({ runExtract }) => runExtract(projectRoot)).catch((err) => {
|
|
153
8
|
console.error(err instanceof Error ? err.message : String(err));
|
|
154
9
|
process.exit(1);
|
|
155
10
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
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-
|
|
2
|
+
import { t as version } from "./package-Bu8wLlvG.js";
|
|
3
3
|
import "./metadata-path-CAkNcfyY.js";
|
|
4
4
|
import { createLocalJWKSet, decodeProtectedHeader, errors, jwtVerify } from "jose";
|
|
5
5
|
//#region src/core/http.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_logger = require("./logger-CN1q-KNn.cjs");
|
|
2
|
-
const require_package = require("./package-
|
|
2
|
+
const require_package = require("./package-BGn-LvT3.cjs");
|
|
3
3
|
require("./metadata-path-zd7NSNoa.cjs");
|
|
4
4
|
let jose = require("jose");
|
|
5
5
|
//#region src/core/http.ts
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
const require_schema = require("./schema-D3vClxb7.cjs");
|
|
2
|
+
const require_package = require("./package-BGn-LvT3.cjs");
|
|
3
|
+
const require_fs_errors = require("./fs-errors-CWNzOV75.cjs");
|
|
4
|
+
let node_fs = require("node:fs");
|
|
5
|
+
let node_path = require("node:path");
|
|
6
|
+
let vite = require("vite");
|
|
7
|
+
let node_crypto = require("node:crypto");
|
|
8
|
+
//#region src/manifest/listing.ts
|
|
9
|
+
function schemaToJsonSchema(definition, pipeStrategy) {
|
|
10
|
+
if (!definition) return null;
|
|
11
|
+
return require_schema.jsonSchemaFromDefinition(definition, pipeStrategy);
|
|
12
|
+
}
|
|
13
|
+
function buildMcpListing(mcp) {
|
|
14
|
+
return {
|
|
15
|
+
server: {
|
|
16
|
+
name: mcp.name,
|
|
17
|
+
version: mcp.version,
|
|
18
|
+
title: mcp.title
|
|
19
|
+
},
|
|
20
|
+
tools: mcp.tools.map((tool) => ({
|
|
21
|
+
name: tool.name,
|
|
22
|
+
title: tool.title,
|
|
23
|
+
description: tool.description,
|
|
24
|
+
annotations: tool.annotations,
|
|
25
|
+
inputSchema: schemaToJsonSchema(tool.inputSchema, "input"),
|
|
26
|
+
outputSchema: schemaToJsonSchema(tool.outputSchema, "output")
|
|
27
|
+
}))
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const MANIFEST_RELATIVE_PATH = ".lovable/mcp/manifest.json";
|
|
31
|
+
function manifestAuth(auth) {
|
|
32
|
+
if (!auth) return { type: "none" };
|
|
33
|
+
const oauth = {
|
|
34
|
+
type: "oauth",
|
|
35
|
+
issuer: auth.issuer
|
|
36
|
+
};
|
|
37
|
+
if (auth.resource !== void 0) oauth.resource = auth.resource;
|
|
38
|
+
if (auth.resourceName !== void 0) oauth.resource_name = auth.resourceName;
|
|
39
|
+
if (auth.resourceDocumentation !== void 0) oauth.resource_documentation = auth.resourceDocumentation;
|
|
40
|
+
if (auth.protectedResourceMetadataUrl !== void 0) oauth.protected_resource_metadata_url = auth.protectedResourceMetadataUrl;
|
|
41
|
+
if (auth.requireOAuthClientClaim !== void 0) oauth.require_oauth_client_claim = auth.requireOAuthClientClaim;
|
|
42
|
+
if (auth.acceptResourceClaim !== void 0) oauth.accept_resource_claim = auth.acceptResourceClaim;
|
|
43
|
+
if (auth.acceptedAudiences !== void 0) oauth.accepted_audiences = auth.acceptedAudiences;
|
|
44
|
+
if (auth.requiredScopes !== void 0) oauth.required_scopes = auth.requiredScopes;
|
|
45
|
+
if (auth.jwksUri !== void 0) oauth.jwks_uri = auth.jwksUri;
|
|
46
|
+
if (auth.algorithms !== void 0) oauth.algorithms = auth.algorithms;
|
|
47
|
+
if (auth.clockToleranceSeconds !== void 0) oauth.clock_tolerance_seconds = auth.clockToleranceSeconds;
|
|
48
|
+
return oauth;
|
|
49
|
+
}
|
|
50
|
+
function isToolShape(tool) {
|
|
51
|
+
if (typeof tool !== "object" || tool === null) return false;
|
|
52
|
+
const t = tool;
|
|
53
|
+
return typeof t.name === "string" && typeof t.title === "string" && typeof t.description === "string";
|
|
54
|
+
}
|
|
55
|
+
function isAuthShape(auth) {
|
|
56
|
+
if (auth === void 0) return true;
|
|
57
|
+
if (typeof auth !== "object" || auth === null) return false;
|
|
58
|
+
const a = auth;
|
|
59
|
+
return a.type === "oauth" && typeof a.issuer === "string" && a.issuer.length > 0;
|
|
60
|
+
}
|
|
61
|
+
function manifestFromDefinition(definition, urlPath, source = "the MCP entry") {
|
|
62
|
+
const def = definition;
|
|
63
|
+
if (!(!!def && typeof def === "object" && typeof def.name === "string" && typeof def.title === "string" && typeof def.version === "string" && Array.isArray(def.tools) && def.tools.every(isToolShape) && isAuthShape(def.auth))) throw new Error(`@lovable.dev/mcp-js: ${source} must \`export default defineMcp(...)\` (got ${definition == null ? "no default export" : typeof definition}).`);
|
|
64
|
+
return {
|
|
65
|
+
version: 1,
|
|
66
|
+
sdk_version: require_package.version,
|
|
67
|
+
path: urlPath,
|
|
68
|
+
auth: manifestAuth(def.auth),
|
|
69
|
+
mcp: buildMcpListing(def)
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/manifest/ssr-loader.ts
|
|
74
|
+
async function produceViaSsr(projectRoot, alias, entryAbs, urlPath) {
|
|
75
|
+
const server = await (0, vite.createServer)({
|
|
76
|
+
configFile: false,
|
|
77
|
+
root: projectRoot,
|
|
78
|
+
logLevel: "silent",
|
|
79
|
+
server: {
|
|
80
|
+
middlewareMode: true,
|
|
81
|
+
hmr: false,
|
|
82
|
+
watch: null
|
|
83
|
+
},
|
|
84
|
+
optimizeDeps: { noDiscovery: true },
|
|
85
|
+
resolve: { alias }
|
|
86
|
+
});
|
|
87
|
+
try {
|
|
88
|
+
return manifestFromDefinition((await server.ssrLoadModule(entryAbs)).default, urlPath, entryAbs);
|
|
89
|
+
} finally {
|
|
90
|
+
await server.close();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/manifest/io.ts
|
|
95
|
+
const MCP_PLUGIN_NAME_PREFIX = "@lovable.dev/mcp-js";
|
|
96
|
+
const DEFAULT_MCP_ENTRY = "src/lib/mcp/index.ts";
|
|
97
|
+
const DEFAULT_MCP_PATH = "/mcp";
|
|
98
|
+
function writeManifestIfChanged(file, manifest) {
|
|
99
|
+
const content = JSON.stringify(manifest, null, 2) + "\n";
|
|
100
|
+
let existing;
|
|
101
|
+
try {
|
|
102
|
+
existing = (0, node_fs.readFileSync)(file, "utf8");
|
|
103
|
+
} catch (err) {
|
|
104
|
+
if (!require_fs_errors.isFileMissing(err)) throw err;
|
|
105
|
+
}
|
|
106
|
+
if (existing === content) return;
|
|
107
|
+
(0, node_fs.mkdirSync)((0, node_path.dirname)(file), { recursive: true });
|
|
108
|
+
const tmp = `${file}.${(0, node_crypto.randomUUID)()}.tmp`;
|
|
109
|
+
try {
|
|
110
|
+
(0, node_fs.writeFileSync)(tmp, content, "utf8");
|
|
111
|
+
(0, node_fs.renameSync)(tmp, file);
|
|
112
|
+
} catch (err) {
|
|
113
|
+
try {
|
|
114
|
+
(0, node_fs.unlinkSync)(tmp);
|
|
115
|
+
} catch {}
|
|
116
|
+
throw err;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function removeManifest(file) {
|
|
120
|
+
try {
|
|
121
|
+
(0, node_fs.unlinkSync)(file);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
if (!require_fs_errors.isFileMissing(err)) throw err;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function syncManifest(manifestFile, entryAbs, urlPath, produce) {
|
|
127
|
+
let entryExists = true;
|
|
128
|
+
try {
|
|
129
|
+
(0, node_fs.lstatSync)(entryAbs);
|
|
130
|
+
} catch (err) {
|
|
131
|
+
if (!require_fs_errors.isFileMissing(err)) throw err;
|
|
132
|
+
entryExists = false;
|
|
133
|
+
}
|
|
134
|
+
if (!entryExists) {
|
|
135
|
+
removeManifest(manifestFile);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
writeManifestIfChanged(manifestFile, await produce(entryAbs, urlPath));
|
|
139
|
+
}
|
|
140
|
+
async function runExtract(projectRoot) {
|
|
141
|
+
const resolved = await (0, vite.resolveConfig)({
|
|
142
|
+
root: projectRoot,
|
|
143
|
+
logLevel: "silent"
|
|
144
|
+
}, "serve");
|
|
145
|
+
const alias = resolved.resolve?.alias ?? [];
|
|
146
|
+
const pluginApi = resolved.plugins.find((p) => typeof p.name === "string" && p.name.startsWith(MCP_PLUGIN_NAME_PREFIX))?.api;
|
|
147
|
+
const entryAbs = pluginApi?.mcpEntry ?? (0, node_path.resolve)(projectRoot, "src/lib/mcp/index.ts");
|
|
148
|
+
const urlPath = pluginApi?.urlPath ?? "/mcp";
|
|
149
|
+
await syncManifest((0, node_path.resolve)(projectRoot, MANIFEST_RELATIVE_PATH), entryAbs, urlPath, (entry, path) => produceViaSsr(projectRoot, alias, entry, path));
|
|
150
|
+
}
|
|
151
|
+
//#endregion
|
|
152
|
+
exports.DEFAULT_MCP_ENTRY = DEFAULT_MCP_ENTRY;
|
|
153
|
+
exports.DEFAULT_MCP_PATH = DEFAULT_MCP_PATH;
|
|
154
|
+
exports.runExtract = runExtract;
|
|
155
|
+
exports.syncManifest = syncManifest;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { t as jsonSchemaFromDefinition } from "./schema-CW1jKvio.js";
|
|
2
|
+
import { t as version } from "./package-Bu8wLlvG.js";
|
|
3
|
+
import { t as isFileMissing } from "./fs-errors-PA2t1TIp.js";
|
|
4
|
+
import { lstatSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { dirname, resolve } from "node:path";
|
|
6
|
+
import { createServer, resolveConfig } from "vite";
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
8
|
+
//#region src/manifest/listing.ts
|
|
9
|
+
function schemaToJsonSchema(definition, pipeStrategy) {
|
|
10
|
+
if (!definition) return null;
|
|
11
|
+
return jsonSchemaFromDefinition(definition, pipeStrategy);
|
|
12
|
+
}
|
|
13
|
+
function buildMcpListing(mcp) {
|
|
14
|
+
return {
|
|
15
|
+
server: {
|
|
16
|
+
name: mcp.name,
|
|
17
|
+
version: mcp.version,
|
|
18
|
+
title: mcp.title
|
|
19
|
+
},
|
|
20
|
+
tools: mcp.tools.map((tool) => ({
|
|
21
|
+
name: tool.name,
|
|
22
|
+
title: tool.title,
|
|
23
|
+
description: tool.description,
|
|
24
|
+
annotations: tool.annotations,
|
|
25
|
+
inputSchema: schemaToJsonSchema(tool.inputSchema, "input"),
|
|
26
|
+
outputSchema: schemaToJsonSchema(tool.outputSchema, "output")
|
|
27
|
+
}))
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const MANIFEST_RELATIVE_PATH = ".lovable/mcp/manifest.json";
|
|
31
|
+
function manifestAuth(auth) {
|
|
32
|
+
if (!auth) return { type: "none" };
|
|
33
|
+
const oauth = {
|
|
34
|
+
type: "oauth",
|
|
35
|
+
issuer: auth.issuer
|
|
36
|
+
};
|
|
37
|
+
if (auth.resource !== void 0) oauth.resource = auth.resource;
|
|
38
|
+
if (auth.resourceName !== void 0) oauth.resource_name = auth.resourceName;
|
|
39
|
+
if (auth.resourceDocumentation !== void 0) oauth.resource_documentation = auth.resourceDocumentation;
|
|
40
|
+
if (auth.protectedResourceMetadataUrl !== void 0) oauth.protected_resource_metadata_url = auth.protectedResourceMetadataUrl;
|
|
41
|
+
if (auth.requireOAuthClientClaim !== void 0) oauth.require_oauth_client_claim = auth.requireOAuthClientClaim;
|
|
42
|
+
if (auth.acceptResourceClaim !== void 0) oauth.accept_resource_claim = auth.acceptResourceClaim;
|
|
43
|
+
if (auth.acceptedAudiences !== void 0) oauth.accepted_audiences = auth.acceptedAudiences;
|
|
44
|
+
if (auth.requiredScopes !== void 0) oauth.required_scopes = auth.requiredScopes;
|
|
45
|
+
if (auth.jwksUri !== void 0) oauth.jwks_uri = auth.jwksUri;
|
|
46
|
+
if (auth.algorithms !== void 0) oauth.algorithms = auth.algorithms;
|
|
47
|
+
if (auth.clockToleranceSeconds !== void 0) oauth.clock_tolerance_seconds = auth.clockToleranceSeconds;
|
|
48
|
+
return oauth;
|
|
49
|
+
}
|
|
50
|
+
function isToolShape(tool) {
|
|
51
|
+
if (typeof tool !== "object" || tool === null) return false;
|
|
52
|
+
const t = tool;
|
|
53
|
+
return typeof t.name === "string" && typeof t.title === "string" && typeof t.description === "string";
|
|
54
|
+
}
|
|
55
|
+
function isAuthShape(auth) {
|
|
56
|
+
if (auth === void 0) return true;
|
|
57
|
+
if (typeof auth !== "object" || auth === null) return false;
|
|
58
|
+
const a = auth;
|
|
59
|
+
return a.type === "oauth" && typeof a.issuer === "string" && a.issuer.length > 0;
|
|
60
|
+
}
|
|
61
|
+
function manifestFromDefinition(definition, urlPath, source = "the MCP entry") {
|
|
62
|
+
const def = definition;
|
|
63
|
+
if (!(!!def && typeof def === "object" && typeof def.name === "string" && typeof def.title === "string" && typeof def.version === "string" && Array.isArray(def.tools) && def.tools.every(isToolShape) && isAuthShape(def.auth))) throw new Error(`@lovable.dev/mcp-js: ${source} must \`export default defineMcp(...)\` (got ${definition == null ? "no default export" : typeof definition}).`);
|
|
64
|
+
return {
|
|
65
|
+
version: 1,
|
|
66
|
+
sdk_version: version,
|
|
67
|
+
path: urlPath,
|
|
68
|
+
auth: manifestAuth(def.auth),
|
|
69
|
+
mcp: buildMcpListing(def)
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/manifest/ssr-loader.ts
|
|
74
|
+
async function produceViaSsr(projectRoot, alias, entryAbs, urlPath) {
|
|
75
|
+
const server = await createServer({
|
|
76
|
+
configFile: false,
|
|
77
|
+
root: projectRoot,
|
|
78
|
+
logLevel: "silent",
|
|
79
|
+
server: {
|
|
80
|
+
middlewareMode: true,
|
|
81
|
+
hmr: false,
|
|
82
|
+
watch: null
|
|
83
|
+
},
|
|
84
|
+
optimizeDeps: { noDiscovery: true },
|
|
85
|
+
resolve: { alias }
|
|
86
|
+
});
|
|
87
|
+
try {
|
|
88
|
+
return manifestFromDefinition((await server.ssrLoadModule(entryAbs)).default, urlPath, entryAbs);
|
|
89
|
+
} finally {
|
|
90
|
+
await server.close();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/manifest/io.ts
|
|
95
|
+
const MCP_PLUGIN_NAME_PREFIX = "@lovable.dev/mcp-js";
|
|
96
|
+
const DEFAULT_MCP_ENTRY = "src/lib/mcp/index.ts";
|
|
97
|
+
const DEFAULT_MCP_PATH = "/mcp";
|
|
98
|
+
function writeManifestIfChanged(file, manifest) {
|
|
99
|
+
const content = JSON.stringify(manifest, null, 2) + "\n";
|
|
100
|
+
let existing;
|
|
101
|
+
try {
|
|
102
|
+
existing = readFileSync(file, "utf8");
|
|
103
|
+
} catch (err) {
|
|
104
|
+
if (!isFileMissing(err)) throw err;
|
|
105
|
+
}
|
|
106
|
+
if (existing === content) return;
|
|
107
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
108
|
+
const tmp = `${file}.${randomUUID()}.tmp`;
|
|
109
|
+
try {
|
|
110
|
+
writeFileSync(tmp, content, "utf8");
|
|
111
|
+
renameSync(tmp, file);
|
|
112
|
+
} catch (err) {
|
|
113
|
+
try {
|
|
114
|
+
unlinkSync(tmp);
|
|
115
|
+
} catch {}
|
|
116
|
+
throw err;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function removeManifest(file) {
|
|
120
|
+
try {
|
|
121
|
+
unlinkSync(file);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
if (!isFileMissing(err)) throw err;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function syncManifest(manifestFile, entryAbs, urlPath, produce) {
|
|
127
|
+
let entryExists = true;
|
|
128
|
+
try {
|
|
129
|
+
lstatSync(entryAbs);
|
|
130
|
+
} catch (err) {
|
|
131
|
+
if (!isFileMissing(err)) throw err;
|
|
132
|
+
entryExists = false;
|
|
133
|
+
}
|
|
134
|
+
if (!entryExists) {
|
|
135
|
+
removeManifest(manifestFile);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
writeManifestIfChanged(manifestFile, await produce(entryAbs, urlPath));
|
|
139
|
+
}
|
|
140
|
+
async function runExtract(projectRoot) {
|
|
141
|
+
const resolved = await resolveConfig({
|
|
142
|
+
root: projectRoot,
|
|
143
|
+
logLevel: "silent"
|
|
144
|
+
}, "serve");
|
|
145
|
+
const alias = resolved.resolve?.alias ?? [];
|
|
146
|
+
const pluginApi = resolved.plugins.find((p) => typeof p.name === "string" && p.name.startsWith(MCP_PLUGIN_NAME_PREFIX))?.api;
|
|
147
|
+
const entryAbs = pluginApi?.mcpEntry ?? resolve(projectRoot, "src/lib/mcp/index.ts");
|
|
148
|
+
const urlPath = pluginApi?.urlPath ?? "/mcp";
|
|
149
|
+
await syncManifest(resolve(projectRoot, MANIFEST_RELATIVE_PATH), entryAbs, urlPath, (entry, path) => produceViaSsr(projectRoot, alias, entry, path));
|
|
150
|
+
}
|
|
151
|
+
//#endregion
|
|
152
|
+
export { DEFAULT_MCP_ENTRY, DEFAULT_MCP_PATH, runExtract, syncManifest };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as log, r as describeError } from "./logger-Ctv5xUSD.js";
|
|
2
2
|
import { n as schemaFromDefinition, t as jsonSchemaFromDefinition } from "./schema-CW1jKvio.js";
|
|
3
3
|
import { i as ToolContext, n as errorSummary, r as resolveToolErrorMessage } from "./errors-Bwd1L0Rf.js";
|
|
4
|
-
import { f as finalizeWireResponse, i as normalizeHttpMethod, l as createNoopRecorder, n as createRequestAuthorizer, t as evaluateCors, u as nowMs } from "./cors-
|
|
4
|
+
import { f as finalizeWireResponse, i as normalizeHttpMethod, l as createNoopRecorder, n as createRequestAuthorizer, t as evaluateCors, u as nowMs } from "./cors-BLtFfCwv.js";
|
|
5
5
|
import { getParseErrorMessage, safeParseAsync } from "@modelcontextprotocol/sdk/server/zod-compat.js";
|
|
6
6
|
import { CLIENT_CAPABILITIES_META_KEY, CLIENT_INFO_META_KEY, McpServer, createMcpHandler } from "@modelcontextprotocol/server";
|
|
7
7
|
//#region src/core/content.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const require_logger = require("./logger-CN1q-KNn.cjs");
|
|
2
2
|
const require_schema = require("./schema-D3vClxb7.cjs");
|
|
3
3
|
const require_errors = require("./errors-Cr95rSkB.cjs");
|
|
4
|
-
const require_cors = require("./cors-
|
|
4
|
+
const require_cors = require("./cors-DiBSnA0M.cjs");
|
|
5
5
|
let _modelcontextprotocol_sdk_server_zod_compat_js = require("@modelcontextprotocol/sdk/server/zod-compat.js");
|
|
6
6
|
let _modelcontextprotocol_server = require("@modelcontextprotocol/server");
|
|
7
7
|
//#region src/core/content.ts
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createMcpProtocolHandler } from "../../mcp-
|
|
1
|
+
import { t as createMcpProtocolHandler } from "../../mcp-BQeQCXB4.js";
|
|
2
2
|
export { createMcpProtocolHandler };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_logger = require("../logger-CN1q-KNn.cjs");
|
|
3
|
-
const require_cors = require("../cors-
|
|
3
|
+
const require_cors = require("../cors-DiBSnA0M.cjs");
|
|
4
4
|
//#region src/protocols/oauth-metadata.ts
|
|
5
5
|
function notFound() {
|
|
6
6
|
return new Response(JSON.stringify({ error: "not found" }), {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as log, r as describeError } from "../logger-Ctv5xUSD.js";
|
|
2
|
-
import { a as oauthConfigurationErrorResponse, d as JSON_HEADERS, f as finalizeWireResponse, i as normalizeHttpMethod, l as createNoopRecorder, p as methodNotAllowed, r as getOAuthRuntime, s as resolveProtectedResource, t as evaluateCors } from "../cors-
|
|
2
|
+
import { a as oauthConfigurationErrorResponse, d as JSON_HEADERS, f as finalizeWireResponse, i as normalizeHttpMethod, l as createNoopRecorder, p as methodNotAllowed, r as getOAuthRuntime, s as resolveProtectedResource, t as evaluateCors } from "../cors-BLtFfCwv.js";
|
|
3
3
|
//#region src/protocols/oauth-metadata.ts
|
|
4
4
|
function notFound() {
|
|
5
5
|
return new Response(JSON.stringify({ error: "not found" }), {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_logger = require("../../logger-CN1q-KNn.cjs");
|
|
3
|
-
const require_cors = require("../../cors-
|
|
3
|
+
const require_cors = require("../../cors-DiBSnA0M.cjs");
|
|
4
4
|
const require_metadata_path = require("../../metadata-path-zd7NSNoa.cjs");
|
|
5
|
-
const require_mcp = require("../../mcp-
|
|
5
|
+
const require_mcp = require("../../mcp-LfeCqruq.cjs");
|
|
6
6
|
const require_protocols_oauth_metadata = require("../../protocols/oauth-metadata.cjs");
|
|
7
7
|
const require_forwarded = require("../../forwarded-B37IdmMX.cjs");
|
|
8
8
|
const require_paths = require("../../paths-OP318a6c.cjs");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { s as trimTrailingSlash } from "../../logger-Ctv5xUSD.js";
|
|
2
|
-
import { c as createRecorderForRuntime, o as assertResourcePathShape } from "../../cors-
|
|
2
|
+
import { c as createRecorderForRuntime, o as assertResourcePathShape } from "../../cors-BLtFfCwv.js";
|
|
3
3
|
import { t as OAUTH_PROTECTED_RESOURCE_METADATA_PATH } from "../../metadata-path-CAkNcfyY.js";
|
|
4
|
-
import { t as createMcpProtocolHandler } from "../../mcp-
|
|
4
|
+
import { t as createMcpProtocolHandler } from "../../mcp-BQeQCXB4.js";
|
|
5
5
|
import { createOAuthProtectedResourceMetadataHandler } from "../../protocols/oauth-metadata.js";
|
|
6
6
|
import { t as applyForwardedOrigin } from "../../forwarded-BBXvFeh6.js";
|
|
7
7
|
import { n as assertFunctionName, t as FUNCTIONS_MOUNT_PREFIX } from "../../paths-IS65L6TA.js";
|
|
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_package = require("../../package-
|
|
5
|
+
const require_package = require("../../package-BGn-LvT3.cjs");
|
|
6
6
|
const require_fs_errors = require("../../fs-errors-CWNzOV75.cjs");
|
|
7
7
|
const require_supabase_config = require("../../supabase-config-Dz7dnUv0.cjs");
|
|
8
8
|
const require_paths = require("../../paths-OP318a6c.cjs");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as version } from "../../package-
|
|
1
|
+
import { t as version } from "../../package-Bu8wLlvG.js";
|
|
2
2
|
import { t as isFileMissing } from "../../fs-errors-PA2t1TIp.js";
|
|
3
3
|
import { t as readSupabaseProjectRef } from "../../supabase-config-CakTU8YF.js";
|
|
4
4
|
import { n as assertFunctionName, t as FUNCTIONS_MOUNT_PREFIX } from "../../paths-IS65L6TA.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_cors = require("../../cors-
|
|
3
|
-
const require_mcp = require("../../mcp-
|
|
2
|
+
const require_cors = require("../../cors-DiBSnA0M.cjs");
|
|
3
|
+
const require_mcp = require("../../mcp-LfeCqruq.cjs");
|
|
4
4
|
const require_protocols_oauth_metadata = require("../../protocols/oauth-metadata.cjs");
|
|
5
5
|
const require_forwarded = require("../../forwarded-B37IdmMX.cjs");
|
|
6
6
|
//#region src/stacks/tanstack/handlers.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as createRecorderForRuntime } from "../../cors-
|
|
2
|
-
import { t as createMcpProtocolHandler } from "../../mcp-
|
|
1
|
+
import { c as createRecorderForRuntime } from "../../cors-BLtFfCwv.js";
|
|
2
|
+
import { t as createMcpProtocolHandler } from "../../mcp-BQeQCXB4.js";
|
|
3
3
|
import { createOAuthProtectedResourceMetadataHandler } from "../../protocols/oauth-metadata.js";
|
|
4
4
|
import { t as applyForwardedOrigin } from "../../forwarded-BBXvFeh6.js";
|
|
5
5
|
//#region src/stacks/tanstack/handlers.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lovable.dev/mcp-js",
|
|
3
|
-
"version": "2.0.0",
|
|
3
|
+
"version": "2.0.2-rc.0",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=20"
|
|
6
6
|
},
|
|
@@ -108,14 +108,14 @@
|
|
|
108
108
|
],
|
|
109
109
|
"license": "MIT",
|
|
110
110
|
"dependencies": {
|
|
111
|
-
"@modelcontextprotocol/server": "2.0.0",
|
|
112
111
|
"@modelcontextprotocol/sdk": "1.28.0",
|
|
112
|
+
"@modelcontextprotocol/server": "2.0.0",
|
|
113
113
|
"esbuild": "^0.27.0",
|
|
114
114
|
"jose": "^6.2.2"
|
|
115
115
|
},
|
|
116
116
|
"peerDependencies": {
|
|
117
117
|
"vite": ">=5.0.0 <9.0.0",
|
|
118
|
-
"zod": "
|
|
118
|
+
"zod": "^3.25 || ^4.0"
|
|
119
119
|
},
|
|
120
120
|
"devDependencies": {
|
|
121
121
|
"@types/node": "22.13.13",
|
|
@@ -135,7 +135,8 @@
|
|
|
135
135
|
"format:check": "oxfmt --check src/ tests/",
|
|
136
136
|
"lint": "oxfmt --check src/ tests/ && oxlint -c ../../oxlint.config.ts src/ tests/",
|
|
137
137
|
"lint:fix": "oxfmt --write src/ tests/ && oxlint -c ../../oxlint.config.ts --fix src/ tests/",
|
|
138
|
-
"test": "vitest run --project unit",
|
|
138
|
+
"test": "vitest run --project unit && npm run test:package:zod",
|
|
139
|
+
"test:package:zod": "npm run build && node tests/package/zod-compat.mjs",
|
|
139
140
|
"test:watch": "vitest --project unit",
|
|
140
141
|
"example:tanstack:install": "bun link && cd example/tanstack && bun install && bun link @lovable.dev/mcp-js",
|
|
141
142
|
"example:tanstack:dev": "cd example/tanstack && bun --bun run dev",
|