A2A Agent Management Guide¶
This guide covers registering, managing, and using A2A agents through the MCP Gateway Registry using the mcp-gateway-m2m service account.
Quick Start¶
Service Account: mcp-gateway-m2m¶
All agent management operations use the mcp-gateway-m2m Keycloak M2M service account:
# Register an agent (uses mcp-gateway-m2m token automatically)
uv run python cli/agent_mgmt.py register cli/examples/code_reviewer_agent.json
# List agents
uv run python cli/agent_mgmt.py list
# Get agent details
uv run python cli/agent_mgmt.py get /code-reviewer
# Test agent (verify registry metadata and endpoint accessibility)
uv run python cli/agent_mgmt.py test /code-reviewer
# Test all agents
uv run python cli/agent_mgmt.py test-all
# Search agents (semantic search by capability)
uv run python cli/agent_mgmt.py search "code review agent"
# Update agent
uv run python cli/agent_mgmt.py update /code-reviewer cli/examples/code_reviewer_agent.json
# Toggle agent enabled/disabled status
uv run python cli/agent_mgmt.py toggle /code-reviewer true # Enable
uv run python cli/agent_mgmt.py toggle /code-reviewer false # Disable
# Delete agent
uv run python cli/agent_mgmt.py delete /code-reviewer
Token Details: - File: .oauth-tokens/ingress.json (auto-loaded by CLI) - Generated by: ./credentials-provider/generate_creds.sh - Keycloak Groups: mcp-servers-unrestricted, a2a-agent-admin - Permissions: Full agent management (register, modify, delete, list)
Service Account Details¶
Account Identity¶
| Property | Value |
|---|---|
| Keycloak Client ID | mcp-gateway-m2m |
| Service Account User | service-account-mcp-gateway-m2m |
| Token File | .oauth-tokens/ingress.json |
| Token Generator | ./credentials-provider/generate_creds.sh |
Keycloak Groups (Auto-Assigned)¶
mcp-servers-unrestricted- Full access to unrestricted MCP serversa2a-agent-admin- Full A2A agent management permissions
Permissions¶
- ✅ Register agents
- ✅ Modify agents
- ✅ Delete agents
- ✅ List agents
- ✅ Manage MCP server groups
Authentication Flow¶
1. CLI loads token from .oauth-tokens/ingress.json
└─ JWT contains: groups: ["mcp-servers-unrestricted", "a2a-agent-admin"]
2. POST /api/agents/register with Authorization: Bearer <token>
3. Nginx /api/ location intercepts request
└─ Calls auth-server /validate endpoint
4. Auth-server validates JWT and maps groups to scopes
└─ Returns: X-Scopes: a2a-agent-admin
5. Nginx forwards request to FastAPI with X-Scopes header
6. FastAPI reads X-Scopes and grants permissions
└─ Detects a2a-agent-admin → allows agent registration
7. Agent is registered successfully
Agent Examples¶
Register Code Reviewer Agent¶
Available examples: - code_reviewer_agent.json - Code quality analysis - test_automation_agent.json - Test case generation and execution - data_analysis_agent.json - Statistical analysis and visualization - security_analyzer_agent.json - Vulnerability detection - documentation_agent.json - API documentation generation - devops_deployment_agent.json - Infrastructure automation
Create Custom Agent¶
-
Copy example file:
-
Edit JSON with your agent details:
{ "name": "My Agent", "path": "/my-agent", "description": "What my agent does", "url": "http://my-domain.com/agents/my-agent", "version": "1.0.0", "protocol_version": "1.0", "visibility": "public", "trust_level": "community", "tags": ["custom"], "security_schemes": { "bearer": { "type": "bearer" } } } -
Register:
Verification¶
Check Token Has Correct Groups¶
python3 << 'EOF'
import json, base64
with open('.oauth-tokens/ingress.json') as f:
token = json.load(f)['access_token']
payload = token.split('.')[1]
payload += '='*(4-len(payload)%4)
decoded = json.loads(base64.urlsafe_b64decode(payload))
print("Service Account:", decoded.get('client_id'))
print("Groups:", decoded.get('groups'))
print("Expected groups: ['mcp-servers-unrestricted', 'a2a-agent-admin']")
EOF
Expected output:
Service Account: mcp-gateway-m2m
Groups: ['mcp-servers-unrestricted', 'a2a-agent-admin']
Expected groups: ['mcp-servers-unrestricted', 'a2a-agent-admin']
Check Auth Server Sees Groups¶
TOKEN=$(python3 -c "import json; print(json.load(open('.oauth-tokens/ingress.json'))['access_token'])")
curl -s "http://localhost:8888/validate" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Original-URL: http://localhost/agents/register" | \
python3 -m json.tool | grep -E "groups|scopes"
Expected output should include:
Troubleshooting¶
Issue: "Authentication required" Error¶
Check 1: Token file exists
Check 2: Token has groups
python3 << 'EOF'
import json, base64
with open('.oauth-tokens/ingress.json') as f:
token = json.load(f)['access_token']
payload = token.split('.')[1] + '='*(4-len(token.split('.')[1])%4)
decoded = json.loads(base64.urlsafe_b64decode(payload))
groups = decoded.get('groups', [])
print(f"Groups in token: {groups}")
if 'a2a-agent-admin' not in groups:
print("✗ Missing a2a-agent-admin - try refreshing token:")
print(" ./credentials-provider/generate_creds.sh")
EOF
Check 3: Auth server sees groups
TOKEN=$(python3 -c "import json; print(json.load(open('.oauth-tokens/ingress.json'))['access_token'])")
curl -s "http://localhost:8888/validate" -H "Authorization: Bearer $TOKEN" | \
python3 -m json.tool | grep groups
Should show: "groups": ["mcp-servers-unrestricted", "a2a-agent-admin"]
Check 4: Nginx forwards scopes
curl -v http://localhost/api/agents/register \
-X POST \
-H "Authorization: Bearer $(python3 -c 'import json; print(json.load(open(\".oauth-tokens/ingress.json\"))[\"access_token\"])')" \
2>&1 | grep -i x-scopes
Should include: x-scopes: a2a-agent-admin (note: uses port 80 via Nginx, not direct application port)
Solution: Refresh Token¶
If token is missing groups, regenerate it:
Then verify groups reappear:
python3 << 'EOF'
import json, base64
with open('.oauth-tokens/ingress.json') as f:
token = json.load(f)['access_token']
payload = token.split('.')[1] + '='*(4-len(token.split('.')[1])%4)
decoded = json.loads(base64.urlsafe_b64decode(payload))
print("Groups:", decoded.get('groups'))
EOF
JWT Token Structure¶
The mcp-gateway-m2m service account's JWT token contains:
{
"exp": 1761942660,
"iat": 1761942360,
"iss": "http://localhost:8080/realms/mcp-gateway",
"sub": "user-id-uuid",
"typ": "Bearer",
"azp": "mcp-gateway-m2m",
"client_id": "mcp-gateway-m2m",
"preferred_username": "service-account-mcp-gateway-m2m",
"groups": ["mcp-servers-unrestricted", "a2a-agent-admin"],
"scope": "profile email mcp-servers-restricted/execute mcp-servers-restricted/read mcp-servers-unrestricted/read mcp-servers-unrestricted/execute a2a-agent-admin"
}
Key fields: - client_id: mcp-gateway-m2m - identifies the service account - groups: List of Keycloak groups the account belongs to - scope: Space-separated list of OAuth2 scopes for authorization - a2a-agent-admin: The scope that grants agent management permissions
Setup (Automatic During Initialization)¶
The mcp-gateway-m2m service account is automatically configured during Keycloak initialization:
- Keycloak Client Created -
mcp-gateway-m2mM2M client registered - Service Account User Created -
service-account-mcp-gateway-m2muser created - Groups Assigned - User assigned to
mcp-servers-unrestrictedanda2a-agent-admingroups - Groups Mapper Added - JWT tokens include groups claim
- Auth Scopes Configured - Groups mapped to OAuth2 scopes in auth_server/scopes.yml
- Nginx Protected -
/api/*endpoints require JWT authentication
No manual configuration needed - everything is automatic!
Initialization Files¶
These files are involved in the automatic setup:
| File | Purpose |
|---|---|
keycloak/setup/init-keycloak.sh | Creates groups, assigns M2M to groups, adds groups mapper |
auth_server/scopes.yml | Maps groups to scopes |
docker/nginx_rev_proxy_http_only.conf | Protects /api/ endpoints with authentication |
credentials-provider/generate_creds.sh | Generates fresh JWT tokens |
Related Documentation¶
- Authentication Guide - General authentication and authorization
- CLI Reference - Command-line interface documentation
- Keycloak Integration - Keycloak configuration details
Environment Variables¶
The token generation process uses these environment variables from .env:
# Keycloak Configuration
KEYCLOAK_URL=http://localhost:8080
KEYCLOAK_REALM=mcp-gateway
KEYCLOAK_ADMIN=admin
KEYCLOAK_ADMIN_PASSWORD=SecureKeycloakAdmin123!
# M2M Client Credentials (set by init script)
KEYCLOAK_M2M_CLIENT_ID=mcp-gateway-m2m
KEYCLOAK_M2M_CLIENT_SECRET=<generated>
Common Tasks¶
Register Multiple Agents¶
# Create multiple agent files
cp cli/examples/code_reviewer_agent.json cli/examples/reviewer.json
cp cli/examples/test_automation_agent.json cli/examples/tester.json
# Register each
uv run python cli/agent_mgmt.py register cli/examples/reviewer.json
uv run python cli/agent_mgmt.py register cli/examples/tester.json
# List all
uv run python cli/agent_mgmt.py list
Update Agent Configuration¶
# Modify the agent JSON file
vi cli/examples/my_agent.json
# Re-register to update (will overwrite)
uv run python cli/agent_mgmt.py register cli/examples/my_agent.json
Remove Agent¶
Test Agent Availability¶
# Test that agent is accessible
uv run python cli/agent_mgmt.py test /code-reviewer
# If successful:
# ✓ Agent registered
# ✓ Endpoint is reachable
# ✓ Agent is responding
FAQ¶
Q: What if I get "Agent already exists" error? A: The agent is already registered. Either delete it first or change the path in your JSON.
Q: Where are agents stored? A: In the registry database. Agent metadata is stored at registry/agents/ during development.
Q: Can I use a different service account? A: No, mcp-gateway-m2m is the configured M2M account for all CLI operations. Create separate accounts only if needed for different purposes.
Q: How often should I refresh the token? A: Automatically via ./credentials-provider/generate_creds.sh which is called by the shell startup. Manual refresh only needed if token expires.
Q: What if the token expires? A: Run ./credentials-provider/generate_creds.sh to get a fresh token.
Q: Can agents be private? A: Yes, set "visibility": "private" in agent JSON. Only registered users can access private agents.
Getting Help¶
- Check Troubleshooting section above
- Review JWT token contents and verify groups are present
- Check service is running:
docker-compose ps - View logs:
docker logs mcp-gateway-registry-auth-server-1 - Verify Keycloak groups in admin UI: http://localhost:8080/admin
Summary¶
- Service Account:
mcp-gateway-m2m(auto-created during init) - Token File:
.oauth-tokens/ingress.json(auto-loaded by CLI) - Permissions: Full agent management (register, modify, delete, list)
- Groups:
mcp-servers-unrestricted,a2a-agent-admin(auto-assigned) - Setup: Fully automatic - no manual configuration needed