Skip to content

feat(cli): Add dotagents mcp add|remove|list subcommands#24

Merged
gricha merged 1 commit intomainfrom
feat/mcp-cli-subcommands
Feb 19, 2026
Merged

feat(cli): Add dotagents mcp add|remove|list subcommands#24
gricha merged 1 commit intomainfrom
feat/mcp-cli-subcommands

Conversation

@gricha
Copy link
Member

@gricha gricha commented Feb 19, 2026

MCP servers were previously only configurable by hand-editing
agents.toml. This adds dotagents mcp add|remove|list CLI
subcommands matching the ergonomics of dotagents add /
dotagents remove for skills.

Commands:

dotagents mcp add <name> --command <cmd> [--args <a>...] [--env <VAR>...]
dotagents mcp add <name> --url <url> [--header <Key:Value>...] [--env <VAR>...]
dotagents mcp remove <name>
dotagents mcp list [--json]

Changes:

  • New src/cli/commands/mcp.ts with sub-subcommand dispatch for
    add/remove/list, validation, and error handling
  • Refactored removeBlockByNameremoveBlockByHeader in
    src/config/writer.ts to support both [[skills]] and [[mcp]]
    block types (zero behavior change for skills)
  • Added addMcpToConfig / removeMcpFromConfig writer functions
  • Registered mcp in CLI command index
  • Updated CLI docs page and llms.txt
  • 17 new integration tests for the mcp command, 8 new writer tests

Agent transcript: https://claudescope.sentry.dev/share/FwNRv0iBbvB8cTtCO3O-ws_MdOXK4ZqOwDhsG7lep1c

MCP servers were previously only configurable by hand-editing
agents.toml. This adds CLI subcommands matching the ergonomics of
`dotagents add` / `dotagents remove` for skills.

- `mcp add` supports stdio (--command) and HTTP (--url) transports
  with repeatable --args, --header, and --env flags
- `mcp remove` removes a server declaration by name
- `mcp list` shows declared servers with optional --json output
- Refactors internal `removeBlockByName` to parameterized
  `removeBlockByHeader` to support both [[skills]] and [[mcp]] blocks

Co-Authored-By: Claude <noreply@anthropic.com>

Agent transcript: https://claudescope.sentry.dev/share/XcNMOOwdNjMB4tgyLvD_kmWdTcM6ZnsDub9D5Fmk1OI
@vercel
Copy link

vercel bot commented Feb 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dotagents Ready Ready Preview, Comment Feb 19, 2026 7:22am

Request Review

@gricha gricha marked this pull request as ready for review February 19, 2026 07:27
@gricha gricha merged commit 3d203d4 into main Feb 19, 2026
16 checks passed
@gricha gricha deleted the feat/mcp-cli-subcommands branch February 19, 2026 07:32
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.


while (i < lines.length) {
if (lines[i]!.trim() === "[[skills]]") {
if (lines[i]!.trim() === header) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Block removal ignores sub-tables, may corrupt config

Medium Severity

removeBlockByHeader collects block lines only until it hits an empty line or a line starting with [. If smol-toml's stringify serializes the headers record as a TOML sub-table (e.g., [mcp.headers]) rather than an inline table, removeMcpFromConfig would remove only the [[mcp]] header and its direct key-value lines but leave the [mcp.headers] sub-table and its contents behind as orphaned TOML, corrupting the config file. The old removeBlockByName only handled [[skills]] blocks which never had nested objects, so this fragility is newly exposed by reusing it for [[mcp]] blocks that can contain headers.

Additional Locations (1)

Fix in Cursor Fix in Web


while (i < lines.length) {
if (lines[i]!.trim() === "[[skills]]") {
if (lines[i]!.trim() === header) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name-matching regex fails on lines with leading whitespace

Low Severity

In removeBlockByHeader, the nameLine is found via l.trim().startsWith("name") but the regex ^name\s*=\s*"([^"]+)" is applied to the untrimmed original line. If a user hand-edits agents.toml and indents key-value lines under [[mcp]], the leading whitespace causes the ^name anchor to fail, so removeMcpFromConfig silently keeps the block instead of removing it. The old removeBlockByName had this same issue for [[skills]], but by reusing it for the new [[mcp]] path, the bug is newly exposed for MCP blocks.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments