@ompo-design/mcp-server 0.1.0 → 0.1.2

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
@@ -1,67 +1,106 @@
1
1
  # @ompo-design/mcp-server
2
2
 
3
- Local MCP server for applying Ompo visual edits to a codebase.
3
+ MCP server for applying Ompo visual edits to your codebase.
4
4
 
5
- ## Setup
5
+ ## Important: this is not a web connector
6
6
 
7
- ### Cursor
7
+ **Settings → Connectors → Add custom connector** only works for **remote URLs** (hosted servers).
8
8
 
9
- Add to `.cursor/mcp.json` in your project:
9
+ Ompo is a **local** MCP server. Install it via the steps below — not through the Connectors URL dialog.
10
10
 
11
- ```json
12
- {
13
- "mcpServers": {
14
- "ompo": {
15
- "command": "npx",
16
- "args": ["-y", "@ompo-design/mcp-server"]
17
- }
18
- }
19
- }
11
+ ---
12
+
13
+ ## Claude Desktop — install for ALL projects (recommended)
14
+
15
+ **Prerequisites:** [Node.js](https://nodejs.org) installed.
16
+
17
+ ### 1. Run one command in Terminal
18
+
19
+ ```bash
20
+ npx @ompo-design/mcp-server setup-global
20
21
  ```
21
22
 
22
- ### Claude Code
23
+ This adds Ompo to:
24
+ - Claude Desktop (`claude_desktop_config.json`)
25
+ - Claude Code user config (`~/.claude.json`)
26
+
27
+ Works across **every project**, not just one folder.
28
+
29
+ ### 2. Quit and reopen Claude Desktop
30
+
31
+ Fully quit with **Cmd+Q**, then reopen.
23
32
 
24
- Add to `.mcp.json` in your project:
33
+ ### 3. Verify
34
+
35
+ Open any **Code** project, then type:
36
+
37
+ ```text
38
+ /mcp
39
+ ```
40
+
41
+ **ompo** should show **4 tools**. Approve it if prompted.
42
+
43
+ ---
44
+
45
+ ## Manual install (Claude Desktop)
46
+
47
+ 1. Open **Claude Desktop → Settings → Developer → Edit Config**
48
+ 2. Add inside `mcpServers`:
25
49
 
26
50
  ```json
