@phnx-labs/agents-cli 1.20.67 → 1.20.69
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/CHANGELOG.md +100 -0
- package/README.md +14 -1
- package/dist/bin/agents +0 -0
- package/dist/commands/check.js +96 -2
- package/dist/commands/computer.d.ts +26 -0
- package/dist/commands/computer.js +173 -149
- package/dist/commands/doctor.js +37 -9
- package/dist/commands/exec.d.ts +18 -0
- package/dist/commands/exec.js +126 -6
- package/dist/commands/fork.d.ts +9 -0
- package/dist/commands/fork.js +67 -0
- package/dist/commands/plugins.js +11 -2
- package/dist/commands/repo.js +47 -2
- package/dist/commands/run-account-picker.d.ts +14 -0
- package/dist/commands/run-account-picker.js +131 -0
- package/dist/commands/setup-browser.d.ts +18 -0
- package/dist/commands/setup-browser.js +142 -0
- package/dist/commands/setup-computer.d.ts +19 -0
- package/dist/commands/setup-computer.js +133 -0
- package/dist/commands/setup-share.d.ts +17 -0
- package/dist/commands/setup-share.js +85 -0
- package/dist/commands/setup.d.ts +1 -1
- package/dist/commands/setup.js +58 -1
- package/dist/commands/share.d.ts +15 -0
- package/dist/commands/share.js +10 -4
- package/dist/commands/ssh.js +267 -2
- package/dist/commands/teams.d.ts +11 -0
- package/dist/commands/teams.js +39 -1
- package/dist/commands/view.d.ts +4 -14
- package/dist/commands/view.js +39 -36
- package/dist/index.js +2 -1
- package/dist/lib/agents.d.ts +21 -5
- package/dist/lib/agents.js +59 -24
- package/dist/lib/auth-health.d.ts +103 -0
- package/dist/lib/auth-health.js +232 -0
- package/dist/lib/browser/chrome.d.ts +9 -0
- package/dist/lib/browser/chrome.js +22 -0
- package/dist/lib/browser/profiles.js +4 -25
- package/dist/lib/cli-entry.d.ts +23 -0
- package/dist/lib/cli-entry.js +116 -0
- package/dist/lib/computer/download.d.ts +51 -0
- package/dist/lib/computer/download.js +145 -0
- package/dist/lib/computer-rpc.js +9 -3
- package/dist/lib/daemon.d.ts +2 -2
- package/dist/lib/daemon.js +8 -89
- package/dist/lib/devices/connect.d.ts +15 -0
- package/dist/lib/devices/connect.js +17 -5
- package/dist/lib/devices/fleet.d.ts +23 -0
- package/dist/lib/devices/fleet.js +38 -0
- package/dist/lib/devices/health-report.d.ts +46 -0
- package/dist/lib/devices/health-report.js +159 -0
- package/dist/lib/devices/health.d.ts +14 -4
- package/dist/lib/devices/health.js +49 -8
- package/dist/lib/devices/terminfo.d.ts +44 -0
- package/dist/lib/devices/terminfo.js +167 -0
- package/dist/lib/git.d.ts +10 -0
- package/dist/lib/git.js +23 -0
- package/dist/lib/hosts/option.js +1 -1
- package/dist/lib/hosts/ready.js +5 -3
- package/dist/lib/hosts/remote-cmd.d.ts +12 -0
- package/dist/lib/hosts/remote-cmd.js +17 -1
- package/dist/lib/mcp.d.ts +21 -0
- package/dist/lib/mcp.js +278 -13
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/resources/mcp.js +20 -342
- package/dist/lib/rotate.d.ts +12 -8
- package/dist/lib/rotate.js +22 -23
- package/dist/lib/routines.d.ts +13 -0
- package/dist/lib/routines.js +21 -0
- package/dist/lib/runner.js +18 -40
- package/dist/lib/secrets/agent.js +11 -15
- package/dist/lib/session/fork.d.ts +32 -0
- package/dist/lib/session/fork.js +101 -0
- package/dist/lib/share/capture.js +21 -3
- package/dist/lib/signin-badge.d.ts +41 -0
- package/dist/lib/signin-badge.js +64 -0
- package/dist/lib/ssh-exec.d.ts +5 -0
- package/dist/lib/ssh-exec.js +55 -1
- package/dist/lib/startup/command-registry.d.ts +1 -0
- package/dist/lib/startup/command-registry.js +2 -0
- package/dist/lib/usage.d.ts +40 -3
- package/dist/lib/usage.js +147 -16
- package/package.json +1 -1
|
@@ -117,6 +117,18 @@ export interface WindowsAgentsCommand {
|
|
|
117
117
|
* `& agents …` invokes the CLI from the machine PATH (Windows has no login
|
|
118
118
|
* shell, so there is no `bash -lc` equivalent — the shim is simply on PATH).
|
|
119
119
|
*/
|
|
120
|
+
/**
|
|
121
|
+
* PowerShell prelude that silences the progress stream. PowerShell 5.1 serializes
|
|
122
|
+
* progress records ("Preparing modules for first use.") to CLIXML when stderr is a
|
|
123
|
+
* redirected pipe (an ssh capture, not a console), so a remote `agents …` result
|
|
124
|
+
* otherwise comes back wrapped in a raw `#< CLIXML <Objs …>` blob — unreadable to
|
|
125
|
+
* humans and to the JSON parsers that consume doctor / fleet-status output. Prepend
|
|
126
|
+
* this to EVERY Windows script that invokes `agents` (there is more than one builder
|
|
127
|
+
* in this file). Verified against a live win-mini (PowerShell 5.1): this clears it.
|
|
128
|
+
* (`-OutputFormat Text` does NOT — it governs success-stream object serialization,
|
|
129
|
+
* not the progress stream.)
|
|
130
|
+
*/
|
|
131
|
+
export declare const POWERSHELL_PROGRESS_SILENCE = "$ProgressPreference = 'SilentlyContinue'";
|
|
120
132
|
export declare function windowsAgentsScript(cmd: WindowsAgentsCommand): string;
|
|
121
133
|
/**
|
|
122
134
|
* Build the `ssh <target> <cmd>` string for one `agents …` invocation on a
|
|
@@ -110,6 +110,7 @@ export const RUN_OPTION_FORWARDING = {
|
|
|
110
110
|
lease: 'local-only',
|
|
111
111
|
keepBox: 'local-only',
|
|
112
112
|
copyCreds: 'local-only', // copies creds TO the host before dispatch — local concern only
|
|
113
|
+
authCheck: 'local-only', // --no-auth-check gates the local interactive login preflight; --host runs skip that preflight entirely
|
|
113
114
|
};
|
|
114
115
|
/** Actionable messages for value-aware rejections, keyed by attribute name. */
|
|
115
116
|
export const RUN_OPTION_REJECT_MESSAGES = {
|
|
@@ -190,9 +191,21 @@ export function decodePowershell(encoded) {
|
|
|
190
191
|
* `& agents …` invokes the CLI from the machine PATH (Windows has no login
|
|
191
192
|
* shell, so there is no `bash -lc` equivalent — the shim is simply on PATH).
|
|
192
193
|
*/
|
|
194
|
+
/**
|
|
195
|
+
* PowerShell prelude that silences the progress stream. PowerShell 5.1 serializes
|
|
196
|
+
* progress records ("Preparing modules for first use.") to CLIXML when stderr is a
|
|
197
|
+
* redirected pipe (an ssh capture, not a console), so a remote `agents …` result
|
|
198
|
+
* otherwise comes back wrapped in a raw `#< CLIXML <Objs …>` blob — unreadable to
|
|
199
|
+
* humans and to the JSON parsers that consume doctor / fleet-status output. Prepend
|
|
200
|
+
* this to EVERY Windows script that invokes `agents` (there is more than one builder
|
|
201
|
+
* in this file). Verified against a live win-mini (PowerShell 5.1): this clears it.
|
|
202
|
+
* (`-OutputFormat Text` does NOT — it governs success-stream object serialization,
|
|
203
|
+
* not the progress stream.)
|
|
204
|
+
*/
|
|
205
|
+
export const POWERSHELL_PROGRESS_SILENCE = "$ProgressPreference = 'SilentlyContinue'";
|
|
193
206
|
export function windowsAgentsScript(cmd) {
|
|
194
207
|
const { args, env, cwd, propagateExit = true } = cmd;
|
|
195
|
-
const parts = [];
|
|
208
|
+
const parts = [POWERSHELL_PROGRESS_SILENCE];
|
|
196
209
|
if (env)
|
|
197
210
|
for (const [k, v] of Object.entries(env))
|
|
198
211
|
parts.push(`$env:${k} = ${powershellQuote(v)}`);
|
|
@@ -232,6 +245,9 @@ export function buildWindowsStdinImportCommand(bundle, opts = {}) {
|
|
|
232
245
|
// the secret-bearing temp file would otherwise be left behind (RUSH-1764). $tmp
|
|
233
246
|
// starts null so a GetTempFileName that itself throws leaves nothing to remove.
|
|
234
247
|
const script = [
|
|
248
|
+
// Same CLIXML guard as windowsAgentsScript — this builder also runs `& agents …`
|
|
249
|
+
// and its raw stderr is printed to the user on failure (secrets export --host <win>).
|
|
250
|
+
POWERSHELL_PROGRESS_SILENCE,
|
|
235
251
|
'$in = [Console]::In.ReadToEnd()',
|
|
236
252
|
'$tmp = $null',
|
|
237
253
|
`try { $tmp = [System.IO.Path]::GetTempFileName(); [System.IO.File]::WriteAllText($tmp, $in); ` +
|
package/dist/lib/mcp.d.ts
CHANGED
|
@@ -108,6 +108,27 @@ export declare function registerMcpCommandToTargets(targets: {
|
|
|
108
108
|
directAgents: AgentId[];
|
|
109
109
|
versionSelections: Map<AgentId, string[]>;
|
|
110
110
|
}, name: string, commandSpec: McpCommandSpec, scope?: 'user' | 'project', transport?: string): Promise<McpTargetOperationResult[]>;
|
|
111
|
+
/**
|
|
112
|
+
* MCP server shaped for direct config-file serialization.
|
|
113
|
+
*/
|
|
114
|
+
export interface WritableMcpServer {
|
|
115
|
+
name: string;
|
|
116
|
+
transport: 'stdio' | 'http' | 'sse';
|
|
117
|
+
command?: string;
|
|
118
|
+
args?: string[];
|
|
119
|
+
env?: Record<string, string>;
|
|
120
|
+
url?: string;
|
|
121
|
+
headers?: Record<string, string>;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Serialize MCP servers into an agent-specific config file.
|
|
125
|
+
*
|
|
126
|
+
* `mode: 'overwrite'` replaces the whole MCP section (used for tool-managed
|
|
127
|
+
* version-home configs). `mode: 'merge'` updates/adds the provided server
|
|
128
|
+
* entries while preserving existing entries (used for project-level configs
|
|
129
|
+
* that users may hand-edit or populate via agent CLI commands).
|
|
130
|
+
*/
|
|
131
|
+
export declare function writeMcpConfig(agentId: AgentId, configPath: string, servers: WritableMcpServer[], mode?: 'overwrite' | 'merge'): void;
|
|
111
132
|
/**
|
|
112
133
|
* Install MCP servers to an agent.
|
|
113
134
|
* For Claude/Codex: uses CLI commands (claude mcp add, codex mcp add)
|
package/dist/lib/mcp.js
CHANGED
|
@@ -10,12 +10,13 @@
|
|
|
10
10
|
import * as fs from 'fs';
|
|
11
11
|
import * as path from 'path';
|
|
12
12
|
import * as yaml from 'yaml';
|
|
13
|
+
import * as TOML from 'smol-toml';
|
|
13
14
|
import { execFileSync } from 'child_process';
|
|
14
15
|
import * as os from 'os';
|
|
15
16
|
import { getMcpDir, getUserMcpDir, getProjectAgentsDir, getVersionsDir, getUserAgentsDir } from './state.js';
|
|
16
17
|
import { getBinaryPath, getVersionHomePath } from './versions.js';
|
|
17
18
|
import { IS_WINDOWS, execFileShellSpec } from './platform/index.js';
|
|
18
|
-
import { AGENTS } from './agents.js';
|
|
19
|
+
import { AGENTS, getMcpConfigPathForHome, getProjectMcpConfigPath } from './agents.js';
|
|
19
20
|
import { isCapable } from './capabilities.js';
|
|
20
21
|
import { setGeminiAutoUpdateDisabled, updateGeminiSettings } from './gemini-settings.js';
|
|
21
22
|
/**
|
|
@@ -634,6 +635,225 @@ function installMcpToOpenCodeConfig(server, versionHome) {
|
|
|
634
635
|
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
635
636
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
636
637
|
}
|
|
638
|
+
/**
|
|
639
|
+
* Agents whose config file format is implemented by `writeMcpConfig`.
|
|
640
|
+
* Others are intentionally skipped until their schema is added.
|
|
641
|
+
*/
|
|
642
|
+
function writeMcpConfigSupportsAgent(agentId) {
|
|
643
|
+
switch (agentId) {
|
|
644
|
+
case 'claude':
|
|
645
|
+
case 'cursor':
|
|
646
|
+
case 'gemini':
|
|
647
|
+
case 'kimi':
|
|
648
|
+
case 'droid':
|
|
649
|
+
case 'forge':
|
|
650
|
+
case 'openclaw':
|
|
651
|
+
case 'codex':
|
|
652
|
+
case 'grok':
|
|
653
|
+
case 'opencode':
|
|
654
|
+
case 'hermes':
|
|
655
|
+
return true;
|
|
656
|
+
default:
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Serialize MCP servers into an agent-specific config file.
|
|
662
|
+
*
|
|
663
|
+
* `mode: 'overwrite'` replaces the whole MCP section (used for tool-managed
|
|
664
|
+
* version-home configs). `mode: 'merge'` updates/adds the provided server
|
|
665
|
+
* entries while preserving existing entries (used for project-level configs
|
|
666
|
+
* that users may hand-edit or populate via agent CLI commands).
|
|
667
|
+
*/
|
|
668
|
+
export function writeMcpConfig(agentId, configPath, servers, mode = 'overwrite') {
|
|
669
|
+
if (servers.length === 0) {
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
switch (agentId) {
|
|
673
|
+
case 'claude':
|
|
674
|
+
case 'cursor':
|
|
675
|
+
case 'gemini':
|
|
676
|
+
case 'kimi':
|
|
677
|
+
case 'droid':
|
|
678
|
+
case 'forge': {
|
|
679
|
+
let config = {};
|
|
680
|
+
if (fs.existsSync(configPath)) {
|
|
681
|
+
try {
|
|
682
|
+
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
683
|
+
}
|
|
684
|
+
catch {
|
|
685
|
+
config = {};
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
const mcpServers = mode === 'merge' && config.mcpServers && typeof config.mcpServers === 'object'
|
|
689
|
+
? { ...config.mcpServers }
|
|
690
|
+
: {};
|
|
691
|
+
for (const server of servers) {
|
|
692
|
+
if (server.transport === 'stdio') {
|
|
693
|
+
mcpServers[server.name] = {
|
|
694
|
+
command: server.command,
|
|
695
|
+
args: server.args || [],
|
|
696
|
+
env: server.env || {},
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
else {
|
|
700
|
+
mcpServers[server.name] = {
|
|
701
|
+
url: server.url,
|
|
702
|
+
...(server.headers && { headers: server.headers }),
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
config.mcpServers = mcpServers;
|
|
707
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
708
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
709
|
+
break;
|
|
710
|
+
}
|
|
711
|
+
case 'openclaw': {
|
|
712
|
+
let config = {};
|
|
713
|
+
if (fs.existsSync(configPath)) {
|
|
714
|
+
try {
|
|
715
|
+
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
716
|
+
}
|
|
717
|
+
catch {
|
|
718
|
+
config = {};
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
if (!config.mcp || typeof config.mcp !== 'object') {
|
|
722
|
+
config.mcp = {};
|
|
723
|
+
}
|
|
724
|
+
const mcp = config.mcp;
|
|
725
|
+
const mcpServers = mode === 'merge' && mcp.servers && typeof mcp.servers === 'object'
|
|
726
|
+
? { ...mcp.servers }
|
|
727
|
+
: {};
|
|
728
|
+
for (const server of servers) {
|
|
729
|
+
if (server.transport === 'stdio') {
|
|
730
|
+
mcpServers[server.name] = {
|
|
731
|
+
command: server.command,
|
|
732
|
+
args: server.args || [],
|
|
733
|
+
env: server.env || {},
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
else {
|
|
737
|
+
mcpServers[server.name] = {
|
|
738
|
+
url: server.url,
|
|
739
|
+
transport: server.transport,
|
|
740
|
+
...(server.headers && { headers: server.headers }),
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
mcp.servers = mcpServers;
|
|
745
|
+
config.mcp = mcp;
|
|
746
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
747
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
748
|
+
break;
|
|
749
|
+
}
|
|
750
|
+
case 'codex':
|
|
751
|
+
case 'grok': {
|
|
752
|
+
let config = {};
|
|
753
|
+
if (fs.existsSync(configPath)) {
|
|
754
|
+
try {
|
|
755
|
+
config = TOML.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
756
|
+
}
|
|
757
|
+
catch {
|
|
758
|
+
config = {};
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
const mcpServers = mode === 'merge' && config.mcp_servers && typeof config.mcp_servers === 'object'
|
|
762
|
+
? { ...config.mcp_servers }
|
|
763
|
+
: {};
|
|
764
|
+
for (const server of servers) {
|
|
765
|
+
if (server.transport === 'stdio') {
|
|
766
|
+
mcpServers[server.name] = {
|
|
767
|
+
command: server.command,
|
|
768
|
+
args: server.args || [],
|
|
769
|
+
...(server.env && { env: server.env }),
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
mcpServers[server.name] = {
|
|
774
|
+
url: server.url,
|
|
775
|
+
...(server.headers && { headers: server.headers }),
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
config.mcp_servers = mcpServers;
|
|
780
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
781
|
+
fs.writeFileSync(configPath, TOML.stringify(config), 'utf-8');
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
784
|
+
case 'opencode': {
|
|
785
|
+
let config = {};
|
|
786
|
+
if (fs.existsSync(configPath)) {
|
|
787
|
+
try {
|
|
788
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
789
|
+
const jsonContent = content.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '');
|
|
790
|
+
config = JSON.parse(jsonContent);
|
|
791
|
+
}
|
|
792
|
+
catch {
|
|
793
|
+
config = {};
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
const mcp = mode === 'merge' && config.mcp && typeof config.mcp === 'object'
|
|
797
|
+
? { ...config.mcp }
|
|
798
|
+
: {};
|
|
799
|
+
for (const server of servers) {
|
|
800
|
+
if (server.transport === 'stdio') {
|
|
801
|
+
const commandArray = [server.command, ...(server.args || [])];
|
|
802
|
+
mcp[server.name] = {
|
|
803
|
+
type: 'local',
|
|
804
|
+
command: commandArray,
|
|
805
|
+
...(server.env && { env: server.env }),
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
mcp[server.name] = {
|
|
810
|
+
type: 'remote',
|
|
811
|
+
url: server.url,
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
config.mcp = mcp;
|
|
816
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
817
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
818
|
+
break;
|
|
819
|
+
}
|
|
820
|
+
case 'hermes': {
|
|
821
|
+
let config = {};
|
|
822
|
+
if (fs.existsSync(configPath)) {
|
|
823
|
+
try {
|
|
824
|
+
const parsed = yaml.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
825
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
826
|
+
config = parsed;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
catch {
|
|
830
|
+
config = {};
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
const mcpServers = mode === 'merge' && config.mcp_servers && typeof config.mcp_servers === 'object' && !Array.isArray(config.mcp_servers)
|
|
834
|
+
? { ...config.mcp_servers }
|
|
835
|
+
: {};
|
|
836
|
+
for (const server of servers) {
|
|
837
|
+
if (server.transport === 'stdio') {
|
|
838
|
+
mcpServers[server.name] = {
|
|
839
|
+
command: server.command,
|
|
840
|
+
args: server.args || [],
|
|
841
|
+
...(server.env && { env: server.env }),
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
else {
|
|
845
|
+
mcpServers[server.name] = {
|
|
846
|
+
url: server.url,
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
config.mcp_servers = mcpServers;
|
|
851
|
+
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
852
|
+
fs.writeFileSync(configPath, yaml.stringify(config), 'utf-8');
|
|
853
|
+
break;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
637
857
|
/**
|
|
638
858
|
* Install MCP servers to an agent.
|
|
639
859
|
* For Claude/Codex: uses CLI commands (claude mcp add, codex mcp add)
|
|
@@ -658,47 +878,92 @@ export function installMcpServers(agentId, version, versionHome, mcpNames, optio
|
|
|
658
878
|
binaryPath += '.cmd';
|
|
659
879
|
}
|
|
660
880
|
for (const server of servers) {
|
|
881
|
+
let handled = false;
|
|
661
882
|
try {
|
|
662
883
|
if (agentId === 'claude') {
|
|
663
884
|
installMcpViaClaude(binaryPath, server, versionHome);
|
|
664
|
-
|
|
885
|
+
handled = true;
|
|
665
886
|
}
|
|
666
887
|
else if (agentId === 'codex') {
|
|
667
888
|
installMcpViaCodex(binaryPath, server, versionHome);
|
|
668
|
-
|
|
889
|
+
handled = true;
|
|
669
890
|
}
|
|
670
891
|
else if (agentId === 'gemini') {
|
|
671
892
|
installMcpToGeminiConfig(server, versionHome);
|
|
672
|
-
|
|
893
|
+
handled = true;
|
|
673
894
|
}
|
|
674
895
|
else if (agentId === 'cursor') {
|
|
675
896
|
installMcpToCursorConfig(server, versionHome);
|
|
676
|
-
|
|
897
|
+
handled = true;
|
|
677
898
|
}
|
|
678
899
|
else if (agentId === 'opencode') {
|
|
679
900
|
installMcpToOpenCodeConfig(server, versionHome);
|
|
680
|
-
|
|
901
|
+
handled = true;
|
|
902
|
+
}
|
|
903
|
+
else if (agentId === 'openclaw') {
|
|
904
|
+
// OpenClaw has no install CLI; write the JSON config directly.
|
|
905
|
+
// Use merge because this loop runs once per server.
|
|
906
|
+
const userConfigPath = getMcpConfigPathForHome(agentId, versionHome);
|
|
907
|
+
const writableServer = {
|
|
908
|
+
name: server.config.name,
|
|
909
|
+
transport: server.config.transport,
|
|
910
|
+
command: server.config.command,
|
|
911
|
+
args: server.config.args,
|
|
912
|
+
env: server.config.env,
|
|
913
|
+
url: server.config.url,
|
|
914
|
+
};
|
|
915
|
+
writeMcpConfig(agentId, userConfigPath, [writableServer], 'merge');
|
|
916
|
+
handled = true;
|
|
681
917
|
}
|
|
682
918
|
else if (agentId === 'grok') {
|
|
683
|
-
// Grok
|
|
684
|
-
//
|
|
685
|
-
//
|
|
686
|
-
|
|
919
|
+
// Grok has no working `grok mcp add` CLI, so write the TOML config
|
|
920
|
+
// directly into the version-home directory for all scopes.
|
|
921
|
+
// Use merge because this loop runs once per server.
|
|
922
|
+
const userConfigPath = getMcpConfigPathForHome(agentId, versionHome);
|
|
923
|
+
const writableServer = {
|
|
924
|
+
name: server.config.name,
|
|
925
|
+
transport: server.config.transport,
|
|
926
|
+
command: server.config.command,
|
|
927
|
+
args: server.config.args,
|
|
928
|
+
env: server.config.env,
|
|
929
|
+
url: server.config.url,
|
|
930
|
+
};
|
|
931
|
+
writeMcpConfig(agentId, userConfigPath, [writableServer], 'merge');
|
|
932
|
+
handled = true;
|
|
687
933
|
}
|
|
688
934
|
else if (agentId === 'kimi') {
|
|
689
935
|
installMcpToKimiConfig(server, versionHome);
|
|
690
|
-
|
|
936
|
+
handled = true;
|
|
691
937
|
}
|
|
692
938
|
else if (agentId === 'droid') {
|
|
693
939
|
installMcpToFactoryConfig(server, versionHome);
|
|
694
|
-
|
|
940
|
+
handled = true;
|
|
695
941
|
}
|
|
696
942
|
else if (agentId === 'hermes') {
|
|
697
943
|
installMcpToHermesConfig(server, versionHome);
|
|
698
|
-
|
|
944
|
+
handled = true;
|
|
699
945
|
}
|
|
700
946
|
else if (agentId === 'forge') {
|
|
701
947
|
installMcpToForgeConfig(server, versionHome);
|
|
948
|
+
handled = true;
|
|
949
|
+
}
|
|
950
|
+
// Project-layer servers also get merged into the agent's project-level
|
|
951
|
+
// config (e.g., .mcp.json, .codex/config.toml) so the CLI discovers them
|
|
952
|
+
// when run inside the repo.
|
|
953
|
+
if (server.scope === 'project' && options.cwd && writeMcpConfigSupportsAgent(agentId)) {
|
|
954
|
+
const projectConfigPath = getProjectMcpConfigPath(agentId, options.cwd);
|
|
955
|
+
const writableServer = {
|
|
956
|
+
name: server.config.name,
|
|
957
|
+
transport: server.config.transport,
|
|
958
|
+
command: server.config.command,
|
|
959
|
+
args: server.config.args,
|
|
960
|
+
env: server.config.env,
|
|
961
|
+
url: server.config.url,
|
|
962
|
+
};
|
|
963
|
+
writeMcpConfig(agentId, projectConfigPath, [writableServer], 'merge');
|
|
964
|
+
handled = true;
|
|
965
|
+
}
|
|
966
|
+
if (handled) {
|
|
702
967
|
applied.push(server.name);
|
|
703
968
|
}
|
|
704
969
|
}
|
|
Binary file
|