mcpick 0.0.21 → 0.0.23

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 (48) hide show
  1. package/CHANGELOG.md +30 -5
  2. package/README.md +150 -127
  3. package/dist/add-LJQa2my2.js +164 -0
  4. package/dist/add-json-TEdYweZ5.js +95 -0
  5. package/dist/{backup-DSDhHI5f.js → backup-kyS5IVIr.js} +4 -4
  6. package/dist/{cache-D6kd7qE8.js → cache-DTfzTsEE.js} +3 -3
  7. package/dist/cli-By-0nYNQ.js +112 -0
  8. package/dist/clients-qMozizys.js +30 -0
  9. package/dist/{clone-DYKPEsar.js → clone-BVhYjRGO.js} +5 -6
  10. package/dist/{config-DijVdEFn.js → config-DzMmTJYL.js} +2 -2
  11. package/dist/{dev-DRJRNp7y.js → dev-Cst8WkQ-.js} +5 -5
  12. package/dist/disable-BaOs9lrm.js +83 -0
  13. package/dist/enable--3mjSmTq.js +84 -0
  14. package/dist/{get-Bb1eOOIZ.js → get-CjhNWyRj.js} +3 -3
  15. package/dist/{hooks-Bmn7pUZa.js → hooks-DFmxgD0t.js} +3 -4
  16. package/dist/index.js +1929 -297
  17. package/dist/list-D5CkCXpP.js +100 -0
  18. package/dist/{marketplace-DcKk5dc1.js → marketplace-C3EGyIG0.js} +4 -5
  19. package/dist/output-HtT5HCof.js +17 -0
  20. package/dist/{plugin-cache-Bby9Dxm9.js → plugin-cache-BSgB42wa.js} +34 -15
  21. package/dist/{plugins-Dc7DN6R_.js → plugins-Dn2mPFKm.js} +4 -5
  22. package/dist/{profile-CX97sMGp.js → profile-Dq3ORPil.js} +4 -5
  23. package/dist/redact-wBMtzbno.js +88 -0
  24. package/dist/{reload-CYDhkCVZ.js → reload-257iU7Z7.js} +2 -2
  25. package/dist/remove-26XFzkPd.js +87 -0
  26. package/dist/{reset-project-choices-BfRSNN3m.js → reset-project-choices-D2F04LfC.js} +3 -3
  27. package/dist/{restore-DdMfUljI.js → restore-BYYsoNqF.js} +4 -5
  28. package/dist/rollback-CPdaME91.js +55 -0
  29. package/dist/skills-DfWk9mpk.js +216 -0
  30. package/package.json +22 -8
  31. package/.github/copilot-instructions.md +0 -32
  32. package/.github/workflows/ci.yml +0 -26
  33. package/.vscode/settings.json +0 -5
  34. package/dist/add-BDyaBew0.js +0 -113
  35. package/dist/add-json-BjgzdeG-.js +0 -58
  36. package/dist/atomic-write-BqEykHp9.js +0 -26
  37. package/dist/claude-cli-DnmBJrjg.js +0 -445
  38. package/dist/cli-CsFfnWBo.js +0 -84
  39. package/dist/disable-xJXZfUR_.js +0 -39
  40. package/dist/enable-RrpcN6la.js +0 -40
  41. package/dist/hook-state-Di8lUsPr.js +0 -171
  42. package/dist/list-B8YeDWt6.js +0 -64
  43. package/dist/output-BchYq0mR.js +0 -15
  44. package/dist/profile-DkY_lBEm.js +0 -70
  45. package/dist/redact-O35tjnRD.js +0 -26
  46. package/dist/registry-CfUKT7_C.js +0 -92
  47. package/dist/remove-D1owHLhG.js +0 -31
  48. package/dist/settings-DEcWtzLE.js +0 -201
package/CHANGELOG.md CHANGED
@@ -1,25 +1,50 @@
1
1
  # mcpick
2
2
 
