Build token-efficient AI agents that discover and call MCP tools dynamically
AI agents that can execute code can use the tool CLI to discover and call MCP tools. The agent runs CLI commands to find tools, inspect method signatures, and make calls. This works with any language that can spawn a subprocess. The agent might write Python, JavaScript, Go, or shell scripts.
This page explains how to use the CLI's concise mode, search for tools, inspect methods, and chain calls together. For a deeper dive into the philosophy behind code mode and how it dramatically reduces context usage, see our blog post on Building Context-Efficient Agents.
The CLI has a -c flag that outputs machine-parseable text. Concise mode removes decorative formatting, colors, and extra whitespace. The output is structured for easy parsing.
tool list -c
tool grep issue -c
tool info github -m list_issues -c
tool call github -m list_issues -p owner="anthropics" -p repo="claude-code" -cAdd -H to suppress header lines:
tool list -c -HThe tool grep command searches through all installed tools. It matches against method names, descriptions, and schema contents.
tool grep issue -cOutput:
#path value
['github'].tools.list_issues list_issues
['github'].tools.list_issues.description "List issues in a repository. Args: owner, repo, state..."
['github'].tools.create_issue create_issue
['github'].tools.create_issue.description "Create a new issue. Args: owner, repo, title, body..."
['github'].tools.get_issue get_issue
['github'].tools.get_issue.description "Get details of a specific issue. Args: owner, repo, issue_number..."Each line shows a path into the tool's schema and the value at that path. The descriptions often include parameter names, which can be enough to make a call without further inspection.
To get the full signature of a specific method, use tool info with the -m flag:
tool info github -m list_issues -cOutput:
github:list_issues(owner*: string, repo*: string, state?: string) -> {issues*: {number*: integer, title*: string, state*: string, user*: string}[]}Parameters marked with * are required. Parameters marked with ? are optional. The return type shows the structure of the response.
To see all methods for a tool:
tool info github --tools -cRunning tool info without -m dumps every method signature. For tools with many methods, this produces a lot of output. Use -m to target specific methods when possible.
The tool call command executes a method:
tool call github -m list_issues -p owner="anthropics" -p repo="claude-code" -cThe -p flag passes parameters. You can use multiple -p flags.
Output is JSON:
{"issues":[{"number":42,"title":"Add support for streaming","state":"open","user":"octocat"}]}In a shell, use jq to extract fields:
tool call github -m list_issues -p owner="anthropics" -p repo="claude-code" -c | jq -r '.issues[0].title'In Python, use subprocess and json.loads(). In JavaScript, use child_process.execSync() and JSON.parse().
When one call depends on another, the agent can write a script that does both. This avoids multiple round trips through the agent's reasoning process.
ISSUES=$(tool call github -m list_issues -p owner="anthropics" -p repo="claude-code" -p state="open" -c)
ISSUE_NUM=$(echo "$ISSUES" | jq -r '.issues[0].number')
tool call github -m get_issue -p owner="anthropics" -p repo="claude-code" -p issue_number="$ISSUE_NUM" -cimport subprocess
import json
issues = json.loads(subprocess.check_output([
"tool", "call", "github", "-m", "list_issues",
"-p", "owner=anthropics", "-p", "repo=claude-code",
"-p", "state=open", "-c"
]))
issue = json.loads(subprocess.check_output([
"tool", "call", "github", "-m", "get_issue",
"-p", "owner=anthropics", "-p", "repo=claude-code",
"-p", f"issue_number={issues['issues'][0]['number']}", "-c"
]))
print(json.dumps(issue, indent=2))The agent writes the script, runs it, and gets the final result without stopping to process intermediate output.
Here is how an agent might handle "Show me the latest open issue on anthropics/claude-code."
First, search for issue-related tools:
tool grep issue -cThe results show github has list_issues and get_issue methods. The descriptions include parameter names.
If needed, check the exact signatures:
tool info github -m list_issues -c
tool info github -m get_issue -cThen write a script that lists issues and gets details for the first one. The agent runs one grep command to discover capabilities and one script to get the answer.
Running tool list -c followed by tool info on each tool loads as much schema information as preloading would. Use grep to find what you need.
Running tool info <tool> -c without -m dumps all method signatures. Always specify the method when you can.
Making separate calls when they could be chained creates unnecessary round trips. If call B depends on call A, write a script that does both.
This approach works well when tools have many methods and you only need a few, when the relevant tools vary by request, or when you have a tight token budget.
For agents that use the same small set of tools throughout a conversation, preloading schemas might be simpler. The tradeoff depends on how many tools you have and how predictable the user's needs are.