@lovable.dev/mcp-js 0.21.1-rc.1 → 0.22.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.
Files changed (87) hide show
  1. package/dist/authorize-BMeXd_Sh.d.ts +25 -0
  2. package/dist/base-CM-KCpp6.d.ts +28 -0
  3. package/dist/chunk-4EHZUUS5.js +141 -0
  4. package/dist/chunk-6DXGZZA4.js +6 -0
  5. package/dist/chunk-6KNM7RGD.js +79 -0
  6. package/dist/chunk-6QFZYYUV.js +11 -0
  7. package/dist/chunk-EOFPMSND.js +6 -0
  8. package/dist/chunk-H37EB22A.js +125 -0
  9. package/dist/chunk-MA5H6PSF.js +46 -0
  10. package/dist/chunk-P43FIUMZ.js +114 -0
  11. package/dist/chunk-RK62EMPY.js +741 -0
  12. package/dist/chunk-RLE4UE63.js +58 -0
  13. package/dist/chunk-UQK5UO6C.js +26 -0
  14. package/dist/chunk-XQWJN6DC.js +14 -0
  15. package/dist/chunk-Y3ZFPEQH.js +8 -0
  16. package/dist/cli/extract-manifest.cjs +201 -116
  17. package/dist/cli/extract-manifest.d.cts +1 -1
  18. package/dist/cli/extract-manifest.d.ts +1 -1
  19. package/dist/cli/extract-manifest.js +156 -117
  20. package/dist/index.cjs +329 -129
  21. package/dist/index.d.cts +26 -26
  22. package/dist/index.d.ts +26 -26
  23. package/dist/index.js +177 -118
  24. package/dist/{io-CS4UL6_A.d.ts → io-D4srzRKc.d.ts} +4 -6
  25. package/dist/protocols/mcp/index.cjs +750 -3
  26. package/dist/protocols/mcp/index.d.cts +7 -6
  27. package/dist/protocols/mcp/index.d.ts +7 -6
  28. package/dist/protocols/mcp/index.js +12 -2
  29. package/dist/protocols/oauth-metadata.cjs +539 -48
  30. package/dist/protocols/oauth-metadata.d.cts +6 -5
  31. package/dist/protocols/oauth-metadata.d.ts +6 -5
  32. package/dist/protocols/oauth-metadata.js +10 -52
  33. package/dist/protocols/rest/index.cjs +843 -5
  34. package/dist/protocols/rest/index.d.cts +10 -7
  35. package/dist/protocols/rest/index.d.ts +10 -7
  36. package/dist/protocols/rest/index.js +16 -3
  37. package/dist/stacks/supabase/index.cjs +1318 -76
  38. package/dist/stacks/supabase/index.d.cts +30 -29
  39. package/dist/stacks/supabase/index.d.ts +30 -29
  40. package/dist/stacks/supabase/index.js +89 -73
  41. package/dist/stacks/supabase/vite.cjs +287 -258
  42. package/dist/stacks/supabase/vite.d.cts +24 -24
  43. package/dist/stacks/supabase/vite.d.ts +24 -24
  44. package/dist/stacks/supabase/vite.js +252 -252
  45. package/dist/stacks/tanstack/index.cjs +1272 -42
  46. package/dist/stacks/tanstack/index.d.cts +9 -8
  47. package/dist/stacks/tanstack/index.d.ts +9 -8
  48. package/dist/stacks/tanstack/index.js +41 -36
  49. package/dist/stacks/tanstack/vite.cjs +312 -223
  50. package/dist/stacks/tanstack/vite.d.cts +81 -80
  51. package/dist/stacks/tanstack/vite.d.ts +81 -80
  52. package/dist/stacks/tanstack/vite.js +282 -216
  53. package/dist/types-qqrmJ736.d.ts +321 -0
  54. package/package.json +28 -71
  55. package/dist/authorize-CumVyk7p.d.cts +0 -27
  56. package/dist/authorize-D6p4-9_D.d.ts +0 -27
  57. package/dist/base-CoIFvAmS.d.cts +0 -26
  58. package/dist/base-CoIFvAmS.d.ts +0 -26
  59. package/dist/content-D5LJAHyM.js +0 -12
  60. package/dist/content-NCYIGgOb.cjs +0 -17
  61. package/dist/context-BweeEcoA.cjs +0 -56
  62. package/dist/context-CIpPzN7P.js +0 -51
  63. package/dist/cors-B7CTXIHD.js +0 -829
  64. package/dist/cors-BebjKPrc.cjs +0 -912
  65. package/dist/forwarded--h4efJy-.js +0 -43
  66. package/dist/forwarded-Pi8Hs5Ps.cjs +0 -48
  67. package/dist/fs-errors-CWNzOV75.cjs +0 -11
  68. package/dist/fs-errors-PA2t1TIp.js +0 -6
  69. package/dist/io-CbbUbPY3.d.cts +0 -15
  70. package/dist/list-tools-CBCuS1Tv.cjs +0 -57
  71. package/dist/list-tools-CsWgiRy1.d.ts +0 -8
  72. package/dist/list-tools-CtZHOuPv.d.cts +0 -8
  73. package/dist/list-tools-D75RGtgs.js +0 -46
  74. package/dist/logger-2OXtfiIW.js +0 -141
  75. package/dist/logger-BqPOa_E1.cjs +0 -194
  76. package/dist/mcp-Cdj0AYst.cjs +0 -123
  77. package/dist/mcp-GngXbcqN.js +0 -118
  78. package/dist/metadata-path-CAkNcfyY.js +0 -12
  79. package/dist/metadata-path-zd7NSNoa.cjs +0 -17
  80. package/dist/package-7EUptuSJ.js +0 -4
  81. package/dist/package-BwCGVRcB.cjs +0 -9
  82. package/dist/paths-IS65L6TA.js +0 -7
  83. package/dist/paths-OP318a6c.cjs +0 -18
  84. package/dist/rest-CXH6-zv9.js +0 -113
  85. package/dist/rest-CyV8LHeB.cjs +0 -118
  86. package/dist/types-BYdYYTjk.d.cts +0 -321
  87. package/dist/types-BYdYYTjk.d.ts +0 -321
