@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 +82 -43
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +183 -0
- package/dist/edit-store.js +16 -0
- package/dist/index.js +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,67 +1,106 @@
|
|
|
1
1
|
# @ompo-design/mcp-server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
MCP server for applying Ompo visual edits to your codebase.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Important: this is not a web connector
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**Settings → Connectors → Add custom connector** only works for **remote URLs** (hosted servers).
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Ompo is a **local** MCP server. Install it via the steps below — not through the Connectors URL dialog.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
58
|
+
3. Save, quit Claude Desktop (Cmd+Q), reopen.
|
|
39
59
|
|
|
40
|
-
|
|
60
|
+
Use the full path to `npx` — the Desktop app often cannot find `npx` on its own.
|
|
41
61
|
|
|
42
|
-
|
|
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
|
-
|
|
64
|
+
## Per-project install (optional)
|
|
51
65
|
|
|
52
|
-
|
|
66
|
+
From a project folder:
|
|
53
67
|
|
|
54
|
-
|
|
55
|
-
-
|
|
56
|
-
|
|
57
|
-
- `apply_edit` — structured apply plan for the agent
|
|
68
|
+
```bash
|
|
69
|
+
npx @ompo-design/mcp-server setup
|
|
70
|
+
```
|
|
58
71
|
|
|
59
|
-
|
|
72
|
+
Creates `.mcp.json` in that project only.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Check install
|
|
60
77
|
|
|
61
78
|
```bash
|
|
62
|
-
|
|
63
|
-
npm run build
|
|
64
|
-
npm start
|
|
79
|
+
npx @ompo-design/mcp-server doctor
|
|
65
80
|
```
|
|
66
81
|
|
|
67
|
-
|
|
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
|
+
}
|
package/dist/edit-store.js
CHANGED
|
@@ -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
|
}
|