@lovable.dev/mcp-js 0.21.0 → 0.21.1-rc.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.
Files changed (86) hide show
  1. package/dist/authorize-CumVyk7p.d.cts +27 -0
  2. package/dist/authorize-D6p4-9_D.d.ts +27 -0
  3. package/dist/{base-CFy5vZ5Z.d.ts → base-CoIFvAmS.d.cts} +15 -14
  4. package/dist/base-CoIFvAmS.d.ts +26 -0
  5. package/dist/cli/extract-manifest.cjs +116 -201
  6. package/dist/cli/extract-manifest.d.cts +1 -1
  7. package/dist/cli/extract-manifest.d.ts +1 -1
  8. package/dist/cli/extract-manifest.js +117 -156
  9. package/dist/content-D5LJAHyM.js +12 -0
  10. package/dist/content-NCYIGgOb.cjs +17 -0
  11. package/dist/context-BweeEcoA.cjs +56 -0
  12. package/dist/context-CIpPzN7P.js +51 -0
  13. package/dist/cors-B7CTXIHD.js +829 -0
  14. package/dist/cors-BebjKPrc.cjs +912 -0
  15. package/dist/forwarded--h4efJy-.js +43 -0
  16. package/dist/forwarded-Pi8Hs5Ps.cjs +48 -0
  17. package/dist/fs-errors-CWNzOV75.cjs +11 -0
  18. package/dist/fs-errors-PA2t1TIp.js +6 -0
  19. package/dist/index.cjs +129 -329
  20. package/dist/index.d.cts +26 -26
  21. package/dist/index.d.ts +26 -26
  22. package/dist/index.js +118 -177
  23. package/dist/{io-D4srzRKc.d.ts → io-CS4UL6_A.d.ts} +6 -4
  24. package/dist/io-CbbUbPY3.d.cts +15 -0
  25. package/dist/list-tools-CBCuS1Tv.cjs +57 -0
  26. package/dist/list-tools-CsWgiRy1.d.ts +8 -0
  27. package/dist/list-tools-CtZHOuPv.d.cts +8 -0
  28. package/dist/list-tools-D75RGtgs.js +46 -0
  29. package/dist/logger-2OXtfiIW.js +141 -0
  30. package/dist/logger-BqPOa_E1.cjs +194 -0
  31. package/dist/mcp-Cdj0AYst.cjs +123 -0
  32. package/dist/mcp-GngXbcqN.js +118 -0
  33. package/dist/metadata-path-CAkNcfyY.js +12 -0
  34. package/dist/metadata-path-zd7NSNoa.cjs +17 -0
  35. package/dist/package-7EUptuSJ.js +4 -0
  36. package/dist/package-BwCGVRcB.cjs +9 -0
  37. package/dist/paths-IS65L6TA.js +7 -0
  38. package/dist/paths-OP318a6c.cjs +18 -0
  39. package/dist/protocols/mcp/index.cjs +3 -740
  40. package/dist/protocols/mcp/index.d.cts +6 -7
  41. package/dist/protocols/mcp/index.d.ts +6 -7
  42. package/dist/protocols/mcp/index.js +2 -12
  43. package/dist/protocols/oauth-metadata.cjs +48 -539
  44. package/dist/protocols/oauth-metadata.d.cts +5 -6
  45. package/dist/protocols/oauth-metadata.d.ts +5 -6
  46. package/dist/protocols/oauth-metadata.js +52 -10
  47. package/dist/protocols/rest/index.cjs +5 -839
  48. package/dist/protocols/rest/index.d.cts +7 -10
  49. package/dist/protocols/rest/index.d.ts +7 -10
  50. package/dist/protocols/rest/index.js +3 -16
  51. package/dist/rest-CXH6-zv9.js +113 -0
  52. package/dist/rest-CyV8LHeB.cjs +118 -0
  53. package/dist/stacks/supabase/index.cjs +76 -1302
  54. package/dist/stacks/supabase/index.d.cts +29 -30
  55. package/dist/stacks/supabase/index.d.ts +29 -30
  56. package/dist/stacks/supabase/index.js +73 -89
  57. package/dist/stacks/supabase/vite.cjs +258 -287
  58. package/dist/stacks/supabase/vite.d.cts +24 -24
  59. package/dist/stacks/supabase/vite.d.ts +24 -24
  60. package/dist/stacks/supabase/vite.js +252 -252
  61. package/dist/stacks/tanstack/index.cjs +42 -1256
  62. package/dist/stacks/tanstack/index.d.cts +8 -9
  63. package/dist/stacks/tanstack/index.d.ts +8 -9
  64. package/dist/stacks/tanstack/index.js +36 -41
  65. package/dist/stacks/tanstack/vite.cjs +223 -312
  66. package/dist/stacks/tanstack/vite.d.cts +80 -81
  67. package/dist/stacks/tanstack/vite.d.ts +80 -81
  68. package/dist/stacks/tanstack/vite.js +216 -282
  69. package/dist/types-BYdYYTjk.d.cts +321 -0
  70. package/dist/types-BYdYYTjk.d.ts +321 -0
  71. package/package.json +71 -28
  72. package/dist/authorize-BMeXd_Sh.d.ts +0 -25
  73. package/dist/chunk-6DXGZZA4.js +0 -6
  74. package/dist/chunk-6QFZYYUV.js +0 -11
  75. package/dist/chunk-CI7JYLV3.js +0 -104
  76. package/dist/chunk-E3Q3FRKQ.js +0 -6
  77. package/dist/chunk-ENJDNFEB.js +0 -79
  78. package/dist/chunk-H37EB22A.js +0 -125
  79. package/dist/chunk-LFXK3FNF.js +0 -58
  80. package/dist/chunk-MA5H6PSF.js +0 -46
  81. package/dist/chunk-QPKPYDPB.js +0 -137
  82. package/dist/chunk-UQK5UO6C.js +0 -26
  83. package/dist/chunk-XQWJN6DC.js +0 -14
  84. package/dist/chunk-Y3ZFPEQH.js +0 -8
  85. package/dist/chunk-YLU2JTHL.js +0 -739
  86. package/dist/types-qqrmJ736.d.ts +0 -321
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovable.dev/mcp-js",
3
- "version": "0.21.0",
3
+ "version": "0.21.1-rc.1",
4
4
  "description": "Author MCP servers for Lovable apps. Declare tools with defineTool, register them in defineMcp, and a framework adapter (TanStack or Supabase Edge Functions) emits the route(s) at build time.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -20,44 +20,84 @@
