@pharaoh-so/mcp 0.2.12 → 0.3.0

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
@@ -26,7 +26,7 @@ This displays a device code and a URL. Open the URL on **any device** (phone, la
26
26
  ### Step 2 — Add to Claude Code
27
27
 
28
28
  ```bash
29
- claude mcp add pharaoh -- npx @pharaoh-so/mcp
29
+ npx @pharaoh-so/mcp --setup
30
30
  ```
31
31
 
32
32
  Verify the connection:
@@ -43,19 +43,9 @@ If you previously added Pharaoh as an SSE server, remove it first:
43
43
 
44
44
  ```bash
45
45
  claude mcp remove pharaoh
46
- claude mcp add pharaoh -- npx @pharaoh-so/mcp
46
+ npx @pharaoh-so/mcp --setup
47
47
  ```
48
48
 
49
- ### Desktop with Browser (Alternative)
50
-
51
- If you have a browser available (desktop, laptop), you can connect directly via SSE instead:
52
-
53
- ```bash
54
- claude mcp add --transport sse --scope user pharaoh https://mcp.pharaoh.so/sse
55
- ```
56
-
57
- This uses OAuth in the browser and doesn't require this package.
58
-
59
49
  ## How It Works
60
50
 
61
51
  ```
@@ -156,10 +146,10 @@ npx @pharaoh-so/mcp --logout
156
146
 
157
147
  ### Custom Server
158
148
 
159
- For self-hosted Pharaoh instances or development:
149
+ For self-hosted Pharaoh instances or development, register manually:
160
150
 
161
151
  ```bash
162
- claude mcp add pharaoh -- npx @pharaoh-so/mcp --server https://your-pharaoh-instance.com
152
+ claude mcp add --scope user pharaoh -- npx @pharaoh-so/mcp --server https://your-pharaoh-instance.com
163
153
  ```
164
154
 
165
155
  ### Environment Variables
@@ -213,7 +203,7 @@ npx @pharaoh-so/mcp
213
203
  Make sure you added it with the correct command:
214
204
 
215
205
  ```bash
216
- claude mcp add pharaoh -- npx @pharaoh-so/mcp
206
+ npx @pharaoh-so/mcp --setup
217
207
  ```
218
208
 
219
209
  Note the `--` separator between `pharaoh` and `npx`.
@@ -230,7 +220,7 @@ The first run after installation may take a moment as npm downloads the package.
230
220
 
231
221
  ```bash
232
222
  npm install -g @pharaoh-so/mcp
233
- claude mcp add pharaoh -- pharaoh-mcp
223
+ claude mcp add --scope user pharaoh -- pharaoh-mcp
234
224
  ```
235
225
 
236
226
  ## How Pharaoh Works
package/dist/helpers.d.ts CHANGED
@@ -10,6 +10,7 @@ export declare function printLines(...lines: string[]): void;
10
10
  export declare function parseArgs(argv?: string[]): {
11
11
  server: string;
12
12
  logout: boolean;
13
+ setup: boolean;
13
14
  };
14
15
  export declare function printUsage(): void;
15
16
  /**
package/dist/helpers.js CHANGED
@@ -8,6 +8,7 @@ export function printLines(...lines) {
8
8
  export function parseArgs(argv = process.argv.slice(2)) {
9
9
  let server = DEFAULT_SERVER;
10
10
  let logout = false;
11
+ let setup = false;
11
12
  for (let i = 0; i < argv.length; i++) {
12
13
  if (argv[i] === "--server" && argv[i + 1]) {
13
14
  server = argv[i + 1];
@@ -16,6 +17,9 @@ export function parseArgs(argv = process.argv.slice(2)) {
16
17
  else if (argv[i] === "--logout") {
17
18
  logout = true;
18
19
  }
20
+ else if (argv[i] === "--setup") {
21
+ setup = true;
22
+ }
19
23
  }
20
24
  // Strip trailing slash
21
25
  server = server.replace(/\/+$/, "");
@@ -37,10 +41,10 @@ export function parseArgs(argv = process.argv.slice(2)) {
37
41
  printLines(`Pharaoh: --server is not a valid URL: ${server}`);
38
42
  process.exit(1);
39
43
  }
40
- return { server, logout };
44
+ return { server, logout, setup };
41
45
  }
42
46
  export function printUsage() {
43
- printLines("Usage: pharaoh-mcp [options]", "", "Options:", " --server <url> Pharaoh server URL (default: https://mcp.pharaoh.so)", " --logout Clear stored credentials and exit", " --install-skills Force reinstall Pharaoh skills (Claude Code + OpenClaw)", " --help, -h Show this help", "", "Add to Claude Code:", " claude mcp add pharaoh -- npx @pharaoh-so/mcp", "");
47
+ printLines("Usage: pharaoh-mcp [options]", "", "Options:", " --setup Full install: auth, register MCP, install skills (start here)", " --server <url> Pharaoh server URL (default: https://mcp.pharaoh.so)", " --logout Clear stored credentials and exit", " --install-skills Force reinstall Pharaoh skills (Claude Code + OpenClaw)", " --help, -h Show this help", "", "Get started:", " npx @pharaoh-so/mcp --setup", "");
44
48
  }
45
49
  /**
46
50
  * Validate that a server-supplied SSE URL shares the same origin as the configured server.
@@ -96,7 +100,7 @@ export function formatTtl(expiresAt) {
96
100
  * after auth completes (or when credentials already exist).
97
101
  */
98
102
  export function printSetupInstructions() {
99
- printLines("", "┌───────────────────────────────────────────────────────┐", "│ Next step: add Pharaoh to Claude Code │", "│ │", "│ If pharaoh is already registered (e.g. as SSE): │", "│ claude mcp remove pharaoh │", "│ │", "│ Then add as stdio proxy: │", "│ claude mcp add pharaoh -- npx @pharaoh-so/mcp │", "│ │", "│ Verify with: │", "│ claude mcp list │", "└───────────────────────────────────────────────────────┘", "");
103
+ printLines("", "┌───────────────────────────────────────────────────────┐", "│ To register Pharaoh in Claude Code, run: │", "│ npx @pharaoh-so/mcp --setup │", "│ │", "│ This removes stale entries, registers the MCP │", "│ server globally, and installs all skills. │", "└───────────────────────────────────────────────────────┘", "");
100
104
  }
101
105
  /** Format a credential identity string (e.g. "alice (my-org)"). */
102
106
  export function formatIdentity(creds) {
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ async function main() {
33
33
  runInstallSkills();
34
34
  return;
35
35
  }
36
- const { server, logout } = parseArgs(args);
36
+ const { server, logout, setup } = parseArgs(args);
37
37
  if (logout) {
38
38
  deleteCredentials();
39
39
  printLines("Pharaoh: credentials cleared");
@@ -41,6 +41,36 @@ async function main() {
41
41
  }
42
42
  const creds = readCredentials();
43
43
  const isInteractive = Boolean(process.stdin.isTTY);
44
+ // ── Setup mode (--setup): full automated install ──
45
+ // Auth → remove stale → register MCP → install skills → done.
46
+ if (setup) {
47
+ // Authenticate if needed
48
+ let activeCreds = creds && !isExpired(creds) ? creds : null;
49
+ if (activeCreds) {
50
+ printLines(`Pharaoh: authenticated as ${formatIdentity(activeCreds)} — token valid for ${formatTtl(activeCreds.expires_at)}`);
51
+ }
52
+ else {
53
+ printLines("Pharaoh: starting device authorization...");
54
+ const deviceCode = await requestDeviceCode(server);
55
+ printActivationPrompt(deviceCode.user_code, deviceCode.verification_uri);
56
+ const token = await pollForToken(server, deviceCode.device_code, deviceCode.interval);
57
+ if (token.provisional) {
58
+ printLines(`Pharaoh: provisional access — install the GitHub App to map your repos: ${token.install_url ?? ""}`);
59
+ }
60
+ const sseUrl = resolveSseUrl(token.sse_url, server);
61
+ const newCreds = tokenToCredentials(token, sseUrl);
62
+ writeCredentials(newCreds);
63
+ activeCreds = newCreds;
64
+ printAuthSuccess(token.github_login ?? null, token.tenant_name ?? null, token.repos?.length ?? 0);
65
+ }
66
+ // Register MCP server in Claude Code
67
+ const { runSetup } = await import("./setup.js");
68
+ runSetup();
69
+ // Install skills
70
+ runInstallSkills();
71
+ printLines("", "Pharaoh is ready. Start a new Claude Code conversation and ask:", ' "What modules does this codebase have?"', "");
72
+ process.exit(0);
73
+ }
44
74
  // ── Interactive mode (user running in a terminal) ──
45
75
  // Authenticate if needed, print setup instructions, and exit.
46
76
  // The proxy is useless without Claude Code on the other end of stdin.
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Full automated setup: remove stale entries, register MCP server globally,
3
+ * install skills. Requires valid credentials (caller handles auth first).
4
+ *
5
+ * @returns true if setup succeeded, false if Claude CLI not found.
6
+ */
7
+ export declare function runSetup(): boolean;
package/dist/setup.js ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * --setup implementation for the Pharaoh MCP proxy CLI.
3
+ *
4
+ * Full automated install: authenticates via device flow, removes stale MCP
5
+ * entries, registers Pharaoh as a global stdio MCP server, and installs skills.
6
+ * One command does everything: `npx @pharaoh-so/mcp --setup`
7
+ */
8
+ import { execFileSync } from "node:child_process";
9
+ import { printLines } from "./helpers.js";
10
+ /** Check if `claude` CLI is available in PATH. */
11
+ function hasClaude() {
12
+ try {
13
+ const which = process.platform === "win32" ? "where" : "which";
14
+ execFileSync(which, ["claude"], {
15
+ encoding: "utf-8",
16
+ stdio: ["pipe", "pipe", "pipe"],
17
+ });
18
+ return true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ /** Run a claude CLI command, returning true on success. Surfaces stderr on failure. */
25
+ function runClaude(args) {
26
+ try {
27
+ execFileSync("claude", args, {
28
+ encoding: "utf-8",
29
+ stdio: ["pipe", "pipe", "pipe"],
30
+ timeout: 30_000,
31
+ });
32
+ return true;
33
+ }
34
+ catch (err) {
35
+ if (err && typeof err === "object" && "stderr" in err) {
36
+ const stderr = err.stderr?.toString().trim();
37
+ if (stderr)
38
+ printLines(` claude ${args.slice(0, 3).join(" ")}: ${stderr}`);
39
+ }
40
+ return false;
41
+ }
42
+ }
43
+ /**
44
+ * Full automated setup: remove stale entries, register MCP server globally,
45
+ * install skills. Requires valid credentials (caller handles auth first).
46
+ *
47
+ * @returns true if setup succeeded, false if Claude CLI not found.
48
+ */
49
+ export function runSetup() {
50
+ if (!hasClaude()) {
51
+ printLines("Pharaoh: Claude Code CLI not found.", "", "Install Claude Code first: https://claude.ai/download", "Then re-run: npx @pharaoh-so/mcp --setup", "");
52
+ return false;
53
+ }
54
+ printLines("Pharaoh: setting up...");
55
+ // Step 1: Remove any stale entry (ignore failures — may not exist)
56
+ runClaude(["mcp", "remove", "pharaoh"]);
57
+ // Step 2: Register as global stdio MCP server
58
+ const added = runClaude([
59
+ "mcp",
60
+ "add",
61
+ "--scope",
62
+ "user",
63
+ "pharaoh",
64
+ "--",
65
+ "npx",
66
+ "@pharaoh-so/mcp",
67
+ ]);
68
+ if (!added) {
69
+ printLines("Pharaoh: failed to register MCP server.", "Try manually: npx @pharaoh-so/mcp --setup", "");
70
+ return false;
71
+ }
72
+ printLines("Pharaoh: registered as global MCP server (scope: user)");
73
+ // Step 3: Install skills (handled by caller via runInstallSkills)
74
+ // We just report the MCP registration success here.
75
+ return true;
76
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pharaoh-so/mcp",
3
3
  "mcpName": "so.pharaoh/pharaoh",
4
- "version": "0.2.12",
4
+ "version": "0.3.0",
5
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.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -70,12 +70,12 @@ Full docs at [pharaoh.so/docs](https://pharaoh.so/docs).
70
70
 
71
71
  ## Connection options
72
72
 
73
- **Direct SSE** (desktop with browser, uses OAuth):
73
+ **CLI** (Claude Code, OpenClaw — works everywhere):
74
74
  ```
75
- claude mcp add --transport sse --scope user pharaoh https://mcp.pharaoh.so/sse
75
+ npx @pharaoh-so/mcp --setup
76
76
  ```
77
77
 
78
- **Headless** (VPS/SSH/containers, uses device flow authorize on any device):
78
+ **URL** (Claude.ai, Cursor, ChatGPTpaste in settings):
79
79
  ```
80
- claude mcp add pharaoh -- npx @pharaoh-so/mcp
80
+ https://mcp.pharaoh.so/sse
81
81
  ```