openuispec 0.1.35 → 0.1.37

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 CHANGED
@@ -257,14 +257,14 @@ OpenUISpec includes an MCP (Model Context Protocol) server that exposes CLI comm
257
257
  {
258
258
  "mcpServers": {
259
259
  "openuispec": {
260
- "command": "npx",
261
- "args": ["openuispec-mcp"]
260
+ "command": "openuispec",
261
+ "args": ["mcp"]
262
262
  }
263
263
  }
264
264
  }
265
265
  ```
266
266
 
267
- Or run directly: `npx openuispec-mcp`
267
+ Or run directly: `openuispec mcp`
268
268
 
269
269
  Set `OPENUISPEC_PROJECT_DIR` to override the working directory.
270
270
 
package/cli/index.ts CHANGED
@@ -94,6 +94,12 @@ async function main(): Promise<void> {
94
94
  break;
95
95
  }
96
96
 
97
+ case "mcp": {
98
+ const { startMcpServer } = await import("../mcp-server/index.js");
99
+ await startMcpServer();
100
+ break;
101
+ }
102
+
97
103
  case undefined:
98
104
  case "--help":
99
105
  case "-h":
@@ -117,6 +123,7 @@ Usage:
117
123
  openuispec check --target <t> [--json] Composite validation + prepare readiness
118
124
  openuispec validate [group...] [--json] Validate spec files
119
125
  openuispec validate semantic --json Semantic validation as JSON
126
+ openuispec mcp Start MCP server (stdio transport)
120
127
 
121
128
  Validate groups: manifest, tokens, screens, flows, platform, locales, contracts, semantic
122
129
 
package/cli/init.ts CHANGED
@@ -471,11 +471,18 @@ export function updateRules(): void {
471
471
  }
472
472
 
473
473
  // Ensure MCP server is configured
474
+ configureMcp(cwd, true);
475
+ }
476
+
477
+ // ── shared MCP config ───────────────────────────────────────────────
478
+
479
+ const EXPECTED_MCP_CONFIG = {
480
+ command: "openuispec",
481
+ args: ["mcp"],
482
+ };
483
+
484
+ function configureMcp(cwd: string, showRestart: boolean, quiet: boolean = false): void {
474
485
  const claudeJsonPath = join(cwd, ".claude.json");
475
- const mcpConfig = {
476
- command: "npx",
477
- args: ["openuispec-mcp"],
478
- };
479
486
 
480
487
  try {
481
488
  let claudeJson: Record<string, any> = {};
@@ -484,14 +491,25 @@ export function updateRules(): void {
484
491
  } catch {
485
492
  // file doesn't exist or isn't valid JSON — start fresh
486
493
  }
494
+
487
495
  if (!claudeJson.mcpServers) claudeJson.mcpServers = {};
488
- if (!claudeJson.mcpServers.openuispec) {
489
- claudeJson.mcpServers.openuispec = mcpConfig;
496
+
497
+ const existing = claudeJson.mcpServers.openuispec;
498
+ const needsUpdate =
499
+ !existing ||
500
+ existing.command !== EXPECTED_MCP_CONFIG.command ||
501
+ JSON.stringify(existing.args) !== JSON.stringify(EXPECTED_MCP_CONFIG.args);
502
+
503
+ if (needsUpdate) {
504
+ claudeJson.mcpServers.openuispec = { ...EXPECTED_MCP_CONFIG };
490
505
  writeFileSync(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
491
- console.log(` create .claude.json (MCP server configured)`);
506
+ if (!quiet) console.log(` ${existing ? "update" : "create"} .claude.json (MCP server configured)`);
507
+ if (showRestart) console.log(`\n Restart Claude Code to activate the MCP server.`);
508
+ } else {
509
+ if (!quiet) console.log(` skip .claude.json (openuispec MCP already configured)`);
492
510
  }
493
511
  } catch {
494
- // non-critical skip silently
512
+ if (!quiet) console.log(` skip .claude.json (could not configure MCP server)`);
495
513
  }
496
514
  }
497
515
 
@@ -760,30 +778,7 @@ export async function init(argv: string[] = []): Promise<void> {
760
778
 
761
779
  // ── MCP server configuration ────────────────────────────────────
762
780
 
763
- const claudeJsonPath = join(cwd, ".claude.json");
764
- const mcpConfig = {
765
- command: "npx",
766
- args: ["openuispec-mcp"],
767
- };
768
-
769
- try {
770
- let claudeJson: Record<string, any> = {};
771
- try {
772
- claudeJson = JSON.parse(readFileSync(claudeJsonPath, "utf-8"));
773
- } catch {
774
- // file doesn't exist or isn't valid JSON — start fresh
775
- }
776
- if (!claudeJson.mcpServers) claudeJson.mcpServers = {};
777
- if (!claudeJson.mcpServers.openuispec) {
778
- claudeJson.mcpServers.openuispec = mcpConfig;
779
- writeFileSync(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
780
- if (!quiet) console.log(` create .claude.json (MCP server configured)`);
781
- } else {
782
- if (!quiet) console.log(` skip .claude.json (openuispec MCP already configured)`);
783
- }
784
- } catch {
785
- if (!quiet) console.log(` skip .claude.json (could not configure MCP server)`);
786
- }
781
+ configureMcp(cwd, false, quiet);
787
782
 
788
783
  if (answers.configureTargets) {
789
784
  if (!quiet) console.log("\nConfiguring target stacks...\n");
@@ -172,12 +172,19 @@ server.registerTool(
172
172
 
173
173
  // ── start server ─────────────────────────────────────────────────────
174
174
 
175
- async function main() {
175
+ export async function startMcpServer() {
176
176
  const transport = new StdioServerTransport();
177
177
  await server.connect(transport);
178
178
  }
179
179
 
180
- main().catch((err) => {
181
- console.error("Failed to start OpenUISpec MCP server:", err);
182
- process.exit(1);
183
- });
180
+ // Direct execution (npx openuispec-mcp)
181
+ const isDirectRun =
182
+ process.argv[1]?.endsWith("mcp-server/index.ts") ||
183
+ process.argv[1]?.endsWith("mcp-server/index.js");
184
+
185
+ if (isDirectRun) {
186
+ startMcpServer().catch((err) => {
187
+ console.error("Failed to start OpenUISpec MCP server:", err);
188
+ process.exit(1);
189
+ });
190
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openuispec",
3
- "version": "0.1.35",
3
+ "version": "0.1.37",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "A semantic UI specification format for AI-native, platform-native app development",