Tools

Tools are executable capabilities that agents can call. CAPA supports two types of tools: MCP tools and command tools.

Tool Types

MCP Tools

Proxy tools from MCP servers:

tools:
  - id: search
    type: mcp
    description: Search the web using Brave Search
    def:
      server: "@brave"
      tool: brave_web_search
{
  "tools": [
    {
      "id": "search",
      "type": "mcp",
      "description": "Search the web using Brave Search",
      "def": {
        "server": "@brave",
        "tool": "brave_web_search"
      }
    }
  ]
}

Reference a server using @server-id and specify which tool from that server to expose.

Qualified Tool Names

When exposed via MCP, each tool receives a qualified name that combines the server ID and tool ID:

  • MCP tools: server_id.tool_id (e.g., brave.search)
  • Command tools: plain tool_id (e.g., greet_user)

In skill requires arrays, reference MCP tools with the @server_id.tool_id format (e.g., @brave.search). Command tools use their plain ID. In the CLI, MCP tools map to capa sh server_id tool_id (e.g., capa sh brave search).

Command Tools

Execute shell commands:

tools:
  - id: greet_user
    type: command
    def:
      run:
        cmd: echo Hello, {name}!
        args:
          - name: name
            type: string
            description: The name to greet
            required: true
{
  "tools": [
    {
      "id": "greet_user",
      "type": "command",
      "def": {
        "run": {
          "cmd": "echo Hello, {name}!",
          "args": [
            {
              "name": "name",
              "type": "string",
              "description": "The name to greet",
              "required": true
            }
          ]
        }
      }
    }
  ]
}

MCP Tool Definition

MCP tools proxy an existing tool from an MCP server. The tool's id should be a short, descriptive name — CAPA automatically qualifies it as server_id.tool_id when exposed via MCP:

# First, define the server
servers:
  - id: filesystem
    type: mcp
    def:
      cmd: npx -y @modelcontextprotocol/server-filesystem
      args:
        - /path/to/directory

# Then, define tools from that server
tools:
  - id: read_file
    type: mcp
    def:
      server: "@filesystem"
      tool: read_file
  
  - id: write_file
    type: mcp
    def:
      server: "@filesystem"
      tool: write_file
{
  "servers": [
    {
      "id": "filesystem",
      "type": "mcp",
      "def": {
        "cmd": "npx -y @modelcontextprotocol/server-filesystem",
        "args": ["/path/to/directory"]
      }
    }
  ],
  "tools": [
    {
      "id": "read_file",
      "type": "mcp",
      "def": {
        "server": "@filesystem",
        "tool": "read_file"
      }
    },
    {
      "id": "write_file",
      "type": "mcp",
      "def": {
        "server": "@filesystem",
        "tool": "write_file"
      }
    }
  ]
}

These tools are exposed to MCP clients as filesystem.read_file and filesystem.write_file. In skill requires, reference them as @filesystem.read_file and @filesystem.write_file.

Command Tool Definition

Command tools execute shell commands with parameters:

tools:
  - id: get_weather
    type: command
    def:
      run:
        cmd: curl "https://wttr.in/{city}?format=%C+%t"
        args:
          - name: city
            type: string
            description: City name
            required: true
{
  "tools": [
    {
      "id": "get_weather",
      "type": "command",
      "def": {
        "run": {
          "cmd": "curl \"https://wttr.in/{city}?format=%C+%t\"",
          "args": [
            {
              "name": "city",
              "type": "string",
              "description": "City name",
              "required": true
            }
          ]
        }
      }
    }
  ]
}

Command Arguments

Each argument in a command tool can have:

  • name: Argument name (used in {name} substitution)
  • type: Argument type (string, number, boolean)
  • description: Description shown to the agent
  • required: Whether the argument is required

Tool Description

Both MCP tools and command tools support an optional top-level description field. This text is shown in capa sh and is used as the tool's description when the schema is sent to MCP clients. For command tools, CAPA falls back to "Command tool: <id>" when the field is absent.

tools:
  - id: find_skills
    type: command
    description: Search the skills.sh ecosystem for reusable agent skills
    def:
      run:
        cmd: npx skills find {query}
        args:
          - name: query
            type: string
            description: Search query
            required: true

  - id: atlassian_search
    type: mcp
    description: Search Jira and Confluence using Rovo Search
    def:
      server: "@atlassian"
      tool: search
{
  "tools": [
    {
      "id": "find_skills",
      "type": "command",
      "description": "Search the skills.sh ecosystem for reusable agent skills",
      "def": {
        "run": {
          "cmd": "npx skills find {query}",
          "args": [
            {
              "name": "query",
              "type": "string",
              "description": "Search query",
              "required": true
            }
          ]
        }
      }
    },
    {
      "id": "atlassian_search",
      "type": "mcp",
      "description": "Search Jira and Confluence using Rovo Search",
      "def": {
        "server": "@atlassian",
        "tool": "search"
      }
    }
  ]
}

Default Arguments

MCP tools support an optional defaults map that provides pre-filled argument values. Parameters with defaults are exposed as optional in the MCP schema and in capa sh --help, so the AI (or CLI user) only needs to supply them when overriding. At call time, caller-supplied values take precedence over defaults.

tools:
  - id: searchIssue
    type: mcp
    description: Search Jira issues
    def:
      server: "@atlassian"
      tool: getJiraIssue
      defaults:
        cloudId: "abc123-def456"
{
  "tools": [
    {
      "id": "searchIssue",
      "type": "mcp",
      "description": "Search Jira issues",
      "def": {
        "server": "@atlassian",
        "tool": "getJiraIssue",
        "defaults": {
          "cloudId": "abc123-def456"
        }
      }
    }
  ]
}

