add-mcp 1.11.0 → 1.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 CHANGED
@@ -50,7 +50,7 @@ MCP servers can be installed to any of these agents:
50
50
 
51
51
  | Agent | `--agent` | Project Path | Global Path |
52
52
  | ---------------------- | -------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------- |
53
- | Antigravity | `antigravity` | - | `~/.gemini/antigravity/mcp_config.json` |
53
+ | Antigravity | `antigravity` | - | `~/.gemini/config/mcp_config.json` (shared by Antigravity, Antigravity IDE, and Antigravity CLI) |
54
54
  | Cline VSCode Extension | `cline` | - | `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` |
55
55
  | Cline CLI | `cline-cli` | - | `~/.cline/data/settings/cline_mcp_settings.json` |
56
56
  | Claude Code | `claude-code` | `.mcp.json` | `~/.claude.json` |
@@ -128,6 +128,12 @@ npx add-mcp https://mcp.example.com/mcp --header "Authorization: Bearer $TOKEN"
128
128
  # (each agent only keeps the fields it supports; others are dropped with a warning)
129
129
  npx add-mcp https://mcp.example.com/mcp --timeout 30000 --scopes "read,write"
130
130
 
131
+ # Auto-approve all tools for agents that support it (Codex, Claude Code)
132
+ npx add-mcp "executor mcp" --name executor -a codex -a claude-code --auto-approve
133
+
134
+ # Auto-approve only selected tools
135
+ npx add-mcp "executor mcp" --name executor -a codex --auto-approve --approve-tool execute
136
+
131
137
  # npm package (runs via npx)
132
138
  npx add-mcp @modelcontextprotocol/server-postgres
133
139
 
@@ -164,21 +170,23 @@ npx add-mcp https://mcp.example.com/mcp -a cursor -y --gitignore
164
170
 
165
171
  ### Options
166
172
 
167
- | Option | Description |
168
- | ------------------------ | ------------------------------------------------------------------------ |
169
- | `-g, --global` | Install to user directory instead of project |
170
- | `-a, --agent <agent>` | Target specific agents (e.g., `cursor`, `claude-code`). Can be repeated. |
171
- | `-t, --transport <type>` | Transport type for remote servers: `http` (default), `sse` |
172
- | `--type <type>` | Alias for `--transport` |
173
- | `-h, --header <header>` | HTTP header for remote servers (repeatable, `Key: Value`) |
174
- | `--env <env>` | Env var for local stdio servers (repeatable, `KEY=VALUE`) |
175
- | `--timeout <ms>` | Request timeout (ms) for remote servers (capability-gated, see below) |
176
- | `--scopes <scopes>` | OAuth scopes for remote servers, comma-separated (capability-gated) |
177
- | `--oauth-scopes <scopes>`| Alias for `--scopes` |
178
- | `-n, --name <name>` | Server name (auto-inferred if not provided) |
179
- | `-y, --yes` | Skip all confirmation prompts |
180
- | `--all` | Install to all agents |
181
- | `--gitignore` | Add generated config files to `.gitignore` |
173
+ | Option | Description |
174
+ | ------------------------- | ------------------------------------------------------------------------ |
175
+ | `-g, --global` | Install to user directory instead of project |
176
+ | `-a, --agent <agent>` | Target specific agents (e.g., `cursor`, `claude-code`). Can be repeated. |
177
+ | `-t, --transport <type>` | Transport type for remote servers: `http` (default), `sse` |
178
+ | `--type <type>` | Alias for `--transport` |
179
+ | `-h, --header <header>` | HTTP header for remote servers (repeatable, `Key: Value`) |
180
+ | `--env <env>` | Env var for local stdio servers (repeatable, `KEY=VALUE`) |
181
+ | `--timeout <ms>` | Request timeout (ms) for remote servers (capability-gated, see below) |
182
+ | `--scopes <scopes>` | OAuth scopes for remote servers, comma-separated (capability-gated) |
183
+ | `--oauth-scopes <scopes>` | Alias for `--scopes` |
184
+ | `--auto-approve` | Auto-approve MCP tool calls for supported agents (Codex, Claude Code) |
185
+ | `--approve-tool <tool>` | Tool to auto-approve with `--auto-approve` (repeatable; defaults to all) |
186
+ | `-n, --name <name>` | Server name (auto-inferred if not provided) |
187
+ | `-y, --yes` | Skip all confirmation prompts |
188
+ | `--all` | Install to all agents |
189
+ | `--gitignore` | Add generated config files to `.gitignore` |
182
190
 