3
+ ## 0.0.23
4
+
5
+ ### Patch Changes
6
+
7
+ - 291b1d4: Add config rollback command, scoped Claude removals, author
8
+ metadata, and rollback backup tests.
9
+ - 92a0d0e: Improve marketplace add validation, authentication checks,
10
+ and error messages for GitHub repository access failures.
11
+ - 1d191a5: Add safer config writes, non-Claude client mutation
12
+ commands, shell-free git execution, and adapter tests.
13
+
14
+ ## 0.0.22
15
+
16
+ ### Patch Changes
17
+
18
+ - 55a46c0: chore: remove outdated documentation and refresh README for
19
+ vendor-neutral MCPick architecture and current CLI flows
20
+ - f30675a: Add vendor-neutral skills management, client-first TUI
21
+ refactor, and safer redacted CLI output for agents.
22
+
3
23
  ## 0.0.21
4
24
 
5
25
  ### Patch Changes
6
26
 
7
- - 47e40be: chore: reorder TUI menu and update README for agent-first usage
27
+ - 47e40be: chore: reorder TUI menu and update README for agent-first
28
+ usage
8
29
 
9
30
  ## 0.0.20
10
31
 
11
32
  ### Patch Changes
12
33
 
13
34
  - 00ea930: chore: add unit tests and CI workflow with GitHub Actions
14
- - 37a62e1: feat: auto-show help instead of TUI in non-TTY environments for LLM agents
15
- - fc1db54: fix: replace exec with execFile to eliminate shell injection on all platforms
35
+ - 37a62e1: feat: auto-show help instead of TUI in non-TTY environments
36
+ for LLM agents
37
+ - fc1db54: fix: replace exec with execFile to eliminate shell
38
+ injection on all platforms
16
39
 
17
40
  ## 0.0.19
18
41
 
19
42
  ### Patch Changes
20
43
 
21
- - 5ed618e: Migrate build tooling from tsc/prettier to vite-plus, fix all lint warnings
22
- - 08997dc: feat: rewrite --help for LLM agents with workflow, concepts, and examples sections
44
+ - 5ed618e: Migrate build tooling from tsc/prettier to vite-plus, fix
45
+ all lint warnings
46
+ - 08997dc: feat: rewrite --help for LLM agents with workflow,
47
+ concepts, and examples sections
23
48
 
24
49
  ## 0.0.18
25
50
 
package/README.md CHANGED
@@ -1,187 +1,210 @@
1
- # McPick
1
+ # MCPick
2
2
 
