@zeph-to/mcp-server 1.11.2 → 1.11.3

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
@@ -1,5 +1,10 @@
1
1
  # @zeph-to/mcp-server
2
2
 
3
+ [![npm](https://img.shields.io/npm/v/@zeph-to/mcp-server.svg)](https://www.npmjs.com/package/@zeph-to/mcp-server)
4
+ [![downloads](https://img.shields.io/npm/dm/@zeph-to/mcp-server.svg)](https://www.npmjs.com/package/@zeph-to/mcp-server)
5
+ [![node](https://img.shields.io/node/v/@zeph-to/mcp-server.svg)](https://nodejs.org)
6
+ [![license](https://img.shields.io/npm/l/@zeph-to/mcp-server.svg)](./LICENSE)
7
+
3
8
  Zeph MCP server for AI agents. Send notifications, copy to clipboard, request confirmations, and collect text input from users across their devices — all via the [Model Context Protocol](https://modelcontextprotocol.io).
4
9
 
5
10
  ## Setup
@@ -7,7 +12,7 @@ Zeph MCP server for AI agents. Send notifications, copy to clipboard, request co
7
12
  The easiest way to set up for all agents at once:
8
13
 
9
14
  ```bash
10
- npx @zeph-to/hook-sdk install
15
+ npx @zeph-to/cli install
11
16
  ```
12
17
 
13
18
  This saves credentials to `~/.zeph/config.json` and configures your agents automatically. The MCP server reads from this file — no env vars needed.
@@ -54,7 +59,7 @@ Add to `~/.claude/settings.json`:
54
59
  | `ZEPH_BASE_URL` | No | API base URL (default: `https://api.zeph.to/v1`) |
55
60
  | `ZEPH_DISABLE_SESSION_CACHE` | No | Set to `1`/`true` to skip writing the session-id handoff file under `~/.cache/zeph/`. Useful for read-only filesystems, ephemeral CI runners, or sandboxed envs that audit filesystem writes. The plugin's stop hook still works without it (transcript-path UUID extraction is the primary path; the cache is a fallback for older Claude Code versions). |
56
61
 
57
- \* If env vars are not set, the server reads from `~/.zeph/config.json` (created by `npx @zeph-to/hook-sdk install`). Unresolved `${...}` interpolations are also treated as unset.
62
+ \* If env vars are not set, the server reads from `~/.zeph/config.json` (created by `npx @zeph-to/cli install`). Unresolved `${...}` interpolations are also treated as unset.
58
63
 
59
64
  ## Tools
60
65
 
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAEV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,qBAAa,QAAS,SAAQ,KAAK;aAGf,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM;gBAF9B,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM;CAKjC;AAKD,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,eAAe;IAK7B,QAAQ,CAAC,MAAM,EAAE;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,EAAE,CAAC,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACxH,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,GAAG,OAAO,CAAC,YAAY,CAAC;IAInB,WAAW,CACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,QAAQ,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,OAAO,GAAG,OAAO,CAAC;QACzD,KAAK,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,EAAE,CAAC,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACxH,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GACA,OAAO,CAAC,mBAAmB,CAAC;IAIzB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAIzE,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC;IAIvC,UAAU,CAAC,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAQjF,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAIrD,gBAAgB,IAAI,OAAO,CAAC,eAAe,CAAC;IAI5C,YAAY,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAIzC,aAAa,CAAC,MAAM,EAAE;QAC1B,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAI5B,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAc7E,OAAO;CAsCtB"}
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -91,12 +91,17 @@ class ZephApiClient {
91
91
  throw err;
92
92
  }
93
93
  if (!response.ok) {
94
+ // Read the body as text once, then try to parse it. A non-JSON
95
+ // error (HTML proxy page, gateway error) would otherwise be swallowed
96
+ // silently — surface a truncated snippet so failures are debuggable.
97
+ const raw = await response.text().catch(() => '');
94
98
  let errorBody = null;
95
99
  try {
96
- errorBody = (await response.json());
100
+ errorBody = raw ? JSON.parse(raw) : null;
97
101
  }
98
102
  catch {
99
- // Non-JSON error response (e.g., HTML error page)
103
+ if (raw)
104
+ console.error(`[api] ${response.status} non-JSON body: ${raw.slice(0, 200)}`);
100
105
  }
101
106
  const message = errorBody?.error?.message ?? `Request failed with status ${response.status}`;
102
107
  const code = errorBody?.error?.code ?? 'UNKNOWN_ERROR';
package/dist/config.js CHANGED
@@ -123,7 +123,7 @@ const loadConfig = () => {
123
123
  const fileConfig = loadFileConfig();
124
124
  const apiKey = resolvedEnv('ZEPH_API_KEY') ?? fileConfig.apiKey;
125
125
  if (!apiKey) {
126
- throw new Error('ZEPH_API_KEY not found. Run "npx @zeph-to/hook-sdk install" or set ZEPH_API_KEY env var.');
126
+ throw new Error('ZEPH_API_KEY not found. Run "npx @zeph-to/cli install" or set ZEPH_API_KEY env var.');
127
127
  }
128
128
  const sessionId = resolvedEnv('ZEPH_SESSION_ID') ?? detectClaudeSessionId() ?? `sess_${(0, crypto_1.randomBytes)(12).toString('base64url')}`;
129
129
  const projectDir = process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AA4JH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,EAAE,UAAU,MAAM,KAAG,OAAO,CAAC,MAAM,CAsE5E,CAAC;AA8BF,eAAO,MAAM,UAAU,QAAO,aAAa,GAAG,IAAqB,CAAC;AACpE,eAAO,MAAM,YAAY,QAAO,MAAM,GAAG,IAA+B,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,sBAAsB,GACjC,OAAO;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,KACrD,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,IAAI,CAAC;CACnB,CAaA,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,KACd,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAQlE,CAAC"}
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAoJH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,EAAE,UAAU,MAAM,KAAG,OAAO,CAAC,MAAM,CAsE5E,CAAC;AA8BF,eAAO,MAAM,UAAU,QAAO,aAAa,GAAG,IAAqB,CAAC;AACpE,eAAO,MAAM,YAAY,QAAO,MAAM,GAAG,IAA+B,CAAC;AAEzE;;GAEG;AACH,eAAO,MAAM,sBAAsB,GACjC,OAAO;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,KACrD,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,IAAI,CAAC;CACnB,CAaA,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,KACd,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAQlE,CAAC"}
package/dist/crypto.js CHANGED
@@ -34,21 +34,12 @@ const fs_1 = require("fs");
34
34
  const os_1 = require("os");
35
35
  const path_1 = require("path");
36
36
  // ─── Base64 helpers ───
37
- const toBase64 = (buffer) => {
38
- const bytes = new Uint8Array(buffer);
39
- let binary = '';
40
- for (let i = 0; i < bytes.length; i++) {
41
- binary += String.fromCharCode(bytes[i]);
42
- }
43
- return btoa(binary);
44
- };
37
+ const toBase64 = (buffer) => Buffer.from(buffer).toString('base64');
45
38
  const fromBase64 = (base64) => {
46
- const binary = atob(base64);
47
- const bytes = new Uint8Array(binary.length);
48
- for (let i = 0; i < binary.length; i++) {
49
- bytes[i] = binary.charCodeAt(i);
50
- }
51
- return bytes.buffer;
39
+ const buf = Buffer.from(base64, 'base64');
40
+ // Slice to the exact byte range — Buffer may share a larger pooled
41
+ // ArrayBuffer, so `.buffer` alone could expose unrelated memory.
42
+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
52
43
  };
53
44
  // ─── ECDH key management ───
54
45
  const ECDH_PARAMS = { name: 'ECDH', namedCurve: 'P-256' };
@@ -1 +1 @@
1
- {"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../src/poll.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAE5C,gBAAgB,EAAE,CAAC,YAAY,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAOD,eAAO,MAAM,eAAe,GAC1B,QAAQ,aAAa,EACrB,QAAQ,MAAM,EACd,SAAS,MAAM,EACf,gBAAgB,MAAM,EACtB,KAAK,WAAW,KACf,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAwClC,CAAC"}
1
+ {"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../src/poll.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAE5C,gBAAgB,EAAE,CAAC,YAAY,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAOD,eAAO,MAAM,eAAe,GAC1B,QAAQ,aAAa,EACrB,QAAQ,MAAM,EACd,SAAS,MAAM,EACf,gBAAgB,MAAM,EACtB,KAAK,WAAW,KACf,OAAO,CAAC,iBAAiB,GAAG,IAAI,CA6ClC,CAAC"}
package/dist/poll.js CHANGED
@@ -17,6 +17,11 @@ const pollForResponse = async (client, hookId, eventId, timeoutSeconds, ctx) =>
17
17
  throw new Error('User cancelled the request');
18
18
  if (event.data.status === 'timed_out')
19
19
  return null;
20
+ // Only 'pending' should keep us polling. Anything else is server
21
+ // contract drift — fail fast instead of spinning until the timeout.
22
+ if (event.data.status !== 'pending') {
23
+ throw new Error(`Unexpected hook event status: ${String(event.data.status)}`);
24
+ }
20
25
  // Throttled progress notification (every 5s)
21
26
  if (progressToken !== undefined) {
22
27
  const elapsed = Math.floor((Date.now() - startTime) / 1000);
@@ -1 +1 @@
1
- {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;CAC5C;AAeD;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAIhE,CAAC;AASF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,GAAG,SAAS,KAAG,eAAe,EAAE,GAAG,SAgB7E,CAAC"}
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;CAC5C;AAeD;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,GAAG,SAAS,KAAG,MAAM,GAAG,SAIhE,CAAC;AAkBF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,GAAG,SAAS,KAAG,eAAe,EAAE,GAAG,SAgB7E,CAAC"}
package/dist/sanitize.js CHANGED
@@ -42,9 +42,17 @@ const sanitizeText = (text) => {
42
42
  return cut === -1 ? text : text.slice(0, cut).trimEnd();
43
43
  };
44
44
  exports.sanitizeText = sanitizeText;
45
+ // Bounds mirror the zeph_ask contract (1–4 actions). Length caps on the
46
+ // recovered strings keep a malformed/oversized leak from producing absurd
47
+ // buttons; the real server enforces its own limits too.
45
48
  const isActionArray = (value) => Array.isArray(value) &&
46
49
  value.length > 0 &&
47
- value.every((a) => a && typeof a.id === 'string' && typeof a.label === 'string');
50
+ value.length <= 4 &&
51
+ value.every((a) => a &&
52
+ typeof a.id === 'string' &&
53
+ a.id.length <= 50 &&
54
+ typeof a.label === 'string' &&
55
+ a.label.length <= 100);
48
56
  /**
49
57
  * Recover an `actions` array that leaked into the body of a malformed
50
58
  * zeph_ask call. Returns undefined when nothing parseable is found.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeph-to/mcp-server",
3
- "version": "1.11.2",
3
+ "version": "1.11.3",
4
4
  "description": "Zeph MCP server — AI agent notifications, prompts, and input via MCP protocol",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -62,5 +62,9 @@
62
62
  "cursor",
63
63
  "gemini"
64
64
  ],
65
- "license": "Apache-2.0"
65
+ "license": "Apache-2.0",
66
+ "publishConfig": {
67
+ "access": "public",
68
+ "registry": "https://registry.npmjs.org/"
69
+ }
66
70
  }