@pharaoh-so/mcp 0.2.2 → 0.2.4
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/.claude-plugin/plugin.json +25 -0
- package/.mcp.json +8 -0
- package/dist/install-skills.d.ts +2 -2
- package/dist/install-skills.js +137 -30
- package/package.json +4 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pharaoh",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Codebase knowledge graph with 23 development workflow skills. Query architecture, dependencies, blast radius, and more instead of reading files one at a time.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Pharaoh",
|
|
7
|
+
"email": "hello@pharaoh.so",
|
|
8
|
+
"url": "https://pharaoh.so"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://pharaoh.so",
|
|
11
|
+
"repository": "https://github.com/Pharaoh-so/pharaoh-mcp",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"code-intelligence",
|
|
15
|
+
"architecture",
|
|
16
|
+
"mcp",
|
|
17
|
+
"knowledge-graph",
|
|
18
|
+
"dependencies",
|
|
19
|
+
"blast-radius",
|
|
20
|
+
"dead-code",
|
|
21
|
+
"code-review",
|
|
22
|
+
"refactoring",
|
|
23
|
+
"test-coverage"
|
|
24
|
+
]
|
|
25
|
+
}
|
package/.mcp.json
ADDED
package/dist/install-skills.d.ts
CHANGED
|
@@ -25,8 +25,8 @@ export declare function mergeOpenClawConfig(home?: string): boolean;
|
|
|
25
25
|
/**
|
|
26
26
|
* Main entry point for --install-skills.
|
|
27
27
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* Detection priority: Claude Code > OpenClaw > manual instructions.
|
|
29
|
+
* Installs to all detected platforms (a user may use both).
|
|
30
30
|
*
|
|
31
31
|
* @param home - Home directory override (defaults to os.homedir()).
|
|
32
32
|
*/
|
package/dist/install-skills.js
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* --install-skills implementation for the Pharaoh MCP proxy CLI.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Installs bundled skills as a Claude Code plugin (primary) or to
|
|
5
|
+
* OpenClaw's ~/.openclaw/skills/ directory (fallback). Also merges
|
|
6
|
+
* the Pharaoh MCP server config into the target platform.
|
|
7
7
|
*/
|
|
8
|
-
import { cpSync, existsSync, mkdirSync,
|
|
8
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
10
|
import { dirname, join } from "node:path";
|
|
11
11
|
import { fileURLToPath } from "node:url";
|
|
12
12
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
/** Path to the bundled
|
|
14
|
-
const
|
|
13
|
+
/** Path to the bundled package root (one level up from dist/). */
|
|
14
|
+
const PKG_ROOT = join(__dirname, "..");
|
|
15
|
+
/** Path to the bundled skills directory. */
|
|
16
|
+
const BUNDLED_SKILLS_DIR = join(PKG_ROOT, "skills");
|
|
17
|
+
// ── Detection ───────────────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Detect whether Claude Code is installed by checking for ~/.claude/.
|
|
20
|
+
*
|
|
21
|
+
* @param home - Home directory override (defaults to os.homedir()).
|
|
22
|
+
* @returns True if ~/.claude/ exists.
|
|
23
|
+
*/
|
|
24
|
+
function detectClaudeCode(home = homedir()) {
|
|
25
|
+
return existsSync(join(home, ".claude"));
|
|
26
|
+
}
|
|
15
27
|
/**
|
|
16
28
|
* Detect whether OpenClaw is installed by checking for ~/.openclaw/.
|
|
17
29
|
*
|
|
@@ -21,6 +33,78 @@ const BUNDLED_SKILLS_DIR = join(__dirname, "..", "skills");
|
|
|
21
33
|
export function detectOpenClaw(home = homedir()) {
|
|
22
34
|
return existsSync(join(home, ".openclaw"));
|
|
23
35
|
}
|
|
36
|
+
// ── Claude Code installer ───────────────────────────────────────────
|
|
37
|
+
/**
|
|
38
|
+
* Install Pharaoh as a Claude Code plugin by copying the full plugin
|
|
39
|
+
* structure (`.claude-plugin/`, `skills/`, `.mcp.json`) to a persistent
|
|
40
|
+
* directory under `~/.claude/plugins/data/pharaoh/`.
|
|
41
|
+
*
|
|
42
|
+
* Claude Code auto-discovers skills from the `skills/` subdirectory
|
|
43
|
+
* when the plugin manifest (`.claude-plugin/plugin.json`) is present.
|
|
44
|
+
*
|
|
45
|
+
* @param home - Home directory override (defaults to os.homedir()).
|
|
46
|
+
* @returns Number of skill directories installed, or -1 on failure.
|
|
47
|
+
*/
|
|
48
|
+
function installClaudeCodePlugin(home = homedir()) {
|
|
49
|
+
const pluginDir = join(home, ".claude", "plugins", "data", "pharaoh");
|
|
50
|
+
mkdirSync(pluginDir, { recursive: true });
|
|
51
|
+
// Copy .claude-plugin/ manifest
|
|
52
|
+
const manifestSrc = join(PKG_ROOT, ".claude-plugin");
|
|
53
|
+
const manifestDst = join(pluginDir, ".claude-plugin");
|
|
54
|
+
if (existsSync(manifestSrc)) {
|
|
55
|
+
cpSync(manifestSrc, manifestDst, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
process.stderr.write("Pharaoh: .claude-plugin/ manifest not found in package — cannot install.\n");
|
|
59
|
+
return -1;
|
|
60
|
+
}
|
|
61
|
+
// Copy skills/
|
|
62
|
+
if (existsSync(BUNDLED_SKILLS_DIR)) {
|
|
63
|
+
cpSync(BUNDLED_SKILLS_DIR, join(pluginDir, "skills"), { recursive: true, force: true });
|
|
64
|
+
}
|
|
65
|
+
// Copy .mcp.json
|
|
66
|
+
const mcpSrc = join(PKG_ROOT, ".mcp.json");
|
|
67
|
+
if (existsSync(mcpSrc)) {
|
|
68
|
+
cpSync(mcpSrc, join(pluginDir, ".mcp.json"), { force: true });
|
|
69
|
+
}
|
|
70
|
+
// Count installed skills
|
|
71
|
+
const entries = readdirSync(BUNDLED_SKILLS_DIR, { withFileTypes: true });
|
|
72
|
+
return entries.filter((e) => e.isDirectory()).length;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Register Pharaoh in Claude Code's installed_plugins.json.
|
|
76
|
+
* Does NOT overwrite an existing entry.
|
|
77
|
+
*
|
|
78
|
+
* @param home - Home directory override (defaults to os.homedir()).
|
|
79
|
+
* @returns True if the entry was added, false if already present.
|
|
80
|
+
*/
|
|
81
|
+
function registerClaudeCodePlugin(home = homedir()) {
|
|
82
|
+
const registryPath = join(home, ".claude", "plugins", "installed_plugins.json");
|
|
83
|
+
const pluginKey = "pharaoh@pharaoh-so";
|
|
84
|
+
let registry = {};
|
|
85
|
+
if (existsSync(registryPath)) {
|
|
86
|
+
try {
|
|
87
|
+
registry = JSON.parse(readFileSync(registryPath, "utf-8"));
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
process.stderr.write("Pharaoh: installed_plugins.json exists but is not valid JSON — skipping registration.\n");
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (registry[pluginKey]) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
registry[pluginKey] = {
|
|
98
|
+
name: "pharaoh",
|
|
99
|
+
version: "0.2.0",
|
|
100
|
+
source: "npm:@pharaoh-so/mcp",
|
|
101
|
+
pluginRoot: join(home, ".claude", "plugins", "data", "pharaoh"),
|
|
102
|
+
installedAt: new Date().toISOString(),
|
|
103
|
+
};
|
|
104
|
+
writeFileSync(registryPath, JSON.stringify(registry, null, "\t"));
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
// ── OpenClaw installer ──────────────────────────────────────────────
|
|
24
108
|
/**
|
|
25
109
|
* Copy all bundled skill directories to ~/.openclaw/skills/.
|
|
26
110
|
* Overwrites existing skill dirs on reinstall (cpSync recursive + force).
|
|
@@ -59,7 +143,6 @@ export function mergeOpenClawConfig(home = homedir()) {
|
|
|
59
143
|
config = JSON.parse(raw);
|
|
60
144
|
}
|
|
61
145
|
catch {
|
|
62
|
-
// Corrupted JSON — refuse to overwrite to avoid losing existing config
|
|
63
146
|
process.stderr.write([
|
|
64
147
|
"Pharaoh: ~/.openclaw/openclaw.json exists but is not valid JSON.",
|
|
65
148
|
"Fix or delete it manually, then re-run --install-skills.",
|
|
@@ -71,7 +154,6 @@ export function mergeOpenClawConfig(home = homedir()) {
|
|
|
71
154
|
if (!config.mcpServers) {
|
|
72
155
|
config.mcpServers = {};
|
|
73
156
|
}
|
|
74
|
-
// Don't overwrite an existing pharaoh entry
|
|
75
157
|
if (config.mcpServers.pharaoh) {
|
|
76
158
|
return false;
|
|
77
159
|
}
|
|
@@ -82,40 +164,65 @@ export function mergeOpenClawConfig(home = homedir()) {
|
|
|
82
164
|
writeFileSync(configPath, JSON.stringify(config, null, "\t"));
|
|
83
165
|
return true;
|
|
84
166
|
}
|
|
167
|
+
// ── Main entry point ────────────────────────────────────────────────
|
|
85
168
|
/**
|
|
86
169
|
* Main entry point for --install-skills.
|
|
87
170
|
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
171
|
+
* Detection priority: Claude Code > OpenClaw > manual instructions.
|
|
172
|
+
* Installs to all detected platforms (a user may use both).
|
|
90
173
|
*
|
|
91
174
|
* @param home - Home directory override (defaults to os.homedir()).
|
|
92
175
|
*/
|
|
93
176
|
export function runInstallSkills(home = homedir()) {
|
|
177
|
+
const hasClaudeCode = detectClaudeCode(home);
|
|
94
178
|
const hasOpenClaw = detectOpenClaw(home);
|
|
95
|
-
|
|
179
|
+
let installed = false;
|
|
180
|
+
// ── Claude Code ──
|
|
181
|
+
if (hasClaudeCode) {
|
|
182
|
+
const count = installClaudeCodePlugin(home);
|
|
183
|
+
if (count >= 0) {
|
|
184
|
+
const registered = registerClaudeCodePlugin(home);
|
|
185
|
+
const regMsg = registered
|
|
186
|
+
? "Plugin registered in installed_plugins.json"
|
|
187
|
+
: "Plugin already registered — skipped";
|
|
188
|
+
process.stderr.write([
|
|
189
|
+
`Pharaoh: installed ${count} skills as Claude Code plugin`,
|
|
190
|
+
` → ~/.claude/plugins/data/pharaoh/`,
|
|
191
|
+
` → ${regMsg}`,
|
|
192
|
+
"",
|
|
193
|
+
"Restart Claude Code to pick up the new skills.",
|
|
194
|
+
"",
|
|
195
|
+
].join("\n"));
|
|
196
|
+
installed = true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// ── OpenClaw ──
|
|
200
|
+
if (hasOpenClaw) {
|
|
201
|
+
const count = installSkills(home);
|
|
202
|
+
const configUpdated = mergeOpenClawConfig(home);
|
|
203
|
+
const configMsg = configUpdated
|
|
204
|
+
? "Pharaoh MCP server added to ~/.openclaw/openclaw.json"
|
|
205
|
+
: "Pharaoh already present in ~/.openclaw/openclaw.json — skipped";
|
|
206
|
+
process.stderr.write([
|
|
207
|
+
`Pharaoh: installed ${count} skills to ~/.openclaw/skills/`,
|
|
208
|
+
` → ${configMsg}`,
|
|
209
|
+
"",
|
|
210
|
+
"Restart OpenClaw to pick up the new skills.",
|
|
211
|
+
"",
|
|
212
|
+
].join("\n"));
|
|
213
|
+
installed = true;
|
|
214
|
+
}
|
|
215
|
+
// ── Neither detected ──
|
|
216
|
+
if (!installed) {
|
|
96
217
|
process.stderr.write([
|
|
97
|
-
"Pharaoh:
|
|
218
|
+
"Pharaoh: no supported skill platform detected.",
|
|
98
219
|
"",
|
|
99
|
-
"
|
|
220
|
+
"Supported platforms:",
|
|
221
|
+
" • Claude Code — install from https://claude.ai/download",
|
|
222
|
+
" • OpenClaw — install from https://openclaw.dev/install",
|
|
100
223
|
"",
|
|
101
|
-
"
|
|
102
|
-
` 1. Copy the skills/ directory from this package to ~/.openclaw/skills/`,
|
|
103
|
-
` 2. Add Pharaoh to ~/.openclaw/openclaw.json under mcpServers:`,
|
|
104
|
-
` "pharaoh": { "command": "npx", "args": ["@pharaoh-so/mcp"] }`,
|
|
224
|
+
"Once installed, re-run: npx @pharaoh-so/mcp --install-skills",
|
|
105
225
|
"",
|
|
106
226
|
].join("\n"));
|
|
107
|
-
return;
|
|
108
227
|
}
|
|
109
|
-
const count = installSkills(home);
|
|
110
|
-
const configUpdated = mergeOpenClawConfig(home);
|
|
111
|
-
const configMsg = configUpdated
|
|
112
|
-
? "Pharaoh MCP server added to ~/.openclaw/openclaw.json"
|
|
113
|
-
: "Pharaoh already present in ~/.openclaw/openclaw.json — skipped";
|
|
114
|
-
process.stderr.write([
|
|
115
|
-
`Pharaoh: installed ${count} skills to ~/.openclaw/skills/`,
|
|
116
|
-
configMsg,
|
|
117
|
-
"",
|
|
118
|
-
"Restart OpenClaw to pick up the new skills.",
|
|
119
|
-
"",
|
|
120
|
-
].join("\n"));
|
|
121
228
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pharaoh-so/mcp",
|
|
3
|
-
"
|
|
3
|
+
"mcpName": "so.pharaoh/pharaoh",
|
|
4
|
+
"version": "0.2.4",
|
|
4
5
|
"description": "MCP proxy for Pharaoh — maps codebases into queryable knowledge graphs for AI agents. Enables Claude Code in headless environments (VPS, SSH, CI) via device flow auth.",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "dist/index.js",
|
|
@@ -11,6 +12,8 @@
|
|
|
11
12
|
"files": [
|
|
12
13
|
"dist",
|
|
13
14
|
"skills",
|
|
15
|
+
".claude-plugin",
|
|
16
|
+
".mcp.json",
|
|
14
17
|
"inspect-tools.json",
|
|
15
18
|
"README.md",
|
|
16
19
|
"CHANGELOG.md",
|