27
- {
28
- "mcpServers": {
29
- "ompo": {
30
- "type": "stdio",
31
- "command": "npx",
32
- "args": ["-y", "@ompo-design/mcp-server"]
33
- }
34
- }
51
+ "ompo": {
52
+ "command": "/usr/local/bin/npx",
53
+ "args": ["-y", "@ompo-design/mcp-server"],
54
+ "env": {}
35
55
  }
36
56
  ```
37
57
 
38
- Restart your IDE session after adding the config. In Claude Code, run `/mcp` to confirm `ompo` is connected with 4 tools.
58
+ 3. Save, quit Claude Desktop (Cmd+Q), reopen.
39
59
 
40
- ## Workflow
60
+ Use the full path to `npx` — the Desktop app often cannot find `npx` on its own.
41
61
 
42
- 1. Edit your localhost site in Ompo
43
- 2. Click **Send** and copy the prompt
44
- 3. Paste the prompt into Cursor or Claude Code
45
- 4. The agent calls:
46
- - `get_edit({ id: "ed_8K42P" })`
47
- - `apply_edit({ id: "ed_8K42P" })`
48
- 5. The agent applies only the listed property changes to source files
62
+ ---
49
63
 
50
- Ompo writes edit bundles to `.ompo/edits/` in your project. Open that project in your IDE so the MCP server can find them.
64
+ ## Per-project install (optional)
51
65
 
52
- ## Tools
66
+ From a project folder:
53
67
 
54
- - `list_edits` — list saved edit bundles in `.ompo/edits/`
55
- - `get_edit` — load a bundle by id
56
- - `explain_edit` — short summary of an edit
57
- - `apply_edit` — structured apply plan for the agent
68
+ ```bash
69
+ npx @ompo-design/mcp-server setup
70
+ ```
58
71
 
59
- ## Development
72
+ Creates `.mcp.json` in that project only.
73
+
74
+ ---
75
+
76
+ ## Check install
60
77
 
61
78
  ```bash
62
- npm install
63
- npm run build
64
- npm start
79
+ npx @ompo-design/mcp-server doctor
65
80
  ```
66
81
 
67
- For local testing before publish, point your MCP config at `node /absolute/path/to/mcp-server/dist/index.js`.
82
+ ---
83
+
84
+ ## Using Ompo
85
+
86
+ 1. Edit your site in **Ompo**
87
+ 2. Click **Send** (creates `.ompo/edits/` in your project)
88
+ 3. Open that **same project** in Claude Code
89
+ 4. Paste the Send prompt — Claude calls `get_edit` and `apply_edit`
90
+
91
+ ---
92
+
93
+ ## Cursor
94
+
95
+ `.cursor/mcp.json`:
96
+
97
+ ```json
98
+ {
99
+ "mcpServers": {
100
+ "ompo": {
101
+ "command": "npx",
102
+ "args": ["-y", "@ompo-design/mcp-server"]
103
+ }
104
+ }
105
+ }
106
+ ```
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function runCli(argv: string[]): boolean;
package/dist/cli.js ADDED
@@ -0,0 +1,183 @@
1
+ import { execSync } from 'child_process';
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
3
+ import { homedir } from 'os';
4
+ import { join, resolve } from 'path';
5
+ import { findProjectRoot } from './edit-store.js';
6
+ const PACKAGE_NAME = '@ompo-design/mcp-server';
7
+ const SERVER_NAME = 'ompo';
8
+ function resolveExecutable(name) {
9
+ try {
10
+ return execSync(`which ${name}`, { encoding: 'utf8' }).trim();
11
+ }
12
+ catch {
13
+ return name;
14
+ }
15
+ }
16
+ function ompoServerEntry() {
17
+ const npxPath = resolveExecutable('npx');
18
+ return {
19
+ type: 'stdio',
20
+ command: npxPath,
21
+ args: ['-y', PACKAGE_NAME],
22
+ env: {}
23
+ };
24
+ }
25
+ function ompoDesktopEntry() {
26
+ const npxPath = resolveExecutable('npx');
27
+ return {
28
+ command: npxPath,
29
+ args: ['-y', PACKAGE_NAME],
30
+ env: {}
31
+ };
32
+ }
33
+ const CLAUDE_CODE_CONFIG = {
34
+ mcpServers: {
35
+ [SERVER_NAME]: ompoServerEntry()
36
+ }
37
+ };
38
+ function readJsonFile(path) {
39
+ if (!existsSync(path))
40
+ return {};
41
+ try {
42
+ return JSON.parse(readFileSync(path, 'utf8'));
43
+ }
44
+ catch {
45
+ return {};
46
+ }
47
+ }
48
+ function writeJsonFile(path, data) {
49
+ const directory = join(path, '..');
50
+ if (!existsSync(directory))
51
+ mkdirSync(directory, { recursive: true });
52
+ writeFileSync(path, `${JSON.stringify(data, null, 2)}\n`, 'utf8');
53
+ }
54
+ function mergeMcpServer(config, serverName, serverEntry) {
55
+ const mcpServers = typeof config.mcpServers === 'object' && config.mcpServers !== null
56
+ ? { ...config.mcpServers }
57
+ : {};
58
+ mcpServers[serverName] = serverEntry;
59
+ return {
60
+ ...config,
61
+ mcpServers
62
+ };
63
+ }
64
+ function claudeDesktopConfigPath() {
65
+ if (process.platform === 'darwin') {
66
+ return join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
67
+ }
68
+ if (process.platform === 'win32' && process.env.APPDATA) {
69
+ return join(process.env.APPDATA, 'Claude', 'claude_desktop_config.json');
70
+ }
71
+ return join(homedir(), '.config', 'Claude', 'claude_desktop_config.json');
72
+ }
73
+ function claudeCodeUserConfigPath() {
74
+ return join(homedir(), '.claude.json');
75
+ }
76
+ export function runCli(argv) {
77
+ const command = argv[0];
78
+ if (command === 'setup') {
79
+ runProjectSetup();
80
+ return true;
81
+ }
82
+ if (command === 'setup-global') {
83
+ runGlobalSetup();
84
+ return true;
85
+ }
86
+ if (command === 'doctor') {
87
+ runDoctor();
88
+ return true;
89
+ }
90
+ if (command === 'help' || command === '--help' || command === '-h') {
91
+ printHelp();
92
+ return true;
93
+ }
94
+ return false;
95
+ }
96
+ function runProjectSetup() {
97
+ const projectRoot = resolve(process.cwd());
98
+ const configPath = join(projectRoot, '.mcp.json');
99
+ writeJsonFile(configPath, CLAUDE_CODE_CONFIG);
100
+ console.log(`Created ${configPath}`);
101
+ printProjectNextSteps(projectRoot);
102
+ }
103
+ function runGlobalSetup() {
104
+ const desktopPath = claudeDesktopConfigPath();
105
+ const claudeCodePath = claudeCodeUserConfigPath();
106
+ const npxPath = resolveExecutable('npx');
107
+ const desktopConfig = mergeMcpServer(readJsonFile(desktopPath), SERVER_NAME, ompoDesktopEntry());
108
+ const claudeCodeConfig = mergeMcpServer(readJsonFile(claudeCodePath), SERVER_NAME, ompoServerEntry());
109
+ writeJsonFile(desktopPath, desktopConfig);
110
+ writeJsonFile(claudeCodePath, claudeCodeConfig);
111
+ console.log('Installed Ompo MCP globally for Claude Desktop and Claude Code.');
112
+ console.log('');
113
+ console.log(` Claude Desktop: ${desktopPath}`);
114
+ console.log(` Claude Code: ${claudeCodePath}`);
115
+ console.log(` npx path: ${npxPath}`);
116
+ console.log('');
117
+ console.log('Next steps:');
118
+ console.log(' 1. Quit Claude Desktop completely (Cmd+Q)');
119
+ console.log(' 2. Reopen Claude Desktop');
120
+ console.log(' 3. Open any Code project and run /mcp');
121
+ console.log(' 4. Approve ompo if prompted');
122
+ console.log(' 5. In Ompo, click Send on an edit before using the tools');
123
+ }
124
+ function runDoctor() {
125
+ const projectRoot = resolve(process.cwd());
126
+ const configPath = join(projectRoot, '.mcp.json');
127
+ const desktopPath = claudeDesktopConfigPath();
128
+ const claudeCodePath = claudeCodeUserConfigPath();
129
+ const editsRoot = findProjectRoot(projectRoot);
130
+ console.log('Ompo MCP doctor');
131
+ console.log('');
132
+ console.log(`Project folder: ${projectRoot}`);
133
+ console.log(`Node: ${process.version}`);
134
+ console.log(`npx: ${resolveExecutable('npx')}`);
135
+ console.log('');
136
+ for (const [label, path] of [
137
+ ['Project config', configPath],
138
+ ['Claude Desktop', desktopPath],
139
+ ['Claude Code user', claudeCodePath]
140
+ ]) {
141
+ const config = readJsonFile(path);
142
+ const servers = typeof config.mcpServers === 'object' && config.mcpServers !== null
143
+ ? config.mcpServers
144
+ : {};
145
+ if (servers[SERVER_NAME]) {
146
+ console.log(`${label}: ompo configured (${path})`);
147
+ }
148
+ else if (existsSync(path)) {
149
+ console.log(`${label}: found, but ompo missing (${path})`);
150
+ }
151
+ else {
152
+ console.log(`${label}: missing (${path})`);
153
+ }
154
+ }
155
+ console.log('');
156
+ if (editsRoot) {
157
+ console.log(`Edits: found ${join(editsRoot, '.ompo/edits/')}`);
158
+ }
159
+ else {
160
+ console.log('Edits: none yet (use Send in Ompo first)');
161
+ }
162
+ console.log('');
163
+ console.log('Global install: npx @ompo-design/mcp-server setup-global');
164
+ }
165
+ function printProjectNextSteps(projectRoot) {
166
+ console.log('');
167
+ console.log('Next steps:');
168
+ console.log(` 1. cd ${projectRoot}`);
169
+ console.log(' 2. Start Claude Code in this folder');
170
+ console.log(' 3. Run /mcp and approve ompo if prompted');
171
+ console.log(' 4. In Ompo, click Send on an edit (creates .ompo/edits/)');
172
+ console.log('');
173
+ console.log('For all projects, run: npx @ompo-design/mcp-server setup-global');
174
+ }
175
+ function printHelp() {
176
+ console.log(`Ompo MCP server (${PACKAGE_NAME})`);
177
+ console.log('');
178
+ console.log('Usage:');
179
+ console.log(` npx ${PACKAGE_NAME} Run MCP server (used by your IDE)`);
180
+ console.log(` npx ${PACKAGE_NAME} setup Create .mcp.json in current project`);
181
+ console.log(` npx ${PACKAGE_NAME} setup-global Install for all Claude projects`);
182
+ console.log(` npx ${PACKAGE_NAME} doctor Check install status`);
183
+ }
@@ -1,7 +1,23 @@
1
1
  import { existsSync, readFileSync, writeFileSync } from 'fs';
2
2
  import { dirname, join, resolve } from 'path';
3
3
  import { OMPo_EDITS_DIR } from './types.js';
4
+ function projectRootCandidates(startDir = process.cwd()) {
5
+ const candidates = [
6
+ process.env.OMPO_PROJECT_ROOT,
7
+ process.env.CLAUDE_PROJECT_DIR,
8
+ startDir
9
+ ].filter((value) => Boolean(value?.trim()));
10
+ return [...new Set(candidates.map((value) => resolve(value)))];
11
+ }
4
12
  export function findProjectRoot(startDir = process.cwd()) {
13
+ for (const candidate of projectRootCandidates(startDir)) {
14
+ const found = findProjectRootFrom(candidate);
15
+ if (found)
16
+ return found;
17
+ }
18
+ return null;
19
+ }
20
+ function findProjectRootFrom(startDir) {
5
21
  let current = resolve(startDir);
6
22
  while (true) {
7
23
  const editsDirectory = join(current, OMPo_EDITS_DIR);
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { z } from 'zod';
5
5
  import { buildApplyPlan, explainEdit } from './apply-plan.js';
6
+ import { runCli } from './cli.js';
6
7
  import { findProjectRoot, listEdits, readEditBundle, recordEditApplied, recordEditPull } from './edit-store.js';
7
8
  const server = new McpServer({
8
9
  name: 'ompo-mcp-server',
@@ -81,6 +82,8 @@ server.tool('apply_edit', 'Build an apply plan for an Ompo edit. The agent shoul
81
82
  };
82
83
  });
83
84
  async function main() {
85
+ if (runCli(process.argv.slice(2)))
86
+ return;
84
87
  const transport = new StdioServerTransport();
85
88
  await server.connect(transport);
86
89
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ompo-design/mcp-server",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "MCP server for applying Ompo visual edits to a codebase",
5
5
  "type": "module",
6
6
  "license": "MIT",