20
20
  "types": "./dist/index.d.ts",
21
21
  "exports": {
22
22
  ".": {
23
- "types": "./dist/index.d.ts",
24
- "import": "./dist/index.js",
25
- "require": "./dist/index.cjs"
23
+ "import": {
24
+ "types": "./dist/index.d.ts",
25
+ "default": "./dist/index.js"
26
+ },
27
+ "require": {
28
+ "types": "./dist/index.d.cts",
29
+ "default": "./dist/index.cjs"
30
+ }
26
31
  },
27
32
  "./protocols/mcp": {
28
- "types": "./dist/protocols/mcp/index.d.ts",
29
- "import": "./dist/protocols/mcp/index.js",
30
- "require": "./dist/protocols/mcp/index.cjs"
33
+ "import": {
34
+ "types": "./dist/protocols/mcp/index.d.ts",
35
+ "default": "./dist/protocols/mcp/index.js"
36
+ },
37
+ "require": {
38
+ "types": "./dist/protocols/mcp/index.d.cts",
39
+ "default": "./dist/protocols/mcp/index.cjs"
40
+ }
31
41
  },
32
42
  "./protocols/oauth-metadata": {
33
- "types": "./dist/protocols/oauth-metadata.d.ts",
34
- "import": "./dist/protocols/oauth-metadata.js",
35
- "require": "./dist/protocols/oauth-metadata.cjs"
43
+ "import": {
44
+ "types": "./dist/protocols/oauth-metadata.d.ts",
45
+ "default": "./dist/protocols/oauth-metadata.js"
46
+ },
47
+ "require": {
48
+ "types": "./dist/protocols/oauth-metadata.d.cts",
49
+ "default": "./dist/protocols/oauth-metadata.cjs"
50
+ }
36
51
  },
37
52
  "./protocols/rest": {
38
- "types": "./dist/protocols/rest/index.d.ts",
39
- "import": "./dist/protocols/rest/index.js",
40
- "require": "./dist/protocols/rest/index.cjs"
53
+ "import": {
54
+ "types": "./dist/protocols/rest/index.d.ts",
55
+ "default": "./dist/protocols/rest/index.js"
56
+ },
57
+ "require": {
58
+ "types": "./dist/protocols/rest/index.d.cts",
59
+ "default": "./dist/protocols/rest/index.cjs"
60
+ }
41
61
  },
42
62
  "./stacks/tanstack": {
43
- "types": "./dist/stacks/tanstack/index.d.ts",
44
- "import": "./dist/stacks/tanstack/index.js",
45
- "require": "./dist/stacks/tanstack/index.cjs"
63
+ "import": {
64
+ "types": "./dist/stacks/tanstack/index.d.ts",
65
+ "default": "./dist/stacks/tanstack/index.js"
66
+ },
67
+ "require": {
68
+ "types": "./dist/stacks/tanstack/index.d.cts",
69
+ "default": "./dist/stacks/tanstack/index.cjs"
70
+ }
46
71
  },
47
72
  "./stacks/tanstack/vite": {
48
- "types": "./dist/stacks/tanstack/vite.d.ts",
49
- "import": "./dist/stacks/tanstack/vite.js",
50
- "require": "./dist/stacks/tanstack/vite.cjs"
73
+ "import": {
74
+ "types": "./dist/stacks/tanstack/vite.d.ts",
75
+ "default": "./dist/stacks/tanstack/vite.js"
76
+ },
77
+ "require": {
78
+ "types": "./dist/stacks/tanstack/vite.d.cts",
79
+ "default": "./dist/stacks/tanstack/vite.cjs"
80
+ }
51
81
  },
52
82
  "./stacks/supabase": {
53
- "types": "./dist/stacks/supabase/index.d.ts",
54
- "import": "./dist/stacks/supabase/index.js",
55
- "require": "./dist/stacks/supabase/index.cjs"
83
+ "import": {
84
+ "types": "./dist/stacks/supabase/index.d.ts",
85
+ "default": "./dist/stacks/supabase/index.js"
86
+ },
87
+ "require": {
88
+ "types": "./dist/stacks/supabase/index.d.cts",
89
+ "default": "./dist/stacks/supabase/index.cjs"
90
+ }
56
91
  },
57
92
  "./stacks/supabase/vite": {
58
- "types": "./dist/stacks/supabase/vite.d.ts",
59
- "import": "./dist/stacks/supabase/vite.js",
60
- "require": "./dist/stacks/supabase/vite.cjs"
93
+ "import": {
94
+ "types": "./dist/stacks/supabase/vite.d.ts",
95
+ "default": "./dist/stacks/supabase/vite.js"
96
+ },
97
+ "require": {
98
+ "types": "./dist/stacks/supabase/vite.d.cts",
99
+ "default": "./dist/stacks/supabase/vite.cjs"
100
+ }
61
101
  }
62
102
  },