@@ -1,89 +1,140 @@
1
- Object.defineProperties(exports, {
2
- __esModule: { value: true },
3
- [Symbol.toStringTag]: { value: "Module" }
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/stacks/tanstack/vite.ts
21
+ var vite_exports = {};
22
+ __export(vite_exports, {
23
+ assertMetadataPathShape: () => assertMetadataPathShape,
24
+ assertUrlPathShape: () => assertUrlPathShape,
25
+ default: () => vite_default,
26
+ deriveRouteFileName: () => deriveRouteFileName,
27
+ mcpPlugin: () => mcpPlugin
4
28
  });
5
- require("../../metadata-path-zd7NSNoa.cjs");
6
- const require_fs_errors = require("../../fs-errors-CWNzOV75.cjs");
7
- let node_fs = require("node:fs");
8
- let node_path = require("node:path");
9
- //#region src/stacks/tanstack/vite.ts
10
- const GENERATED_BANNER = "// AUTO-GENERATED by @lovable.dev/mcp-js — do not edit. Regenerated by the Vite plugin.\n// To take ownership, delete this banner line; the plugin then leaves the file alone.";
29
+ module.exports = __toCommonJS(vite_exports);
30
+ var import_node_fs = require("fs");
31
+ var import_node_path = require("path");
32
+
33
+ // src/auth/metadata-path.ts
34
+ var OAUTH_PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource";
35
+
36
+ // src/core/fs-errors.ts
37
+ function isFileMissing(err) {
38
+ return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
39
+ }
40
+
41
+ // src/stacks/tanstack/vite.ts
42
+ var GENERATED_BANNER = "// AUTO-GENERATED by @lovable.dev/mcp-js \u2014 do not edit. Regenerated by the Vite plugin.\n// To take ownership, delete this banner line; the plugin then leaves the file alone.";
11
43
  function normalizePath(p) {
12
- return p.split(node_path.sep).join("/");
44
+ return p.split(import_node_path.sep).join("/");
13
45
  }
14
46
  function assertContains(parent, child, label) {
15
- if (child !== parent && !child.startsWith(parent + node_path.sep)) throw new Error(`@lovable.dev/mcp-js: ${label} must resolve under ${parent}, got ${child}`);
47
+ if (child !== parent && !child.startsWith(parent + import_node_path.sep)) {
48
+ throw new Error(`@lovable.dev/mcp-js: ${label} must resolve under ${parent}, got ${child}`);
49
+ }
16
50
  }
17
51
  function wellKnownRouteFile(routesDir, urlPath) {
18
- const segments = urlPath.replace(/^\//, "").split("/");
19
- return (0, node_path.resolve)(routesDir, ...segments.map((segment, index) => {
20
- const escaped = segment.startsWith(".") ? `[${segment}]` : segment;
21
- return index === segments.length - 1 ? `${escaped}.ts` : escaped;
22
- }));
52
+ const segments = urlPath.replace(/^\//, "").split("/");
53
+ const fileSegments = segments.map((segment, index) => {
54
+ const escaped = segment.startsWith(".") ? `[${segment}]` : segment;
55
+ return index === segments.length - 1 ? `${escaped}.ts` : escaped;
56
+ });
57
+ return (0, import_node_path.resolve)(routesDir, ...fileSegments);
23
58
  }
24
59
  function resolveRestRoutes(routesDir, mcpUrlPath) {
25
- const parentSegments = mcpUrlPath.replace(/^\/+/, "").replace(/\/+$/, "").split("/").slice(0, -1);
26
- const restDir = (0, node_path.resolve)(routesDir, ...parentSegments, "[.mcp]");
27
- const restUrlBase = `/${[...parentSegments, ".mcp"].join("/")}`;
28
- return {
29
- listToolsRouteFile: (0, node_path.resolve)(restDir, "list-tools.ts"),
30
- invokeToolRouteFile: (0, node_path.resolve)(restDir, "invoke-tool", "$tool.ts"),
31
- listToolsLiteral: `${restUrlBase}/list-tools`,
32
- invokeToolLiteral: `${restUrlBase}/invoke-tool/$tool`
33
- };
60
+ const parentSegments = mcpUrlPath.replace(/^\/+/, "").replace(/\/+$/, "").split("/").slice(0, -1);
61
+ const restDir = (0, import_node_path.resolve)(routesDir, ...parentSegments, "[.mcp]");
62
+ const restUrlBase = `/${[...parentSegments, ".mcp"].join("/")}`;
63
+ return {
64
+ listToolsRouteFile: (0, import_node_path.resolve)(restDir, "list-tools.ts"),
65
+ invokeToolRouteFile: (0, import_node_path.resolve)(restDir, "invoke-tool", "$tool.ts"),
66
+ listToolsLiteral: `${restUrlBase}/list-tools`,
67
+ invokeToolLiteral: `${restUrlBase}/invoke-tool/$tool`
68
+ };
34
69
  }
35
70
  function resolveAllRoutes(projectRoot, routesDirOption, routeFileName, mcpUrlPath, metadataUrlPath) {
36
- const routesDir = (0, node_path.resolve)(projectRoot, routesDirOption);
37
- assertContains(projectRoot, routesDir, `routesDir "${routesDirOption}"`);
38
- const mcpRouteFile = (0, node_path.resolve)(routesDir, routeFileName);
39
- assertContains(routesDir, mcpRouteFile, `routeFileName "${routeFileName}"`);
40
- const metadataRouteFile = wellKnownRouteFile(routesDir, metadataUrlPath);
41
- assertContains(routesDir, metadataRouteFile, `metadataPath "${metadataUrlPath}"`);
42
- const rest = resolveRestRoutes(routesDir, mcpUrlPath);
43
- assertContains(routesDir, rest.listToolsRouteFile, `REST routes for path "${mcpUrlPath}"`);
44
- assertContains(routesDir, rest.invokeToolRouteFile, `REST routes for path "${mcpUrlPath}"`);
45
- return {
46
- routesDir,
47
- mcpRouteFile,
48
- metadataRouteFile,
49
- ...rest
50
- };
71
+ const routesDir = (0, import_node_path.resolve)(projectRoot, routesDirOption);
72
+ assertContains(projectRoot, routesDir, `routesDir "${routesDirOption}"`);
73
+ const mcpRouteFile = (0, import_node_path.resolve)(routesDir, routeFileName);
74
+ assertContains(routesDir, mcpRouteFile, `routeFileName "${routeFileName}"`);
75
+ const metadataRouteFile = wellKnownRouteFile(routesDir, metadataUrlPath);
76
+ assertContains(routesDir, metadataRouteFile, `metadataPath "${metadataUrlPath}"`);
77
+ const rest = resolveRestRoutes(routesDir, mcpUrlPath);
78
+ assertContains(routesDir, rest.listToolsRouteFile, `REST routes for path "${mcpUrlPath}"`);
79
+ assertContains(routesDir, rest.invokeToolRouteFile, `REST routes for path "${mcpUrlPath}"`);
80
+ return { routesDir, mcpRouteFile, metadataRouteFile, ...rest };
51
81
  }
52
82
  function assertUrlPathShape(urlPath) {
53
- if (!urlPath.startsWith("/")) throw new Error(`@lovable.dev/mcp-js: path must start with "/", got "${urlPath}"`);
54
- if (/\/{2,}/.test(urlPath)) throw new Error(`@lovable.dev/mcp-js: path "${urlPath}" contains empty segments ("//")`);
55
- const trimmed = urlPath.replace(/^\/+/, "").replace(/\/+$/, "");
56
- if (!trimmed) throw new Error(`@lovable.dev/mcp-js: path "${urlPath}" has no route segment`);
57
- if (!/^[a-zA-Z0-9_\-/]+$/.test(trimmed)) throw new Error(`@lovable.dev/mcp-js: path "${urlPath}" contains unsupported characters`);
58
- return trimmed;
83
+ if (!urlPath.startsWith("/")) {
84
+ throw new Error(`@lovable.dev/mcp-js: path must start with "/", got "${urlPath}"`);
85
+ }
86
+ if (/\/{2,}/.test(urlPath)) {
87
+ throw new Error(`@lovable.dev/mcp-js: path "${urlPath}" contains empty segments ("//")`);
88
+ }
89
+ const trimmed = urlPath.replace(/^\/+/, "").replace(/\/+$/, "");
90
+ if (!trimmed) {
91
+ throw new Error(`@lovable.dev/mcp-js: path "${urlPath}" has no route segment`);
92
+ }
93
+ if (!/^[a-zA-Z0-9_\-/]+$/.test(trimmed)) {
94
+ throw new Error(`@lovable.dev/mcp-js: path "${urlPath}" contains unsupported characters`);
95
+ }
96
+ return trimmed;
59
97
  }
60
98
  function deriveRouteFileName(urlPath) {
61
- return `${assertUrlPathShape(urlPath)}.ts`;
99
+ return `${assertUrlPathShape(urlPath)}.ts`;
62
100
  }
63
101
  function assertMetadataPathShape(metadataPath) {
64
- if (!metadataPath.startsWith("/")) throw new Error(`@lovable.dev/mcp-js: metadataPath must start with "/", got "${metadataPath}"`);
65
- if (/\/{2,}/.test(metadataPath)) throw new Error(`@lovable.dev/mcp-js: metadataPath "${metadataPath}" contains empty segments ("//")`);
66
- if (/(^|\/)\.\.(\/|$)/.test(metadataPath)) throw new Error(`@lovable.dev/mcp-js: metadataPath "${metadataPath}" must not contain ".." segments`);
67
- const trimmed = metadataPath.replace(/^\/+/, "").replace(/\/+$/, "");
68
- if (!trimmed) throw new Error(`@lovable.dev/mcp-js: metadataPath "${metadataPath}" has no route segment`);
69
- if (!/^[a-zA-Z0-9_\-./]+$/.test(trimmed)) throw new Error(`@lovable.dev/mcp-js: metadataPath "${metadataPath}" contains unsupported characters`);
102
+ if (!metadataPath.startsWith("/")) {
103
+ throw new Error(`@lovable.dev/mcp-js: metadataPath must start with "/", got "${metadataPath}"`);
104
+ }
105
+ if (/\/{2,}/.test(metadataPath)) {
106
+ throw new Error(`@lovable.dev/mcp-js: metadataPath "${metadataPath}" contains empty segments ("//")`);
107
+ }
108
+ if (/(^|\/)\.\.(\/|$)/.test(metadataPath)) {
109
+ throw new Error(`@lovable.dev/mcp-js: metadataPath "${metadataPath}" must not contain ".." segments`);
110
+ }
111
+ const trimmed = metadataPath.replace(/^\/+/, "").replace(/\/+$/, "");
112
+ if (!trimmed) {
113
+ throw new Error(`@lovable.dev/mcp-js: metadataPath "${metadataPath}" has no route segment`);
114
+ }
115
+ if (!/^[a-zA-Z0-9_\-./]+$/.test(trimmed)) {
116
+ throw new Error(`@lovable.dev/mcp-js: metadataPath "${metadataPath}" contains unsupported characters`);
117
+ }
70
118
  }
71
119
  function canonicalUrlPath(urlPath) {
72
- return `/${urlPath.replace(/^\/+/, "").replace(/\/+$/, "")}`;
120
+ return `/${urlPath.replace(/^\/+/, "").replace(/\/+$/, "")}`;
73
121
  }
74
122
  function relativeImportSpecifier(routeFile, target) {
75
- const withoutExt = normalizePath((0, node_path.relative)((0, node_path.dirname)(routeFile), target)).replace(/\.ts$/, "");
76
- return withoutExt.startsWith(".") ? withoutExt : `./${withoutExt}`;
123
+ const rel = normalizePath((0, import_node_path.relative)((0, import_node_path.dirname)(routeFile), target));
124
+ const withoutExt = rel.replace(/\.ts$/, "");
125
+ return withoutExt.startsWith(".") ? withoutExt : `./${withoutExt}`;
77
126
  }
78
127
  function buildRouteSource(route, resourcePath, metadataPath, trustForwardedHost, mcpEntry, projectRoot) {
79
- const mcpImport = relativeImportSpecifier(route.file, mcpEntry);
80
- const routeRel = normalizePath((0, node_path.relative)(projectRoot, route.file));
81
- const note = route.spaFallbackNote ? " // ANY: TanStack returns SPA HTML for methods not in `handlers`; the SDK 405s instead.\n" : "";
82
- const optionEntries = [`resourcePath: "${resourcePath}"`];
83
- if (metadataPath !== void 0) optionEntries.push(`metadataPath: "${metadataPath}"`);
84
- if (trustForwardedHost) optionEntries.push("trustForwardedHost: true");
85
- const runtimeOptions = `{ ${optionEntries.join(", ")} }`;
86
- return `${GENERATED_BANNER}
128
+ const mcpImport = relativeImportSpecifier(route.file, mcpEntry);
129
+ const routeRel = normalizePath((0, import_node_path.relative)(projectRoot, route.file));
130
+ const note = route.spaFallbackNote ? " // ANY: TanStack returns SPA HTML for methods not in `handlers`; the SDK 405s instead.\n" : "";
131
+ const optionEntries = [`resourcePath: "${resourcePath}"`];
132
+ if (metadataPath !== void 0)
133
+ optionEntries.push(`metadataPath: "${metadataPath}"`);
134
+ if (trustForwardedHost)
135
+ optionEntries.push("trustForwardedHost: true");
136
+ const runtimeOptions = `{ ${optionEntries.join(", ")} }`;
137
+ return `${GENERATED_BANNER}
87
138
  // route: ${route.routeLiteral}
88
139
  // emitted to: ${routeRel}
89
140
 
@@ -102,172 +153,210 @@ ${note} ANY: ${route.handlerFactory}(mcp, ${runtimeOptions}),
102
153
  });
103
154
  `;
104
155
  }
105
- /**
106
- * Writes `content` to `file` if it differs from what's there. Refuses to
107
- * overwrite files without `GENERATED_BANNER` — the banner is the consent token.
108
- */
109
156
  function hasGeneratedBanner(content) {
110
- return content.replace(/\r\n/g, "\n").startsWith(GENERATED_BANNER);
157
+ return content.replace(/\r\n/g, "\n").startsWith(GENERATED_BANNER);
111
158
  }
112
159
  function writeIfChanged(file, content) {
113
- let existing;
114
- try {
115
- existing = (0, node_fs.readFileSync)(file, "utf8");
116
- } catch (err) {
117
- if (!require_fs_errors.isFileMissing(err)) throw err;
118
- }
119
- if (existing !== void 0) {
120
- if (!hasGeneratedBanner(existing)) throw new Error(`@lovable.dev/mcp-js: refusing to overwrite user-authored route at ${file}. Delete it or move it first.`);
121
- if (existing === content) return false;
122
- }
123
- (0, node_fs.mkdirSync)((0, node_path.dirname)(file), { recursive: true });
124
- (0, node_fs.writeFileSync)(file, content, "utf8");
125
- return true;
160
+ let existing;
161
+ try {
162
+ existing = (0, import_node_fs.readFileSync)(file, "utf8");
163
+ } catch (err) {
164
+ if (!isFileMissing(err))
165
+ throw err;
166
+ }
167
+ if (existing !== void 0) {
168
+ if (!hasGeneratedBanner(existing)) {
169
+ throw new Error(
170
+ `@lovable.dev/mcp-js: refusing to overwrite user-authored route at ${file}. Delete it or move it first.`
171
+ );
172
+ }
173
+ if (existing === content)
174
+ return false;
175
+ }
176
+ (0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(file), { recursive: true });
177
+ (0, import_node_fs.writeFileSync)(file, content, "utf8");
178
+ return true;
126
179
  }
127
180
  function fileStartsWithBanner(file) {
128
- try {
129
- return hasGeneratedBanner((0, node_fs.readFileSync)(file, "utf8"));
130
- } catch (err) {
131
- if (require_fs_errors.isFileMissing(err)) return false;
132
- throw err;
133
- }
181
+ try {
182
+ return hasGeneratedBanner((0, import_node_fs.readFileSync)(file, "utf8"));
183
+ } catch (err) {
184
+ if (isFileMissing(err))
185
+ return false;
186
+ throw err;
187
+ }
134
188
  }
135
189
  function findAdoptedFiles(routesDir) {
136
- const adopted = [];
137
- const visit = (dir) => {
138
- let entries;
139
- try {
140
- entries = (0, node_fs.readdirSync)(dir);
141
- } catch (err) {
142
- if (require_fs_errors.isFileMissing(err)) return;
143
- throw err;
144
- }
145
- for (const entry of entries) {
146
- const full = (0, node_path.join)(dir, entry);
147
- let stat;
148
- try {
149
- stat = (0, node_fs.lstatSync)(full);
150
- } catch (err) {
151
- if (require_fs_errors.isFileMissing(err)) continue;
152
- throw err;
153
- }
154
- if (stat.isDirectory()) visit(full);
155
- else if (entry.endsWith(".ts") && fileStartsWithBanner(full)) adopted.push(full);
156
- }
157
- };
158
- visit(routesDir);
159
- return adopted;
190
+ const adopted = [];
191
+ const visit = (dir) => {
192
+ let entries;
193
+ try {
194
+ entries = (0, import_node_fs.readdirSync)(dir);
195
+ } catch (err) {
196
+ if (isFileMissing(err))
197
+ return;
198
+ throw err;
199
+ }
200
+ for (const entry of entries) {
201
+ const full = (0, import_node_path.join)(dir, entry);
202
+ let stat;
203
+ try {
204
+ stat = (0, import_node_fs.lstatSync)(full);
205
+ } catch (err) {
206
+ if (isFileMissing(err))
207
+ continue;
208
+ throw err;
209
+ }
210
+ if (stat.isDirectory()) {
211
+ visit(full);
212
+ } else if (entry.endsWith(".ts") && fileStartsWithBanner(full)) {
213
+ adopted.push(full);
214
+ }
215
+ }
216
+ };
217
+ visit(routesDir);
218
+ return adopted;
160
219
  }
161
- /**
162
- * Generate the TanStack route(s) that mount the MCP server.
163
- *
164
- * Place this in your `vite.config.ts` plugins array. Emits during
165
- * `configResolved` (so dev-server boot and the TanStack file-router both
166
- * see the routes on the first request) and re-emits when the MCP entry
167
- * file appears or disappears during dev.
168
- *
169
- * The `.lovable/mcp/manifest.json` snapshot is produced separately by the
170
- * `lovable-mcp-extract-manifest` CLI (run by a host platform at build/commit
171
- * time) — not by this plugin.
172
- */
173
220
  function mcpPlugin(options = {}) {
174
- const mcpEntryOption = options.mcpEntry ?? "src/lib/mcp/index.ts";
175
- const routesDirOption = options.routesDir ?? "src/routes";
176
- const rawUrlPath = options.path ?? "/mcp";
177
- assertUrlPathShape(rawUrlPath);
178
- const routeFileName = options.routeFileName ?? deriveRouteFileName(rawUrlPath);
179
- const urlPath = canonicalUrlPath(rawUrlPath);
180
- const emitRestRoutes = options.restRoutes !== false;
181
- const emitProtectedResourceMetadataRoute = options.protectedResourceMetadataRoute !== false;
182
- if (options.metadataPath !== void 0) {
183
- if (!emitProtectedResourceMetadataRoute) throw new Error(`@lovable.dev/mcp-js: metadataPath sets where the protected-resource metadata route is served, so it can't be combined with protectedResourceMetadataRoute: false.`);
184
- assertMetadataPathShape(options.metadataPath);
185
- }
186
- const metadataUrlPath = canonicalUrlPath(options.metadataPath ?? "/.well-known/oauth-protected-resource");
187
- const injectedMetadataPath = emitProtectedResourceMetadataRoute ? metadataUrlPath : void 0;
188
- const trustForwardedHost = options.trustForwardedHost !== false;
189
- let projectRoot = process.cwd();
190
- let mcpEntry = (0, node_path.resolve)(projectRoot, mcpEntryOption);
191
- let { routesDir, mcpRouteFile, metadataRouteFile, listToolsRouteFile, invokeToolRouteFile, listToolsLiteral, invokeToolLiteral } = resolveAllRoutes(projectRoot, routesDirOption, routeFileName, urlPath, metadataUrlPath);
192
- const regenerate = () => {
193
- let mcpEntryExists = true;
194
- try {
195
- (0, node_fs.lstatSync)(mcpEntry);
196
- } catch (err) {
197
- if (!require_fs_errors.isFileMissing(err)) throw err;
198
- mcpEntryExists = false;
199
- }
200
- const expected = /* @__PURE__ */ new Set();
201
- if (mcpEntryExists) {
202
- const routes = [{
203
- file: mcpRouteFile,
204
- routeLiteral: urlPath,
205
- handlerFactory: "createTanStackMcpHandler"
206
- }];
207
- if (emitProtectedResourceMetadataRoute) routes.push({
208
- file: metadataRouteFile,
209
- routeLiteral: metadataUrlPath,
210
- handlerFactory: "createTanStackOAuthProtectedResourceMetadataHandler"
211
- });
212
- if (emitRestRoutes) routes.push({
213
- file: listToolsRouteFile,
214
- routeLiteral: listToolsLiteral,
215
- handlerFactory: "createTanStackListToolsHandler",
216
- spaFallbackNote: true
217
- }, {
218
- file: invokeToolRouteFile,
219
- routeLiteral: invokeToolLiteral,
220
- handlerFactory: "createTanStackInvokeToolHandler",
221
- spaFallbackNote: true
222
- });
223
- for (const route of routes) {
224
- expected.add(route.file);
225
- writeIfChanged(route.file, buildRouteSource(route, urlPath, injectedMetadataPath, trustForwardedHost, mcpEntry, projectRoot));
226
- }
227
- }
228
- for (const file of findAdoptedFiles(routesDir)) if (!expected.has(file)) try {
229
- (0, node_fs.unlinkSync)(file);
230
- } catch (err) {
231
- if (!require_fs_errors.isFileMissing(err)) throw err;
232
- }
233
- };
234
- return {
235
- name: "@lovable.dev/mcp-js",
236
- api: {
237
- get mcpEntry() {
238
- return mcpEntry;
239
- },
240
- get urlPath() {
241
- return urlPath;
242
- }
243
- },
244
- configResolved(config) {
245
- projectRoot = config.root;
246
- mcpEntry = (0, node_path.resolve)(projectRoot, mcpEntryOption);
247
- ({routesDir, mcpRouteFile, metadataRouteFile, listToolsRouteFile, invokeToolRouteFile, listToolsLiteral, invokeToolLiteral} = resolveAllRoutes(projectRoot, routesDirOption, routeFileName, urlPath, metadataUrlPath));
248
- regenerate();
249
- },
250
- configureServer(server) {
251
- const onChange = (file) => {
252
- if (normalizePath(file) === normalizePath(mcpEntry)) regenerate();
253
- };
254
- server.watcher.on("add", onChange);
255
- server.watcher.on("change", onChange);
256
- server.watcher.on("unlink", onChange);
257
- server.watcher.once("close", () => {
258
- server.watcher.off("add", onChange);
259
- server.watcher.off("change", onChange);
260
- server.watcher.off("unlink", onChange);
261
- });
262
- },
263
- buildStart() {
264
- regenerate();
265
- }
266
- };
221
+ const mcpEntryOption = options.mcpEntry ?? "src/lib/mcp/index.ts";
222
+ const routesDirOption = options.routesDir ?? "src/routes";
223
+ const rawUrlPath = options.path ?? "/mcp";
224
+ assertUrlPathShape(rawUrlPath);
225
+ const routeFileName = options.routeFileName ?? deriveRouteFileName(rawUrlPath);
226
+ const urlPath = canonicalUrlPath(rawUrlPath);
227
+ const emitRestRoutes = options.restRoutes !== false;
228
+ const emitProtectedResourceMetadataRoute = options.protectedResourceMetadataRoute !== false;
229
+ if (options.metadataPath !== void 0) {
230
+ if (!emitProtectedResourceMetadataRoute) {
231
+ throw new Error(
232
+ `@lovable.dev/mcp-js: metadataPath sets where the protected-resource metadata route is served, so it can't be combined with protectedResourceMetadataRoute: false.`
233
+ );
234
+ }
235
+ assertMetadataPathShape(options.metadataPath);
236
+ }
237
+ const metadataUrlPath = canonicalUrlPath(options.metadataPath ?? OAUTH_PROTECTED_RESOURCE_METADATA_PATH);
238
+ const injectedMetadataPath = emitProtectedResourceMetadataRoute ? metadataUrlPath : void 0;
239
+ const trustForwardedHost = options.trustForwardedHost !== false;
240
+ let projectRoot = process.cwd();
241
+ let mcpEntry = (0, import_node_path.resolve)(projectRoot, mcpEntryOption);
242
+ let {
243
+ routesDir,
244
+ mcpRouteFile,
245
+ metadataRouteFile,
246
+ listToolsRouteFile,
247
+ invokeToolRouteFile,
248
+ listToolsLiteral,
249
+ invokeToolLiteral
250
+ } = resolveAllRoutes(projectRoot, routesDirOption, routeFileName, urlPath, metadataUrlPath);
251
+ const regenerate = () => {
252
+ let mcpEntryExists = true;
253
+ try {
254
+ (0, import_node_fs.lstatSync)(mcpEntry);
255
+ } catch (err) {
256
+ if (!isFileMissing(err))
257
+ throw err;
258
+ mcpEntryExists = false;
259
+ }
260
+ const expected = /* @__PURE__ */ new Set();
261
+ if (mcpEntryExists) {
262
+ const routes = [
263
+ { file: mcpRouteFile, routeLiteral: urlPath, handlerFactory: "createTanStackMcpHandler" }
264
+ ];
265
+ if (emitProtectedResourceMetadataRoute) {
266
+ routes.push({
267
+ file: metadataRouteFile,
268
+ routeLiteral: metadataUrlPath,
269
+ handlerFactory: "createTanStackOAuthProtectedResourceMetadataHandler"
270
+ });
271
+ }
272
+ if (emitRestRoutes) {
273
+ routes.push(
274
+ {
275
+ file: listToolsRouteFile,
276
+ routeLiteral: listToolsLiteral,
277
+ handlerFactory: "createTanStackListToolsHandler",
278
+ spaFallbackNote: true
279
+ },
280
+ {
281
+ file: invokeToolRouteFile,
282
+ routeLiteral: invokeToolLiteral,
283
+ handlerFactory: "createTanStackInvokeToolHandler",
284
+ spaFallbackNote: true
285
+ }
286
+ );
287
+ }
288
+ for (const route of routes) {
289
+ expected.add(route.file);
290
+ writeIfChanged(
291
+ route.file,
292
+ buildRouteSource(route, urlPath, injectedMetadataPath, trustForwardedHost, mcpEntry, projectRoot)
293
+ );
294
+ }
295
+ }
296
+ for (const file of findAdoptedFiles(routesDir)) {
297
+ if (!expected.has(file)) {
298
+ try {
299
+ (0, import_node_fs.unlinkSync)(file);
300
+ } catch (err) {
301
+ if (!isFileMissing(err))
302
+ throw err;
303
+ }
304
+ }
305
+ }
306
+ };
307
+ return {
308
+ name: "@lovable.dev/mcp-js",
309
+ // The extract CLI reads the resolved entry + URL path back through this
310
+ // (via `resolveConfig().plugins`) so the manifest honors custom
311
+ // `mcpEntry`/`path` instead of assuming the defaults. Getters because
312
+ // `mcpEntry` is finalized in `configResolved`.
313
+ api: {
314
+ get mcpEntry() {
315
+ return mcpEntry;
316
+ },
317
+ get urlPath() {
318
+ return urlPath;
319
+ }
320
+ },
321
+ configResolved(config) {
322
+ projectRoot = config.root;
323
+ mcpEntry = (0, import_node_path.resolve)(projectRoot, mcpEntryOption);
324
+ ({
325
+ routesDir,
326
+ mcpRouteFile,
327
+ metadataRouteFile,
328
+ listToolsRouteFile,
329
+ invokeToolRouteFile,
330
+ listToolsLiteral,
331
+ invokeToolLiteral
332
+ } = resolveAllRoutes(projectRoot, routesDirOption, routeFileName, urlPath, metadataUrlPath));
333
+ regenerate();
334
+ },
335
+ configureServer(server) {
336
+ const onChange = (file) => {
337
+ if (normalizePath(file) === normalizePath(mcpEntry)) {
338
+ regenerate();
339
+ }
340
+ };
341
+ server.watcher.on("add", onChange);
342
+ server.watcher.on("change", onChange);
343
+ server.watcher.on("unlink", onChange);
344
+ server.watcher.once("close", () => {
345
+ server.watcher.off("add", onChange);
346
+ server.watcher.off("change", onChange);
347
+ server.watcher.off("unlink", onChange);
348
+ });
349
+ },
350
+ buildStart() {
351
+ regenerate();
352
+ }
353
+ };
267
354
  }
268
- //#endregion
269
- exports.assertMetadataPathShape = assertMetadataPathShape;
270
- exports.assertUrlPathShape = assertUrlPathShape;
271
- exports.default = mcpPlugin;
272
- exports.mcpPlugin = mcpPlugin;
273
- exports.deriveRouteFileName = deriveRouteFileName;
355
+ var vite_default = mcpPlugin;
356
+ // Annotate the CommonJS export names for ESM import in node:
357
+ 0 && (module.exports = {
358
+ assertMetadataPathShape,
359
+ assertUrlPathShape,
360
+ deriveRouteFileName,
361
+ mcpPlugin
362
+ });