Skip to content

feat(mcp): approve multiple tools in one invocation - #116

Merged
leet-c1 merged 1 commit into
mainfrom
feat/mcp-tools-approve-batch
Sep 3, 2026
Merged

feat(mcp): approve multiple tools in one invocation#116
leet-c1 merged 1 commit into
mainfrom
feat/mcp-tools-approve-batch

Conversation

@leet-c1

@leet-c1 leet-c1 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Closes ledger item C146.

mcp tools approve took exactly one tool id, so approving a toolset meant one process, token fetch and TLS handshake per tool — the slowest stage of a real MCP setup. It now takes one or more ids.

What changed

  • Use: "approve <tool-id>...", cobra.MinimumNArgs(1) — variadic positional (the id stays positional, scope ids stay flags), so approve id1 id2 id3 --app-id A --connector-id C works.
  • The API has no batch approve (id is in the path, request message is singular), so each id is still its own request. One confirmation line per tool; a failure doesn't stop the rest; the command exits non-zero (classified from the first failure) if any fail.
  • Backward compatible: a single id behaves exactly as before (same output, same error wrapping).

Convention

Extends the id-positional convention rather than moving to a flag: an action applying the same mutation to several instances pluralizes its positional. approve is removed from the single-resource guard test; TestMcpToolsApproveIsMultiIDPositional pins the new contract; CLAUDE.md documents the case.

Validation

Live on a tenant (idempotent re-approval of already-APPROVED tools, zero net change):

  • two ids → two APPROVED confirmations in one run
  • one id → unchanged
  • one real + one bogus id → real approved, bogus reported to stderr, exit 2 (400 classification), other tool still attempted

Two independent reviews (full + delta), no bugs. Batch behavior mutation-proven and shuffle-clean. Gates: build, vet, test, -shuffle=on, golangci-lint (0), gosec (0), gitleaks (clean), govulncheck (clean), go mod tidy clean.

🤖 Generated with Claude Code

`mcp tools approve` took exactly one tool id, so approving a toolset meant one
process, token fetch and TLS handshake per tool. It now takes one or more ids
as variadic positional args and sends one request per id in a single process
(the API has no batch approve — the id is in the path and the request message
is singular). One confirmation line per tool; a failure doesn't stop the rest,
and the command exits non-zero (classified from the first failure) if any fail.
Backward compatible: a single id behaves exactly as before.

The id stays positional (pluralized to <tool-id>...), scope ids stay flags, so
this extends the id-positional convention rather than moving to a flag. The
single-resource guard test excludes approve; TestMcpToolsApproveIsMultiIDPositional
pins the new contract, and CLAUDE.md documents the pluralize-the-positional case.

Live-validated on a tenant: two ids -> two APPROVED confirmations in one run;
one id -> unchanged; one real + one bogus id -> real approved, bogus reported,
exit 2 (400 classification), other tool still attempted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@leet-c1
leet-c1 merged commit 8d03210 into main Sep 3, 2026
2 checks passed
leet-c1 added a commit that referenced this pull request Sep 3, 2026
A full audit of every tracked .md file against the current command/help surface
and recent PRs (#103-#117) found gaps where a shipped change had not reached one
or more docs. No behavioral defects and no branding/identifier leaks were found;
these are documentation-only fixes.

HIGH:
- cmd/agents.md: document the v0.6.0 BREAKING envelope-unwrap in "Reading
  output" — typed `get` prints the resource flat (`.id`, not `.app.id`), naming
  a wrapper key in `--fields` exits 2, and `mcp servers get` has only
  `connectorId`. README already covered this; the agent-facing doc did not.
- README.md: add the `docs search` no-relevance-threshold caveat (#117), which
  had reached help + `docs agents` but not README.
- CHANGELOG.md: merge the duplicated `### Added`/`### Changed` headers in
  [Unreleased] into one block each (Added/Changed/Fixed); all 14 entries
  preserved verbatim.

MED:
- README.md: `policies` step_kinds/baseline_policy_id + the auto-approval jq
  recipe (#103); `mcp servers register --user-id` and the flags settable at
  register time.
- cmd/agents.md: `mcp tools approve` takes multiple ids in one process (#116).
- CLAUDE.md: document the shared repeatable-flag registrar convention (#111).

LOW:
- README.md: `--tool-id` caps (100/32), requestable-connectors non-pagination,
  `entitlements create --resource-type` default CUSTOM, `requests create
  --duration` is Go-style vs the protobuf-duration flags.
- cmd/agents.md + skill: malformed-`--url` rejection (#115).
- CLAUDE.md: negative `--limit`/`--page-size` rejection + page-size clamp.
- .claude/commands/c1i.md: add `auth token`, the ~/.c1i.yaml wrong-tenant
  stderr warning, a pointer to the command groups, and the docs-search caveat.

Every claim verified against `--help` or live behavior; embedded `docs agents`
re-checked to render the new content. Build/vet/test/shuffle/lint/gosec/gitleaks
/govulncheck all clean.

Co-authored-by: leet-c1 <264029741+leet-c1@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant