sunpeak 0.10.6 → 0.10.7

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 (33) hide show
  1. package/bin/commands/mcp.mjs +213 -46
  2. package/dist/chatgpt/index.cjs +1 -1
  3. package/dist/chatgpt/index.js +1 -1
  4. package/dist/index.cjs +1 -1
  5. package/dist/index.js +2 -2
  6. package/dist/mcp/entry.cjs +2 -1
  7. package/dist/mcp/entry.cjs.map +1 -1
  8. package/dist/mcp/entry.js +2 -1
  9. package/dist/mcp/entry.js.map +1 -1
  10. package/dist/mcp/index.cjs +1 -1
  11. package/dist/mcp/index.js +1 -1
  12. package/dist/mcp/types.d.ts +7 -0
  13. package/dist/{server-CnRhUNGQ.js → server-BLKltt88.js} +124 -28
  14. package/dist/{server-CnRhUNGQ.js.map → server-BLKltt88.js.map} +1 -1
  15. package/dist/{server-B-T6Y3-J.cjs → server-D_oRdZjX.cjs} +124 -28
  16. package/dist/{server-B-T6Y3-J.cjs.map → server-D_oRdZjX.cjs.map} +1 -1
  17. package/dist/{simulator-url-pSDp_VWO.cjs → simulator-url-B6DZi3vV.cjs} +25 -14
  18. package/dist/simulator-url-B6DZi3vV.cjs.map +1 -0
  19. package/dist/{simulator-url-BUKX-wRa.js → simulator-url-izFV6mji.js} +24 -13
  20. package/dist/simulator-url-izFV6mji.js.map +1 -0
  21. package/package.json +1 -1
  22. package/template/dist/albums/albums.js +4 -4
  23. package/template/dist/albums/albums.json +1 -1
  24. package/template/dist/carousel/carousel.js +3 -3
  25. package/template/dist/carousel/carousel.json +1 -1
  26. package/template/dist/map/map.js +8 -8
  27. package/template/dist/map/map.json +1 -1
  28. package/template/dist/review/review.js +3 -3
  29. package/template/dist/review/review.json +1 -1
  30. package/template/node_modules/.vite/deps/_metadata.json +22 -22
  31. package/template/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  32. package/dist/simulator-url-BUKX-wRa.js.map +0 -1
  33. package/dist/simulator-url-pSDp_VWO.cjs.map +0 -1
@@ -1,16 +1,106 @@
1
1
  #!/usr/bin/env node
2
- import { spawn } from 'child_process';
3
- import { existsSync } from 'fs';
4
- import { join } from 'path';
5
- import { detectPackageManager } from '../utils.mjs';
2
+ import { existsSync, readFileSync, readdirSync } from 'fs';
3
+ import { join, dirname, resolve, basename } from 'path';
4
+ import { createRequire } from 'module';
5
+ import { pathToFileURL } from 'url';
6
6
 
7
7
  /**
8
- * Start the MCP server with auto-reload
9
- * Runs in the context of a user's project directory
8
+ * Import a module from the project's node_modules using ESM resolution
10
9
  */
