@pharaoh-so/mcp 0.3.24 → 0.3.25

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.
Files changed (2) hide show
  1. package/dist/gateway.js +25 -6
  2. package/package.json +1 -1
package/dist/gateway.js CHANGED
@@ -17,17 +17,31 @@
17
17
  import { openBrowser, pollOnce, requestDeviceCode, } from "./auth.js";
18
18
  import { readCredentials, writeCredentials } from "./credentials.js";
19
19
  import { resolveSseUrl, tokenToCredentials } from "./helpers.js";
20
- function isAccessExpired(creds) {
20
+ /**
21
+ * True when the credentials' access token is at or past its expiry.
22
+ *
23
+ * Takes `now` as a parameter so boundary tests (Date.now() === expires_at
24
+ * exactly) work naturally with the gateway's injected clock — previously
25
+ * this used Date.now() directly, which couldn't be controlled from tests.
26
+ */
27
+ function isAccessExpired(creds, now) {
21
28
  const expiresAt = new Date(creds.expires_at).getTime();
22
29
  if (Number.isNaN(expiresAt))
23
30
  return true;
24
- return Date.now() >= expiresAt;
31
+ return now() >= expiresAt;
25
32
  }
26
33
  function buildAuthResponse(device) {
34
+ // Stryker disable next-line StringLiteral: user-facing UX copy; wording
35
+ // changes are deliberate and covered by manual review, not mutation testing.
27
36
  const prefix = device.errorMessage ? `${device.errorMessage}\n\n` : "";
28
- const text = `${prefix}Pharaoh authentication required.\n\n` +
37
+ const text =
38
+ // Stryker disable next-line StringLiteral: user-facing UX copy
39
+ `${prefix}Pharaoh authentication required.\n\n` +
40
+ // Stryker disable next-line StringLiteral: user-facing UX copy
29
41
  ` 1. Visit ${device.verification_uri_complete}\n` +
42
+ // Stryker disable next-line StringLiteral: user-facing UX copy
30
43
  ` 2. Enter code: ${device.user_code}\n` +
44
+ // Stryker disable next-line StringLiteral: user-facing UX copy
31
45
  ` 3. Re-run this tool after authorizing.`;
32
46
  return {
33
47
  content: [{ type: "text", text }],
@@ -45,6 +59,12 @@ function buildAuthResponse(device) {
45
59
  */
46
60
  export function createGateway(opts) {
47
61
  const now = opts.now ?? (() => Date.now());
62
+ // Stryker disable next-line LogicalOperator: the `??` fallback is exercised
63
+ // at runtime when no opts.openBrowser is passed, but tests vi.mock auth.js's
64
+ // openBrowser to a noop, so a mutated operator can't be distinguished via
65
+ // observable behavior. vi.mock is the safety net; the fallback is defense
66
+ // in depth for production. See packages/mcp-proxy/tests/*.test.ts for the
67
+ // module-level mock that keeps real browser-open calls out of CI.
48
68
  const openBrowserImpl = opts.openBrowser ?? openBrowser;
49
69
  let pending = null;
50
70
  let lastCreds = null;
@@ -91,8 +111,6 @@ export function createGateway(opts) {
91
111
  }
92
112
  /** Decide whether the cached response is still valid without polling. */
93
113
  function shouldSkipPoll(state) {
94
- if (state.last_poll_at === null)
95
- return false;
96
114
  return now() - state.last_poll_at < state.interval_ms;
97
115
  }
98
116
  /**
@@ -110,6 +128,7 @@ export function createGateway(opts) {
110
128
  // inline so the agent sees why; the user will naturally retry.
111
129
  pending = null;
112
130
  return {
131
+ // Stryker disable next-line StringLiteral: user-facing UX copy
113
132
  content: [{ type: "text", text: `Pharaoh auth denied: ${result.error}` }],
114
133
  isError: true,
115
134
  _meta: {
@@ -153,7 +172,7 @@ export function createGateway(opts) {
153
172
  if (!creds)
154
173
  return false;
155
174
  lastCreds = creds;
156
- return !isAccessExpired(creds);
175
+ return !isAccessExpired(creds, now);
157
176
  }
158
177
  function getCredentials() {
159
178
  return lastCreds;
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.3.24",
4
+ "version": "0.3.25",
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",