@pharaoh-so/mcp 0.2.8 → 0.2.10
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 +1 -1
- package/dist/proxy.d.ts +16 -0
- package/dist/proxy.js +23 -4
- package/package.json +1 -1
- package/skills/pharaoh/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ claude mcp add pharaoh -- npx @pharaoh-so/mcp
|
|
|
51
51
|
If you have a browser available (desktop, laptop), you can connect directly via SSE instead:
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
|
-
claude mcp add --transport sse pharaoh https://mcp.pharaoh.so/sse
|
|
54
|
+
claude mcp add --transport sse --scope user pharaoh https://mcp.pharaoh.so/sse
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
This uses OAuth in the browser and doesn't require this package.
|
package/dist/proxy.d.ts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stdio ↔ SSE proxy — bridges a local MCP stdio connection to a remote Pharaoh SSE server.
|
|
3
|
+
* Uses SDK transports on both ends: StdioServerTransport (local) and SSEClientTransport (remote).
|
|
4
|
+
*
|
|
5
|
+
* RECONNECTION DESIGN:
|
|
6
|
+
* The MCP SDK's SSEClientTransport wraps an EventSource, which has built-in auto-reconnect
|
|
7
|
+
* (every 3 seconds by default). This auto-reconnect is problematic because:
|
|
8
|
+
* 1. Each reconnect creates a NEW server-side session (new auth, new session ID)
|
|
9
|
+
* 2. The proxy's reconnect loop doesn't know about the internal reconnect
|
|
10
|
+
* 3. Tool calls get lost between the stale and new sessions
|
|
11
|
+
*
|
|
12
|
+
* Solution: On any non-fatal SSE error, we explicitly close() the transport to kill
|
|
13
|
+
* the EventSource and its auto-reconnect timer, then let the proxy's own backoff loop
|
|
14
|
+
* create a fresh SSEClientTransport for the next attempt. This ensures one session
|
|
15
|
+
* at a time and clean reconnection semantics.
|
|
16
|
+
*/
|
|
1
17
|
/** Thrown when the remote server returns 401 — token is expired or revoked. */
|
|
2
18
|
export declare class TokenExpiredError extends Error {
|
|
3
19
|
constructor();
|
package/dist/proxy.js
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Stdio ↔ SSE proxy — bridges a local MCP stdio connection to a remote Pharaoh SSE server.
|
|
3
3
|
* Uses SDK transports on both ends: StdioServerTransport (local) and SSEClientTransport (remote).
|
|
4
|
+
*
|
|
5
|
+
* RECONNECTION DESIGN:
|
|
6
|
+
* The MCP SDK's SSEClientTransport wraps an EventSource, which has built-in auto-reconnect
|
|
7
|
+
* (every 3 seconds by default). This auto-reconnect is problematic because:
|
|
8
|
+
* 1. Each reconnect creates a NEW server-side session (new auth, new session ID)
|
|
9
|
+
* 2. The proxy's reconnect loop doesn't know about the internal reconnect
|
|
10
|
+
* 3. Tool calls get lost between the stale and new sessions
|
|
11
|
+
*
|
|
12
|
+
* Solution: On any non-fatal SSE error, we explicitly close() the transport to kill
|
|
13
|
+
* the EventSource and its auto-reconnect timer, then let the proxy's own backoff loop
|
|
14
|
+
* create a fresh SSEClientTransport for the next attempt. This ensures one session
|
|
15
|
+
* at a time and clean reconnection semantics.
|
|
4
16
|
*/
|
|
5
17
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
6
18
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -92,8 +104,6 @@ export async function startProxy(sseUrl, token) {
|
|
|
92
104
|
});
|
|
93
105
|
};
|
|
94
106
|
}
|
|
95
|
-
/** Handle SSE errors — delegates to classifySSEError for 401/403 detection. */
|
|
96
|
-
const handleSSEError = classifySSEError;
|
|
97
107
|
// Connect SSE with reconnect loop — stdio starts AFTER first successful connection
|
|
98
108
|
await connectWithReconnect();
|
|
99
109
|
/** Attempt SSE connection with exponential backoff on failure. */
|
|
@@ -116,18 +126,27 @@ export async function startProxy(sseUrl, token) {
|
|
|
116
126
|
await stdio.start();
|
|
117
127
|
stdioStarted = true;
|
|
118
128
|
}
|
|
129
|
+
else {
|
|
130
|
+
process.stderr.write("Pharaoh: reconnected\n");
|
|
131
|
+
}
|
|
119
132
|
// Wait for close — this promise resolves when SSE disconnects
|
|
120
133
|
await new Promise((resolve, reject) => {
|
|
121
134
|
sse.onclose = () => resolve();
|
|
122
135
|
sse.onerror = (err) => {
|
|
123
136
|
try {
|
|
124
|
-
|
|
137
|
+
classifySSEError(err);
|
|
125
138
|
}
|
|
126
139
|
catch (typed) {
|
|
127
140
|
reject(typed);
|
|
128
141
|
return;
|
|
129
142
|
}
|
|
130
|
-
// Non-fatal error —
|
|
143
|
+
// Non-fatal error — explicitly close the transport to kill
|
|
144
|
+
// EventSource's built-in auto-reconnect. Without this, EventSource
|
|
145
|
+
// reconnects every ~3s, creating ghost sessions on the server
|
|
146
|
+
// (100+ auth successes, zero tool calls completing).
|
|
147
|
+
// close() fires onclose which resolves this promise, handing
|
|
148
|
+
// control back to the proxy's backoff loop.
|
|
149
|
+
sse.close().catch(() => { });
|
|
131
150
|
};
|
|
132
151
|
});
|
|
133
152
|
// SSE closed — attempt reconnect
|
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.
|
|
4
|
+
"version": "0.2.10",
|
|
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",
|
package/skills/pharaoh/SKILL.md
CHANGED
|
@@ -72,7 +72,7 @@ Full docs at [pharaoh.so/docs](https://pharaoh.so/docs).
|
|
|
72
72
|
|
|
73
73
|
**Direct SSE** (desktop with browser, uses OAuth):
|
|
74
74
|
```
|
|
75
|
-
claude mcp add pharaoh https://mcp.pharaoh.so/sse
|
|
75
|
+
claude mcp add --transport sse --scope user pharaoh https://mcp.pharaoh.so/sse
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
**Headless** (VPS/SSH/containers, uses device flow — authorize on any device):
|