Runtime decoupling solution for MCP Java servers, solving the tight coupling issues inherent in stdio-based integration.
The native stdio implementation in the MCP Java SDK creates a tight coupling between the client and server runtimes. This coupling causes several critical issues:
- Resource contention: Client and server compete for the same system resources
- Logging conflicts: Both processes write to the same output streams, making debugging difficult
- Context pollution: Server environment variables and system properties affect the client
- Lifecycle management: Server lifecycle is tied to client process, preventing independent scaling
- Development complexity: Testing and debugging require running both components together
While Streamable HTTP would be the ideal alternative for decoupled communication, the current MCP Java SDK only supports SSE (Server-Sent Events) and stdio transports - not Streamable HTTP. This limitation led to the creation of MCP Java Bridge.
MCP Java Bridge decouples the client and server runtimes while maintaining full stdio compatibility. It introduces a lightweight "connector" that:
- Integrates with MCP clients via stdio (100% compatible with Claude Desktop and other clients)
- Connects to your Java server via TCP behind the scenes
- Runs each component in its own process with isolated resources
- Requires zero changes to your existing MCP server code
- Transparent to both client and developer - just works out of the box
The result is a robust, production-ready integration that solves all the coupling issues while maintaining the simplicity of the MCP protocol.
┌─────────────────┐ stdio ┌───────────────────────────────────┐
│ Claude Desktop │ ◄──────────────────► │ MCP Bridge │
│ (Client) │ │ ┌─────────┐ ┌──────────┐ │
└─────────────────┘ │ │ Stub │ TCP │ Skeleton │ │
│ │ (stdio) │◄────►│ (Java) │ │
│ └─────────┘ └──────────┘ │
└───────────────────────────────────┘
│
│ Embedded
▼
┌─────────────────┐
│ MCP Java Server │
│ (with SDK) │
└─────────────────┘
- All-in-One JAR: Single JAR serves as library, connector, and installer
- Transparent TCP Support: Enables TCP connectivity without client modifications
- Simple Integration: Easy to integrate with existing MCP Java servers
- Production Ready: Includes logging, error handling, and connection management
- Flexible Configuration: Configurable ports and connection settings
- Interactive Installer: Zero-configuration setup for Claude Desktop
- Self-Installing: The JAR can install itself as a connector
Add mcp-java-bridge to your project:
<dependency>
<groupId>org.gegolabs.mcp</groupId>
<artifactId>mcp-java-bridge</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
implementation 'org.gegolabs.mcp:mcp-java-bridge:1.0.0-SNAPSHOT'
Note: This is currently a SNAPSHOT version. Add mavenLocal()
to your repositories if you've installed it locally.
Use the bridge to create your MCP server with TCP transport:
import org.gegolabs.mcp.bridge.McpBridge;
import io.modelcontextprotocol.sdk.McpServer;
public class MyMcpServer {
public static void main(String[] args) throws Exception {
// Create bridge
McpBridge bridge = McpBridge.builder()
.port(3000)
.build();
// Create your MCP server with bridge transport
McpServer server = McpServer.builder()
.transportProvider(bridge.getTransportProvider())
.toolsProvider(() -> /* your tools */)
.toolHandler((name, args) -> /* handle tool calls */)
.build();
server.start();
// Keep the server running
Thread.currentThread().join();
}
}
import org.gegolabs.mcp.bridge.McpBridge;
import io.modelcontextprotocol.sdk.McpServer;
public class MyMcpServer {
public static void main(String[] args) throws Exception {
McpServer server = McpServer.builder()
.transportProvider(McpBridge.tcpTransport(3000))
.toolsProvider(() -> /* your tools */)
.toolHandler((name, args) -> /* handle tool calls */)
.build();
server.start();
Thread.currentThread().join();
}
}
After building your MCP server, you need to configure Claude Desktop to connect to it. The mcp-java-bridge JAR includes a CLI installer for this purpose.
Since you've added mcp-java-bridge as a dependency, you can access it in two ways:
From Maven Repository:
java -jar ~/.m2/repository/org/gegolabs/mcp/mcp-java-bridge/1.0.0/mcp-java-bridge-1.0.0.jar
Or copy it using a Gradle task:
task copyBridgeJar(type: Copy) {
from configurations.runtimeClasspath.filter { it.name.contains('mcp-java-bridge') }
into 'install'
rename { 'mcp-bridge.jar' }
}
Then: ./gradlew copyBridgeJar
Choose one of these three options:
Run the installer without arguments for a guided setup:
java -jar mcp-java-bridge-1.0.0.jar
This will:
- Auto-detect the JAR location
- Prompt for server name (e.g., "my-server")
- Prompt for host (default: localhost)
- Prompt for port (default: 3000)
- Automatically configure Claude Desktop
- Create a backup of existing configuration
For automated setups, use specific parameters:
java -jar mcp-java-bridge-1.0.0.jar install \
-n "my-server" \
-c mcp-java-bridge-1.0.0.jar \
-h localhost \
-p 3000
Parameters:
-n
- Server name in Claude Desktop (required)-c
- Path to the JAR that will act as connector-h
- Server host (default: localhost)-p
- Server port (default: 3000)
If you prefer to configure manually, edit ~/Library/Application Support/Claude/claude_desktop_config.json
:
{
"mcpServers": {
"my-server": {
"command": "java",
"args": [
"-jar",
"/path/to/mcp-java-bridge-1.0.0.jar",
"--connector",
"localhost",
"3000"
]
}
}
}
- Start your MCP server (make sure it's running on the configured port)
- Restart Claude Desktop to load the new configuration
- Your server should now be available in Claude Desktop
The project includes example code in the source:
SimpleExample.java
- Basic echo server showing minimal setupExampleServer.java
- Full-featured server with multiple tools (this is the one built as the demo JAR)
After building, you'll find these JARs in build/libs/
:
mcp-java-bridge-1.0.0-SNAPSHOT.jar
- Main JAR (library + connector + installer)mcp-java-bridge-1.0.0-SNAPSHOT-example.jar
- Demo server applicationmcp-java-bridge-1.0.0-SNAPSHOT-sources.jar
- Source code
The demo JAR (mcp-java-bridge-1.0.0-SNAPSHOT-example.jar
) runs the ExampleServer with these tools:
- echo - Echoes back messages
- get_time - Returns current time in various formats
- todo_list - Manage a simple todo list (add, remove, list, clear)
- key_value_store - Simple key-value storage (get, set, delete, list)
- calculator - Basic math operations (add, subtract, multiply, divide, power, sqrt)
-
Build the project (if not already built):
./gradlew clean build
-
Run the demo server:
# Using the provided script cd examples ./run-demo.sh # Or run directly java -jar build/libs/mcp-java-bridge-1.0.0-SNAPSHOT-example.jar
-
Test with curl (optional): While the server is designed for MCP clients, you can verify it's running:
# This will fail with a protocol error (expected) but confirms the server is listening telnet localhost 3000
-
Configure Claude Desktop using the installer (see Step 3 in Getting Started)
The examples/run-demo.sh
script:
- Checks Java version (requires Java 17+)
- Builds the project if needed
- Starts the example server
- Shows Claude Desktop configuration
The MCP Java Bridge JAR is a multi-purpose tool that serves three different functions:
Running without arguments starts an interactive installer:
java -jar mcp-java-bridge-1.0.0-SNAPSHOT.jar
This will:
- Auto-detect the JAR location
- Prompt for server name (e.g., "my-mcp-server")
- Prompt for host (default: localhost)
- Prompt for port (default: 3000)
- Automatically configure Claude Desktop
- Create a backup of existing configuration
Run as a connector to bridge stdio↔TCP communication. This is what Claude Desktop executes:
# With default settings (localhost:3000)
java -jar mcp-java-bridge-1.0.0-SNAPSHOT.jar --connector
# With custom host/port
java -jar mcp-java-bridge-1.0.0-SNAPSHOT.jar --connector 192.168.1.100 8080
Note: This mode is typically not run manually - it's executed by Claude Desktop.
For non-interactive installation with specific parameters:
java -jar mcp-java-bridge-1.0.0-SNAPSHOT.jar install -n <server-name> -c <jar-path> [-h <host>] [-p <port>]
Arguments:
-n
- Server name in Claude Desktop (required)-c
- Path to the JAR or script that will act as connector-h
- Server host (default: localhost)-p
- Server port (default: 3000)
Examples:
# Install using the same JAR as connector
java -jar mcp-java-bridge-1.0.0-SNAPSHOT.jar install \
-n "my-server" \
-c ./mcp-java-bridge-1.0.0-SNAPSHOT.jar \
-h localhost \
-p 3000
# Install using a custom script as connector (e.g., from uMCP)
java -jar mcp-java-bridge-1.0.0-SNAPSHOT.jar install \
-n "my-umcp-server" \
-c /path/to/uMCP/install/bin/uMCP-connector \
-h localhost \
-p 3000
Display usage information:
java -jar mcp-java-bridge-1.0.0-SNAPSHOT.jar --help
Once connected, you can test the demo tools:
-
Echo Tool:
"Please use the echo tool to say 'Hello from MCP!'"
-
Time Tool:
"What time is it? Show me in different formats."
-
Todo List:
"Add 'Test MCP Bridge' to my todo list" "Show me my todo list" "Remove 'Test MCP Bridge' from the list"
-
Key-Value Store:
"Store my name as 'John Doe' in the key-value store" "What's stored under the key 'name'?"
-
Calculator:
"Calculate 42 * 17 using the calculator tool" "What's the square root of 144?"
The bridge includes utilities for configuring file-based logging, essential for debugging:
import org.gegolabs.mcp.bridge.utils.LoggingUtils;
// Enable file logging
LoggingUtils.initializeFileLogging("my-mcp-server.log");
// Enable debug logging
LoggingUtils.enableDebugLogging();
Logs are saved to ~/.mcp-bridge/logs/
.
Generate JSON schemas for your tool parameters:
import org.gegolabs.mcp.bridge.utils.JsonSchemaUtils;
public class MyToolParams {
@JsonSchemaUtils.Description("The user's name")
private String name;
@JsonSchemaUtils.Description("The user's age")
private int age;
}
// Generate schema
String schema = JsonSchemaUtils.generateJsonSchema(MyToolParams.class);
git clone https://github.com/gegolabs/mcp-java-bridge.git
cd mcp-java-bridge
./gradlew build
./gradlew test
./gradlew publishToMavenLocal
- Java 17 or higher
- MCP Java SDK 0.10.0 or higher
MIT License - see LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.E