Clean, schema-driven implementation of A2A (Agent-to-Agent) protocol with MCP (Model Context Protocol) integration for OpenDirect v2.1.
┌─────────────────────────────────────────────────────────────────┐
│ opendirect.json │
│ (OpenAPI 3.0 Schema) │
└──────────────────────┬──────────────────────────────────────────┘
│
│ Parsed by SchemaParser
▼
┌─────────────────────────────────────────────────────────────────┐
│ MCP Server Layer │
│ • Auto-generates tools from schema │
│ • Handles tool execution │
│ • Returns mock responses │
└──────────────────────┬──────────────────────────────────────────┘
│
│ Provides tool handlers
▼
┌─────────────────────────────────────────────────────────────────┐
│ A2A Agent Layer │
│ • Agent Card Generator (v0.3.0) │
│ • JSON-RPC 2.0 Router │
│ • Agent Executor (OpenAI-powered) │
│ • Task Management │
└──────────────────────┬──────────────────────────────────────────┘
│
│ HTTP/JSON-RPC
▼
┌─────────────────────────────────────────────────────────────────┐
│ JavaScript Client │
│ • @a2a-js/sdk integration │
│ • Agent discovery │
│ • Message sending │
│ • Task polling │
└─────────────────────────────────────────────────────────────────┘
- Schema-Driven: Automatically generates MCP tools from OpenAPI spec
- A2A v0.3.0 Compliant: Full agent card with skills, OAuth2, interfaces
- AI-Powered Execution: Uses OpenAI GPT-4o-mini for tool selection
- Dual Agents: Separate buyer and seller agents with role-specific skills
- JSON-RPC 2.0: Standard protocol for agent communication
- Dynamic URLs: Auto-detects URLs from request headers (Cloud Run ready)
- Task Management: Full task lifecycle (pending → working → completed/failed)
- @a2a-js/sdk: Official A2A SDK integration
- Agent Discovery: Automatic agent card fetching
- Real-time Updates: Task polling for response updates
- Quick Actions: Pre-built message templates
- Clean UI: Modern, responsive interface
a2a-agenticdirect/
├── server/ # TypeScript server
│ ├── src/
│ │ ├── types/
│ │ │ └── index.ts # Type definitions
│ │ ├── mcp/
│ │ │ ├── schema-parser.ts # OpenAPI → MCP tools
│ │ │ └── mcp-server.ts # MCP protocol handler
│ │ ├── a2a/
│ │ │ ├── agent-card.ts # Agent card generator
│ │ │ ├── executor.ts # AI-powered execution
│ │ │ └── router.ts # Express routes
│ │ └── server.ts # Main entry point
│ ├── package.json
│ └── tsconfig.json
├── client/ # JavaScript client
│ ├── src/
│ │ └── app.js # A2A SDK ClientFactory implementation
│ ├── dist/
│ │ └── bundle.js # Bundled client (generated)
│ ├── index.html
│ ├── style.css
│ └── package.json
├── opendirect.json # OpenAPI schema
└── README.md
- Node.js 20+
- OpenAI API key
- Navigate to server directory:
cd server- Install dependencies:
npm install- Create
.envfile:
cp .env.example .env- Add your OpenAI API key to
.env:
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o-mini
PORT=3000- Build and start:
# Development (with auto-reload)
npm run dev
# Production
npm run build
npm startServer will start on http://localhost:3000
- Navigate to client directory:
cd client- Install dependencies:
npm install- Build and run:
# Development mode (with hot reload and bundling)
npm run dev
# Or build once and serve
npm run build
npm run serveClient will be available at http://localhost:8080
Note: The client uses esbuild to bundle @a2a-js/sdk into dist/bundle.js. Always run npm run dev or npm run build before accessing the client.
- Open http://localhost:8080 in your browser
- Configure:
- Server URL:
http://localhost:3000 - Agent Role:
buyerorseller
- Server URL:
- Click Connect to Agent
- Send messages using quick actions or custom text
Example messages for Buyer Agent:
- "Create an account for Nike"
- "Create an order for Adidas campaign"
- "Submit creative for Nike banner ad"
- "List available products"
Example messages for Seller Agent:
- "List available products"
- "Process order for account ABC"
- "Approve creative submission"
curl http://localhost:3000/a2a/buyer/.well-known/agent-card.jsoncurl -X POST http://localhost:3000/a2a/buyer/jsonrpc \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "sendMessage",
"params": {
"message": {
"role": "user",
"parts": [{"kind": "text", "text": "Create an account for Nike"}],
"kind": "message"
}
},
"id": 1
}'Response:
{
"jsonrpc": "2.0",
"result": {
"id": "task-uuid",
"status": {
"state": "working",
"timestamp": "2025-01-02T..."
}
},
"id": 1
}curl -X POST http://localhost:3000/a2a/buyer/jsonrpc \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "getTask",
"params": {
"taskId": "task-uuid"
},
"id": 2
}'Server information and available agents
Health check endpoint
Agent card discovery (A2A v0.3.0)
JSON-RPC 2.0 endpoint for agent communication
Methods:
sendMessage- Send message to agentgetTask- Get task statuscancelTask- Cancel task
{
"name": "opendirect-buyer-agent",
"protocolVersion": "0.3.0",
"version": "1.0.0",
"url": "http://localhost:3000/a2a/buyer",
"description": "...",
"skills": [
{
"id": "order-creation",
"name": "Order Creation",
"description": "Create and manage advertising orders",
"tags": ["advertising", "order"],
"examples": [
"Create an account for Nike",
"Create an order for Adidas campaign"
],
"inputModes": ["application/json"],
"outputModes": ["application/json"]
}
],
"capabilities": {
"pushNotifications": false,
"streaming": true,
"mcpIntegration": true
},
"securitySchemes": {
"oauth2": {
"type": "oauth2",
"flows": {
"clientCredentials": {...},
"authorizationCode": {...}
}
}
},
"additionalInterfaces": [
{
"protocol": "jsonrpc",
"version": "2.0",
"transport": "http",
"url": "http://localhost:3000/a2a/buyer/jsonrpc"
},
{
"protocol": "mcp",
"version": "2024-11-05",
"transport": "sse",
"tools": ["create_account", "create_order", ...]
}
]
}SchemaParser reads opendirect.json (OpenAPI 3.0 spec) and extracts:
- Operations → MCP tool names (e.g.,
create_account) - Parameters → Input schemas
- Request bodies → Additional parameters
MCPServer creates tool handlers for each operation:
- Validates input against schema
- Executes tool (currently returns mock data)
- Returns structured response
AgentCardGenerator creates compliant agent cards with:
- Dynamic URL detection (X-Forwarded-* headers)
- Role-specific skills with examples
- OAuth2 security schemes
- MCP integration metadata
AgentExecutor uses OpenAI to:
- Analyze user message
- Select appropriate tool
- Extract parameters
- Execute and respond
A2ARouter handles:
- Message reception
- Task creation and tracking
- Asynchronous execution
- Status polling
| Variable | Required | Default | Description |
|---|---|---|---|
OPENAI_API_KEY |
Yes | - | OpenAI API key |
OPENAI_MODEL |
No | gpt-4o-mini |
OpenAI model |
PORT |
No | 3000 |
Server port |
NODE_ENV |
No | development |
Environment |
PROTOCOL |
No | Auto-detect | Override protocol (http/https) |
HOST |
No | Auto-detect | Override host |
cd server
npm run buildcd server
npm run devTools are automatically generated from opendirect.json. To add new tools:
- Update
opendirect.jsonwith new operations - Restart server - tools auto-refresh
Edit server/src/mcp/mcp-server.ts:
private createToolHandler(tool: MCPTool): MCPToolHandler {
return async (params: any) => {
// Add custom logic here
if (tool.name === 'create_account') {
// Call actual API
return await yourAPI.createAccount(params);
}
// Default mock response
return this.generateMockResponse(tool.name, params);
};
}curl http://localhost:3000/a2a/buyer/.well-known/agent-card.json | jq# 1. Send message
TASK_ID=$(curl -X POST http://localhost:3000/a2a/buyer/jsonrpc \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "sendMessage",
"params": {
"message": {
"role": "user",
"parts": [{"kind": "text", "text": "Create an account for Nike"}],
"kind": "message"
}
},
"id": 1
}' | jq -r '.result.id')
# 2. Check task status
curl -X POST http://localhost:3000/a2a/buyer/jsonrpc \
-H "Content-Type: application/json" \
-d "{
\"jsonrpc\": \"2.0\",
\"method\": \"getTask\",
\"params\": {
\"taskId\": \"$TASK_ID\"
},
\"id\": 2
}" | jq- Check OpenAI API key is valid
- Verify API quota not exceeded
- Check network connectivity
- Restart server to refresh tools from schema
- Verify
opendirect.jsoncontains operation
- Check server logs for errors
- Verify OpenAI API is responding
- Check for rate limiting
- Ensure reverse proxy sets
X-Forwarded-ProtoandX-Forwarded-Host - Or set
PROTOCOLandHOSTenvironment variables
- Built with A2A Protocol v0.3.0
- Uses @a2a-js/sdk
- Implements MCP (Model Context Protocol)
- Based on OpenDirect v2.1