Wanaku MCP Router Internals
This document provides a detailed look at the internal architecture and implementation of the Wanaku MCP Router backend.
Overview
The Wanaku router backend is built around a bridge architecture that abstracts MCP operations and delegates actual work to capability services via gRPC. The bridge pattern separates transport concerns from business logic, enabling flexible and testable implementations.
Core Abstraction: Bridge Interface
The root abstraction for all operations within Wanaku MCP Router is the Bridge interface. All MCP operations are executed by implementations of this interface.
Bridge Hierarchy
classDiagram
class Bridge {
<<interface>>
}
class ResourceBridge {
<<interface>>
+read(arguments, resource) Uni~ResourceResponse~
}
class ToolsBridge {
<<interface>>
+execute(arguments, reference) Uni~ToolResponse~
}
class ProvisionBridge {
<<interface>>
+provision(name, configData, secretsData, service) ProvisioningReference
}
class McpBridge {
<<interface>>
+listTools(client) List~RemoteToolReference~
+executeTool(client, arguments, reference) Uni~ToolResponse~
+listResources(client) List~ResourceReference~
+read(client, arguments, resource) Uni~ResourceResponse~
}
class WanakuBridgeTransport {
<<interface>>
+provision(name, config, secrets, service) ProvisioningReference
+invokeTool(request, service) Uni~ToolResponse~
+acquireResource(request, service, arguments, resource) Uni~List~ResourceContents~~
+executeCode(request, service) Iterator~CodeExecutionReply~
+probeHealth(request, service) HealthProbeReply
}
class ResourceAcquirerBridge {
-transport WanakuBridgeTransport
-provisionerBridge ProvisionerBridge
+read(arguments, resource) Uni~ResourceResponse~
}
class InvokerBridge {
-transport WanakuBridgeTransport
-serviceResolver ServiceResolver
+execute(arguments, reference) Uni~ToolResponse~
}
class ProvisionerBridge {
-serviceResolver ServiceResolver
-transport WanakuBridgeTransport
+provision(...) ProvisioningReference
+resolveService(type, serviceType) ServiceTarget
}
class GrpcTransport {
-channelManager GrpcChannelManager
+provision(...) ProvisioningReference
+invokeTool(...) Uni~ToolResponse~
+acquireResource(...) Uni~List~ResourceContents~~
}
Bridge <|-- ResourceBridge
Bridge <|-- ToolsBridge
ProvisionBridge <|.. ProvisionerBridge
ResourceBridge <|.. ResourceAcquirerBridge
ToolsBridge <|.. InvokerBridge
WanakuBridgeTransport <|.. GrpcTransport
ResourceAcquirerBridge o-- WanakuBridgeTransport
ResourceAcquirerBridge o-- ProvisionerBridge
InvokerBridge o-- WanakuBridgeTransport
style Bridge fill:#4A90E2
style ResourceBridge fill:#50C878
style ToolsBridge fill:#50C878
style ProvisionBridge fill:#50C878
style McpBridge fill:#50C878
style WanakuBridgeTransport fill:#9B59B6
style ResourceAcquirerBridge fill:#FFB347
style InvokerBridge fill:#FFB347
style ProvisionerBridge fill:#FFB347
style GrpcTransport fill:#E67E22
The bridge architecture is organized into specialized interfaces and uses composition over inheritance:
Bridge- Base marker interface for all bridge implementationsResourceBridge- Extended interface for asynchronous resource readingToolsBridge- Extended interface for asynchronous tool executionProvisionBridge- Interface for provisioning configuration and secrets to remote servicesMcpBridge- Interface for interacting with remote MCP servers (forwarding)WanakuBridgeTransport- Transport abstraction interface that decouples protocol from business logic, with async-first operations and built-in response transformation
Transport Abstraction
The bridge architecture uses composition over inheritance to separate transport concerns from business logic:
ResourceAcquirerBridgeandInvokerBridgedelegate all transport operations to aWanakuBridgeTransportimplementationGrpcTransportimplementsWanakuBridgeTransportand handles all gRPC-specific communicationProvisionerBridgeconsolidates shared provisioning logic and service resolution, eliminating duplication between bridges- Response transformers (
ToolResponseTransformer,ResourceResponseTransformer) convert transport-specific types (e.g., gRPC protobuf replies) into MCP domain types within the transport layer, keeping bridge implementations protocol-agnostic - This design enables:
- Easy testing with mock transports
- Support for alternative transport protocols (HTTP, WebSocket, etc.)
- Clear separation between routing logic and communication details
- Independent evolution of transport and business logic
All bridge operations follow an async-first design using Mutiny Uni types. The transport layer returns already-transformed domain objects, so bridges never handle transport-specific types directly.
Leveraging these specialized interfaces, we have the concrete classes ResourceAcquirerBridge and InvokerBridge that use gRPC via the transport abstraction to exchange data with capability services providing access to resources and tools. Additionally, DefaultMcpBridge provides forwarding to remote MCP servers using the langchain4j MCP client.
Resources
A resource is, essentially, anything that can be read by using the MCP protocol. For instance:
- Files
- Read-only JMS Queues
- Topics
- Static resources (i.e.: a web page)
Among other things, resources can be subscribed to, so that changes to its data and state are notified to the subscribers.
For instance, the ability to read files is handled by the wanaku-provider-file which is a gRPC server that is capable of consuming files isolated from other providers:
graph TB
Bridge[Bridge<br/>Base Interface]
ResourceBridge[ResourceBridge<br/>Resource Operations]
ResourceAcquirerBridge[ResourceAcquirerBridge<br/>Business Logic]
Transport[WanakuBridgeTransport<br/>Transport Abstraction]
GrpcTransport[GrpcTransport<br/>gRPC Implementation]
FileProvider[Wanaku Provider - File<br/>gRPC Server]
Bridge -->|extends| ResourceBridge
ResourceBridge -->|implements| ResourceAcquirerBridge
ResourceAcquirerBridge -->|uses| Transport
Transport -->|implements| GrpcTransport
GrpcTransport -->|gRPC| FileProvider
style Bridge fill:#4A90E2
style ResourceBridge fill:#50C878
style ResourceAcquirerBridge fill:#FFB347
style Transport fill:#9B59B6
style GrpcTransport fill:#E67E22
style FileProvider fill:#DDA0DD
Ideally, providers should leverage Apache Camel whenever possible.
Tools
A tool is anything that can be invoked by an LLM in a request/response fashion and used to provide data to it.
Examples:
- Request/reply over JMS
- Calling REST APIs
- Executing subprocesses that provide an output
- Executing an RPC invocation and waiting for its response
In Wanaku, every tool invocation is remote and handled by the InvokerBridge class which uses the gRPC protocol via the transport abstraction to communicate with the service that provides the tool.
graph TB
Bridge[Bridge<br/>Base Interface]
ToolsBridge[ToolsBridge<br/>Tool Operations]
InvokerBridge[InvokerBridge<br/>Business Logic]
Transport[WanakuBridgeTransport<br/>Transport Abstraction]
GrpcTransport[GrpcTransport<br/>gRPC Implementation]
ToolProvider[Tool Service<br/>HTTP/Exec/Tavily/etc.<br/>gRPC Server]
Bridge -->|extends| ToolsBridge
ToolsBridge -->|implements| InvokerBridge
InvokerBridge -->|uses| Transport
Transport -->|implements| GrpcTransport
GrpcTransport -->|gRPC| ToolProvider
style Bridge fill:#4A90E2
style ToolsBridge fill:#50C878
style InvokerBridge fill:#FFB347
style Transport fill:#9B59B6
style GrpcTransport fill:#E67E22
style ToolProvider fill:#DDA0DD
Configuration and Secrets Provisioning System
Both resource providers and tool services support a provisioning system that handles configuration and secret management. Provisioning logic is consolidated in the ProvisionerBridge class, which eliminates duplication between InvokerBridge and ResourceAcquirerBridge.
Provisioning Flow
sequenceDiagram
participant Router as Router Backend
participant PB as ProvisionerBridge
participant Transport as WanakuBridgeTransport
participant Service as Capability Service
participant ConfigStore as Configuration Store
Router->>PB: provision(name, config, secrets, service)
PB->>Transport: provision(name, config, secrets, service)
Transport->>Service: gRPC Provision(config, secrets)
Service->>Service: Apply Configuration
Service-->>Transport: ProvisionReply
Transport-->>PB: ProvisioningReference
PB-->>Router: ProvisioningReference
Note over Service: Service ready<br/>with configuration
Provisioning Capabilities
The provisioning system allows runtime configuration of services through gRPC-based provisioning requests that establish:
- Configuration URIs: Service-specific settings (endpoints, options, parameters)
- Secret URIs: Sensitive credentials (API keys, passwords, tokens)
- Property Schemas: Expected configuration structure and validation rules
Benefits
- Dynamic Configuration: Update service settings without restarting services
- Secure Credential Management: Secrets delivered via encrypted gRPC channels
- Schema Validation: Ensure configuration correctness before deployment
- Centralized Management: Configuration managed through router backend
- Flexible Deployment: Support different configurations per environment
Implementation Details
Provisioning is implemented through:
ProvisionerBridge: Consolidates provisioning logic and service resolution, shared by both tool and resource bridges- gRPC Protocol: Capability services implement the
ProvisionergRPC interface - Configuration Store: Router backend stores tool/resource configurations in Infinispan
- Secret Integration: Integration with Kubernetes Secrets or external secret managers
- Validation: Schema-based validation ensures configuration correctness
Component Interaction Patterns
Resource Read Pattern
When an LLM requests a resource, the following interaction occurs:
sequenceDiagram
participant MCP as MCP Client
participant Router as Router Backend
participant RAB as ResourceAcquirerBridge
participant PB as ProvisionerBridge
participant Transport as GrpcTransport
participant Provider as Resource Provider
MCP->>Router: ReadResource(file:///data/doc.txt)
Router->>RAB: read(arguments, resource)
RAB->>PB: resolveService(type, "resource-provider")
PB-->>RAB: ServiceTarget
RAB->>RAB: Build ResourceRequest
RAB->>Transport: acquireResource(request, service, arguments, resource)
Transport->>Provider: gRPC ReadResource(uri)
Provider->>Provider: Read File from Filesystem
Provider-->>Transport: gRPC Response (contents)
Transport->>Transport: Transform via ResourceResponseTransformer
Transport-->>RAB: Uni~List~ResourceContents~~
RAB-->>Router: Uni~ResourceResponse~
Router-->>MCP: MCP Resource Response
Tool Invocation Pattern
When an LLM invokes a tool, the interaction pattern is:
sequenceDiagram
participant MCP as MCP Client
participant Router as Router Backend
participant IB as InvokerBridge
participant Transport as GrpcTransport
participant Tool as Tool Service
MCP->>Router: CallTool(http://api.example.com/data)
Router->>IB: execute(toolArguments, toolReference)
IB->>IB: Resolve service, build ToolInvokeRequest
IB->>Transport: invokeTool(request, service)
Transport->>Tool: gRPC InvokeTool(uri, params)
Tool->>Tool: Execute HTTP Request
Tool-->>Transport: gRPC Response (result)
Transport->>Transport: Transform via ToolResponseTransformer
Transport-->>IB: Uni~ToolResponse~
IB-->>Router: Uni~ToolResponse~
Router-->>MCP: MCP Tool Response
Key Design Patterns
Bridge Pattern
The router uses the Bridge pattern to:
- Separate abstraction (business logic) from implementation (transport)
- Provide a unified interface for MCP operations
- Enable composition over inheritance for flexibility
- Support multiple transport implementations (gRPC, HTTP, etc.)
- Facilitate testing with mock transports
Composition Over Inheritance
The architecture favors composition:
- Bridges have-a transport instead of being-a transport
InvokerBridgeandResourceAcquirerBridgedelegate toWanakuBridgeTransportGrpcTransportimplements transport-specific logic- Clear separation enables independent evolution of components
Factory Pattern
Service creation uses factories to:
- Instantiate appropriate proxy implementations based on URI schemes
- Manage gRPC client lifecycle
- Handle service registration and deregistration
Strategy Pattern
Different capability types use strategy pattern to:
- Implement specific tool invocation logic
- Handle different resource types and protocols
- Apply different authentication mechanisms
Thread Safety and Concurrency
Concurrent Request Handling
- Async Processing: Router uses Quarkus reactive programming model
- Thread Pools: Dedicated thread pools for MCP requests and gRPC calls
- Connection Pooling: gRPC channels are pooled and reused
- State Management: Service registry uses concurrent data structures
Isolation Guarantees
- Request Isolation: Each MCP request is processed independently
- Service Isolation: Capability services run in separate processes
- Namespace Isolation: Tools/resources in different namespaces don't interfere
Related Documentation
- Persistence - Persistence information
- Service Registration - Service registration information
- Architecture Overview - High-level system architecture and components
- Configuration Guide - Router and service configuration reference
- Contributing Guide - How to extend Wanaku with new capabilities