3
3
  [![built with vite+](https://img.shields.io/badge/built%20with-Vite+-646CFF?logo=vite&logoColor=white)](https://viteplus.dev)
4
4
  [![tested with vitest](https://img.shields.io/badge/tested%20with-Vitest-6E9F18?logo=vitest&logoColor=white)](https://vitest.dev)
5
5
 
6
- Claude Code extension manager MCP servers, plugins (skills, hooks,
7
- agents), and marketplaces.
6
+ Vendor-neutral MCP configuration manager with first-class Claude Code
7
+ support.
8
8
 
9
- ## Quick Start
9
+ MCPick helps humans and LLM agents inspect, toggle, and back up MCP
10
+ server configuration across multiple AI clients. Claude Code-specific
11
+ plugins, hooks, marketplaces, and cache commands remain available, but
12
+ they are no longer the core product model.
10
13
 
11
- Use mcpick inline in Claude Code sessions. Tell Claude:
14
+ ## Install
12
15
 
13
- ```
14
- Use npx mcpick to add the marketplace at spences10/claude-code-toolkit
16
+ ```bash
17
+ npm install -g mcpick
18
+ # or run without installing
19
+ npx mcpick --help
15
20
  ```
16
21
 
17
- ```
18
- Use npx mcpick to list my plugins and disable the ones I'm not using
19
- ```
22
+ Requirements:
20
23
 
21
- ```
22
- Use npx mcpick to enable only the mcp-sqlite-tools server
23
- ```
24
+ - Node.js 22+
25
+ - Claude Code is required only for Claude Code-specific commands
26
+ - The external `skills` CLI is used through `npx -y skills@latest` for
27
+ portable skills commands
24
28
 
25
- McPick auto-detects non-TTY environments and shows structured help
26
- instead of launching the interactive TUI — so LLM agents can read
27
- `npx mcpick --help` and figure out the rest.
29
+ ## Agent-first CLI
28
30
 
29
- ## Concepts
31
+ In non-TTY environments, MCPick shows help instead of launching the
32
+ interactive TUI. This makes it safer for prompts like:
30
33
 
31
- Marketplaces contain plugins. Plugins contain skills
32
- (`/slash-commands`), hooks, agents, and MCP servers.
34
+ > “Use mcpick to work out how to enable this MCP server.”
33
35
 
34
- ```
35
- Marketplace → Plugin → Skills, Hooks, Agents, MCP Servers
36
- ```
37
-
38
- ## Common Workflows
39
-
40
- ### Install skills from a marketplace
36
+ Start with:
41
37
 
42
38
  ```bash
43
- # 1. Add the marketplace
44
- npx mcpick marketplace add spences10/claude-code-toolkit
39
+ npx mcpick --help
40
+ npx mcpick clients
41
+ npx mcpick list --json
42
+ ```
45
43
 
46
- # 2. Install a plugin from it
47
- npx mcpick plugins install my-plugin@claude-code-toolkit
44
+ MCPick redacts known secret patterns before printing output. MCP
45
+ configs often contain env vars and authorization headers, so `env` and
46
+ `headers` values are shown as `***` in JSON output.
48
47
 
49
- # 3. Skills are now available as /slash-commands in Claude Code
50
- ```
48
+ ## MCP clients
51
49
 
52
- Marketplace sources can be:
50
+ Supported client adapters:
53
51
 
54
- - `owner/repo` GitHub shorthand
55
- - `https://github.com/owner/repo` full URL
56
- - `./local-path` local directory
52
+ | Client | Scopes | Command examples |
53
+ | --------------------- | -------------------- | ------------------------------------------------- |
54
+ | Claude Code | local, project, user | `mcpick list`, `mcpick enable <server>` |
55
+ | Gemini CLI | project, user | `mcpick list --client gemini-cli --scope project` |
56
+ | VS Code / Copilot | project | `mcpick list --client vscode --scope project` |
57
+ | Cursor | project, user | `mcpick list --client cursor --scope user` |
58
+ | Windsurf | user | `mcpick list --client windsurf --scope user` |
59
+ | OpenCode | project, user | `mcpick list --client opencode --scope project` |
60
+ | Pi via pi-mcp-adapter | project, user | `mcpick list --client pi --scope user` |
57
61
 
58
- ### Toggle MCP servers
62
+ Show known config locations:
59
63
 
60
64
  ```bash
61
- npx mcpick list # List servers and status
62
- npx mcpick enable <server> # Enable a server
63
- npx mcpick disable <server> # Disable a server
64
- npx mcpick add --name <n> ... # Add a new server
65
- npx mcpick remove <server> # Remove a server
65
+ npx mcpick clients
66
+ npx mcpick clients --json
66
67
  ```
67
68
 
68
- ### Manage plugins
69
+ ## MCP server commands
69
70
 
70
71
  ```bash
71
- npx mcpick plugins list # List plugins and status
72
- npx mcpick plugins install <key> # Install from marketplace
73
- npx mcpick plugins uninstall <key> # Remove plugin
74
- npx mcpick plugins update <key> # Update to latest
75
- npx mcpick plugins enable <key> # Enable plugin
76
- npx mcpick plugins disable <key> # Disable plugin
77
- ```
72
+ # List Claude Code registry/status
73
+ npx mcpick list
74
+ npx mcpick list --json
78
75
 
79
- ### Manage marketplaces
76
+ # List another client
77
+ npx mcpick list --client pi --scope user --json
78
+ npx mcpick list --client opencode --scope project
80
79
 
81
- ```bash
82
- npx mcpick marketplace list # List configured marketplaces
83
- npx mcpick marketplace add <src> # Add a marketplace
84
- npx mcpick marketplace remove <n> # Remove a marketplace
85
- npx mcpick marketplace update # Update all marketplaces
80
+ # Claude Code enable/disable
81
+ npx mcpick enable <server> --scope local
82
+ npx mcpick disable <server> --scope local
83
+
84
+ # Add/remove Claude Code server definitions
85
+ npx mcpick add --name <server> --command npx --args "-y,package-name"
86
+ npx mcpick add-json <name> '{"command":"npx","args":["-y","package-name"]}'
87
+ npx mcpick remove <server>
86
88
  ```
87
89
 
88
- ### Manage hooks
90
+ For secret-backed servers, prefer environment variable references and
91
+ secret-safe loading tools. MCPick redacts printed values, but MCP
92
+ client config files may still store secrets in plain text because that
93
+ is how many clients currently load MCP credentials.
89
94
 
90
- ```bash
91
- npx mcpick hooks list # List all hooks
92
- npx mcpick hooks add # Add a settings hook
93
- npx mcpick hooks remove # Remove a hook
94
- ```
95
+ ## Portable skills
95
96
 
96
- ### Plugin cache
97
+ MCPick delegates portable SKILL.md management to the external `skills`
98
+ CLI.
97
99
 
98
100
  ```bash
99
- npx mcpick cache status # Show staleness info
100
- npx mcpick cache clear [key] # Clear plugin cache
101
- npx mcpick cache clean-orphaned # Remove orphaned dirs
102
- npx mcpick cache refresh # Git pull marketplaces
103
- ```
101
+ # List installed skills for a client
102
+ npx mcpick skills list --agent pi --json
104
103
 
105
- ### Profiles
104
+ # See available skills from a source without installing
105
+ npx mcpick skills add spences10/skills --list
106
106
 
107
- Switch between server/plugin configurations instantly:
107
+ # Install one skill
108
+ npx mcpick skills add spences10/skills --agent pi --skill svelte-runes --yes
108
109
 
109
- ```bash
110
- npx mcpick --profile database # Apply a profile
111
- npx mcpick --save-profile mysetup # Save current config
112
- npx mcpick --list-profiles # List profiles
110
+ # Install all skills for a client globally
111
+ npx mcpick skills add spences10/skills --agent opencode --skill '*' --global --yes
112
+
113
+ # Update/remove
114
+ npx mcpick skills update --global --yes
115
+ npx mcpick skills remove svelte-runes --agent pi --yes
113
116
  ```
114
117
 
115
- ### Backups
118
+ ## Claude Code-specific tools
119
+
120
+ These commands wrap Claude Code concepts and are intentionally
121
+ client-specific:
116
122
 
117
123
  ```bash
118
- npx mcpick backup # Create timestamped backup
119
- npx mcpick restore [file] # Restore from backup
124
+ # Plugins
125
+ npx mcpick plugins list
126
+ npx mcpick plugins install <name>@<marketplace>
127
+ npx mcpick plugins enable <name>@<marketplace>
128
+ npx mcpick plugins disable <name>@<marketplace>
129
+
130
+ # Marketplaces
131
+ npx mcpick marketplace list
132
+ npx mcpick marketplace add <source>
133
+ npx mcpick marketplace update
134
+ npx mcpick marketplace remove <name>
135
+
136
+ # Hooks and plugin cache
137
+ npx mcpick hooks list
138
+ npx mcpick cache status
139
+ npx mcpick cache refresh
120
140
  ```
121
141
 
122
- All commands support `--json` for machine-readable output.
142
+ ## Profiles and backups
123
143
 
124
- ## Interactive TUI
144
+ Profiles and backups currently preserve MCP server and Claude Code
145
+ plugin state.
125
146
 
126
- Running `npx mcpick` in a terminal (TTY) launches the interactive
127
- menu for human use:
147
+ ```bash
148
+ npx mcpick --profile database
149
+ npx mcpick --save-profile mysetup
150
+ npx mcpick --list-profiles
128
151
 
129
- ```
130
- ┌ MCPick - Claude Code Extension Manager
131
-
132
- ◆ What would you like to do?
133
- │ ● Enable / Disable MCP servers
134
- │ ○ Manage plugins
135
- │ ○ Manage marketplaces
136
- │ ○ Manage hooks
137
- │ ○ Manage plugin cache
138
- │ ○ Backup config
139
- │ ○ Add MCP server
140
- │ ○ Restore from backup
141
- │ ○ Load profile
142
- │ ○ Save profile
143
- │ ○ Exit
144
-
152
+ npx mcpick backup
153
+ npx mcpick restore [file]
154
+
155
+ # Safe-write rollback backups created before config mutations
156
+ npx mcpick rollback --list
157
+ npx mcpick rollback [file]
145
158
  ```
146
159
 
147
- In non-TTY environments (LLM agents, piped output), mcpick
148
- automatically shows `--help` instead.
160
+ ## Interactive TUI
149
161
 
150
- ## The Problem
162
+ Running `npx mcpick` in a terminal launches the human-facing menu:
151
163
 
152
- Claude Code loads **all** MCP servers at startup. With many servers
153
- configured, `/doctor` shows:
164
+ ```text
165
+ MCPick - MCP Configuration Manager
154
166
 
155
- ```
156
- Context Usage Warnings
157
- └ ⚠ Large MCP tools context (~66,687 tokens > 25,000)
167
+ What would you like to do?
168
+ Enable / Disable MCP servers
169
+ Skills
170
+ Client-specific tools
171
+ Load profile
172
+ Save profile
173
+ Backup config
174
+ Restore from backup
175
+ Exit
158
176
  ```
159
177
 
160
- This means slower startup, wasted context tokens, and cognitive
161
- overload from too many tools. McPick lets you toggle servers on/off so
162
- you only load what you need.
178
+ The primary TUI flow is client-first: choose a client, then toggle its
179
+ MCP servers. Claude Code plugins, hooks, marketplaces, and cache live
180
+ under “Client-specific tools”.
163
181
 
164
- ## Scope Support
182
+ ## Config locations
165
183
 
166
- | Scope | Description | Storage Location |
167
- | ----------- | ---------------------------------- | --------------------------------------------- |
168
- | **Local** | Project-specific servers (default) | `~/.claude.json` → `projects[cwd].mcpServers` |
169
- | **Project** | Shared via `.mcp.json` in repo | `.mcp.json` in project root |
170
- | **User** | Global servers for all projects | `~/.claude.json` → `mcpServers` |
184
+ MCPick reads the standard locations used by each client adapter.
185
+ Common paths include:
171
186
 
172
- ## File Locations
187
+ | Path | Purpose |
188
+ | ------------------------ | ----------------------------------------------- |
189
+ | `~/.claude.json` | Claude Code local/user MCP config |
190
+ | `.mcp.json` | Shared project MCP config |
191
+ | `.gemini/settings.json` | Gemini CLI project config |
192
+ | `.vscode/mcp.json` | VS Code / Copilot project config |
193
+ | `.cursor/mcp.json` | Cursor project config |
194
+ | `opencode.json` | OpenCode project config |
195
+ | `~/.config/mcp/mcp.json` | Shared global MCP config used by pi-mcp-adapter |
196
+ | `.pi/mcp.json` | Pi project override |
173
197
 
174
- | File | Purpose |
175
- | ------------------------------------------ | ---------------------------- |
176
- | `~/.claude.json` | Claude Code configuration |
177
- | `.mcp.json` | Project-specific shared config |
178
- | `~/.claude/mcpick/servers.json` | Server registry |
179
- | `~/.claude/mcpick/backups/` | Configuration backups |
180
- | `~/.claude/mcpick/profiles/` | Saved profiles |
181
- | `~/.claude/plugins/cache/` | Cached plugin files |
182
- | `~/.claude/plugins/marketplaces/` | Marketplace git clones |
198
+ MCPick-owned state lives under `~/.claude/mcpick/` for historical
199
+ compatibility.
183
200
 
184
- ## Requirements
201
+ ## Development
185
202
 
186
- - Node.js 22+
187
- - Claude Code installed and configured
203
+ ```bash
204
+ pnpm install
205
+ pnpm test
206
+ pnpm run check
207
+ pnpm build
208
+ ```
209
+
210
+ See `docs/VENDOR_NEUTRAL_ARCHITECTURE.md` for architecture notes.
@@ -0,0 +1,164 @@
1
+ import { n as validate_mcp_server } from "./validation-xMlbgGCF.js";
2
+ import { A as add_client_server, F as resolve_client_location, M as get_client_adapter, d as add_mcp_via_cli, w as add_server_to_registry } from "./index.js";
3
+ import { n as output, t as error } from "./output-HtT5HCof.js";
4
+ import { defineCommand } from "citty";
5
+ //#region src/cli/commands/add.ts
6
+ var add_default = defineCommand({
7
+ meta: {
8
+ name: "add",
9
+ description: "Add a new MCP server to the registry and enable it"
10
+ },
11
+ args: {
12
+ name: {
13
+ type: "string",
14
+ description: "Server name",
15
+ required: true
16
+ },
17
+ command: {
18
+ type: "string",
19
+ description: "Command to run (for stdio transport)"
20
+ },
21
+ args: {
22
+ type: "string",
23
+ description: "Comma-separated arguments (e.g. \"npx,-y,mcp-sqlite\")"
24
+ },
25
+ url: {
26
+ type: "string",
27
+ description: "URL (for sse or http transport)"
28
+ },
29
+ type: {
30
+ type: "string",
31
+ description: "Transport type: stdio, sse, or http (default: stdio)",
32
+ default: "stdio"
33
+ },
34
+ env: {
35
+ type: "string",
36
+ description: "Environment variables as KEY=val,KEY=val"
37
+ },
38
+ headers: {
39
+ type: "string",
40
+ description: "HTTP headers as KEY=val,KEY=val"
41
+ },
42
+ description: {
43
+ type: "string",
44
+ description: "Server description"
45
+ },
46
+ client: {
47
+ type: "string",
48
+ description: "Client to edit: claude-code, gemini-cli, vscode, cursor, windsurf, opencode, or pi",
49
+ default: "claude-code"
50
+ },
51
+ scope: {
52
+ type: "string",
53
+ description: "Scope: local, project, or user (default: local for Claude Code)"
54
+ },
55
+ location: {
56
+ type: "string",
57
+ description: "Exact config path when a client has multiple matching locations"
58
+ },
59
+ json: {
60
+ type: "boolean",
61
+ description: "Output as JSON",
62
+ default: false
63
+ }
64
+ },
65
+ async run({ args }) {
66
+ const transport = args.type;
67
+ if (![
68
+ "stdio",
69
+ "sse",
70
+ "http"
71
+ ].includes(transport)) error(`Invalid type: ${transport}. Use stdio, sse, or http.`);
72
+ const add_args = args;
73
+ const portable = build_portable_server(add_args, transport);
74
+ if (add_args.client && add_args.client !== "claude-code") {
75
+ await add_to_client(add_args.client, portable, add_args.scope, add_args.location, add_args.json);
76
+ return;
77
+ }
78
+ const scope = add_args.scope || "local";
79
+ if (![
80
+ "local",
81
+ "project",
82
+ "user"
83
+ ].includes(scope)) error(`Invalid scope: ${scope}. Use local, project, or user.`);
84
+ const server_data = {
85
+ name: portable.name,
86
+ ...transport !== "stdio" ? { type: transport } : {},
87
+ ...portable.command ? { command: portable.command } : {},
88
+ ...portable.args ? { args: portable.args } : {},
89
+ ...portable.url ? { url: portable.url } : {},
90
+ ...portable.env ? { env: portable.env } : {},
91
+ ...portable.headers ? { headers: portable.headers } : {},
92
+ ...portable.description ? { description: portable.description } : {}
93
+ };
94
+ let server;
95
+ try {
96
+ server = validate_mcp_server(server_data);
97
+ } catch (err) {
98
+ error(`Invalid server config: ${err instanceof Error ? err.message : "validation failed"}`);
99
+ }
100
+ await add_server_to_registry(server);
101
+ const result = await add_mcp_via_cli(server, scope);
102
+ if (add_args.json) output({
103
+ added: server.name,
104
+ client: "claude-code",
105
+ scope,
106
+ cli: result.success,
107
+ error: result.error
108
+ }, true);
109
+ else if (result.success) console.log(`Added '${server.name}' and enabled (scope: ${scope})`);
110
+ else console.log(`Added '${server.name}' to registry but CLI failed: ${result.error}`);
111
+ }
112
+ });
113
+ function build_portable_server(args, transport) {
114
+ const server = {
115
+ name: args.name,
116
+ transport
117
+ };
118
+ if (transport === "stdio") {
119
+ if (!args.command) error("--command is required for stdio transport");
120
+ server.command = args.command;
121
+ if (args.args) server.args = args.args.split(",");
122
+ } else {
123
+ if (!args.url) error(`--url is required for ${transport} transport`);
124
+ server.url = args.url;
125
+ if (args.headers) server.headers = parse_key_value_pairs(args.headers);
126
+ }
127
+ if (args.env) server.env = parse_key_value_pairs(args.env);
128
+ if (args.description) server.description = args.description;
129
+ return server;
130
+ }
131
+ async function add_to_client(client, server, scope, location_path, json) {
132
+ const adapter = get_client_adapter(client);
133
+ if (!adapter) error(`Invalid client: ${client}. Use claude-code, gemini-cli, vscode, cursor, windsurf, opencode, or pi.`);
134
+ if (scope && ![
135
+ "local",
136
+ "project",
137
+ "user"
138
+ ].includes(scope)) error(`Invalid scope: ${scope}. Use local, project, or user.`);
139
+ try {
140
+ const location = resolve_client_location(adapter, scope, location_path);
141
+ await add_client_server(adapter, location, server);
142
+ if (json) output({
143
+ added: server.name,
144
+ client: adapter.id,
145
+ scope: location.scope,
146
+ location: location.path
147
+ }, true);
148
+ else console.log(`Added '${server.name}' (${adapter.id}:${location.scope})`);
149
+ } catch (err) {
150
+ error(err instanceof Error ? err.message : "Failed to add server");
151
+ }
152
+ }
153
+ function parse_key_value_pairs(input) {
154
+ const result = {};
155
+ for (const pair of input.split(",")) {
156
+ const eq = pair.indexOf("=");
157
+ if (eq > 0) result[pair.substring(0, eq)] = pair.substring(eq + 1);
158
+ }
159
+ return result;
160
+ }
161
+ //#endregion
162
+ export { add_default as default };
163
+
164
+ //# sourceMappingURL=add-LJQa2my2.js.map
@@ -0,0 +1,95 @@
1
+ import { F as resolve_client_location, M as get_client_adapter, _ as mcp_add_json_via_cli, j as add_client_server_config } from "./index.js";
2
+ import { n as output, t as error } from "./output-HtT5HCof.js";
3
+ import { defineCommand } from "citty";
4
+ //#region src/cli/commands/add-json.ts
5
+ var add_json_default = defineCommand({
6
+ meta: {
7
+ name: "add-json",
8
+ description: "Add an MCP server from a JSON configuration string"
9
+ },
10
+ args: {
11
+ name: {
12
+ type: "positional",
13
+ description: "Server name",
14
+ required: true
15
+ },
16
+ config: {
17
+ type: "positional",
18
+ description: "JSON configuration string",
19
+ required: true
20
+ },
21
+ client: {
22
+ type: "string",
23
+ description: "Client to edit: claude-code, gemini-cli, vscode, cursor, windsurf, opencode, or pi",
24
+ default: "claude-code"
25
+ },
26
+ scope: {
27
+ type: "string",
28
+ description: "Scope: local, project, or user (default: local for Claude Code)"
29
+ },
30
+ location: {
31
+ type: "string",
32
+ description: "Exact config path when a client has multiple matching locations"
33
+ },
34
+ json: {
35
+ type: "boolean",
36
+ description: "Output as JSON",
37
+ default: false
38
+ }
39
+ },
40
+ async run({ args }) {
41
+ let parsed;
42
+ try {
43
+ parsed = JSON.parse(args.config);
44
+ } catch {
45
+ error("Invalid JSON configuration. Provide a valid JSON string.");
46
+ }
47
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) error("JSON configuration must be an object.");
48
+ if (args.client && args.client !== "claude-code") {
49
+ await add_json_to_client(args.client, args.name, parsed, args.scope, args.location, args.json);
50
+ return;
51
+ }
52
+ const scope = args.scope || "local";
53
+ if (![
54
+ "local",
55
+ "project",
56
+ "user"
57
+ ].includes(scope)) error(`Invalid scope: ${scope}. Use local, project, or user.`);
58
+ const result = await mcp_add_json_via_cli(args.name, args.config, scope);
59
+ if (args.json) output({
60
+ added: args.name,
61
+ client: "claude-code",
62
+ scope,
63
+ success: result.success,
64
+ error: result.error
65
+ }, true);
66
+ else if (result.success) console.log(`Added '${args.name}' from JSON (scope: ${scope})`);
67
+ else error(result.error || "Unknown error");
68
+ }
69
+ });
70
+ async function add_json_to_client(client, name, config, scope, location_path, json) {
71
+ const adapter = get_client_adapter(client);
72
+ if (!adapter) error(`Invalid client: ${client}. Use claude-code, gemini-cli, vscode, cursor, windsurf, opencode, or pi.`);
73
+ if (scope && ![
74
+ "local",
75
+ "project",
76
+ "user"
77
+ ].includes(scope)) error(`Invalid scope: ${scope}. Use local, project, or user.`);
78
+ try {
79
+ const location = resolve_client_location(adapter, scope, location_path);
80
+ await add_client_server_config(adapter, location, name, config);
81
+ if (json) output({
82
+ added: name,
83
+ client: adapter.id,
84
+ scope: location.scope,
85
+ location: location.path
86
+ }, true);
87
+ else console.log(`Added '${name}' from JSON (${adapter.id}:${location.scope})`);
88
+ } catch (err) {
89
+ error(err instanceof Error ? err.message : "Failed to add server");
90
+ }
91
+ }
92
+ //#endregion
93
+ export { add_json_default as default };
94
+
95
+ //# sourceMappingURL=add-json-TEdYweZ5.js.map
@@ -1,7 +1,7 @@
1
1
  import { m as get_plugin_backup_filename, n as get_backup_filename, r as get_backups_dir, t as ensure_directory_exists } from "./paths-BPISiJi4.js";
2
- import { s as read_claude_config } from "./config-DijVdEFn.js";
3
- import { a as read_claude_settings } from "./settings-DEcWtzLE.js";
4
- import { n as output } from "./output-BchYq0mR.js";
2
+ import { s as read_claude_config } from "./config-DzMmTJYL.js";
3
+ import { V as read_claude_settings } from "./index.js";
4
+ import { n as output } from "./output-HtT5HCof.js";
5
5
  import { readdir, unlink, writeFile } from "node:fs/promises";
6
6
  import { join } from "node:path";
7
7
  import { defineCommand } from "citty";
@@ -61,4 +61,4 @@ var backup_default = defineCommand({
61
61
  //#endregion
62
62
  export { backup_default as default };
63
63
 
64
- //# sourceMappingURL=backup-DSDhHI5f.js.map
64
+ //# sourceMappingURL=backup-kyS5IVIr.js.map