@zeph-to/cli 2.11.0 → 2.12.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 +8 -2
- package/dist/check-update.d.ts +7 -0
- package/dist/check-update.d.ts.map +1 -1
- package/dist/check-update.js +29 -12
- package/dist/cli.js +6 -0
- package/dist/installer.d.ts +0 -12
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +10 -32
- package/dist/mcp-command.d.ts +45 -0
- package/dist/mcp-command.d.ts.map +1 -0
- package/dist/mcp-command.js +50 -0
- package/dist/mcp.d.ts +19 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +29 -0
- package/dist/verify.d.ts +34 -0
- package/dist/verify.d.ts.map +1 -1
- package/dist/verify.js +116 -6
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -179,10 +179,15 @@ way. `zeph install` does not wire Hermes either — add the MCP server to
|
|
|
179
179
|
```yaml
|
|
180
180
|
mcp_servers:
|
|
181
181
|
zeph:
|
|
182
|
-
command: "
|
|
183
|
-
args: ["
|
|
182
|
+
command: "zeph"
|
|
183
|
+
args: ["mcp"]
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
+
`zeph mcp` runs the MCP server inside the CLI process. The older
|
|
187
|
+
`command: "npx"` / `args: ["-y", "@zeph-to/mcp-server"]` form still works,
|
|
188
|
+
but leaves an `npm exec` launcher resident beside the server for as long as
|
|
189
|
+
the session lives — `zeph verify` flags a config still on it.
|
|
190
|
+
|
|
186
191
|
Add the entry; do not replace the file. `mcp_servers` is shared with
|
|
187
192
|
every other server you have configured, and nothing under `~/.hermes` is
|
|
188
193
|
in version control. Then `/reload-mcp` inside Hermes.
|
|
@@ -523,6 +528,7 @@ zeph notify --title "Hello" --json
|
|
|
523
528
|
| `rename <name>` | Set the current agent session's display name in the app — run inside a `zeph cc` session (`--clear` resets). Auto-detects the tmux session + this machine's listener device id, so the alias lands on the right device |
|
|
524
529
|
| `test` | Verify connection and API key |
|
|
525
530
|
| `cc` · `codex` · `gemini` | Run the agent in a `zeph-<project>` tmux session — reattaches a detached session of that project (newest suffix first) when there is one, else auto-suffixes `-2`, `-3`, …. Auto-spawns the background listener on first invocation so the phone picker just works. Trailing args pass through to the agent (`zeph cc --resume "..."`) |
|
|
531
|
+
| `mcp` | Run the MCP server on stdio, in this process. What agent MCP configs launch — `zeph install` registers it and you never type it. Replaces the old `npx -y @zeph-to/mcp-server` registration, which left an `npm exec` launcher resident alongside the server for the life of the session. `@zeph-to/mcp-server` ships as a dependency now, so it updates with the CLI rather than being re-fetched by `npx` on every launch — `zeph check-update` reports the version you actually have |
|
|
526
532
|
| `listener` | (Usually unnecessary — `zeph cc` autospawns it.) Resident daemon: subscribes via WebSocket, reports tmux session inventory every 5 s, injects `agent.command` pushes into the matching session. Run in the foreground for SDK development; otherwise let `zeph cc` manage it |
|
|
527
533
|
|
|
528
534
|
### Notify Options
|
package/dist/check-update.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
/** Semver-ish compare: returns true when `latest` is strictly newer than `current`. */
|
|
2
2
|
export declare const isNewer: (latest: string, current: string) => boolean;
|
|
3
|
+
/**
|
|
4
|
+
* The mcp-server version this CLI will actually run. It ships as a dependency
|
|
5
|
+
* (see mcp.ts), so it is pinned at install time — no longer "whatever npx
|
|
6
|
+
* fetched last". Returns null on a broken install rather than throwing; the
|
|
7
|
+
* report degrades to "latest is vX" the way it always did for this package.
|
|
8
|
+
*/
|
|
9
|
+
export declare const installedMcpServerVersion: () => string | null;
|
|
3
10
|
export declare const handleCheckUpdate: (args: Record<string, string | boolean>) => Promise<number>;
|
|
4
11
|
//# sourceMappingURL=check-update.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-update.d.ts","sourceRoot":"","sources":["../src/check-update.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"check-update.d.ts","sourceRoot":"","sources":["../src/check-update.ts"],"names":[],"mappings":"AAuBA,uFAAuF;AACvF,eAAO,MAAM,OAAO,GAAI,QAAQ,MAAM,EAAE,SAAS,MAAM,KAAG,OAQzD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,QAAO,MAAM,GAAG,IASrD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CA4C9F,CAAC"}
|
package/dist/check-update.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleCheckUpdate = exports.isNewer = void 0;
|
|
3
|
+
exports.handleCheckUpdate = exports.installedMcpServerVersion = exports.isNewer = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
4
5
|
const config_js_1 = require("./config.js");
|
|
5
6
|
// Compares installed versions against the npm registry. Pure read-only —
|
|
6
7
|
// never installs anything; just tells the user if a newer release exists.
|
|
@@ -34,19 +35,35 @@ const isNewer = (latest, current) => {
|
|
|
34
35
|
return false;
|
|
35
36
|
};
|
|
36
37
|
exports.isNewer = isNewer;
|
|
38
|
+
/**
|
|
39
|
+
* The mcp-server version this CLI will actually run. It ships as a dependency
|
|
40
|
+
* (see mcp.ts), so it is pinned at install time — no longer "whatever npx
|
|
41
|
+
* fetched last". Returns null on a broken install rather than throwing; the
|
|
42
|
+
* report degrades to "latest is vX" the way it always did for this package.
|
|
43
|
+
*/
|
|
44
|
+
const installedMcpServerVersion = () => {
|
|
45
|
+
try {
|
|
46
|
+
const pkg = JSON.parse((0, fs_1.readFileSync)(require.resolve('@zeph-to/mcp-server/package.json'), 'utf-8'));
|
|
47
|
+
return pkg.version ?? null;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
exports.installedMcpServerVersion = installedMcpServerVersion;
|
|
37
54
|
const handleCheckUpdate = async (args) => {
|
|
38
55
|
const isJson = args.json === true;
|
|
39
|
-
//
|
|
40
|
-
// mcp-server's
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
}
|
|
56
|
+
// Both installed versions are knowable: the CLI's from its own
|
|
57
|
+
// package.json, and mcp-server's because `zeph mcp` runs it in-process,
|
|
58
|
+
// which makes it a dependency rather than an npx download of unknown age.
|
|
59
|
+
// Two unrelated registry round-trips — awaiting them one after the other
|
|
60
|
+
// doubled the command's wall time for nothing.
|
|
61
|
+
const latestVersions = await Promise.all(PACKAGES.map(fetchLatest));
|
|
62
|
+
const results = PACKAGES.map((pkg, i) => {
|
|
63
|
+
const latest = latestVersions[i];
|
|
64
|
+
const current = pkg === '@zeph-to/cli' ? config_js_1.VERSION : (0, exports.installedMcpServerVersion)();
|
|
65
|
+
return { pkg, current, latest, outdated: !!(latest && current && (0, exports.isNewer)(latest, current)) };
|
|
66
|
+
});
|
|
50
67
|
if (isJson) {
|
|
51
68
|
console.log(JSON.stringify({ results }, null, 2));
|
|
52
69
|
return 0;
|
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ const verify_js_1 = require("./verify.js");
|
|
|
11
11
|
const check_update_js_1 = require("./check-update.js");
|
|
12
12
|
const ask_js_1 = require("./ask.js");
|
|
13
13
|
const wrapper_js_1 = require("./wrapper.js");
|
|
14
|
+
const mcp_js_1 = require("./mcp.js");
|
|
14
15
|
const listener_js_1 = require("./listener.js");
|
|
15
16
|
const config_js_1 = require("./config.js");
|
|
16
17
|
const gate_js_1 = require("./gate.js");
|
|
@@ -84,6 +85,9 @@ ${usageAgentLines()}
|
|
|
84
85
|
-2/-3/… only when every existing one has a client
|
|
85
86
|
attached. Any args after the subcommand are forwarded
|
|
86
87
|
verbatim, e.g. 'zeph cc --resume')
|
|
88
|
+
mcp Run the MCP server on stdio. This is what agent MCP
|
|
89
|
+
configs launch — 'zeph install' registers it, you
|
|
90
|
+
never type it
|
|
87
91
|
listener Resident daemon — receives 'agent.command' pushes from
|
|
88
92
|
the phone picker and injects them into the matching
|
|
89
93
|
tmux session.
|
|
@@ -491,6 +495,8 @@ const main = async () => {
|
|
|
491
495
|
return handleRename(args);
|
|
492
496
|
case 'test':
|
|
493
497
|
return handleTest(args);
|
|
498
|
+
case 'mcp':
|
|
499
|
+
return (0, mcp_js_1.handleMcp)();
|
|
494
500
|
case 'listener':
|
|
495
501
|
return (0, listener_js_1.handleListener)(args);
|
|
496
502
|
case 'remote-hook':
|
package/dist/installer.d.ts
CHANGED
|
@@ -12,18 +12,6 @@ export declare const shouldReauth: (currentKey: string | undefined, relogin: boo
|
|
|
12
12
|
/** Exported for tests (installGemini shells out to the real `gemini` binary,
|
|
13
13
|
* so the merge semantics can't be covered through it deterministically). */
|
|
14
14
|
export declare const mergeJsonFile: (filePath: string, patch: Record<string, unknown>) => void;
|
|
15
|
-
/**
|
|
16
|
-
* opencode.json's own MCP schema — top-level `mcp` key (not `mcpServers`),
|
|
17
|
-
* `command` as ARRAY (binary + args), `type: "local"`. No `environment` —
|
|
18
|
-
* opencode is a terminal app that inherits shell env, and the MCP server
|
|
19
|
-
* falls back to ~/.zeph/config.json anyway (an unexpanded "${ZEPH_API_KEY}"
|
|
20
|
-
* literal would shadow that fallback with junk). Exported for tests (shape pin).
|
|
21
|
-
*/
|
|
22
|
-
export declare const OPENCODE_MCP_ENTRY: {
|
|
23
|
-
type: string;
|
|
24
|
-
command: string[];
|
|
25
|
-
enabled: boolean;
|
|
26
|
-
};
|
|
27
15
|
/** Add the zeph entry under `key` in an MCP registry JSON file, preserving
|
|
28
16
|
* everything else in it. Exported for tests (merge semantics). */
|
|
29
17
|
export declare const injectMcpEntry: (filePath: string, key: string, entry: Record<string, unknown>) => void;
|
package/dist/installer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../src/installer.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AA+BzC;;;GAGG;AACH;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,YAAY,MAAM,GAAG,SAAS,EAAE,SAAS,OAAO,KAAG,OACxD,CAAC;AAoBzB;6EAC6E;AAC7E,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAqBhF,CAAC;AAsCF;mEACmE;AACnE,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,EAAE,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAQ9F,CAAC;AAmPF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,KAAK,EAAE,EAAE,MAAM,MAAM,KAAG,KAAK,EAKxE,CAAC;AA8EF;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EACtC,gBAAgB,OAAO,KACtB,KAAK,GAAG,IAAI,GAAG,KAKjB,CAAC;AAgCF,eAAO,MAAM,aAAa,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CAuH1F,CAAC"}
|
package/dist/installer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleInstall = exports.serviceInstallChoice = exports.filterAgentsByIds = exports.injectMcpEntry = exports.
|
|
3
|
+
exports.handleInstall = exports.serviceInstallChoice = exports.filterAgentsByIds = exports.injectMcpEntry = exports.mergeJsonFile = exports.shouldReauth = void 0;
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const os_1 = require("os");
|
|
@@ -10,6 +10,7 @@ const zeph_hook_js_1 = require("./zeph-hook.js");
|
|
|
10
10
|
const config_js_1 = require("./config.js");
|
|
11
11
|
const login_js_1 = require("./login.js");
|
|
12
12
|
const agents_js_1 = require("./agents.js");
|
|
13
|
+
const mcp_command_js_1 = require("./mcp-command.js");
|
|
13
14
|
const listener_service_js_1 = require("./listener-service.js");
|
|
14
15
|
const templates_js_1 = require("./templates.js");
|
|
15
16
|
const HOME = (0, os_1.homedir)();
|
|
@@ -104,27 +105,6 @@ const addAiderReadDirective = (confPath, conventionsPath) => {
|
|
|
104
105
|
(0, fs_1.writeFileSync)(confPath, (base ? `${base}\n\n` : '') + line);
|
|
105
106
|
};
|
|
106
107
|
// ── Per-Agent Installers ─────────────────────────────────────────
|
|
107
|
-
// Pass through env explicitly so the MCP server doesn't have to rely on
|
|
108
|
-
// process-env inheritance (which behaves differently per IDE — Cursor and
|
|
109
|
-
// Windsurf spawn the MCP from a graphical context that may not inherit
|
|
110
|
-
// shell env). Mirrors plugin/.mcp.json.
|
|
111
|
-
const MCP_SERVERS_ENTRY = {
|
|
112
|
-
command: 'npx',
|
|
113
|
-
args: ['-y', '@zeph-to/mcp-server'],
|
|
114
|
-
env: { ZEPH_API_KEY: '${ZEPH_API_KEY}' },
|
|
115
|
-
};
|
|
116
|
-
/**
|
|
117
|
-
* opencode.json's own MCP schema — top-level `mcp` key (not `mcpServers`),
|
|
118
|
-
* `command` as ARRAY (binary + args), `type: "local"`. No `environment` —
|
|
119
|
-
* opencode is a terminal app that inherits shell env, and the MCP server
|
|
120
|
-
* falls back to ~/.zeph/config.json anyway (an unexpanded "${ZEPH_API_KEY}"
|
|
121
|
-
* literal would shadow that fallback with junk). Exported for tests (shape pin).
|
|
122
|
-
*/
|
|
123
|
-
exports.OPENCODE_MCP_ENTRY = {
|
|
124
|
-
type: 'local',
|
|
125
|
-
command: ['npx', '-y', '@zeph-to/mcp-server'],
|
|
126
|
-
enabled: true,
|
|
127
|
-
};
|
|
128
108
|
/** Add the zeph entry under `key` in an MCP registry JSON file, preserving
|
|
129
109
|
* everything else in it. Exported for tests (merge semantics). */
|
|
130
110
|
const injectMcpEntry = (filePath, key, entry) => {
|
|
@@ -153,7 +133,7 @@ const installClaude = () => {
|
|
|
153
133
|
};
|
|
154
134
|
const installCursor = () => {
|
|
155
135
|
try {
|
|
156
|
-
(0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.cursor', 'mcp.json'), 'mcpServers', MCP_SERVERS_ENTRY);
|
|
136
|
+
(0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.cursor', 'mcp.json'), 'mcpServers', mcp_command_js_1.MCP_SERVERS_ENTRY);
|
|
157
137
|
ok('MCP server added');
|
|
158
138
|
}
|
|
159
139
|
catch {
|
|
@@ -176,7 +156,7 @@ const installCursor = () => {
|
|
|
176
156
|
};
|
|
177
157
|
const installWindsurf = () => {
|
|
178
158
|
try {
|
|
179
|
-
(0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.codeium', 'windsurf', 'mcp_config.json'), 'mcpServers', MCP_SERVERS_ENTRY);
|
|
159
|
+
(0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.codeium', 'windsurf', 'mcp_config.json'), 'mcpServers', mcp_command_js_1.MCP_SERVERS_ENTRY);
|
|
180
160
|
ok('MCP server added');
|
|
181
161
|
}
|
|
182
162
|
catch {
|
|
@@ -201,20 +181,18 @@ const installWindsurf = () => {
|
|
|
201
181
|
};
|
|
202
182
|
const installGemini = () => {
|
|
203
183
|
try {
|
|
204
|
-
//
|
|
205
|
-
// the
|
|
206
|
-
|
|
207
|
-
// legacy `mcp add zeph -- npx …` form; fall back for those.
|
|
208
|
-
(0, child_process_1.execSync)('gemini mcp add -s user zeph npx -- -y @zeph-to/mcp-server', { stdio: 'pipe' });
|
|
184
|
+
// Both forms are built in mcp-command.ts; older gemini CLIs only accept
|
|
185
|
+
// the legacy one, so try the modern form first and fall back.
|
|
186
|
+
(0, child_process_1.execSync)(mcp_command_js_1.GEMINI_MCP_ADD, { stdio: 'pipe' });
|
|
209
187
|
ok('MCP server added');
|
|
210
188
|
}
|
|
211
189
|
catch {
|
|
212
190
|
try {
|
|
213
|
-
(0, child_process_1.execSync)(
|
|
191
|
+
(0, child_process_1.execSync)(mcp_command_js_1.GEMINI_MCP_ADD_LEGACY, { stdio: 'pipe' });
|
|
214
192
|
ok('MCP server added (legacy gemini CLI)');
|
|
215
193
|
}
|
|
216
194
|
catch {
|
|
217
|
-
fail(
|
|
195
|
+
fail(`MCP add failed. Manual: ${mcp_command_js_1.GEMINI_MCP_ADD}`);
|
|
218
196
|
}
|
|
219
197
|
}
|
|
220
198
|
try {
|
|
@@ -320,7 +298,7 @@ const installPi = () => {
|
|
|
320
298
|
};
|
|
321
299
|
const installOpencode = () => {
|
|
322
300
|
try {
|
|
323
|
-
(0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.config', 'opencode', 'opencode.json'), 'mcp',
|
|
301
|
+
(0, exports.injectMcpEntry)((0, path_1.join)(HOME, '.config', 'opencode', 'opencode.json'), 'mcp', mcp_command_js_1.OPENCODE_MCP_ENTRY);
|
|
324
302
|
ok('MCP server added');
|
|
325
303
|
}
|
|
326
304
|
catch {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How every agent launches the Zeph MCP server — one source, three schemas.
|
|
3
|
+
*
|
|
4
|
+
* Registrations used to say `npx -y @zeph-to/mcp-server`, which left an
|
|
5
|
+
* `npm exec` launcher resident beside the server for the life of the session.
|
|
6
|
+
* `zeph mcp` (see mcp.ts) runs the server in the CLI's own process instead.
|
|
7
|
+
*
|
|
8
|
+
* Cursor/Windsurf, Gemini and OpenCode each want that launch in a different
|
|
9
|
+
* shape, and the shapes drifted apart when each site spelled the command out
|
|
10
|
+
* itself. Everything below is derived from MCP_LAUNCH_ARGV.
|
|
11
|
+
*/
|
|
12
|
+
/** What the agents run. `zeph` resolves out of the same global bin dir as `npx`. */
|
|
13
|
+
export declare const MCP_LAUNCH_ARGV: readonly ["zeph", "mcp"];
|
|
14
|
+
/**
|
|
15
|
+
* `mcpServers.zeph` — what the installer writes for Cursor and Windsurf.
|
|
16
|
+
* The env block is deliberate: both spawn the MCP server from a graphical
|
|
17
|
+
* context that may not inherit shell env, so the key is passed through
|
|
18
|
+
* explicitly rather than left to inheritance.
|
|
19
|
+
*
|
|
20
|
+
* `zeph-to/plugin`'s `.mcp.json` holds the same shape but is a HAND-KEPT COPY —
|
|
21
|
+
* it lives in another repo and cannot import this. Change one, change both.
|
|
22
|
+
*/
|
|
23
|
+
export declare const MCP_SERVERS_ENTRY: {
|
|
24
|
+
command: "zeph";
|
|
25
|
+
args: "mcp"[];
|
|
26
|
+
env: {
|
|
27
|
+
ZEPH_API_KEY: string;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* opencode.json's own MCP schema — top-level `mcp` key (not `mcpServers`),
|
|
32
|
+
* `command` as ARRAY (binary + args), `type: "local"`. No `environment` —
|
|
33
|
+
* opencode is a terminal app that inherits shell env, and the MCP server
|
|
34
|
+
* falls back to ~/.zeph/config.json anyway (an unexpanded "${ZEPH_API_KEY}"
|
|
35
|
+
* literal would shadow that fallback with junk).
|
|
36
|
+
*/
|
|
37
|
+
export declare const OPENCODE_MCP_ENTRY: {
|
|
38
|
+
type: string;
|
|
39
|
+
command: ("zeph" | "mcp")[];
|
|
40
|
+
enabled: boolean;
|
|
41
|
+
};
|
|
42
|
+
export declare const GEMINI_MCP_ADD: string;
|
|
43
|
+
/** Older gemini CLIs only accept `mcp add <name> -- <command…>`, with no scope flag. */
|
|
44
|
+
export declare const GEMINI_MCP_ADD_LEGACY: string;
|
|
45
|
+
//# sourceMappingURL=mcp-command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-command.d.ts","sourceRoot":"","sources":["../src/mcp-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,oFAAoF;AACpF,eAAO,MAAM,eAAe,0BAA2B,CAAC;AAIxD;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB;;;;;;CAI7B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAC;AAMF,eAAO,MAAM,cAAc,QAA0E,CAAC;AAEtG,wFAAwF;AACxF,eAAO,MAAM,qBAAqB,QAAwD,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* How every agent launches the Zeph MCP server — one source, three schemas.
|
|
4
|
+
*
|
|
5
|
+
* Registrations used to say `npx -y @zeph-to/mcp-server`, which left an
|
|
6
|
+
* `npm exec` launcher resident beside the server for the life of the session.
|
|
7
|
+
* `zeph mcp` (see mcp.ts) runs the server in the CLI's own process instead.
|
|
8
|
+
*
|
|
9
|
+
* Cursor/Windsurf, Gemini and OpenCode each want that launch in a different
|
|
10
|
+
* shape, and the shapes drifted apart when each site spelled the command out
|
|
11
|
+
* itself. Everything below is derived from MCP_LAUNCH_ARGV.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.GEMINI_MCP_ADD_LEGACY = exports.GEMINI_MCP_ADD = exports.OPENCODE_MCP_ENTRY = exports.MCP_SERVERS_ENTRY = exports.MCP_LAUNCH_ARGV = void 0;
|
|
15
|
+
/** What the agents run. `zeph` resolves out of the same global bin dir as `npx`. */
|
|
16
|
+
exports.MCP_LAUNCH_ARGV = ['zeph', 'mcp'];
|
|
17
|
+
const [MCP_BIN, ...MCP_SUBCOMMAND] = exports.MCP_LAUNCH_ARGV;
|
|
18
|
+
/**
|
|
19
|
+
* `mcpServers.zeph` — what the installer writes for Cursor and Windsurf.
|
|
20
|
+
* The env block is deliberate: both spawn the MCP server from a graphical
|
|
21
|
+
* context that may not inherit shell env, so the key is passed through
|
|
22
|
+
* explicitly rather than left to inheritance.
|
|
23
|
+
*
|
|
24
|
+
* `zeph-to/plugin`'s `.mcp.json` holds the same shape but is a HAND-KEPT COPY —
|
|
25
|
+
* it lives in another repo and cannot import this. Change one, change both.
|
|
26
|
+
*/
|
|
27
|
+
exports.MCP_SERVERS_ENTRY = {
|
|
28
|
+
command: MCP_BIN,
|
|
29
|
+
args: [...MCP_SUBCOMMAND],
|
|
30
|
+
env: { ZEPH_API_KEY: '${ZEPH_API_KEY}' },
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* opencode.json's own MCP schema — top-level `mcp` key (not `mcpServers`),
|
|
34
|
+
* `command` as ARRAY (binary + args), `type: "local"`. No `environment` —
|
|
35
|
+
* opencode is a terminal app that inherits shell env, and the MCP server
|
|
36
|
+
* falls back to ~/.zeph/config.json anyway (an unexpanded "${ZEPH_API_KEY}"
|
|
37
|
+
* literal would shadow that fallback with junk).
|
|
38
|
+
*/
|
|
39
|
+
exports.OPENCODE_MCP_ENTRY = {
|
|
40
|
+
type: 'local',
|
|
41
|
+
command: [...exports.MCP_LAUNCH_ARGV],
|
|
42
|
+
enabled: true,
|
|
43
|
+
};
|
|
44
|
+
// gemini ≥0.26 syntax: `mcp add [-s scope] <name> <command> [args…]`. The
|
|
45
|
+
// server NAME and the BINARY are both "zeph" here, so the doubled word below
|
|
46
|
+
// is correct, not a copy-paste slip. Default scope is "project" (cwd-local
|
|
47
|
+
// .gemini/), so user scope is pinned for a machine-wide install.
|
|
48
|
+
exports.GEMINI_MCP_ADD = `gemini mcp add -s user zeph ${MCP_BIN} -- ${MCP_SUBCOMMAND.join(' ')}`;
|
|
49
|
+
/** Older gemini CLIs only accept `mcp add <name> -- <command…>`, with no scope flag. */
|
|
50
|
+
exports.GEMINI_MCP_ADD_LEGACY = `gemini mcp add zeph -- ${exports.MCP_LAUNCH_ARGV.join(' ')}`;
|
package/dist/mcp.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `zeph mcp` — run the Zeph MCP server inside THIS process.
|
|
3
|
+
*
|
|
4
|
+
* Every registration used to say `npx -y @zeph-to/mcp-server`, which left an
|
|
5
|
+
* `npm exec` launcher resident for the whole session on top of the server it
|
|
6
|
+
* spawned — two node processes where one does the work. `@zeph-to/mcp-server`
|
|
7
|
+
* is a dependency of this package now, so agents register `zeph mcp` and get
|
|
8
|
+
* exactly one process.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Importing `@zeph-to/mcp-server` IS starting it: the package is a bin entry
|
|
12
|
+
* whose module body wires an McpServer to a StdioServerTransport and exports
|
|
13
|
+
* nothing. Verified against 2.3.0 (`dist/index.js` ends in `main().catch(…)`).
|
|
14
|
+
* Injectable so tests don't need the real package resolvable.
|
|
15
|
+
*/
|
|
16
|
+
type McpServerLoader = () => Promise<unknown>;
|
|
17
|
+
export declare const handleMcp: (load?: McpServerLoader) => Promise<number>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=mcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,KAAK,eAAe,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;AAI9C,eAAO,MAAM,SAAS,GAAU,OAAM,eAAiC,KAAG,OAAO,CAAC,MAAM,CAcvF,CAAC"}
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `zeph mcp` — run the Zeph MCP server inside THIS process.
|
|
4
|
+
*
|
|
5
|
+
* Every registration used to say `npx -y @zeph-to/mcp-server`, which left an
|
|
6
|
+
* `npm exec` launcher resident for the whole session on top of the server it
|
|
7
|
+
* spawned — two node processes where one does the work. `@zeph-to/mcp-server`
|
|
8
|
+
* is a dependency of this package now, so agents register `zeph mcp` and get
|
|
9
|
+
* exactly one process.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.handleMcp = void 0;
|
|
13
|
+
const importMcpServer = () => import('@zeph-to/mcp-server');
|
|
14
|
+
const handleMcp = async (load = importMcpServer) => {
|
|
15
|
+
try {
|
|
16
|
+
await load();
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
20
|
+
console.error(`zeph: could not start the MCP server (@zeph-to/mcp-server): ${reason}`);
|
|
21
|
+
console.error('zeph: reinstall the CLI with `npm i -g @zeph-to/cli`.');
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
// The server owns this process from here: it holds stdio open and decides
|
|
25
|
+
// when to exit. Resolving would hand cli.ts a code for `process.exit()`,
|
|
26
|
+
// killing the server the line above just started.
|
|
27
|
+
return new Promise(() => { });
|
|
28
|
+
};
|
|
29
|
+
exports.handleMcp = handleMcp;
|
package/dist/verify.d.ts
CHANGED
|
@@ -1,2 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The launch argv a registry file records for zeph, verbatim — null when the
|
|
3
|
+
* file is absent, unparseable, or has no zeph entry. Two schemas in the wild:
|
|
4
|
+
* `command` + `args` (Cursor/Windsurf/Gemini) and `command` as a whole array
|
|
5
|
+
* (opencode). Returned as-is on purpose: a stale entry is only detectable if
|
|
6
|
+
* the reader does not normalize it into the shape it expects.
|
|
7
|
+
*/
|
|
8
|
+
export declare const registeredMcpArgv: (filePath: string, key: string) => string[] | null;
|
|
9
|
+
/**
|
|
10
|
+
* Can this launch binary actually be run? Registered commands come out of a
|
|
11
|
+
* config file, so they can be an absolute path with spaces in it — the shared
|
|
12
|
+
* `hasCommand` interpolates into `which ${cmd}`, where such a path splits into
|
|
13
|
+
* two words and reports a perfectly good binary as missing (and where any `;`
|
|
14
|
+
* in the file would reach the shell). Nothing here touches a shell.
|
|
15
|
+
*/
|
|
16
|
+
export declare const binaryResolves: (bin: string) => boolean;
|
|
17
|
+
/**
|
|
18
|
+
* What a recorded registration is worth right now. `unresolvable` outranks
|
|
19
|
+
* `stale`: a stale entry still starts a server (through the npm launcher this
|
|
20
|
+
* release exists to delete), an unresolvable one starts nothing at all and
|
|
21
|
+
* takes the agent's whole zeph toolset down with it, silently — the config is
|
|
22
|
+
* read once at install time and never checked again.
|
|
23
|
+
*/
|
|
24
|
+
export type McpRegistration = {
|
|
25
|
+
readonly state: 'current';
|
|
26
|
+
} | {
|
|
27
|
+
readonly state: 'stale';
|
|
28
|
+
readonly argv: string[];
|
|
29
|
+
} | {
|
|
30
|
+
readonly state: 'unresolvable';
|
|
31
|
+
readonly argv: string[];
|
|
32
|
+
};
|
|
33
|
+
/** null = this agent has no zeph registration at all, so there is nothing to report. */
|
|
34
|
+
export declare const classifyMcpRegistration: (argv: string[] | null, isOnPath: (bin: string) => boolean) => McpRegistration | null;
|
|
1
35
|
export declare const handleVerify: (args: Record<string, string | boolean>) => Promise<number>;
|
|
2
36
|
//# sourceMappingURL=verify.d.ts.map
|
package/dist/verify.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"AA6DA;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,EAAE,GAAG,IAa5E,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,OAQ5C,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GACrB;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GAC7B;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAElE,wFAAwF;AACxF,eAAO,MAAM,uBAAuB,GAChC,MAAM,MAAM,EAAE,GAAG,IAAI,EACrB,UAAU,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KACnC,eAAe,GAAG,IAMpB,CAAC;AAYF,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAG,OAAO,CAAC,MAAM,CA+GzF,CAAC"}
|
package/dist/verify.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleVerify = void 0;
|
|
3
|
+
exports.handleVerify = exports.classifyMcpRegistration = exports.binaryResolves = exports.registeredMcpArgv = void 0;
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const os_1 = require("os");
|
|
6
6
|
const path_1 = require("path");
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
7
8
|
const agents_js_1 = require("./agents.js");
|
|
8
9
|
const config_js_1 = require("./config.js");
|
|
9
10
|
const listener_service_js_1 = require("./listener-service.js");
|
|
10
11
|
const zeph_hook_js_1 = require("./zeph-hook.js");
|
|
12
|
+
const mcp_command_js_1 = require("./mcp-command.js");
|
|
11
13
|
const HOME = (0, os_1.homedir)();
|
|
12
14
|
const pass = (msg) => console.log(` ✓ ${msg}`);
|
|
13
15
|
const warn = (msg) => console.log(` ! ${msg}`);
|
|
@@ -41,6 +43,83 @@ const AGENT_RULE_PRESENT = {
|
|
|
41
43
|
pi: () => hasManagedBlock((0, path_1.join)(HOME, '.pi', 'agent', 'AGENTS.md')),
|
|
42
44
|
opencode: () => hasManagedBlock((0, path_1.join)(HOME, '.config', 'opencode', 'AGENTS.md')),
|
|
43
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Where each agent records the MCP launch, and under which container key.
|
|
48
|
+
* `agent` matches the label `detectAgents` uses so one report never names the
|
|
49
|
+
* same agent two ways. Cursor/Windsurf/OpenCode are files the installer writes
|
|
50
|
+
* itself; the Gemini row is READ-ONLY — `zeph install` shells out to
|
|
51
|
+
* `gemini mcp add`, so this path is the gemini CLI's own storage layout,
|
|
52
|
+
* confirmed by reading the file it produced, not something Zeph chose.
|
|
53
|
+
*/
|
|
54
|
+
const MCP_REGISTRIES = [
|
|
55
|
+
{ agent: 'Cursor', path: (0, path_1.join)(HOME, '.cursor', 'mcp.json'), key: 'mcpServers' },
|
|
56
|
+
{ agent: 'Windsurf', path: (0, path_1.join)(HOME, '.codeium', 'windsurf', 'mcp_config.json'), key: 'mcpServers' },
|
|
57
|
+
{ agent: 'Gemini CLI', path: (0, path_1.join)(HOME, '.gemini', 'settings.json'), key: 'mcpServers' },
|
|
58
|
+
{ agent: 'OpenCode', path: (0, path_1.join)(HOME, '.config', 'opencode', 'opencode.json'), key: 'mcp' },
|
|
59
|
+
];
|
|
60
|
+
/**
|
|
61
|
+
* The launch argv a registry file records for zeph, verbatim — null when the
|
|
62
|
+
* file is absent, unparseable, or has no zeph entry. Two schemas in the wild:
|
|
63
|
+
* `command` + `args` (Cursor/Windsurf/Gemini) and `command` as a whole array
|
|
64
|
+
* (opencode). Returned as-is on purpose: a stale entry is only detectable if
|
|
65
|
+
* the reader does not normalize it into the shape it expects.
|
|
66
|
+
*/
|
|
67
|
+
const registeredMcpArgv = (filePath, key) => {
|
|
68
|
+
let data;
|
|
69
|
+
try {
|
|
70
|
+
data = JSON.parse((0, fs_1.readFileSync)(filePath, 'utf-8'));
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const container = data[key];
|
|
76
|
+
const entry = container?.zeph;
|
|
77
|
+
if (!entry)
|
|
78
|
+
return null;
|
|
79
|
+
if (Array.isArray(entry.command))
|
|
80
|
+
return entry.command.map(String);
|
|
81
|
+
if (typeof entry.command !== 'string')
|
|
82
|
+
return null;
|
|
83
|
+
return [entry.command, ...(Array.isArray(entry.args) ? entry.args.map(String) : [])];
|
|
84
|
+
};
|
|
85
|
+
exports.registeredMcpArgv = registeredMcpArgv;
|
|
86
|
+
/**
|
|
87
|
+
* Can this launch binary actually be run? Registered commands come out of a
|
|
88
|
+
* config file, so they can be an absolute path with spaces in it — the shared
|
|
89
|
+
* `hasCommand` interpolates into `which ${cmd}`, where such a path splits into
|
|
90
|
+
* two words and reports a perfectly good binary as missing (and where any `;`
|
|
91
|
+
* in the file would reach the shell). Nothing here touches a shell.
|
|
92
|
+
*/
|
|
93
|
+
const binaryResolves = (bin) => {
|
|
94
|
+
try {
|
|
95
|
+
if (bin.includes('/'))
|
|
96
|
+
(0, fs_1.accessSync)(bin, fs_1.constants.X_OK);
|
|
97
|
+
else
|
|
98
|
+
(0, child_process_1.execFileSync)('which', [bin], { stdio: 'pipe' });
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
exports.binaryResolves = binaryResolves;
|
|
106
|
+
/** null = this agent has no zeph registration at all, so there is nothing to report. */
|
|
107
|
+
const classifyMcpRegistration = (argv, isOnPath) => {
|
|
108
|
+
if (!argv || argv.length === 0)
|
|
109
|
+
return null;
|
|
110
|
+
if (!isOnPath(argv[0]))
|
|
111
|
+
return { state: 'unresolvable', argv };
|
|
112
|
+
const isCanonical = argv.length === mcp_command_js_1.MCP_LAUNCH_ARGV.length
|
|
113
|
+
&& argv.every((token, i) => token === mcp_command_js_1.MCP_LAUNCH_ARGV[i]);
|
|
114
|
+
return isCanonical ? { state: 'current' } : { state: 'stale', argv };
|
|
115
|
+
};
|
|
116
|
+
exports.classifyMcpRegistration = classifyMcpRegistration;
|
|
117
|
+
/** The registries that actually hold a zeph entry, classified. Agents that were
|
|
118
|
+
* never installed drop out here so the report has no row for them. */
|
|
119
|
+
const activeMcpRegistrations = (isOnPath) => MCP_REGISTRIES.flatMap((registry) => {
|
|
120
|
+
const result = (0, exports.classifyMcpRegistration)((0, exports.registeredMcpArgv)(registry.path, registry.key), isOnPath);
|
|
121
|
+
return result ? [{ agent: registry.agent, result }] : [];
|
|
122
|
+
});
|
|
44
123
|
const handleVerify = async (args) => {
|
|
45
124
|
const doPing = args.ping === true;
|
|
46
125
|
const checks = [];
|
|
@@ -64,12 +143,28 @@ const handleVerify = async (args) => {
|
|
|
64
143
|
? 'ZEPH_HOOK_ID is set (two-way zeph_ask/prompt/input enabled)'
|
|
65
144
|
: 'ZEPH_HOOK_ID not set (notify-only — set it for remote control)', hookId ? 'pass' : 'warn');
|
|
66
145
|
// ── Runtime ──────────────────────────────────────────────────
|
|
146
|
+
// One resolution per binary: `zeph` alone was being looked up five times
|
|
147
|
+
// (twice here, once per registry below), and each lookup is a spawn.
|
|
148
|
+
const resolved = new Map();
|
|
149
|
+
const resolves = (bin) => {
|
|
150
|
+
const cached = resolved.get(bin);
|
|
151
|
+
if (cached !== undefined)
|
|
152
|
+
return cached;
|
|
153
|
+
const found = (0, exports.binaryResolves)(bin);
|
|
154
|
+
resolved.set(bin, found);
|
|
155
|
+
return found;
|
|
156
|
+
};
|
|
67
157
|
console.log('\n Runtime:');
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
158
|
+
const hasNode = resolves('node');
|
|
159
|
+
const hasNpx = resolves('npx');
|
|
160
|
+
const hasZeph = resolves('zeph');
|
|
161
|
+
record(hasNode ? 'node available' : 'node not found', hasNode ? 'pass' : 'fail');
|
|
162
|
+
record(hasNpx ? 'npx available (hook fallback when zeph is off PATH)' : 'npx not found', hasNpx ? 'pass' : 'warn');
|
|
163
|
+
// Not a warning any more: `zeph mcp` IS the MCP server, so a zeph that
|
|
164
|
+
// isn't on PATH means no MCP tools at all, not just a slower first call.
|
|
165
|
+
record(hasZeph
|
|
166
|
+
? 'zeph CLI on PATH (runs the MCP server and the hooks)'
|
|
167
|
+
: 'zeph CLI not on PATH — MCP tools will not start. Reinstall: npm i -g @zeph-to/cli', hasZeph ? 'pass' : 'fail');
|
|
73
168
|
// ── Login-time service ───────────────────────────────────────
|
|
74
169
|
// Optional, so a missing one is a warning. A broken one is not: every way
|
|
75
170
|
// it breaks still looks installed from the outside.
|
|
@@ -79,6 +174,21 @@ const handleVerify = async (args) => {
|
|
|
79
174
|
for (const row of serviceRows)
|
|
80
175
|
record(row.label, row.state);
|
|
81
176
|
}
|
|
177
|
+
// ── MCP registrations ────────────────────────────────────────
|
|
178
|
+
const registrations = activeMcpRegistrations(resolves);
|
|
179
|
+
if (registrations.length > 0) {
|
|
180
|
+
console.log('\n MCP registrations:');
|
|
181
|
+
for (const { agent, result } of registrations) {
|
|
182
|
+
if (result.state === 'current')
|
|
183
|
+
record(`${agent}: launches \`${mcp_command_js_1.MCP_LAUNCH_ARGV.join(' ')}\``, 'pass');
|
|
184
|
+
else if (result.state === 'stale') {
|
|
185
|
+
record(`${agent}: still launches \`${result.argv.join(' ')}\` — one extra resident process per session. Re-run: zeph install`, 'warn');
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
record(`${agent}: launches \`${result.argv[0]}\`, which is not on PATH — zeph tools will not load. Re-run: zeph install`, 'fail');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
82
192
|
// ── Per-agent config ─────────────────────────────────────────
|
|
83
193
|
console.log('\n Agents:');
|
|
84
194
|
const detected = (0, agents_js_1.detectAgents)().filter((a) => a.detected);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeph-to/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.0",
|
|
4
4
|
"description": "Zeph CLI + push notification SDK for AI agents",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"@inquirer/prompts": "^8.4.3",
|
|
75
|
+
"@zeph-to/mcp-server": "^2.3.0",
|
|
75
76
|
"ws": "^8.21.0"
|
|
76
77
|
}
|
|
77
78
|
}
|