Building a Dual-Protocol RAG Application with A2A and MCP
In this tutorial, we'll build a sophisticated Retrieval-Augmented Generation (RAG) application that supports both Google's Agent-to-Agent (A2A) protocol and Model Context Protocol (MCP). The unique aspect? We'll create a single application that seamlessly works with both protocols using a2ajava, a versatile framework for building agent-based applications.It is multi-protocol — works seamlessly with both A2A (Agent-to-Agent) and MCP (Model Context Protocol). It is multi-language — supports Java, Kotlin, and Groovy. It is multi-platform — compatible with Gemini, OpenAI, Claude, and Grok. It is multi-client — includes A2A and MCP clients with connectors in Java, Node, and Python. It provides multi-integration — out-of-the-box support for Selenium, human-in-the-loop workflows, multi-LLM voting for consensus-based decision making, RAG integration, Spring Security, and RBAC control. Agents built using the A2A protocol with a2ajava run seamlessly on MCP as well, ensuring maximum interoperability across platforms. It is also multi-channel — supports Shell, HTTP endpoints, and Java actions, with hundreds of examples and live demos, making it incredibly easy to get started. Additionally, it can integrate with robotics applications, acting as an LLM-based router to intelligently route HTTP REST calls to microcontrollers.
System Architecture
The system architecture combines several key components:
- RAG Engine: MongoDB Atlas Vector Store for semantic search
- Protocol Support: Dual protocol handlers for A2A and MCP
- Agent Services: Annotated Java classes that auto-convert to both A2A tasks and MCP tools
Live Demo
The application is deployed and accessible at:
https://vishalmysore-a2amcpmongo.hf.space/
Adding the Agent
For A2A clients, add the agent using:
vishalmysore-a2amcpmongo.hf.space
The agent card will automatically load from:
https://vishalmysore-a2amcpmongo.hf.space/.well-known/agent.json
MCP Integration
For MCP clients like Claude Desktop, add the following configuration:
Java Connector
{
"laundry": {
"command": "java",
"args": [
"-jar",
"/work/a2a-mcp-bridge/target/mcp-connector-full.jar",
"https://vishalmysore-a2amcpmongo.hf.space/"
],
"timeout": 30000
}
}
Node.js Connector
{
"admincar": {
"command": "node",
"args": [
"/work/a2a-mcp-bridge/src/main/resources/a2ajava.cjs",
"https://vishalmysore-a2amcpdemo.hf.space/"
],
"timeout": 30000
}
}
The MCP connector code is available on GitHub:
https://github.com/vishalmysore/mcp-connector/
API Documentation and Testing
Swagger UI
API documentation is available through Swagger UI:
https://vishalmysore-a2amcpmongo.hf.space/swagger-ui/index.html
MCP Tools List
View available MCP tools:
https://vishalmysore-a2amcpmongo.hf.space/mcp/list-tools
RAG Search Example
Query the vector database for similar tasks:
curl -X 'GET' \
'https://vishalmysore-a2amcpmongo.hf.space/getTask?taskText=wedding%20dress' \
-H 'accept: */*'
Protocol Conversion
Example of protocol conversion between A2A and MCP
Implementation Details
The magic behind the protocol conversion lies in the agent implementation. The following Java class automatically gets converted into both A2A tasks and MCP tools:
package vishalmysore;
import com.t4a.annotations.Action;
import com.t4a.annotations.Agent;
import com.t4a.detect.ActionCallback;
import com.t4a.detect.ActionState;
import lombok.extern.java.Log;
@log
@agent(groupName = "laundry", groupDescription = "actions related to laundry")
public class LaundryMachine {
private ActionCallback callback;
private boolean isRunning = false;
private int temperature = 30;
private String cycleType = "normal";
@Action(description = "Start the washing machine")
public void startWashing() {
log.info("Washing started");
}
@Action(description = "get quote for laundry")
public Integer getQuoteForLaundry(String typeOfCloth, String weight) {
log.info("Quote for laundry: " + typeOfCloth + ", " + weight);
if(callback!= null) {
callback.sendtStatus("Quote for laundry: " + typeOfCloth + ", " + weight+" is "+100, ActionState.COMPLETED);
}
return 100;
}
@Action(description = "Stop the washing machine")
public void stopWashing() {
isRunning = false;
log.info("Washing stopped");
if(callback != null) {
callback.sendtStatus("Washing machine stopped", ActionState.COMPLETED);
}
}
@Action(description = "Set washing temperature")
public void setTemperature(int temp) {
this.temperature = temp;
log.info("Temperature set to: " + temp);
if(callback != null) {
callback.sendtStatus("Temperature set to " + temp + " degrees", ActionState.COMPLETED);
}
}
@Action(description = "Select washing cycle type")
public void setCycleType(String cycle) {
this.cycleType = cycle;
log.info("Cycle type set to: " + cycle);
if(callback != null) {
callback.sendtStatus("Cycle type changed to " + cycle, ActionState.COMPLETED);
}
}
@Action(description = "Get machine status")
public String getStatus() {
String status = String.format("Machine is %s, Temperature: %d°C, Cycle: %s",
isRunning ? "running" : "stopped", temperature, cycleType);
log.info("Status checked: " + status);
return status;
}
}
How It Works
- The
@Agent
annotation defines the service group and description - Each
@Action
annotated method becomes both:- An A2A task endpoint
- An MCP tool
- Methods are exposed via JSON-RPC endpoints
- RAG integration stores task details in MongoDB vector store
- Semantic search enables natural language querying
Testing in Different Environments
Claude Integration
Using the service through Claude
Tool Chain View
Visualizing the tool chain integration
Conclusion
This implementation demonstrates the power of protocol-agnostic design in AI services. By supporting both A2A and MCP protocols, we enable broader integration possibilities while maintaining a single, maintainable codebase.
For more examples and detailed documentation, visit the a2ajava GitHub repository.
✅ Advantages of the Dual-Protocol Architecture
1. Maximum Interoperability
- Supports both Google A2A and Anthropic MCP protocols
- Agents serve multiple ecosystems (Gemini, Claude) simultaneously
- Single codebase works across different vendors, tools, and LLM providers
2. Single Codebase, Multiple Targets
Thanks to annotation-based design (@Agent
, @Action
), you write once and expose as:
- A2A Tasks
- MCP Tools
- REST Endpoints
- Shell Commands (optional)
This approach reduces development effort, ensures maintainability, and prevents protocol lock-in.
3. Multi-Language + Multi-Platform
- JVM Ecosystem: Java, Kotlin, Groovy support
- LLM Integration: OpenAI, Claude, Grok, Gemini
- Client Support: Java, Node.js, Python
4. Built-in AI Ops and RAG Integration
- Seamless MongoDB Atlas integration for vector storage
- Protocol-agnostic retrieval and generation
- Agents learn and serve from vectorized memory
5. Full DevSecOps Support
- RBAC and Spring Security integration
- Selenium for agent testing
- Multi-LLM voting capabilities
- Production-ready AI platform features
6. Human-in-the-Loop and Robotic Control
- Critical decision workflow support
- REST-based hardware control
- LLM routers for physical actuation (e.g., Chotu Robo)
🚀 Future Expansion Opportunities
1. Agent Orchestration Layer
Build a meta-agent system that can:
- Discover agents dynamically (agent registry)
- Assign tasks based on capabilities and load
- Track agent skills and performance
- Implement dynamic load balancing
2. Agent Marketplace
- Agent registration with metadata (capabilities.json, requirements.json)
- Runtime plugin system for third-party agents
- Simple deployment via JAR or .agent.json descriptors
3. Monitoring Console
Create a Spring Boot + React UI for:
- Real-time agent status visualization
- Workflow triggering and management
- LLM response and RAG query monitoring
4. Scalability and Edge Computing
- Containerized agent deployment
- Auto-scaling based on LLM request volume
- Edge deployment support (Raspberry Pi, ESP32)
- Microservice-style agent interactions
5. Advanced Voting Strategies
Enhance multi-LLM decision making with:
- Weighted voting systems
- Specialty-based routing (e.g., Claude for legal, Grok for tech)
- Response-time-based fallback mechanisms
6. Memory-Aware Agent Chains
Implement sophisticated workflows:
- RAG-based information retrieval
- LLM-powered decision making
- External system integration
- Shared vector memory storage
- Long-term context preservation
7. Enhanced Security and Observability
Integrate with:
- OpenTelemetry for distributed tracing
- Spring Boot Actuator for health metrics
- Comprehensive request auditing
- Protocol-specific interaction logging
8. Universal Protocol Conversion
Create dynamic protocol converters:
- JSON-RPC ↔ LangChain tools
- A2A ↔ OpenAI Function Calls
- MCP ↔ Zapier plugins
📌 Strategic Vision
This architecture represents more than just a dual-protocol application—it's a comprehensive platform strategy. With a2ajava, you're positioned at the intersection of:
- Agent-based computing
- LLM interoperability
- Full-stack enterprise integration
By expanding into agent orchestration, edge deployment, and developer plugins, this framework is poised to become the standard for enterprise GenAI applications.
Top comments (0)