A simple command-line utility for calling AdCP agents directly without writing code. Features protocol auto-detection and agent alias management for quick access.
npm install -g @adcp/sdkAfter global installation, the adcp command will be available system-wide.
npm install @adcp/sdkThen use via npx:
npx adcp [arguments...]# Save agent with alias
adcp --save-auth test https://test-agent.adcontextprotocol.org
# Prompts for protocol (optional) and auth token (optional)
# Now use the alias
adcp test get_products '{"brief":"coffee brands"}'Protocol auto-detection - no need to specify mcp or a2a:
# List available tools
adcp https://test-agent.adcontextprotocol.org
# Call a tool
adcp https://agent.example.com get_products '{"brief":"coffee brands"}'adcp <alias|url> [tool-name] [payload] [options]
- alias|url: Saved agent alias (e.g.,
test) or full URL to agent endpoint - tool-name: Name of the AdCP tool/task to call (omit to list available tools)
- payload: JSON payload for the tool (default:
{})- Inline JSON:
'{"brief":"text"}' - File path:
@payload.json - Stdin:
-
- Inline JSON:
--protocol PROTO: Force protocol:mcpora2a(default: auto-detect)--auth TOKEN: Authentication token for the agent--wait: Wait for async/webhook responses (requires ngrok or --local)--local: Use local webhook without ngrok (for local agents only)--timeout MS: Webhook timeout in milliseconds (default: 300000 = 5min)--help, -h: Show help message--json: Output raw JSON response (default: pretty print)--debug: Show debug information
--save-auth <alias> [url] [protocol]: Save agent configuration--list-agents: List all saved agents--remove-agent <alias>: Remove saved agent configuration--show-config: Show config file location
# Save agents
adcp --save-auth test https://test-agent.adcontextprotocol.org
adcp --save-auth prod https://prod-agent.example.com
# List saved agents
adcp --list-agents
# Use aliases
adcp test
adcp test get_products '{"brief":"coffee brands"}'
adcp prod create_media_buy @payload.jsonDiscover what an agent can do (no tool name = list tools):
# Auto-detect protocol
adcp https://test-agent.adcontextprotocol.org
adcp test
# Explicit protocol (if needed)
adcp mcp https://agent.example.com/mcp
adcp a2a https://agent.example.comExample output:
🔍 Auto-detecting protocol...
✓ Detected protocol: MCP
📋 Agent Information
Name: CLI Agent
Protocol: MCP
URL: https://agent.example.com/mcp
Available Tools (14):
1. get_products
Get available products matching the brief
2. create_media_buy
Create a media buy with the specified parameters
3. list_creative_formats
List all available creative formats
...
# With alias (auto-detect)
adcp test get_products '{"brief":"coffee subscription service"}'
# With URL (auto-detect)
adcp https://agent.example.com get_products '{"brief":"coffee brands"}'
# Force specific protocol
adcp https://agent.example.com get_products '{"brief":"coffee brands"}' --protocol mcp
adcp test list_authorized_properties --protocol a2a# 1. Saved in agent config (recommended)
adcp --save-auth prod https://prod-agent.com
# Prompts for token securely
adcp prod get_products '{"brief":"..."}'
# 2. Explicit flag (overrides saved config)
adcp test get_products '{"brief":"..."}' --auth your_token_here
# 3. Environment variable (fallback)
export ADCP_AUTH_TOKEN=your_token
adcp https://agent.example.com get_products '{"brief":"..."}'
# 4. HTTP Basic (gateway-fronted agents — Apigee, Kong, AWS API GW)
adcp --save-auth gw https://gw.example.com/mcp --auth 'USER:PASS' --auth-scheme basic
# See docs/guides/BASIC-AUTH.md for the gateway pattern, the auth_token-
# suppression invariant, and a copyable wire-trace verification test.Create a payload file:
{
"brief": "Eco-friendly products for millennials",
"brand_manifest": {"promoted_offering": "Sustainable consumer goods"},
"budget": 50000
}Then call:
# With alias
adcp test get_products @payload.json
# With URL
adcp https://agent.example.com get_products @payload.jsonecho '{"brief":"travel packages"}' | adcp test get_products -adcp mcp https://agent.example.com/mcp create_media_buy '{
"brief": "Summer campaign",
"packages": [
{
"format_ids": [{"agent_url": "https://creative.example.com", "id": "banner_300x250"}],
"impressions": 100000
}
]
}' --auth $TOKENadcp mcp https://agent.example.com/mcp get_products '{"brief":"test"}' --debugOutput includes:
- Configuration details
- Request/response timing
- Full error stack traces
# Get raw JSON for parsing
adcp mcp https://agent.example.com/mcp get_products '{"brief":"test"}' --json > output.json
# Use with jq
adcp mcp https://agent.example.com/mcp get_products '{"brief":"test"}' --json | jq '.products[0].name'The CLI includes two higher-level evaluation flows on top of the existing scenario runner.
Runs all applicable capability tracks against an agent and reports the full picture instead of stopping at the first failure.
Note:
adcp complystill works as a deprecated alias foradcp storyboard runbut will be removed in v5.
# Run all applicable tracks
adcp storyboard run myagent
# Target a specific bundle or storyboard
adcp storyboard run myagent --storyboards creative-template
# Limit to a subset of tracks
adcp storyboard run myagent --tracks core,products,media_buy
# Pin the compliance cache/spec line used for storyboard resolution
adcp storyboard run myagent --compliance-version 3.0.12
# Recommended for CI: --json for machine-readable output + --strict-flags
# so stale flags fail the build instead of passing advisory warnings.
adcp storyboard run https://agent.example.com/mcp --auth "$ADCP_AUTH_TOKEN" --json --strict-flagsAvailable tracks:
coreproductsmedia_buycreativereportinggovernancesignalssiaudiences
Useful flags:
--storyboards ID,...: Run specific storyboard or bundle IDs instead of capability-driven selection--tracks core,products,...: Restrict the run to specific tracks--compliance-version VERSION: Select the compliance cache/spec line, for example3.0.12or3.1.0-beta.7; use the same flag withstoryboard list,show, andstepwhen reproducing a pinned run--compliance-dir PATH: Use a specific compliance cache directory, mainly for local protocol/cache development--brief TEXT: Override the default sample discovery brief--dry-run: Preview steps without executing--json: Emit machine-readable output for automation--strict-flags: Exit non-zero if any removed flag (e.g.--platform-type, removed in 5.1) is passed — recommended for CI--oauth: Complete the browser OAuth flow inline when the saved alias has no valid tokens (MCP only — requires a saved alias)
Removed in 5.1:
--platform-type/--list-platform-types/--storyboardsoptions. Agent selection is now driven byget_adcp_capabilities(supported_protocols+specialisms). Use--storyboardsabove to target a specific bundle.
Storyboard runs reuse OAuth tokens saved under an alias (see ~/.adcp/agents.json). Two supported flows:
# 1. Save tokens once, then run any number of storyboard assessments
adcp --save-auth spotify-agent https://agents.scope3.com/spotify --oauth
adcp storyboard run spotify-agent
# 2. Save the alias without auth, then let the storyboard command drive the flow
adcp --save-auth spotify-agent https://agents.scope3.com/spotify --no-auth
adcp storyboard run spotify-agent --oauthThe first time storyboard run sees --oauth on an alias without valid tokens, it opens a browser, completes the PKCE flow, and persists the tokens to the alias. Subsequent runs reuse the cached tokens (auto-refreshing via the stored refresh_token). Static --auth TOKEN tokens are unaffected and still work the same way.
CI / headless environments. The browser flow requires a local machine. For CI, save tokens once locally (adcp --save-auth <alias> <url> --oauth), copy ~/.adcp/agents.json into the CI runner's home directory (or mount it as a secret), and run adcp storyboard run <alias> without --oauth — the stored refresh_token auto-refreshes on 401. Passing --oauth with a raw URL under --json exits with { "error": "oauth_requires_alias" } and code 2 so pipelines fail fast instead of hanging on a browser prompt that will never arrive.
Set a default authentication token:
export ADCP_AUTH_TOKEN="your_token_here"
adcp mcp https://agent.example.com/mcp get_products '{"brief":"test"}'The --auth flag overrides this environment variable.
Enable debug mode by default:
export ADCP_DEBUG=true
adcp mcp https://agent.example.com/mcp get_products '{"brief":"test"}'The CLI can automatically handle async agent responses using ngrok to create temporary webhook endpoints.
First, install ngrok:
# Mac
brew install ngrok
# Windows
choco install ngrok
# Linux
# Download from https://ngrok.com/downloadUse the --wait flag to wait for async responses from remote agents:
adcp mcp https://agent.example.com/mcp create_media_buy @payload.json --auth $TOKEN --waitWhat happens:
- CLI starts a local webhook server
- ngrok creates a public tunnel to your local server
- CLI calls the agent with the ngrok webhook URL
- If the agent returns
submittedorworkingstatus, CLI waits for webhook - Agent sends response to webhook when ready
- CLI displays the final response and cleans up
Use --wait --local for local development without ngrok:
adcp mcp http://localhost:3000/mcp create_media_buy @payload.json --wait --localPerfect for:
- Testing with local agent servers
- Development without internet
- No ngrok account needed
- Faster setup (no tunnel creation)
Example output:
🌐 Webhook endpoint ready
URL: https://abc123.ngrok.io
Timeout: 300s
📤 Task submitted, waiting for async response...
⏳ Waiting for async response...
✅ Response received after 45.2s
✅ ASYNC RESPONSE RECEIVED
Response:
{
"status": "approved",
"media_buy_id": "mb_12345",
...
}
--wait: Enable webhook waiting (requires ngrok or--local)--local: Use local webhook without ngrok (for local agents only)--timeout MS: Set webhook timeout in milliseconds (default: 300000 = 5 minutes)--debug: Show detailed webhook setup and progress
Remote agent with ngrok:
# Create payload file
cat > media-buy.json <<EOF
{
"brief": "Summer campaign",
"packages": [{
"format_ids": [{"agent_url": "...", "id": "banner_300x250"}],
"impressions": 100000
}]
}
EOF
# Submit and wait for approval
adcp mcp https://agent.example.com/mcp create_media_buy @media-buy.json \
--auth $TOKEN \
--wait \
--timeout 600000Local agent without ngrok:
# Start your local agent first
# cd my-agent && npm start
# Then submit request
adcp mcp http://localhost:3000/mcp create_media_buy @media-buy.json \
--wait \
--local \
--timeout 600000"ngrok not found":
- Make sure ngrok is installed and in your PATH
- Run
which ngrokto verify installation
"Webhook timeout":
- Agent took longer than timeout to respond
- Increase timeout with
--timeout 600000(10 minutes) - Check agent status independently
ngrok connection issues:
- Check your internet connection
- Free ngrok accounts have rate limits
- Consider upgrading to ngrok paid plan for production use
0: Success1: General error (network issues, invalid JSON, etc.)2: Invalid arguments (wrong protocol, missing required args)3: Agent error (task failed, authentication failed, webhook timeout)
#!/bin/bash
AGENT_URL="https://agent.example.com/mcp"
AUTH_TOKEN="your_token"
# Discover products
products=$(adcp mcp "$AGENT_URL" get_products '{
"brief": "Summer fashion campaign",
"promoted_offering": "Sustainable clothing"
}' --auth "$AUTH_TOKEN" --json)
# Check if successful
if [ $? -eq 0 ]; then
echo "Found products:"
echo "$products" | jq '.products[] | .name'
else
echo "Failed to get products"
exit 1
fiimport { execSync } from 'child_process';
try {
const result = execSync(
`adcp mcp https://agent.example.com/mcp get_products '{"brief":"test"}' --json`,
{ encoding: 'utf-8' }
);
const data = JSON.parse(result);
console.log('Products:', data.products);
} catch (error) {
console.error('CLI failed:', error.message);
}Common AdCP tools you can call:
get_products- Discover advertising productslist_creative_formats- List available creative formatscreate_media_buy- Create a new media buyupdate_media_buy- Update an existing media buysync_creatives- Sync creative assetslist_creatives- List creative assetsget_media_buy_delivery- Get delivery informationlist_authorized_properties- List authorized propertiesprovide_performance_feedback- Provide campaign feedbackget_signals- Get audience signalsactivate_signal- Activate audience signals
Make sure the library is built:
npm run build:libCheck that:
- Your token is valid and not expired
- The agent URL is correct
- The agent supports the protocol you specified
Ensure your JSON is properly escaped:
# Good - single quotes around JSON
adcp mcp https://agent.example.com/mcp get_products '{"brief":"test"}'
# Bad - unescaped quotes
adcp mcp https://agent.example.com/mcp get_products {"brief":"test"}Or use a file:
adcp mcp https://agent.example.com/mcp get_products @payload.json# Discover products, extract first product ID, create media buy
product_id=$(adcp mcp https://agent.example.com/mcp get_products '{"brief":"test"}' --json | jq -r '.products[0].id')
adcp mcp https://agent.example.com/mcp create_media_buy "{
\"product_id\": \"$product_id\",
\"impressions\": 100000
}" --auth $TOKENif ! adcp mcp https://agent.example.com/mcp get_products '{"brief":"test"}' 2>/dev/null; then
echo "First agent failed, trying backup..."
adcp a2a https://backup-agent.example.com get_products '{"brief":"test"}'
fiadcp mcp https://agent.example.com/mcp get_products '{"brief":"coffee"}' --auth $TOKENimport { AdCPClient } from '@adcp/sdk';
const client = new AdCPClient({
id: 'agent',
name: 'Agent',
agent_uri: 'https://agent.example.com/mcp',
protocol: 'mcp',
auth_token_env: process.env.TOKEN
});
const result = await client.getProducts({
brief: 'coffee'
});The CLI is perfect for:
- Quick testing and exploration
- Shell scripts and automation
- CI/CD pipelines
- One-off API calls
The library is better for:
- Complex multi-agent workflows
- Conversation management
- Input handlers and clarifications
- Production applications
- CLI Help:
adcp --help - Library Docs: https://github.com/adcontextprotocol/adcp-client
- Issues: https://github.com/adcontextprotocol/adcp-client/issues
- Email: maintainers@adcontextprotocol.org