63
103
  "bin": {
@@ -84,17 +124,20 @@
84
124
  "zod": ">=3.23.0"
85
125
  },
86
126
  "devDependencies": {
127
+ "@arethetypeswrong/cli": "^0.18.5",
87
128
  "@types/node": "22.13.13",
129
+ "publint": "^0.3.21",
88
130
  "rimraf": "^5.0.0",
89
- "tsup": "^7.2.0",
131
+ "tsdown": "^0.22.5",
90
132
  "typescript": "^5.9.3",
91
133
  "vite": "^7.3.1",
92
134
  "vitest": "^4.1.5",
93
135
  "zod": "^4.1.13"
94
136
  },
95
137
  "scripts": {
96
- "build": "tsup src/index.ts src/protocols/mcp/index.ts src/protocols/oauth-metadata.ts src/protocols/rest/index.ts src/stacks/tanstack/index.ts src/stacks/tanstack/vite.ts src/stacks/supabase/index.ts src/stacks/supabase/vite.ts src/cli/extract-manifest.ts --format cjs,esm --dts --outDir dist",
97
- "dev": "tsup src/index.ts src/protocols/mcp/index.ts src/protocols/oauth-metadata.ts src/protocols/rest/index.ts src/stacks/tanstack/index.ts src/stacks/tanstack/vite.ts src/stacks/supabase/index.ts src/stacks/supabase/vite.ts src/cli/extract-manifest.ts --format cjs,esm --dts --watch",
138
+ "build": "tsdown",
139
+ "check:package": "tmp=$(mktemp -d) && pnpm pack --out \"$tmp/pkg.tgz\" && tar -xzf \"$tmp/pkg.tgz\" -C \"$tmp\" && publint \"$tmp/package\" --strict && attw \"$tmp/pkg.tgz\" --profile node16",
140
+ "dev": "tsdown --watch",
98
141
  "typecheck": "tsgo --noEmit",
99
142
  "format": "oxfmt --write src/ tests/",
100
143
  "format:check": "oxfmt --check src/ tests/",
@@ -1,25 +0,0 @@
1
- interface McpRuntimeOptions {
2
- /**
3
- * Public MCP protocol path. REST companion handlers pass this so OAuth
4
- * resource/audience checks bind to `/mcp`, not internal `/.mcp/*` RPC URLs.
5
- */
6
- resourcePath?: string;
7
- /**
8
- * Host-relative path of the SDK-served protected-resource metadata document.
9
- * The Vite plugin injects it into every emitted handler when it generates the
10
- * PRM route, so the 401 challenge advertises the same path the route serves.
11
- * Its presence is the signal that the SDK owns the PRM document, so it is
12
- * mutually exclusive with `auth.protectedResourceMetadataUrl` (which points at
13
- * an externally hosted document). Defaults to the well-known path when absent.
14
- */
15
- metadataPath?: string;
16
- /**
17
- * Derive the request origin (and thus the advertised `resource`/metadata URLs)
18
- * from `X-Forwarded-Host` rather than the rewritten `Host`. Stack adapters read
19
- * this before invoking the handler, so the OAuth runtime never sees it; safe
20
- * only behind a proxy that overwrites the header (see `core/forwarded.ts`).
21
- */
22
- trustForwardedHost?: boolean;
23
- }
24
-
25
- export type { McpRuntimeOptions as M };
@@ -1,6 +0,0 @@
1
- // src/auth/metadata-path.ts
2
- var OAUTH_PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource";
3
-
4
- export {
5
- OAUTH_PROTECTED_RESOURCE_METADATA_PATH
6
- };
@@ -1,11 +0,0 @@
1
- // src/core/content.ts
2
- function extractTextContent(content) {
3
- if (!content)
4
- return void 0;
5
- const text = content.filter((block) => block.type === "text").map((block) => block.text).join("\n").trim();
6
- return text.length > 0 ? text : void 0;
7
- }
8
-
9
- export {
10
- extractTextContent
11
- };
@@ -1,104 +0,0 @@
1
- import {
2
- extractTextContent
3
- } from "./chunk-6QFZYYUV.js";
4
- import {
5
- ToolContext
6
- } from "./chunk-MA5H6PSF.js";
7
- import {
8
- corsPreflightResponse,
9
- createNoopRecorder,
10
- createRequestAuthorizer,
11
- nowMs,
12
- withCors
13
- } from "./chunk-YLU2JTHL.js";
14
- import {
15
- describeError,
16
- log
17
- } from "./chunk-H37EB22A.js";
18
-
19
- // src/protocols/mcp/protocol.ts
20
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
21
- import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
22
- function adaptToolToSdkCallback(tool, auth, recorder) {
23
- return async (first) => {
24
- const args = tool.inputSchema ? first ?? {} : {};
25
- const start = nowMs();
26
- let result;
27
- try {
28
- result = await tool.handler(args, new ToolContext(auth));
29
- } catch {
30
- await recorder.emit({
31
- tool: tool.name,
32
- method: "tools/call",
33
- outcome: "handler_error",
34
- durationMs: nowMs() - start
35
- });
36
- return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
37
- }
38
- if (result == null) {
39
- await recorder.emit({
40
- tool: tool.name,
41
- method: "tools/call",
42
- outcome: "handler_error",
43
- durationMs: nowMs() - start
44
- });
45
- return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
46
- }
47
- await recorder.emit({
48
- tool: tool.name,
49
- method: "tools/call",
50
- outcome: result.isError ? "tool_error" : "ok",
51
- durationMs: nowMs() - start,
52
- errorText: result.isError ? extractTextContent(result.content) : void 0
53
- });
54
- return { content: result.content ?? [], structuredContent: result.structuredContent, isError: result.isError };
55
- };
56
- }
57
- function createMcpProtocolHandler(mcp, options = {}) {
58
- const authorizer = createRequestAuthorizer(mcp, options);
59
- const handle = async (request, recorder) => {
60
- const authResult = await authorizer.authorize(request, recorder);
61
- if (!authResult.ok)
62
- return authResult.response;
63
- try {
64
- const server = new McpServer(
65
- { name: mcp.name, version: mcp.version, title: mcp.title },
66
- { instructions: mcp.instructions }
67
- );
68
- for (const tool of mcp.tools) {
69
- server.registerTool(
70
- tool.name,
71
- {
72
- title: tool.title,
73
- description: tool.description,
74
- inputSchema: tool.inputSchema,
75
- outputSchema: tool.outputSchema,
76
- annotations: tool.annotations
77
- },
78
- adaptToolToSdkCallback(tool, authResult.auth, recorder)
79
- );
80
- }
81
- const transport = new WebStandardStreamableHTTPServerTransport({
82
- sessionIdGenerator: void 0
83
- });
84
- await server.connect(transport);
85
- return await transport.handleRequest(request);
86
- } catch (err) {
87
- await recorder.emit({ tool: null, method: "transport", outcome: "transport_error", durationMs: 0 });
88
- log.error("mcp.transport_error", { ...describeError(err), outcome: "500 internal error" });
89
- return Response.json(
90
- { jsonrpc: "2.0", id: null, error: { code: -32603, message: "internal error" } },
91
- { status: 500 }
92
- );
93
- }
94
- };
95
- return async (request, recorder = createNoopRecorder()) => {
96
- if (request.method === "OPTIONS")
97
- return corsPreflightResponse("GET, POST, DELETE, OPTIONS");
98
- return withCors(await handle(request, recorder));
99
- };
100
- }
101
-
102
- export {
103
- createMcpProtocolHandler
104
- };
@@ -1,6 +0,0 @@
1
- // package.json
2
- var version = "0.21.0";
3
-
4
- export {
5
- version
6
- };
@@ -1,79 +0,0 @@
1
- import {
2
- JSON_HEADERS,
3
- corsPreflightResponse,
4
- getOAuthRuntime,
5
- headResponse,
6
- methodNotAllowed,
7
- oauthConfigurationErrorResponse,
8
- resolveProtectedResource,
9
- withCors
10
- } from "./chunk-YLU2JTHL.js";
11
- import {
12
- describeError,
13
- log
14
- } from "./chunk-H37EB22A.js";
15
-
16
- // src/protocols/oauth-metadata.ts
17
- function notFound() {
18
- return withCors(
19
- new Response(JSON.stringify({ error: "not found" }), {
20
- status: 404,
21
- // `no-store` so a 404 (OAuth unconfigured) isn't heuristically cached and
22
- // then served past a later deploy that enables OAuth and starts returning 200.
23
- headers: { ...JSON_HEADERS, "Cache-Control": "no-store" }
24
- })
25
- );
26
- }
27
- async function buildProtectedResourceMetadata(mcp, auth, request, options, discovery) {
28
- const issuer = await discovery.resolveIssuer();
29
- const body = {
30
- resource: resolveProtectedResource(auth, request, options),
31
- authorization_servers: [issuer],
32
- bearer_methods_supported: ["header"],
33
- resource_name: auth.resourceName ?? mcp.title,
34
- resource_documentation: auth.resourceDocumentation
35
- };
36
- if (auth.requiredScopes && auth.requiredScopes.length > 0)
37
- body.scopes_supported = auth.requiredScopes;
38
- return body;
39
- }
40
- function createOAuthProtectedResourceMetadataHandler(mcp, options = {}) {
41
- const runtime = getOAuthRuntime(mcp, options);
42
- if (runtime.kind === "configured" && runtime.auth.protectedResourceMetadataUrl === void 0 && runtime.auth.resource === void 0 && runtime.options.resourcePath === void 0) {
43
- throw new Error(
44
- `@lovable.dev/mcp-js: auth.resource or a resourcePath is required so the protected-resource metadata doesn't advertise the well-known URL as the resource`
45
- );
46
- }
47
- return async (request) => {
48
- if (runtime.kind !== "configured" || runtime.auth.protectedResourceMetadataUrl !== void 0)
49
- return notFound();
50
- if (request.method === "OPTIONS")
51
- return corsPreflightResponse("GET, HEAD, OPTIONS");
52
- if (request.method !== "GET" && request.method !== "HEAD")
53
- return withCors(methodNotAllowed("GET, HEAD, OPTIONS"));
54
- const headers = {
55
- ...JSON_HEADERS,
56
- "Cache-Control": "public, max-age=300",
57
- Vary: "Host"
58
- };
59
- try {
60
- const metadata = await buildProtectedResourceMetadata(
61
- mcp,
62
- runtime.auth,
63
- request,
64
- runtime.options,
65
- runtime.discovery
66
- );
67
- const response = withCors(Response.json(metadata, { headers }));
68
- return request.method === "HEAD" ? headResponse(response) : response;
69
- } catch (err) {
70
- log.error("oauth.metadata.config_error", { ...describeError(err), outcome: "500 oauth configuration error" });
71
- const response = withCors(oauthConfigurationErrorResponse());
72
- return request.method === "HEAD" ? headResponse(response) : response;
73
- }
74
- };
75
- }
76
-
77
- export {
78
- createOAuthProtectedResourceMetadataHandler
79
- };
@@ -1,125 +0,0 @@
1
- // src/core/logger.ts
2
- var LEVEL_RANK = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 };
3
- function isLogLevel(value) {
4
- return typeof value === "string" && value in LEVEL_RANK;
5
- }
6
- var LOG_LEVEL_ENV_VAR = "LOVABLE_MCP_LOG_LEVEL";
7
- function readEnvLevel() {
8
- try {
9
- const raw = typeof process !== "undefined" ? process.env?.[LOG_LEVEL_ENV_VAR] : void 0;
10
- const normalized = raw?.trim().toLowerCase();
11
- return isLogLevel(normalized) ? normalized : void 0;
12
- } catch {
13
- return void 0;
14
- }
15
- }
16
- var currentLevel = readEnvLevel() ?? "debug";
17
- function setLogLevel(level) {
18
- currentLevel = level;
19
- }
20
- function parseLogLevel(raw) {
21
- const normalized = raw?.trim().toLowerCase();
22
- return isLogLevel(normalized) ? normalized : void 0;
23
- }
24
- function applyLogLevelFromEnv(raw) {
25
- setLogLevel(parseLogLevel(raw) ?? "debug");
26
- }
27
- function enabled(level) {
28
- return LEVEL_RANK[level] <= LEVEL_RANK[currentLevel];
29
- }
30
- function emit(level, method, event, fields) {
31
- if (!enabled(level))
32
- return;
33
- const message = `[mcp-js] ${event}`;
34
- if (fields)
35
- console[method](message, fields);
36
- else
37
- console[method](message);
38
- }
39
- var log = {
40
- error: (event, fields) => emit("error", "error", event, fields),
41
- warn: (event, fields) => emit("warn", "warn", event, fields),
42
- info: (event, fields) => emit("info", "info", event, fields),
43
- debug: (event, fields) => emit("debug", "debug", event, fields)
44
- };
45
- function describeError(err) {
46
- if (err instanceof Error) {
47
- const code = err.code;
48
- return { name: err.name, message: err.message, ...typeof code === "string" ? { code } : {} };
49
- }
50
- return { value: String(err) };
51
- }
52
-
53
- // src/metrics/config.ts
54
- var DEFAULT_METRICS_ENDPOINT = "https://api.lovable.dev/v1/app-mcp-usage";
55
- var METRICS_API_KEY_ENV_VAR = "LOVABLE_API_KEY";
56
- function assertMetricsEndpoint(endpoint) {
57
- let url;
58
- try {
59
- url = new URL(endpoint);
60
- } catch {
61
- throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be an absolute URL, got ${JSON.stringify(endpoint)}`);
62
- }
63
- if (url.protocol !== "https:" && url.protocol !== "http:") {
64
- throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be http(s), got ${JSON.stringify(endpoint)}`);
65
- }
66
- }
67
- function resolveMetricsConfig(config = true) {
68
- const options = typeof config === "boolean" ? { enabled: config } : config;
69
- const endpoint = options.endpoint ?? DEFAULT_METRICS_ENDPOINT;
70
- assertMetricsEndpoint(endpoint);
71
- return Object.freeze({
72
- enabled: options.enabled ?? true,
73
- endpoint,
74
- headers: options.headers ?? {},
75
- apiKeyEnvVar: METRICS_API_KEY_ENV_VAR
76
- });
77
- }
78
-
79
- // src/core/url.ts
80
- function trimTrailingSlash(value) {
81
- return value.replace(/\/+$/, "");
82
- }
83
- function isLocalHTTPHost(hostname) {
84
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
85
- }
86
- function urlSafetyProblem(url) {
87
- const isAllowedHTTP = url.protocol === "http:" && isLocalHTTPHost(url.hostname);
88
- if (url.protocol !== "https:" && !isAllowedHTTP) {
89
- return "must use https://, except localhost development URLs";
90
- }
91
- if (url.username || url.password) {
92
- return "must not include credentials";
93
- }
94
- if (url.search || url.hash) {
95
- return "must not include query or fragment";
96
- }
97
- return void 0;
98
- }
99
-
100
- // src/core/validation.ts
101
- function parseSafeUrl(subject, raw, ErrorClass = Error) {
102
- let url;
103
- try {
104
- url = new URL(raw);
105
- } catch {
106
- throw new ErrorClass(`${subject} must be an absolute URL`);
107
- }
108
- const problem = urlSafetyProblem(url);
109
- if (problem) {
110
- throw new ErrorClass(`${subject} ${problem}`);
111
- }
112
- return url;
113
- }
114
-
115
- export {
116
- DEFAULT_METRICS_ENDPOINT,
117
- resolveMetricsConfig,
118
- trimTrailingSlash,
119
- parseSafeUrl,
120
- LOG_LEVEL_ENV_VAR,
121
- setLogLevel,
122
- applyLogLevelFromEnv,
123
- log,
124
- describeError
125
- };
@@ -1,58 +0,0 @@
1
- import {
2
- assertRestResourceBinding,
3
- corsPreflightResponse,
4
- createNoopRecorder,
5
- createRequestAuthorizer,
6
- headResponse,
7
- methodNotAllowed,
8
- withCors
9
- } from "./chunk-YLU2JTHL.js";
10
-
11
- // src/protocols/rest/list-tools.ts
12
- import { objectFromShape } from "@modelcontextprotocol/sdk/server/zod-compat.js";
13
- import { toJsonSchemaCompat } from "@modelcontextprotocol/sdk/server/zod-json-schema-compat.js";
14
- function shapeToJsonSchema(shape) {
15
- if (!shape)
16
- return null;
17
- try {
18
- return toJsonSchemaCompat(objectFromShape(shape));
19
- } catch {
20
- return null;
21
- }
22
- }
23
- function buildMcpListing(mcp) {
24
- return {
25
- server: { name: mcp.name, version: mcp.version, title: mcp.title },
26
- tools: mcp.tools.map((tool) => ({
27
- name: tool.name,
28
- title: tool.title,
29
- description: tool.description,
30
- annotations: tool.annotations,
31
- inputSchema: shapeToJsonSchema(tool.inputSchema),
32
- outputSchema: shapeToJsonSchema(tool.outputSchema)
33
- }))
34
- };
35
- }
36
- function createListToolsHandler(mcp, options = {}) {
37
- assertRestResourceBinding(mcp, options);
38
- const authorizer = createRequestAuthorizer(mcp, options);
39
- const handle = async (request, recorder) => {
40
- const authResult = await authorizer.authorize(request, recorder);
41
- if (!authResult.ok)
42
- return authResult.response;
43
- if (request.method !== "GET" && request.method !== "HEAD")
44
- return methodNotAllowed("GET, HEAD, OPTIONS");
45
- const response = Response.json(buildMcpListing(mcp));
46
- return request.method === "HEAD" ? headResponse(response) : response;
47
- };
48
- return async (request, recorder = createNoopRecorder()) => {
49
- if (request.method === "OPTIONS")
50
- return corsPreflightResponse("GET, HEAD, OPTIONS");
51
- return withCors(await handle(request, recorder));
52
- };
53
- }
54
-
55
- export {
56
- buildMcpListing,
57
- createListToolsHandler
58
- };
@@ -1,46 +0,0 @@
1
- // src/auth/context.ts
2
- var ToolContext = class {
3
- #auth;
4
- constructor(auth) {
5
- this.#auth = auth;
6
- }
7
- /** Whether the in-flight tool call carries a verified auth context. */
8
- isAuthenticated() {
9
- return this.#auth !== void 0;
10
- }
11
- /** The verified bearer token, or `undefined` when unauthenticated. Pass it to downstream APIs; never return or log it. */
12
- getToken() {
13
- return this.#auth?.bearer.token;
14
- }
15
- /** The verified user id (the token `sub`), or `undefined`. */
16
- getUserId() {
17
- return this.#auth?.principal.sub;
18
- }
19
- /** The verified user email, or `undefined` when absent. */
20
- getUserEmail() {
21
- return this.#auth?.principal.email;
22
- }
23
- /** The verified OAuth `client_id`, or `undefined`. */
24
- getClientId() {
25
- return this.#auth?.principal.clientId;
26
- }
27
- /** The verified OAuth scopes, or `undefined` when unauthenticated. */
28
- getScopes() {
29
- return this.#auth?.principal.scopes;
30
- }
31
- /** The verified token issuer, or `undefined`. */
32
- getIssuer() {
33
- return this.#auth?.principal.issuer;
34
- }
35
- /**
36
- * The full verified JWT claims, or `undefined`. Use this for app/business
37
- * authorization on issuer-specific claims that have no dedicated accessor.
38
- */
39
- getClaims() {
40
- return this.#auth?.principal.claims;
41
- }
42
- };
43
-
44
- export {
45
- ToolContext
46
- };