In this example, cloudId is always sent as "abc123-def456" unless the caller explicitly provides a different value. The parameter still appears in the schema (with its default shown) but is no longer required.

This is useful when:

  • A parameter is always the same for a given project (e.g., cloud IDs, workspace names, project keys)
  • You want to simplify the tool interface without losing the ability to override

Grouping Command Tools

Command tools can be nested under a shared parent group in capa sh using the optional group field. Tools that share the same group value are listed together under that group name:

tools:
  - id: deploy_service
    type: command
    group: deploy
    description: Deploy a service to production
    def:
      run:
        cmd: ./deploy.sh {service}
        args:
          - name: service
            type: string
            required: true

  - id: rollback_service
    type: command
    group: deploy
    description: Roll back a service to the previous version
    def:
      run:
        cmd: ./rollback.sh {service}
        args:
          - name: service
            type: string
            required: true
{
  "tools": [
    {
      "id": "deploy_service",
      "type": "command",
      "group": "deploy",
      "description": "Deploy a service to production",
      "def": {
        "run": {
          "cmd": "./deploy.sh {service}",
          "args": [{ "name": "service", "type": "string", "required": true }]
        }
      }
    },
    {
      "id": "rollback_service",
      "type": "command",
      "group": "deploy",
      "description": "Roll back a service to the previous version",
      "def": {
        "run": {
          "cmd": "./rollback.sh {service}",
          "args": [{ "name": "service", "type": "string", "required": true }]
        }
      }
    }
  ]
}

In capa sh this produces:

$ capa sh deploy

deploy - subcommands:

  deploy-service          Deploy a service to production
  rollback-service        Roll back a service to the previous version

Usage: capa sh deploy <subcommand> [--arg val]
       capa sh deploy <subcommand> --help   Show parameter details

Single-subcommand promotion: If only one tool belongs to a group, that tool is shown at the top level directly — the extra nesting is skipped.

Initialization Block

Command tools can have an optional init block that runs once before first use:

tools:
  - id: pandas_query
    type: command
    def:
      init:
        cmd: pip install pandas
      run:
        cmd: python -c "import pandas as pd; df = pd.read_csv('{file}'); print(df.query('{query}'))"
        args:
          - name: file
            type: string
            required: true
          - name: query
            type: string
            required: true
{
  "tools": [
    {
      "id": "pandas_query",
      "type": "command",
      "def": {
        "init": {
          "cmd": "pip install pandas"
        },
        "run": {
          "cmd": "python -c \"import pandas as pd; df = pd.read_csv('{file}'); print(df.query('{query}'))\"",
          "args": [
            {
              "name": "file",
              "type": "string",
              "required": true
            },
            {
              "name": "query",
              "type": "string",
              "required": true
            }
          ]
        }
      }
    }
  ]
}

The init command runs only once, before the first execution of the tool. This is useful for:

  • Installing dependencies
  • Setting up environments
  • Downloading required files

Complete Example

servers:
  - id: brave
    type: mcp
    description: Brave web search
    def:
      cmd: npx -y @modelcontextprotocol/server-brave-search
      env:
        BRAVE_API_KEY: ${BraveApiKey}

tools:
  # MCP tool — exposed as brave.search
  - id: search
    type: mcp
    description: Search the web using Brave Search
    def:
      server: "@brave"
      tool: brave_web_search
  
  # Command tool without init — exposed as hello_world
  - id: hello_world
    type: command
    def:
      run:
        cmd: echo Hello, World!
        args: []
  
  # Command tool with init — exposed as scrape_web
  - id: scrape_web
    type: command
    def:
      init:
        cmd: pip install beautifulsoup4 requests
      run:
        cmd: python -c "import requests; from bs4 import BeautifulSoup; print(BeautifulSoup(requests.get('{url}').text, 'html.parser').get_text())"
        args:
          - name: url
            type: string
            description: URL to scrape
            required: true
{
  "servers": [
    {
      "id": "brave",
      "type": "mcp",
      "description": "Brave web search",
      "def": {
        "cmd": "npx -y @modelcontextprotocol/server-brave-search",
        "env": {
          "BRAVE_API_KEY": "${BraveApiKey}"
        }
      }
    }
  ],
  "tools": [
    {
      "id": "search",
      "type": "mcp",
      "description": "Search the web using Brave Search",
      "def": {
        "server": "@brave",
        "tool": "brave_web_search"
      }
    },
    {
      "id": "hello_world",
      "type": "command",
      "def": {
        "run": {
          "cmd": "echo Hello, World!",
          "args": []
        }
      }
    },
    {
      "id": "scrape_web",
      "type": "command",
      "def": {
        "init": {
          "cmd": "pip install beautifulsoup4 requests"
        },
        "run": {
          "cmd": "python -c \"import requests; from bs4 import BeautifulSoup; print(BeautifulSoup(requests.get('{url}').text, 'html.parser').get_text())\"",
          "args": [
            {
              "name": "url",
              "type": "string",
              "description": "URL to scrape",
              "required": true
            }
          ]
        }
      }
    }
  ]
}

Best Practices

  • Use descriptive IDs: Tool IDs should be short and clear (e.g., search, not s). For MCP tools, the server ID is prepended automatically (e.g., brave.search)
  • Provide good descriptions: Help the agent understand what each tool does
  • Test commands independently: Verify command tools work in your shell first
  • Handle errors: Consider adding error handling to command tools
  • Use init wisely: Only use init for one-time setup, not for every execution

Related Documentation