183
191
  #### Capability-gated fields (`--timeout`, `--scopes`)
184
192
 
@@ -186,15 +194,36 @@ Not every MCP client understands every field. `add-mcp` keeps one canonical
186
194
  server config and each agent declares which optional fields it supports, mapping
187
195
  them into that client's native shape:
188
196
 
189
- | Field | Flag | Supported by | Mapped to |
190
- | ---------- | ---------------- | --------------------------- | ---------------------------------- |
191
- | Timeout | `--timeout` | Claude Code, Gemini CLI | `timeout` (milliseconds) |
192
- | OAuth scopes | `--scopes` | Cursor, Gemini CLI | Cursor `auth.scopes`, Gemini `oauth.scopes` |
197
+ | Field | Flag | Supported by | Mapped to |
198
+ | ------------------ | ----------------------------------- | ----------------------- | -------------------------------------------------------- |
199
+ | Timeout | `--timeout` | Claude Code, Gemini CLI | `timeout` (milliseconds) |
200
+ | OAuth scopes | `--scopes` | Cursor, Gemini CLI | Cursor `auth.scopes`, Gemini `oauth.scopes` |
201
+ | Tool auto-approval | `--auto-approve` / `--approve-tool` | Codex, Claude Code | Codex approval modes; Claude Code permission allow rules |
193
202
 
194
203
  When you target an agent that does not support a field, `add-mcp` drops it from
195
204
  that agent's config and prints a warning (e.g. _"request timeout is not
196
205
  supported by VS Code; dropped from that config."_). Other agents still receive