11
- export async function mcp(projectRoot = process.cwd(), args = []) {
12
- const pm = detectPackageManager(projectRoot);
10
+ async function importFromProject(require, moduleName) {
11
+ const resolvedPath = require.resolve(moduleName);
12
+
13
+ // Walk up to find package.json
14
+ let pkgDir = dirname(resolvedPath);
15
+ let pkg;
16
+ while (pkgDir !== dirname(pkgDir)) {
17
+ try {
18
+ const pkgJsonPath = join(pkgDir, 'package.json');
19
+ pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
20
+ if (pkg.name === moduleName || moduleName.startsWith(pkg.name + '/')) {
21
+ break;
22
+ }
23
+ } catch {
24
+ // No package.json at this level, keep looking
25
+ }
26
+ pkgDir = dirname(pkgDir);
27
+ }
28
+
29
+ if (!pkg) {
30
+ return import(resolvedPath);
31
+ }
32
+
33
+ // Determine ESM entry
34
+ let entry = pkg.main || 'index.js';
35
+ if (pkg.exports) {
36
+ const exp = pkg.exports['.'] || pkg.exports;
37
+ if (typeof exp === 'string') {
38
+ entry = exp;
39
+ } else if (exp.import) {
40
+ entry = typeof exp.import === 'string' ? exp.import : exp.import.default;
41
+ } else if (exp.default) {
42
+ entry = exp.default;
43
+ }
44
+ } else if (pkg.module) {
45
+ entry = pkg.module;
46
+ }
47
+
48
+ const entryPath = join(pkgDir, entry);
49
+ return import(pathToFileURL(entryPath).href);
50
+ }
13
51
 
52
+ /**
53
+ * Discover simulations from src/resources directories
54
+ */
55
+ function discoverSimulations(projectRoot) {
56
+ const resourcesDir = join(projectRoot, 'src/resources');
57
+ const resourceDirs = readdirSync(resourcesDir, { withFileTypes: true }).filter((entry) =>
58
+ entry.isDirectory()
59
+ );
60
+
61
+ const simulations = [];
62
+
63
+ for (const entry of resourceDirs) {
64
+ const resourceKey = entry.name;
65
+ const resourceDir = join(resourcesDir, resourceKey);
66
+ const resourcePath = join(resourceDir, `${resourceKey}-resource.json`);
67
+
68
+ if (!existsSync(resourcePath)) {
69
+ continue;
70
+ }
71
+
72
+ const resource = JSON.parse(readFileSync(resourcePath, 'utf-8'));
73
+
74
+ const dirFiles = readdirSync(resourceDir);
75
+ for (const file of dirFiles) {
76
+ if (file.endsWith('-simulation.json')) {
77
+ const simulationKey = file.replace(/-simulation\.json$/, '');
78
+ const simulationPath = join(resourceDir, file);
79
+ const simulation = JSON.parse(readFileSync(simulationPath, 'utf-8'));
80
+
81
+ simulations.push({
82
+ ...simulation,
83
+ name: simulationKey,
84
+ distPath: join(projectRoot, `dist/${resourceKey}/${resourceKey}.js`),
85
+ srcPath: `/src/resources/${resourceKey}/${resourceKey}-resource.tsx`,
86
+ resource,
87
+ });
88
+ }
89
+ }
90
+ }
91
+
92
+ return simulations;
93
+ }
94
+
95
+ /**
96
+ * Start the MCP server with Vite HMR
97
+ *
98
+ * Architecture:
99
+ * 1. Vite dev server runs in middleware mode on the same port
100
+ * 2. MCP resources return HTML that loads from Vite
101
+ * 3. Vite handles all HMR natively - no custom WebSocket needed
102
+ */
103
+ export async function mcp(projectRoot = process.cwd(), args = []) {
14
104
  // Check for package.json
15
105
  const pkgJsonPath = join(projectRoot, 'package.json');
16
106
  if (!existsSync(pkgJsonPath)) {
@@ -19,51 +109,128 @@ export async function mcp(projectRoot = process.cwd(), args = []) {
19
109
  process.exit(1);
20
110
  }
21
111
 
22
- console.log('Starting MCP server with auto-reload...');
23
- console.log('Watching src/ for changes...\n');
24
-
25
- // Build nodemon command
26
- const nodemonCommand = pm === 'npm' ? 'npx' : pm;
27
- const nodemonArgs = pm === 'npm' ? ['nodemon'] : ['exec', 'nodemon'];
28
-
29
- // Add inline nodemon configuration
30
- nodemonArgs.push(
31
- '--watch', 'src',
32
- '--ext', 'ts,tsx,js,jsx,css,json',
33
- '--ignore', 'dist',
34
- '--ignore', 'node_modules',
35
- '--ignore', '.tmp',
36
- '--delay', '500ms',
37
- '--exec', 'sunpeak build && tsx node_modules/sunpeak/dist/mcp/entry.js'
38
- );
112
+ // Check for --no-vite flag (production mode)
113
+ const noVite = args.includes('--no-vite');
39
114
 
40
- // Add any additional args
41
- nodemonArgs.push(...args);
42
-
43
- // Spawn nodemon process
44
- const child = spawn(nodemonCommand, nodemonArgs, {
45
- cwd: projectRoot,
46
- stdio: 'inherit',
47
- env: {
48
- ...process.env,
49
- FORCE_COLOR: '1',
50
- },
51
- });
115
+ const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
116
+ const require = createRequire(join(projectRoot, 'package.json'));
52
117
 
53
- // Forward signals
54
- process.on('SIGINT', () => {
55
- child.kill('SIGINT');
56
- process.exit(0);
118
+ // Discover simulations
119
+ const simulations = discoverSimulations(projectRoot);
120
+ if (simulations.length === 0) {
121
+ console.error('Error: No simulations found in src/resources/');
122
+ process.exit(1);
123
+ }
124
+
125
+ console.log(`Found ${simulations.length} simulation(s)`);
126
+
127
+ let viteServer = null;
128
+
129
+ if (!noVite) {
130
+ console.log('Starting Vite dev server for HMR...\n');
131
+
132
+ // Import vite and plugins from the project's node_modules
133
+ const vite = await importFromProject(require, 'vite');
134
+ const reactPlugin = await importFromProject(require, '@vitejs/plugin-react');
135
+ const react = reactPlugin.default;
136
+ const tailwindPlugin = await importFromProject(require, '@tailwindcss/vite');
137
+ const tailwindcss = tailwindPlugin.default;
138
+
139
+ // Check if we're in the sunpeak workspace (directory is named "template")
140
+ const isTemplate = basename(projectRoot) === 'template';
141
+ const parentSrc = resolve(projectRoot, '../src');
142
+
143
+ // Virtual entry module plugin for consistent React resolution
144
+ // This ensures React/ReactDOM imports in the entry module resolve to the same
145
+ // pre-bundled versions as the component imports
146
+ const sunpeakEntryPlugin = () => ({
147
+ name: 'sunpeak-entry',
148
+ resolveId(id) {
149
+ if (id.startsWith('virtual:sunpeak-entry')) {
150
+ return id;
151
+ }
152
+ },
153
+ load(id) {
154
+ if (id.startsWith('virtual:sunpeak-entry')) {
155
+ const url = new URL(id.replace('virtual:sunpeak-entry', 'http://x'));
156
+ const srcPath = url.searchParams.get('src');
157
+ const componentName = url.searchParams.get('component');
158
+
159
+ if (!srcPath || !componentName) {
160
+ return 'console.error("Missing src or component param");';
161
+ }
162
+
163
+ return `
164
+ import { createElement } from 'react';
165
+ import { createRoot } from 'react-dom/client';
166
+ import * as ResourceModule from '${srcPath}';
167
+
168
+ const Component = ResourceModule.default || ResourceModule['${componentName}'];
169
+ if (!Component) {
170
+ document.getElementById('root').innerHTML = '<pre style="color:red;padding:16px">Component not found: ${componentName}\\nExports: ' + Object.keys(ResourceModule).join(', ') + '</pre>';
171
+ } else {
172
+ createRoot(document.getElementById('root')).render(createElement(Component));
173
+ }
174
+ `;
175
+ }
176
+ },
177
+ });
178
+
179
+ // Create Vite dev server in middleware mode (matching skybridge's approach)
180
+ viteServer = await vite.createServer({
181
+ root: projectRoot,
182
+ plugins: [react(), tailwindcss(), sunpeakEntryPlugin()],
183
+ resolve: {
184
+ alias: {
185
+ // In workspace dev mode, use local sunpeak source
186
+ ...(isTemplate && {
187
+ sunpeak: parentSrc,
188
+ }),
189
+ },
190
+ },
191
+ server: {
192
+ middlewareMode: true,
193
+ // Allow all hosts for tunnel services (ngrok, cloudflared, etc.)
194
+ allowedHosts: true,
195
+ // Don't override HMR - let Vite handle it (like skybridge)
196
+ },
197
+ optimizeDeps: {
198
+ include: ['react', 'react-dom/client'],
199
+ },
200
+ appType: 'custom',
201
+ });
202
+ } else {
203
+ console.log('Starting MCP server (production mode, no HMR)...\n');
204
+ }
205
+
206
+ // Import runMCPServer from sunpeak/mcp
207
+ // Use direct import with file URL for workspace compatibility
208
+ const sunpeakMcpPath = join(require.resolve('sunpeak').replace(/dist\/index\.(c)?js$/, ''), 'dist/mcp/index.js');
209
+ const sunpeakMcp = await import(pathToFileURL(sunpeakMcpPath).href);
210
+ const { runMCPServer } = sunpeakMcp;
211
+
212
+ // Start MCP server with Vite integration
213
+ runMCPServer({
214
+ name: pkg.name || 'Sunpeak',
215
+ version: pkg.version || '0.1.0',
216
+ simulations,
217
+ port: 6766,
218
+ viteServer,
57
219
  });
58
220
 
59
- process.on('SIGTERM', () => {
60
- child.kill('SIGTERM');
221
+ // Handle signals
222
+ process.on('SIGINT', async () => {
223
+ if (viteServer) {
224
+ await viteServer.close();
225
+ }
61
226
  process.exit(0);
62
227
  });
63
228
 
64
- // Handle child exit
65
- child.on('exit', (code) => {
66
- process.exit(code || 0);
229
+ process.on('SIGTERM', async () => {
230
+ if (viteServer) {
231
+ await viteServer.close();
232
+ }
233
+ process.exit(0);
67
234
  });
68
235
  }
69
236
 
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const simulatorUrl = require("../simulator-url-pSDp_VWO.cjs");
3
+ const simulatorUrl = require("../simulator-url-B6DZi3vV.cjs");
4
4
  exports.ChatGPTSimulator = simulatorUrl.ChatGPTSimulator;
5
5
  exports.IframeResource = simulatorUrl.IframeResource;
6
6
  exports.ThemeProvider = simulatorUrl.ThemeProvider;
@@ -1,4 +1,4 @@
1
- import { C, I, T, c, i, u } from "../simulator-url-BUKX-wRa.js";
1
+ import { C, I, T, c, i, u } from "../simulator-url-izFV6mji.js";
2
2
  export {
3
3
  C as ChatGPTSimulator,
4
4
  I as IframeResource,
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const simulatorUrl = require("./simulator-url-pSDp_VWO.cjs");
3
+ const simulatorUrl = require("./simulator-url-B6DZi3vV.cjs");
4
4
  const React = require("react");
5
5
  function _interopNamespaceDefault(e) {
6
6
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { a as clsx } from "./simulator-url-BUKX-wRa.js";
2
- import { C, I, S, T, c, v, s, q, i, r, w, t, e, f, g, h, j, u, k, l, m, n, d, b, o, p } from "./simulator-url-BUKX-wRa.js";
1
+ import { a as clsx } from "./simulator-url-izFV6mji.js";
2
+ import { C, I, S, T, c, v, s, q, i, r, w, t, e, f, g, h, j, u, k, l, m, n, d, b, o, p } from "./simulator-url-izFV6mji.js";
3
3
  import * as React from "react";
4
4
  const MOBILE_BREAKPOINT = 768;
5
5
  function useIsMobile() {
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- const server = require("../server-B-T6Y3-J.cjs");
3
+ const server = require("../server-D_oRdZjX.cjs");
4
4
  const path = require("path");
5
5
  const fs = require("fs");
6
6
  const projectRoot = process.cwd();
@@ -32,6 +32,7 @@ async function startServer() {
32
32
  ...simulation,
33
33
  name: simulationKey,
34
34
  distPath: path.join(projectRoot, `dist/${resourceKey}/${resourceKey}.js`),
35
+ srcPath: `/src/resources/${resourceKey}/${resourceKey}-resource.tsx`,
35
36
  resource
36
37
  });
37
38
  }
@@ -1 +1 @@
1
- {"version":3,"file":"entry.cjs","sources":["../../src/mcp/entry.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Internal MCP server entry point\n * This is run by nodemon or directly to start the MCP server\n *\n * Auto-discovers simulations and resources by file naming convention:\n * - resources/{resource}/{resource}-{scenario}-simulation.json (e.g., resources/albums/albums-show-simulation.json)\n * - resources/{resource}/{resource}-resource.json\n */\nimport { runMCPServer, type SimulationWithDist } from './index.js';\nimport path from 'path';\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport type { Resource } from '@modelcontextprotocol/sdk/types.js';\n\n// Determine project root (where this is being run from)\nconst projectRoot = process.cwd();\n\nasync function startServer() {\n // Read package.json for app metadata\n const pkgPath = path.join(projectRoot, 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n\n // Auto-discover resources and simulations from subdirectories\n const resourcesDir = path.join(projectRoot, 'src/resources');\n const resourceDirs = readdirSync(resourcesDir, { withFileTypes: true }).filter((entry) =>\n entry.isDirectory()\n );\n\n const resourcesMap = new Map<string, Resource>();\n const simulations: SimulationWithDist[] = [];\n\n for (const entry of resourceDirs) {\n const resourceKey = entry.name;\n const resourceDir = path.join(resourcesDir, resourceKey);\n const resourcePath = path.join(resourceDir, `${resourceKey}-resource.json`);\n\n // Skip directories without a resource file\n if (!existsSync(resourcePath)) {\n continue;\n }\n\n // Load resource\n const resource = JSON.parse(readFileSync(resourcePath, 'utf-8')) as Resource;\n resourcesMap.set(resourceKey, resource);\n\n // Discover simulation files in the same directory\n const dirFiles = readdirSync(resourceDir);\n for (const file of dirFiles) {\n if (file.endsWith('-simulation.json')) {\n // Extract simulation key from filename: 'albums-show-simulation.json' -> 'albums-show'\n const simulationKey = file.replace(/-simulation\\.json$/, '');\n const simulationPath = path.join(resourceDir, file);\n const simulation = JSON.parse(readFileSync(simulationPath, 'utf-8'));\n\n simulations.push({\n ...simulation,\n name: simulationKey,\n distPath: path.join(projectRoot, `dist/${resourceKey}/${resourceKey}.js`),\n resource,\n });\n }\n }\n }\n\n runMCPServer({\n name: pkg.name || 'Sunpeak',\n version: pkg.version || '0.1.0',\n simulations,\n port: 6766,\n });\n}\n\nstartServer().catch((error) => {\n console.error('Failed to start MCP server:', error);\n process.exit(1);\n});\n"],"names":["readFileSync","readdirSync","existsSync","runMCPServer"],"mappings":";;;;;AAeA,MAAM,cAAc,QAAQ,IAAA;AAE5B,eAAe,cAAc;AAE3B,QAAM,UAAU,KAAK,KAAK,aAAa,cAAc;AACrD,QAAM,MAAM,KAAK,MAAMA,GAAAA,aAAa,SAAS,OAAO,CAAC;AAGrD,QAAM,eAAe,KAAK,KAAK,aAAa,eAAe;AAC3D,QAAM,eAAeC,GAAAA,YAAY,cAAc,EAAE,eAAe,KAAA,CAAM,EAAE;AAAA,IAAO,CAAC,UAC9E,MAAM,YAAA;AAAA,EAAY;AAGpB,QAAM,mCAAmB,IAAA;AACzB,QAAM,cAAoC,CAAA;AAE1C,aAAW,SAAS,cAAc;AAChC,UAAM,cAAc,MAAM;AAC1B,UAAM,cAAc,KAAK,KAAK,cAAc,WAAW;AACvD,UAAM,eAAe,KAAK,KAAK,aAAa,GAAG,WAAW,gBAAgB;AAG1E,QAAI,CAACC,GAAAA,WAAW,YAAY,GAAG;AAC7B;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,MAAMF,GAAAA,aAAa,cAAc,OAAO,CAAC;AAC/D,iBAAa,IAAI,aAAa,QAAQ;AAGtC,UAAM,WAAWC,GAAAA,YAAY,WAAW;AACxC,eAAW,QAAQ,UAAU;AAC3B,UAAI,KAAK,SAAS,kBAAkB,GAAG;AAErC,cAAM,gBAAgB,KAAK,QAAQ,sBAAsB,EAAE;AAC3D,cAAM,iBAAiB,KAAK,KAAK,aAAa,IAAI;AAClD,cAAM,aAAa,KAAK,MAAMD,GAAAA,aAAa,gBAAgB,OAAO,CAAC;AAEnE,oBAAY,KAAK;AAAA,UACf,GAAG;AAAA,UACH,MAAM;AAAA,UACN,UAAU,KAAK,KAAK,aAAa,QAAQ,WAAW,IAAI,WAAW,KAAK;AAAA,UACxE;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEAG,sBAAa;AAAA,IACX,MAAM,IAAI,QAAQ;AAAA,IAClB,SAAS,IAAI,WAAW;AAAA,IACxB;AAAA,IACA,MAAM;AAAA,EAAA,CACP;AACH;AAEA,cAAc,MAAM,CAAC,UAAU;AAC7B,UAAQ,MAAM,+BAA+B,KAAK;AAClD,UAAQ,KAAK,CAAC;AAChB,CAAC;"}
1
+ {"version":3,"file":"entry.cjs","sources":["../../src/mcp/entry.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Internal MCP server entry point\n * This is run by the mcp command to start the MCP server\n *\n * Auto-discovers simulations and resources by file naming convention:\n * - resources/{resource}/{resource}-{scenario}-simulation.json (e.g., resources/albums/albums-show-simulation.json)\n * - resources/{resource}/{resource}-resource.json\n */\nimport { runMCPServer, type SimulationWithDist } from './index.js';\nimport path from 'path';\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport type { Resource } from '@modelcontextprotocol/sdk/types.js';\n\n// Determine project root (where this is being run from)\nconst projectRoot = process.cwd();\n\nasync function startServer() {\n // Read package.json for app metadata\n const pkgPath = path.join(projectRoot, 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n\n // Auto-discover resources and simulations from subdirectories\n const resourcesDir = path.join(projectRoot, 'src/resources');\n const resourceDirs = readdirSync(resourcesDir, { withFileTypes: true }).filter((entry) =>\n entry.isDirectory()\n );\n\n const resourcesMap = new Map<string, Resource>();\n const simulations: SimulationWithDist[] = [];\n\n for (const entry of resourceDirs) {\n const resourceKey = entry.name;\n const resourceDir = path.join(resourcesDir, resourceKey);\n const resourcePath = path.join(resourceDir, `${resourceKey}-resource.json`);\n\n // Skip directories without a resource file\n if (!existsSync(resourcePath)) {\n continue;\n }\n\n // Load resource\n const resource = JSON.parse(readFileSync(resourcePath, 'utf-8')) as Resource;\n resourcesMap.set(resourceKey, resource);\n\n // Discover simulation files in the same directory\n const dirFiles = readdirSync(resourceDir);\n for (const file of dirFiles) {\n if (file.endsWith('-simulation.json')) {\n // Extract simulation key from filename: 'albums-show-simulation.json' -> 'albums-show'\n const simulationKey = file.replace(/-simulation\\.json$/, '');\n const simulationPath = path.join(resourceDir, file);\n const simulation = JSON.parse(readFileSync(simulationPath, 'utf-8'));\n\n simulations.push({\n ...simulation,\n name: simulationKey,\n distPath: path.join(projectRoot, `dist/${resourceKey}/${resourceKey}.js`),\n srcPath: `/src/resources/${resourceKey}/${resourceKey}-resource.tsx`,\n resource,\n });\n }\n }\n }\n\n runMCPServer({\n name: pkg.name || 'Sunpeak',\n version: pkg.version || '0.1.0',\n simulations,\n port: 6766,\n });\n}\n\nstartServer().catch((error) => {\n console.error('Failed to start MCP server:', error);\n process.exit(1);\n});\n"],"names":["readFileSync","readdirSync","existsSync","runMCPServer"],"mappings":";;;;;AAeA,MAAM,cAAc,QAAQ,IAAA;AAE5B,eAAe,cAAc;AAE3B,QAAM,UAAU,KAAK,KAAK,aAAa,cAAc;AACrD,QAAM,MAAM,KAAK,MAAMA,GAAAA,aAAa,SAAS,OAAO,CAAC;AAGrD,QAAM,eAAe,KAAK,KAAK,aAAa,eAAe;AAC3D,QAAM,eAAeC,GAAAA,YAAY,cAAc,EAAE,eAAe,KAAA,CAAM,EAAE;AAAA,IAAO,CAAC,UAC9E,MAAM,YAAA;AAAA,EAAY;AAGpB,QAAM,mCAAmB,IAAA;AACzB,QAAM,cAAoC,CAAA;AAE1C,aAAW,SAAS,cAAc;AAChC,UAAM,cAAc,MAAM;AAC1B,UAAM,cAAc,KAAK,KAAK,cAAc,WAAW;AACvD,UAAM,eAAe,KAAK,KAAK,aAAa,GAAG,WAAW,gBAAgB;AAG1E,QAAI,CAACC,GAAAA,WAAW,YAAY,GAAG;AAC7B;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,MAAMF,GAAAA,aAAa,cAAc,OAAO,CAAC;AAC/D,iBAAa,IAAI,aAAa,QAAQ;AAGtC,UAAM,WAAWC,GAAAA,YAAY,WAAW;AACxC,eAAW,QAAQ,UAAU;AAC3B,UAAI,KAAK,SAAS,kBAAkB,GAAG;AAErC,cAAM,gBAAgB,KAAK,QAAQ,sBAAsB,EAAE;AAC3D,cAAM,iBAAiB,KAAK,KAAK,aAAa,IAAI;AAClD,cAAM,aAAa,KAAK,MAAMD,GAAAA,aAAa,gBAAgB,OAAO,CAAC;AAEnE,oBAAY,KAAK;AAAA,UACf,GAAG;AAAA,UACH,MAAM;AAAA,UACN,UAAU,KAAK,KAAK,aAAa,QAAQ,WAAW,IAAI,WAAW,KAAK;AAAA,UACxE,SAAS,kBAAkB,WAAW,IAAI,WAAW;AAAA,UACrD;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEAG,sBAAa;AAAA,IACX,MAAM,IAAI,QAAQ;AAAA,IAClB,SAAS,IAAI,WAAW;AAAA,IACxB;AAAA,IACA,MAAM;AAAA,EAAA,CACP;AACH;AAEA,cAAc,MAAM,CAAC,UAAU;AAC7B,UAAQ,MAAM,+BAA+B,KAAK;AAClD,UAAQ,KAAK,CAAC;AAChB,CAAC;"}
package/dist/mcp/entry.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { r as runMCPServer } from "../server-CnRhUNGQ.js";
2
+ import { r as runMCPServer } from "../server-BLKltt88.js";
3
3
  import path from "path";
4
4
  import { readFileSync, readdirSync, existsSync } from "fs";
5
5
  const projectRoot = process.cwd();
@@ -31,6 +31,7 @@ async function startServer() {
31
31
  ...simulation,
32
32
  name: simulationKey,
33
33
  distPath: path.join(projectRoot, `dist/${resourceKey}/${resourceKey}.js`),
34
+ srcPath: `/src/resources/${resourceKey}/${resourceKey}-resource.tsx`,
34
35
  resource
35
36
  });
36
37
  }
@@ -1 +1 @@
1
- {"version":3,"file":"entry.js","sources":["../../src/mcp/entry.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Internal MCP server entry point\n * This is run by nodemon or directly to start the MCP server\n *\n * Auto-discovers simulations and resources by file naming convention:\n * - resources/{resource}/{resource}-{scenario}-simulation.json (e.g., resources/albums/albums-show-simulation.json)\n * - resources/{resource}/{resource}-resource.json\n */\nimport { runMCPServer, type SimulationWithDist } from './index.js';\nimport path from 'path';\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport type { Resource } from '@modelcontextprotocol/sdk/types.js';\n\n// Determine project root (where this is being run from)\nconst projectRoot = process.cwd();\n\nasync function startServer() {\n // Read package.json for app metadata\n const pkgPath = path.join(projectRoot, 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n\n // Auto-discover resources and simulations from subdirectories\n const resourcesDir = path.join(projectRoot, 'src/resources');\n const resourceDirs = readdirSync(resourcesDir, { withFileTypes: true }).filter((entry) =>\n entry.isDirectory()\n );\n\n const resourcesMap = new Map<string, Resource>();\n const simulations: SimulationWithDist[] = [];\n\n for (const entry of resourceDirs) {\n const resourceKey = entry.name;\n const resourceDir = path.join(resourcesDir, resourceKey);\n const resourcePath = path.join(resourceDir, `${resourceKey}-resource.json`);\n\n // Skip directories without a resource file\n if (!existsSync(resourcePath)) {\n continue;\n }\n\n // Load resource\n const resource = JSON.parse(readFileSync(resourcePath, 'utf-8')) as Resource;\n resourcesMap.set(resourceKey, resource);\n\n // Discover simulation files in the same directory\n const dirFiles = readdirSync(resourceDir);\n for (const file of dirFiles) {\n if (file.endsWith('-simulation.json')) {\n // Extract simulation key from filename: 'albums-show-simulation.json' -> 'albums-show'\n const simulationKey = file.replace(/-simulation\\.json$/, '');\n const simulationPath = path.join(resourceDir, file);\n const simulation = JSON.parse(readFileSync(simulationPath, 'utf-8'));\n\n simulations.push({\n ...simulation,\n name: simulationKey,\n distPath: path.join(projectRoot, `dist/${resourceKey}/${resourceKey}.js`),\n resource,\n });\n }\n }\n }\n\n runMCPServer({\n name: pkg.name || 'Sunpeak',\n version: pkg.version || '0.1.0',\n simulations,\n port: 6766,\n });\n}\n\nstartServer().catch((error) => {\n console.error('Failed to start MCP server:', error);\n process.exit(1);\n});\n"],"names":[],"mappings":";;;;AAeA,MAAM,cAAc,QAAQ,IAAA;AAE5B,eAAe,cAAc;AAE3B,QAAM,UAAU,KAAK,KAAK,aAAa,cAAc;AACrD,QAAM,MAAM,KAAK,MAAM,aAAa,SAAS,OAAO,CAAC;AAGrD,QAAM,eAAe,KAAK,KAAK,aAAa,eAAe;AAC3D,QAAM,eAAe,YAAY,cAAc,EAAE,eAAe,KAAA,CAAM,EAAE;AAAA,IAAO,CAAC,UAC9E,MAAM,YAAA;AAAA,EAAY;AAGpB,QAAM,mCAAmB,IAAA;AACzB,QAAM,cAAoC,CAAA;AAE1C,aAAW,SAAS,cAAc;AAChC,UAAM,cAAc,MAAM;AAC1B,UAAM,cAAc,KAAK,KAAK,cAAc,WAAW;AACvD,UAAM,eAAe,KAAK,KAAK,aAAa,GAAG,WAAW,gBAAgB;AAG1E,QAAI,CAAC,WAAW,YAAY,GAAG;AAC7B;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC;AAC/D,iBAAa,IAAI,aAAa,QAAQ;AAGtC,UAAM,WAAW,YAAY,WAAW;AACxC,eAAW,QAAQ,UAAU;AAC3B,UAAI,KAAK,SAAS,kBAAkB,GAAG;AAErC,cAAM,gBAAgB,KAAK,QAAQ,sBAAsB,EAAE;AAC3D,cAAM,iBAAiB,KAAK,KAAK,aAAa,IAAI;AAClD,cAAM,aAAa,KAAK,MAAM,aAAa,gBAAgB,OAAO,CAAC;AAEnE,oBAAY,KAAK;AAAA,UACf,GAAG;AAAA,UACH,MAAM;AAAA,UACN,UAAU,KAAK,KAAK,aAAa,QAAQ,WAAW,IAAI,WAAW,KAAK;AAAA,UACxE;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,eAAa;AAAA,IACX,MAAM,IAAI,QAAQ;AAAA,IAClB,SAAS,IAAI,WAAW;AAAA,IACxB;AAAA,IACA,MAAM;AAAA,EAAA,CACP;AACH;AAEA,cAAc,MAAM,CAAC,UAAU;AAC7B,UAAQ,MAAM,+BAA+B,KAAK;AAClD,UAAQ,KAAK,CAAC;AAChB,CAAC;"}
1
+ {"version":3,"file":"entry.js","sources":["../../src/mcp/entry.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Internal MCP server entry point\n * This is run by the mcp command to start the MCP server\n *\n * Auto-discovers simulations and resources by file naming convention:\n * - resources/{resource}/{resource}-{scenario}-simulation.json (e.g., resources/albums/albums-show-simulation.json)\n * - resources/{resource}/{resource}-resource.json\n */\nimport { runMCPServer, type SimulationWithDist } from './index.js';\nimport path from 'path';\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport type { Resource } from '@modelcontextprotocol/sdk/types.js';\n\n// Determine project root (where this is being run from)\nconst projectRoot = process.cwd();\n\nasync function startServer() {\n // Read package.json for app metadata\n const pkgPath = path.join(projectRoot, 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n\n // Auto-discover resources and simulations from subdirectories\n const resourcesDir = path.join(projectRoot, 'src/resources');\n const resourceDirs = readdirSync(resourcesDir, { withFileTypes: true }).filter((entry) =>\n entry.isDirectory()\n );\n\n const resourcesMap = new Map<string, Resource>();\n const simulations: SimulationWithDist[] = [];\n\n for (const entry of resourceDirs) {\n const resourceKey = entry.name;\n const resourceDir = path.join(resourcesDir, resourceKey);\n const resourcePath = path.join(resourceDir, `${resourceKey}-resource.json`);\n\n // Skip directories without a resource file\n if (!existsSync(resourcePath)) {\n continue;\n }\n\n // Load resource\n const resource = JSON.parse(readFileSync(resourcePath, 'utf-8')) as Resource;\n resourcesMap.set(resourceKey, resource);\n\n // Discover simulation files in the same directory\n const dirFiles = readdirSync(resourceDir);\n for (const file of dirFiles) {\n if (file.endsWith('-simulation.json')) {\n // Extract simulation key from filename: 'albums-show-simulation.json' -> 'albums-show'\n const simulationKey = file.replace(/-simulation\\.json$/, '');\n const simulationPath = path.join(resourceDir, file);\n const simulation = JSON.parse(readFileSync(simulationPath, 'utf-8'));\n\n simulations.push({\n ...simulation,\n name: simulationKey,\n distPath: path.join(projectRoot, `dist/${resourceKey}/${resourceKey}.js`),\n srcPath: `/src/resources/${resourceKey}/${resourceKey}-resource.tsx`,\n resource,\n });\n }\n }\n }\n\n runMCPServer({\n name: pkg.name || 'Sunpeak',\n version: pkg.version || '0.1.0',\n simulations,\n port: 6766,\n });\n}\n\nstartServer().catch((error) => {\n console.error('Failed to start MCP server:', error);\n process.exit(1);\n});\n"],"names":[],"mappings":";;;;AAeA,MAAM,cAAc,QAAQ,IAAA;AAE5B,eAAe,cAAc;AAE3B,QAAM,UAAU,KAAK,KAAK,aAAa,cAAc;AACrD,QAAM,MAAM,KAAK,MAAM,aAAa,SAAS,OAAO,CAAC;AAGrD,QAAM,eAAe,KAAK,KAAK,aAAa,eAAe;AAC3D,QAAM,eAAe,YAAY,cAAc,EAAE,eAAe,KAAA,CAAM,EAAE;AAAA,IAAO,CAAC,UAC9E,MAAM,YAAA;AAAA,EAAY;AAGpB,QAAM,mCAAmB,IAAA;AACzB,QAAM,cAAoC,CAAA;AAE1C,aAAW,SAAS,cAAc;AAChC,UAAM,cAAc,MAAM;AAC1B,UAAM,cAAc,KAAK,KAAK,cAAc,WAAW;AACvD,UAAM,eAAe,KAAK,KAAK,aAAa,GAAG,WAAW,gBAAgB;AAG1E,QAAI,CAAC,WAAW,YAAY,GAAG;AAC7B;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,MAAM,aAAa,cAAc,OAAO,CAAC;AAC/D,iBAAa,IAAI,aAAa,QAAQ;AAGtC,UAAM,WAAW,YAAY,WAAW;AACxC,eAAW,QAAQ,UAAU;AAC3B,UAAI,KAAK,SAAS,kBAAkB,GAAG;AAErC,cAAM,gBAAgB,KAAK,QAAQ,sBAAsB,EAAE;AAC3D,cAAM,iBAAiB,KAAK,KAAK,aAAa,IAAI;AAClD,cAAM,aAAa,KAAK,MAAM,aAAa,gBAAgB,OAAO,CAAC;AAEnE,oBAAY,KAAK;AAAA,UACf,GAAG;AAAA,UACH,MAAM;AAAA,UACN,UAAU,KAAK,KAAK,aAAa,QAAQ,WAAW,IAAI,WAAW,KAAK;AAAA,UACxE,SAAS,kBAAkB,WAAW,IAAI,WAAW;AAAA,UACrD;AAAA,QAAA,CACD;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,eAAa;AAAA,IACX,MAAM,IAAI,QAAQ;AAAA,IAClB,SAAS,IAAI,WAAW;AAAA,IACxB;AAAA,IACA,MAAM;AAAA,EAAA,CACP;AACH;AAEA,cAAc,MAAM,CAAC,UAAU;AAC7B,UAAQ,MAAM,+BAA+B,KAAK;AAClD,UAAQ,KAAK,CAAC;AAChB,CAAC;"}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const server = require("../server-B-T6Y3-J.cjs");
3
+ const server = require("../server-D_oRdZjX.cjs");
4
4
  exports.runMCPServer = server.runMCPServer;
5
5
  //# sourceMappingURL=index.cjs.map
package/dist/mcp/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { r } from "../server-CnRhUNGQ.js";
1
+ import { r } from "../server-BLKltt88.js";
2
2
  export {
3
3
  r as runMCPServer
4
4
  };
@@ -6,6 +6,7 @@ import { Resource, Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.
6
6
  export interface SimulationWithDist {
7
7
  name: string;
8
8
  distPath: string;
9
+ srcPath?: string;
9
10
  tool: Tool;
10
11
  resource: Resource;
11
12
  callToolResult?: CallToolResult;
@@ -19,4 +20,10 @@ export interface MCPServerConfig {
19
20
  version?: string;
20
21
  port?: number;
21
22
  simulations: SimulationWithDist[];
23
+ /**
24
+ * Vite dev server instance for HMR mode.
25
+ * When provided, resources are served as HTML that loads from Vite.
26
+ * When not provided, resources serve bundled JS (production mode).
27
+ */
28
+ viteServer?: unknown;
22
29
  }