1‐Getting Started - makbn/mcp_mediator GitHub Wiki

Why an MCP Mediator?

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 new McpMediatorRequestHandler, 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.


DefaultMcpMediator Lifecycle & Call Trace

Below is a step‑by‑step view of what happens from startup through handling a single request:

1. Construction

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.

2. Handler Registration

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.

3. Initialization

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.

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.

4. Incoming Request

A client sends a JSON‑RPC call on STDIO:

{"jsonrpc":"2.0","method":"docker.listContainers","params":{"loadAllContainers":"false"},"id":1}

5. Dispatching

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 the McpMediatorRequestHandler#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.

6. Tool Execution

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 of T and the McpMediatorRequestHandler#canHandle(McpMediatorRequest<?> request) method returns true 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.

7. Response Delivery

  • DefaultMcpMediator wraps the handler’s output in JSON‑RPC format.
  • The transport server writes it back on STDIO (or SSE/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.

8. Lifecycle Hooks

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.

⚠️ **GitHub.com Fallback** ⚠️