197
- it. Both flags apply to remote servers only.
206
+ it. `--timeout` and `--scopes` apply to remote servers only; `--auto-approve`
207
+ applies to both remote and local servers.
208
+
209
+ #### Auto-approving tool calls (`--auto-approve`)
210
+
211
+ `--auto-approve` preconfigures agent-level approval so the agent doesn't prompt
212
+ before each MCP tool call — useful for servers that already gate actions
213
+ internally. Use `--approve-tool <name>` (repeatable) to approve only specific
214
+ tools; without it, all tools are approved.
215
+
216
+ - **Codex** — writes approval modes into `config.toml`: per-tool
217
+ `tools.<name>.approval_mode = "approve"`, or `default_tools_approval_mode = "approve"` for all tools.
218
+ - **Claude Code** — writes permission allow rules to a separate settings file
219
+ (`.claude/settings.local.json` for project installs, `~/.claude/settings.json`
220
+ for global), e.g. `mcp__<server>__<tool>`, or `mcp__<server>` for all tools.
221
+ The MCP server entry itself stays clean.
222
+
223
+ > Note: Claude Code's all-tools rule (`mcp__<server>`) follows the documented
224
+ > format, but a known Claude Code bug ([#34739](https://github.com/anthropics/claude-code/issues/34739))
225
+ > can still prompt for non-fully-qualified MCP rules. Listing tools explicitly
226
+ > with `--approve-tool` is the most reliable path there.
198
227
 
199
228
  ### Transport Types
200
229
 
@@ -232,14 +261,16 @@ npx add-mcp find github --all --gitignore
232
261
 
233
262
  ### Options
234
263
 
235
- | Option | Description |
236
- | --------------------- | ------------------------------------------------------------------------ |
237
- | `-g, --global` | Install to user directory instead of project |
238
- | `-a, --agent <agent>` | Target specific agents (e.g., `cursor`, `claude-code`). Can be repeated. |
239
- | `-n, --name <name>` | Server name override (defaults to the selected catalog entry name) |
240
- | `-y, --yes` | Skip confirmation prompts |
241
- | `--all` | Install to all agents |
242
- | `--gitignore` | Add generated config files to `.gitignore` |
264
+ | Option | Description |
265
+ | ----------------------- | ------------------------------------------------------------------------ |
266
+ | `-g, --global` | Install to user directory instead of project |
267
+ | `-a, --agent <agent>` | Target specific agents (e.g., `cursor`, `claude-code`). Can be repeated. |
268
+ | `-n, --name <name>` | Server name override (defaults to the selected catalog entry name) |
269
+ | `-y, --yes` | Skip confirmation prompts |
270
+ | `--auto-approve` | Auto-approve MCP tool calls for supported agents (Codex, Claude Code) |
271
+ | `--approve-tool <tool>` | Tool to auto-approve with `--auto-approve` (repeatable; defaults to all) |
272
+ | `--all` | Install to all agents |
273
+ | `--gitignore` | Add generated config files to `.gitignore` |
243
274
 
244
275
  Transport for `find`/`search` is inferred from registry metadata. The CLI prefers HTTP remotes when available and only falls back to SSE when HTTP is not available for the selected install context.
245
276
 
@@ -133,7 +133,7 @@ var { appSupport, vscodePath, gooseConfigPath } = getPlatformPaths();
133
133
  var antigravityConfigPath = join2(
134
134
  home,
135
135
  ".gemini",
136
- "antigravity",
136
+ "config",
137
137
  "mcp_config.json"
138
138
  );
139
139
  var clineCliConfigPath = join2(
@@ -250,6 +250,17 @@ function transformOpenCodeConfig(_serverName, config) {
250
250
  environment: config.env || {}
251
251
  };
252
252
  }
253
+ function applyCodexApproval(target, autoApproveTools) {
254
+ if (!autoApproveTools) return target;
255
+ if (autoApproveTools.length === 0) {
256
+ target.default_tools_approval_mode = "approve";
257
+ return target;
258
+ }
259
+ target.tools = Object.fromEntries(
260
+ autoApproveTools.map((tool) => [tool, { approval_mode: "approve" }])
261
+ );
262
+ return target;
263
+ }
253
264
  function transformCodexConfig(_serverName, config) {
254
265
  if (config.url) {
255
266
  const remoteConfig = {
@@ -259,13 +270,16 @@ function transformCodexConfig(_serverName, config) {
259
270
  if (config.headers && Object.keys(config.headers).length > 0) {
260
271
  remoteConfig.http_headers = config.headers;
261
272
  }
262
- return remoteConfig;
273
+ return applyCodexApproval(remoteConfig, config.autoApproveTools);
263
274
  }
264
- return {
265
- command: config.command,
266
- args: config.args || [],
267
- env: config.env
268
- };
275
+ return applyCodexApproval(
276
+ {
277
+ command: config.command,
278
+ args: config.args || [],
279
+ env: config.env
280
+ },
281
+ config.autoApproveTools
282
+ );
269
283
  }
270
284
  function transformCursorConfig(_serverName, config) {
271
285
  if (config.url) {
@@ -375,7 +389,7 @@ var agents = {
375
389
  supportedTransports: ["stdio", "http", "sse"],
376
390
  supportedFields: [],
377
391
  detectGlobalInstall: async () => {
378
- return existsSync(join2(home, ".gemini"));
392
+ return existsSync(join2(home, ".gemini", "config"));
379
393
  },
380
394
  transformConfig: transformAntigravityConfig
381
395
  },
@@ -418,7 +432,7 @@ var agents = {
418
432
  configKey: "mcpServers",
419
433
  format: "json",
420
434
  supportedTransports: ["stdio", "http", "sse"],
421
- supportedFields: ["timeout"],
435
+ supportedFields: ["timeout", "autoApprove"],
422
436
  detectGlobalInstall: async () => {
423
437
  return existsSync(join2(home, ".claude"));
424
438
  },
@@ -452,7 +466,7 @@ var agents = {
452
466
  configKey: "mcp_servers",
453
467
  format: "toml",
454
468
  supportedTransports: ["stdio", "http", "sse"],
455
- supportedFields: [],
469
+ supportedFields: ["autoApprove"],
456
470
  detectGlobalInstall: async () => {
457
471
  return existsSync(join2(home, ".codex"));
458
472
  },
@@ -1181,6 +1195,15 @@ var OPTIONAL_FIELD_SPECS = {
1181
1195
  clear: (config) => {
1182
1196
  delete config.oauthScopes;
1183
1197
  }
1198
+ },
1199
+ autoApprove: {
1200
+ label: "tool auto-approval",
1201
+ // An empty array is meaningful ("approve all tools"), so presence alone
1202
+ // counts as set — unlike scopes where an empty list means "nothing".
1203
+ isSet: (config) => Array.isArray(config.autoApproveTools),
1204
+ clear: (config) => {
1205
+ delete config.autoApproveTools;
1206
+ }
1184
1207
  }
1185
1208
  };
1186
1209
  var ALL_OPTIONAL_FIELDS = Object.keys(
@@ -1193,6 +1216,7 @@ function applyFieldSupport(config, supportedFields) {
1193
1216
  const supported = new Set(supportedFields);
1194
1217
  const copy = { ...config };
1195
1218
  if (copy.oauthScopes) copy.oauthScopes = [...copy.oauthScopes];
1219
+ if (copy.autoApproveTools) copy.autoApproveTools = [...copy.autoApproveTools];
1196
1220
  const dropped = [];
1197
1221
  for (const field of ALL_OPTIONAL_FIELDS) {
1198
1222
  const spec = OPTIONAL_FIELD_SPECS[field];
@@ -1206,7 +1230,9 @@ function applyFieldSupport(config, supportedFields) {
1206
1230
 
1207
1231
  // src/installer.ts
1208
1232
  import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
1233
+ import { homedir as homedir3 } from "os";
1209
1234
  import { join as join3, dirname as dirname6, isAbsolute, relative, sep } from "path";
1235
+ var home2 = homedir3();
1210
1236
  function buildServerConfig(parsed, options = {}) {
1211
1237
  if (parsed.type === "remote") {
1212
1238
  const config2 = {
@@ -1222,6 +1248,9 @@ function buildServerConfig(parsed, options = {}) {
1222
1248
  if (options.oauthScopes && options.oauthScopes.length > 0) {
1223
1249
  config2.oauthScopes = options.oauthScopes;
1224
1250
  }
1251
+ if (options.autoApproveTools) {
1252
+ config2.autoApproveTools = options.autoApproveTools;
1253
+ }
1225
1254
  return config2;
1226
1255
  }
1227
1256
  if (parsed.type === "command") {
@@ -1243,6 +1272,9 @@ function buildServerConfig(parsed, options = {}) {
1243
1272
  if (options.env && Object.keys(options.env).length > 0) {
1244
1273
  config2.env = options.env;
1245
1274
  }
1275
+ if (options.autoApproveTools) {
1276
+ config2.autoApproveTools = options.autoApproveTools;
1277
+ }
1246
1278
  return config2;
1247
1279
  }
1248
1280
  const config = {
@@ -1252,8 +1284,66 @@ function buildServerConfig(parsed, options = {}) {
1252
1284
  if (options.env && Object.keys(options.env).length > 0) {
1253
1285
  config.env = options.env;
1254
1286
  }
1287
+ if (options.autoApproveTools) {
1288
+ config.autoApproveTools = options.autoApproveTools;
1289
+ }
1255
1290
  return config;
1256
1291
  }
1292
+ function readJsonObject(filePath) {
1293
+ if (!existsSync5(filePath)) {
1294
+ return {};
1295
+ }
1296
+ const parsed = JSON.parse(readFileSync4(filePath, "utf-8"));
1297
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
1298
+ }
1299
+ function writeJsonObject(filePath, value) {
1300
+ const dir = dirname6(filePath);
1301
+ if (!existsSync5(dir)) {
1302
+ mkdirSync4(dir, { recursive: true });
1303
+ }
1304
+ writeFileSync4(filePath, `${JSON.stringify(value, null, 2)}
1305
+ `, "utf-8");
1306
+ }
1307
+ function addUniqueStrings(existing, additions) {
1308
+ const values = Array.isArray(existing) ? existing.filter((value) => typeof value === "string") : [];
1309
+ for (const addition of additions) {
1310
+ if (!values.includes(addition)) {
1311
+ values.push(addition);
1312
+ }
1313
+ }
1314
+ return values;
1315
+ }
1316
+ function claudeAutoApproveRules(serverName, tools) {
1317
+ if (tools.length === 0) {
1318
+ return [`mcp__${serverName}`];
1319
+ }
1320
+ return tools.map((tool) => `mcp__${serverName}__${tool}`);
1321
+ }
1322
+ function getClaudeCodeSettingsPath(options = {}) {
1323
+ const local = Boolean(options.local);
1324
+ const cwd = options.cwd || process.cwd();
1325
+ return local ? join3(cwd, ".claude", "settings.local.json") : join3(home2, ".claude", "settings.json");
1326
+ }
1327
+ function installClaudeCodeAutoApproval(serverName, tools, options = {}) {
1328
+ const settingsPath = getClaudeCodeSettingsPath(options);
1329
+ try {
1330
+ const settings = readJsonObject(settingsPath);
1331
+ const permissions = settings.permissions && typeof settings.permissions === "object" && !Array.isArray(settings.permissions) ? settings.permissions : {};
1332
+ permissions.allow = addUniqueStrings(
1333
+ permissions.allow,
1334
+ claudeAutoApproveRules(serverName, tools)
1335
+ );
1336
+ settings.permissions = permissions;
1337
+ writeJsonObject(settingsPath, settings);
1338
+ return { success: true, path: settingsPath };
1339
+ } catch (error) {
1340
+ return {
1341
+ success: false,
1342
+ path: settingsPath,
1343
+ error: error instanceof Error ? error.message : "Unknown error"
1344
+ };
1345
+ }
1346
+ }
1257
1347
  function updateGitignoreWithPaths(paths, options = {}) {
1258
1348
  const cwd = options.cwd || process.cwd();
1259
1349
  const gitignorePath = join3(cwd, ".gitignore");
@@ -1324,10 +1414,27 @@ function installServerForAgent(serverName, serverConfig, agentType, options = {}
1324
1414
  const configKey = getConfigKey(agent, options);
1325
1415
  const config = buildConfigWithKey(configKey, serverName, transformedConfig);
1326
1416
  writeConfig2(configPath, config, agent.format, configKey);
1417
+ const extraPaths = [];
1418
+ if (agentType === "claude-code" && gatedConfig.autoApproveTools) {
1419
+ const approval = installClaudeCodeAutoApproval(
1420
+ serverName,
1421
+ gatedConfig.autoApproveTools,
1422
+ options
1423
+ );
1424
+ if (!approval.success) {
1425
+ return {
1426
+ success: false,
1427
+ path: approval.path,
1428
+ error: approval.error
1429
+ };
1430
+ }
1431
+ extraPaths.push(approval.path);
1432
+ }
1327
1433
  return {
1328
1434
  success: true,
1329
1435
  path: configPath,
1330
- ...dropped.length > 0 ? { droppedFields: dropped } : {}
1436
+ ...dropped.length > 0 ? { droppedFields: dropped } : {},
1437
+ ...extraPaths.length > 0 ? { extraPaths } : {}
1331
1438
  };
1332
1439
  } catch (error) {
1333
1440
  return {
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  selectAgentsInteractive,
24
24
  supportsProjectConfig,
25
25
  updateGitignoreWithPaths
26
- } from "./chunk-2OCTBM45.js";
26
+ } from "./chunk-IPCKQUBH.js";
27
27
 
28
28
  // src/index.ts
29
29
  import { program } from "commander";
@@ -783,7 +783,7 @@ async function runFind(query, options) {
783
783
  // package.json
784
784
  var package_default = {
785
785
  name: "add-mcp",
786
- version: "1.11.0",
786
+ version: "1.12.0",
787
787
  description: "Add MCP servers to your favorite coding agents with a single command.",
788
788
  author: "Andre Landgraf <andre@neon.tech>",
789
789
  license: "Apache-2.0",
@@ -974,6 +974,25 @@ function extractSubcommandOptionsFromArgv() {
974
974
  result.gitignore = true;
975
975
  continue;
976
976
  }
977
+ if (arg === "--auto-approve") {
978
+ result.autoApprove = true;
979
+ continue;
980
+ }
981
+ if (arg === "--approve-tool") {
982
+ const tools = result.approveTool ? [...result.approveTool] : [];
983
+ let j = i + 1;
984
+ while (j < argv.length) {
985
+ const value = argv[j];
986
+ if (!value || value.startsWith("-")) break;
987
+ tools.push(value);
988
+ j += 1;
989
+ }
990
+ if (tools.length > 0) {
991
+ result.approveTool = tools;
992
+ }
993
+ i = j - 1;
994
+ continue;
995
+ }
977
996
  if ((arg === "-h" || arg === "--header") && argv[i + 1]) {
978
997
  const headers = result.header ? [...result.header] : [];
979
998
  headers.push(argv[i + 1]);
@@ -1126,7 +1145,15 @@ program.name("add-mcp").description(
1126
1145
  ).option(
1127
1146
  "--scopes <scopes>",
1128
1147
  "OAuth scopes to request for remote servers (comma-separated). Only applied to agents that support it (e.g. Cursor, Gemini CLI); dropped with a warning elsewhere."
1129
- ).option("--oauth-scopes <scopes>", "Alias for --scopes").option("-y, --yes", "Skip confirmation prompts").option("--all", "Install to all agents").option("--gitignore", "Add generated project config files to .gitignore").action(async (target, options) => {
1148
+ ).option("--oauth-scopes <scopes>", "Alias for --scopes").option(
1149
+ "--auto-approve",
1150
+ "Auto-approve MCP tool calls for agents that support it (Codex, Claude Code). Dropped with a warning for other agents."
1151
+ ).option(
1152
+ "--approve-tool <tool>",
1153
+ "Tool name to auto-approve when --auto-approve is set (repeatable; defaults to all tools)",
1154
+ collect,
1155
+ []
1156
+ ).option("-y, --yes", "Skip confirmation prompts").option("--all", "Install to all agents").option("--gitignore", "Add generated project config files to .gitignore").action(async (target, options) => {
1130
1157
  await main(target, options);
1131
1158
  });
1132
1159
  program.command("list-agents").description("List all supported coding agents").action(() => {
@@ -1172,7 +1199,15 @@ program.command("find [keyword]").description(
1172
1199
  ).option("-a, --agent <agent>", "Specify agents to install to", collect, []).option(
1173
1200
  "-n, --name <name>",
1174
1201
  "Server name override (defaults to catalog entry name)"
1175
- ).option("-y, --yes", "Skip confirmation prompts").option("--all", "Install to all agents").option("--gitignore", "Add generated project config files to .gitignore").action(
1202
+ ).option("-y, --yes", "Skip confirmation prompts").option(
1203
+ "--auto-approve",
1204
+ "Auto-approve MCP tool calls for agents that support it (Codex, Claude Code)"
1205
+ ).option(
1206
+ "--approve-tool <tool>",
1207
+ "Tool name to auto-approve when --auto-approve is set (repeatable; defaults to all tools)",
1208
+ collect,
1209
+ []
1210
+ ).option("--all", "Install to all agents").option("--gitignore", "Add generated project config files to .gitignore").action(
1176
1211
  async (keyword, options) => {
1177
1212
  await runFindCommand(keyword, options);
1178
1213
  }
@@ -1183,7 +1218,15 @@ program.command("search [keyword]").description("Alias for find").option(
1183
1218
  ).option("-a, --agent <agent>", "Specify agents to install to", collect, []).option(
1184
1219
  "-n, --name <name>",
1185
1220
  "Server name override (defaults to catalog entry name)"
1186
- ).option("-y, --yes", "Skip confirmation prompts").option("--all", "Install to all agents").option("--gitignore", "Add generated project config files to .gitignore").action(
1221
+ ).option("-y, --yes", "Skip confirmation prompts").option(
1222
+ "--auto-approve",
1223
+ "Auto-approve MCP tool calls for agents that support it (Codex, Claude Code)"
1224
+ ).option(
1225
+ "--approve-tool <tool>",
1226
+ "Tool name to auto-approve when --auto-approve is set (repeatable; defaults to all tools)",
1227
+ collect,
1228
+ []
1229
+ ).option("--all", "Install to all agents").option("--gitignore", "Add generated project config files to .gitignore").action(
1187
1230
  async (keyword, options) => {
1188
1231
  await runFindCommand(keyword, options);
1189
1232
  }
@@ -1829,13 +1872,16 @@ async function main(target, options) {
1829
1872
  p2.log.warn("--scopes is only used for remote URLs, ignoring");
1830
1873
  }
1831
1874
  }
1875
+ const approveTools = [...new Set(options.approveTool ?? [])];
1876
+ const autoApproveTools = options.autoApprove || approveTools.length > 0 ? approveTools : void 0;
1832
1877
  const serverConfig = buildServerConfig(parsed, {
1833
1878
  transport: resolvedTransport,
1834
1879
  headers: headersForConfig && Object.keys(headersForConfig).length > 0 ? headersForConfig : void 0,
1835
1880
  env: envForConfig && Object.keys(envForConfig).length > 0 ? envForConfig : void 0,
1836
1881
  args: argsForConfig && argsForConfig.length > 0 ? argsForConfig : void 0,
1837
1882
  timeout: resolvedTimeout,
1838
- oauthScopes: resolvedScopes
1883
+ oauthScopes: resolvedScopes,
1884
+ autoApproveTools
1839
1885
  });
1840
1886
  let targetAgents;
1841
1887
  const allAgentTypes = getAgentTypes();
@@ -2031,6 +2077,11 @@ async function main(target, options) {
2031
2077
  const summaryLines = [];
2032
2078
  summaryLines.push(`${chalk.cyan("Server:")} ${serverName}`);
2033
2079
  summaryLines.push(`${chalk.cyan("Type:")} ${sourceType}`);
2080
+ if (autoApproveTools) {
2081
+ summaryLines.push(
2082
+ `${chalk.cyan("Auto-approve:")} ${autoApproveTools.length === 0 ? "All tools" : autoApproveTools.join(", ")}`
2083
+ );
2084
+ }
2034
2085
  const localAgents = targetAgents.filter(
2035
2086
  (a) => agentRouting.get(a) === "local"
2036
2087
  );
@@ -2083,6 +2134,11 @@ async function main(target, options) {
2083
2134
  resultLines.push(
2084
2135
  `${chalk.green("\u2713")} ${agent.displayName}: ${chalk.dim(shortPath)}`
2085
2136
  );
2137
+ for (const extraPath of result.extraPaths ?? []) {
2138
+ resultLines.push(
2139
+ ` ${chalk.dim("\u21B3 permissions:")} ${chalk.dim(shortenPath(extraPath))}`
2140
+ );
2141
+ }
2086
2142
  }
2087
2143
  p2.note(
2088
2144
  resultLines.join("\n"),
@@ -2123,7 +2179,10 @@ async function main(target, options) {
2123
2179
  "--gitignore is only supported for project-scoped installations; ignoring."
2124
2180
  );
2125
2181
  } else if (options.gitignore) {
2126
- const successfulPaths = successful.map(([_, result]) => result.path);
2182
+ const successfulPaths = successful.flatMap(([_, result]) => [
2183
+ result.path,
2184
+ ...result.extraPaths ?? []
2185
+ ]);
2127
2186
  const gitignoreUpdate = updateGitignoreWithPaths(successfulPaths);
2128
2187
  if (gitignoreUpdate.added.length > 0) {
2129
2188
  p2.log.info(
package/dist/lib.d.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  * before its transform runs, guaranteeing that only known fields are ever
9
9
  * written to a client config.
10
10
  */
11
- type OptionalField = "timeout" | "scopes";
11
+ type OptionalField = "timeout" | "scopes" | "autoApprove";
12
12
 
13
13
  type AgentType = "antigravity" | "cline" | "cline-cli" | "claude-code" | "claude-desktop" | "codex" | "cursor" | "gemini-cli" | "goose" | "github-copilot-cli" | "mcporter" | "opencode" | "vscode" | "windsurf" | "zed";
14
14
  type ConfigFormat = "json" | "yaml" | "toml";
@@ -79,6 +79,15 @@ interface McpServerConfig {
79
79
  * their own native shape (e.g. Cursor `auth.scopes`, Gemini `oauth.scopes`).
80
80
  */
81
81
  oauthScopes?: string[];
82
+ /**
83
+ * Tools to auto-approve (skip the agent's per-call approval prompt). An empty
84
+ * array means "all tools". This is an install directive rather than a literal
85
+ * server-config key: capability-gated via `"autoApprove"` in `supportedFields`
86
+ * and each supporting agent applies it in its own way (e.g. Codex emits
87
+ * approval modes in its config; Claude Code writes permission allow rules to a
88
+ * separate settings file). It is never written into a server entry verbatim.
89
+ */
90
+ autoApproveTools?: string[];
82
91
  }
83
92
 
84
93
  interface InstallOptions {
@@ -96,6 +105,12 @@ interface InstallResult {
96
105
  * does not support them. Empty/undefined when nothing was dropped.
97
106
  */
98
107
  droppedFields?: OptionalField[];
108
+ /**
109
+ * Additional files written beyond the main config (e.g. a Claude Code
110
+ * permissions settings file for auto-approval). Surfaced so the CLI can
111
+ * report them and include them in `--gitignore`.
112
+ */
113
+ extraPaths?: string[];
99
114
  }
100
115
 
101
116
  declare const agents: Record<AgentType, AgentConfig>;
package/dist/lib.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  listInstalledServers,
11
11
  readConfig,
12
12
  removeServerFromConfig
13
- } from "./chunk-2OCTBM45.js";
13
+ } from "./chunk-IPCKQUBH.js";
14
14
 
15
15
  // src/lib.ts
16
16
  import { existsSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "add-mcp",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Add MCP servers to your favorite coding agents with a single command.",
5
5
  "author": "Andre Landgraf <andre@neon.tech>",
6
6
  "license": "Apache-2.0",