1‐Getting Started - makbn/mcp_mediator GitHub Wiki
At its core, the MCP Mediator is about extensibility and composition:
-
Aggregate existing MCP servers
Many services already expose MCP‑compatible endpoints (e.g. language models, Docker, Dropbox). A Default Mediator lets you bring all of those under one roof without touching each server’s code. -
Inject new functionality
By simply writing and registering a newMcpMediatorRequestHandler
, you “plug in” a brand‑new tool or workflow (for example, a Kubernetes handler, a database query tool, or custom domain logic). -
Unified transport/shipping
You get STDIO, SSE or even HTTP/S transports “for free” via configuration. No need to rewire JSON‑RPC, message framing, retries, etc., every time.
Put another way, the Default Mediator is your extension bus: it wires up all existing tools and gives you a clean hook to add whatever you need next.
Below is a step‑by‑step view of what happens from startup through handling a single request:
By constructing the MCP Mediator, we are defining all the protocol-related and server functionality details of the MCP Mediator Server. Most of the configurations are set at this point in time and cannot be changed later.
DefaultMcpMediator mediator = new DefaultMcpMediator(config);
- Stores your McpMediatorConfigurationSpec (transport, serverName, version, etc.).
- Initializes internal lists for handlers and listeners.
Read more about the available configuration point on the Configuration page.
mediator.registerHandler(new DockerMcpRequestHandler());
mediator.registerHandler(new MyCustomHandler());
McpRequestHandler
is the main component for expanding the functionality, connecting to existing servers, connection to existing server layers, and invoing any form of procss. There are some implementations avilable as exmaples. During the request handler registration, MCP Mediator:
- Internally adds each handler to a List.
- Creates a map between all the recievable/handlable request and their approporate requst handler.
Important
No network I/O happens yet—just in‑memory registration.
we can register request handler after initializing/starting tht Mediator instance, it will update the recievable/handlable request map, registers the new handler as a MCP Tool and notify the clients of the change in the list of available tools.
mediator.initialize();
- Builds the transport server (e.g. McpSyncServer over
STDIO
). - Calls
delegate()
:- Creates a connection between the registered MCP Mediator Request Hnadlers and MCP Server
Tools
- Registers each request hander as a MCP server capability to be advertiesed to the MCP Client during initialization lifecycle.
- Creates an adapter to deserialize the incoming call/request from client to this call to extract the request from the invocation paramters
- Defaines the step to Serialize the the request handler execution result as the MCP Toll invocation callback.
- Starts listening on the chosen transport.
- Creates a connection between the registered MCP Mediator Request Hnadlers and MCP Server
In the proxy mode, this step also creates the connection between the Proxy MCP Mediator class and stablish the delegation between the client and remote MCP servers similar to the request handlers initialization process. Read more about that on the Proxy MCP Mediator section.
A client sends a JSON‑RPC call on STDIO
:
{"jsonrpc":"2.0","method":"docker.listContainers","params":{"loadAllContainers":"false"},"id":1}
- The transport server deserializes it to an instance of
McpRequest
in this case,AllDockerContainersMcpRequest
.
MCP Mediator intervene the call to the MCP Tool in McpMediator#execute(T request)
after converting the incoming request to an isnatnce of McpRequest
.
- The
McpRequest
is routed to the appropriate registered MCP Mediator Request Handler—or to the remote MCP server when in proxy mode—based on the existing mapping between MCP tools and their corresponding handlers. To delegate the handling of a request, the MCP Mediator queries all registered handlers to determine which one is capable of processing the request. This is done via theMcpMediatorRequestHandler#canHandle(McpMediatorRequest<?> request)
method. This mechanism enables dynamic routing of incoming requests—either for immediate handling or to be passed along—without the need to propagate further down the call stack.
Each registered MCP Mediator Request Handler is responsible for handling requests by implementing the McpMediatorRequestHandler#handle(T request)
method. This method should process the request synchronously. If the underlying logic is asynchronous, the implementation must ensure it waits for the result and returns it synchronously. Currently, the MCP Mediator manages both sync and async execution modes internally.
-
A single
McpMediatorRequestHandler<T extends McpMediatorRequest<R>, R>
can be responsible for handling multiple request types, as long as each request is a subclass ofT
and theMcpMediatorRequestHandler#canHandle(McpMediatorRequest<?> request)
method returnstrue
for it. -
Any unhandled exception thrown during the execution of
handle(T request)
will result in an error callback to the MCP Tool, sending the exception’s message back to the client.
-
DefaultMcpMediator
wraps the handler’s output in JSON‑RPC format. - The transport server writes it back on
STDIO
(orSSE/HTTP
).
For now, all the MCP CallToolResult
are a list of TextContent
. Based on the requiremest of the project in future, this might change to generic Content
to support ImageContent
and EmbeddedResource
as well.
At key points—initialization, before/after each request, shutdown—you can attach McpMediatorListeners to log metrics, perform cleanup, or fire custom events.
Note
This feature is not implemented yet but the main goal here is to make it easier to receive the events happening during the lifecycle of the mediator and make it easier to collect information for debugging. Anything that aligns with the goal will be avalible as an MCP Mediator Event.