A robust, cross-platform Rust library for managing Model Context Protocol (MCP) server processes with advanced retry logic, health monitoring, and platform-specific optimizations.
GPMCP Layer provides a high-level abstraction for spawning, managing, and communicating with MCP servers. It handles process lifecycle management, automatic reconnection with configurable retry strategies, and platform-specific optimizations for both Unix and Windows systems.
- Cross-Platform Support: Native implementations for Unix (Linux, macOS) and Windows
- Robust Process Management: Advanced process lifecycle management with graceful termination
- Configurable Retry Logic: Exponential backoff, jitter, and customizable retry strategies
- Health Monitoring: Built-in health checks and automatic recovery
- Transport Flexibility: Support for stdio and SSE (Server-Sent Events) transports
- Resource Management: Automatic cleanup and resource management
- Async/Await Support: Fully asynchronous API built on Tokio
The project is organized as a Rust workspace with the following crates:
├── gpmcp-layer/ # Main library with high-level API
├── gpmcp-layer-core/ # Platform-independent traits and configurations
├── gpmcp-layer-unix/ # Unix-specific process management
└── gpmcp-layer-windows/ # Windows-specific process management
Add this to your Cargo.toml:
[dependencies]
gpmcp-layer = { git = "https://github.com/gpmcp/layer/" }
tokio = { version = "1.0", features = ["full"] }use std::borrow::Cow;use gpmcp_layer::{CallToolRequestParam,GpmcpLayer,RunnerConfig,Transport};#[tokio::main]asyncfnmain() -> anyhow::Result<()>{// Configure the MCP serverlet config = RunnerConfig::builder().name("my-mcp-server").version("1.0.0").command("python3").args(["server.py","--port","8080"]).transport(Transport::Sse{url:"http://localhost:8080/sse".to_string(),}).build()?;// Create and connect the layer to the serverlet layer = GpmcpLayer::new(config)?.connect().await?;// List available toolslet tools = layer.list_tools().await?;println!("Available tools: {:?}", tools);// Call a toollet request = CallToolRequestParam{name:Cow::Borrowed("example_tool"),arguments: serde_json::json!({"input":"test"}).as_object().cloned(),};let result = layer.call_tool(request).await?;println!("Tool result: {:?}", result);// Cleanup
layer.cancel().await?;Ok(())}Practical examples are available in the examples/ directory:
- Simple StdIO Client (
examples/simple_stdio/) - Basic GPMCP Layer usage demonstrating server connection, tool discovery, and communication patterns using StdIO transport. - Simple SSE Client (
examples/simple_sse/) - Basic GPMCP Layer usage demonstrating server connection, tool discovery, and communication patterns using SSE transport. - Counter Server (
examples/test-mcp-server/) - Sample MCP server implementing stateful counter operations with both StdIO and SSE transport support
See the examples README for detailed usage instructions.
new(config)- Create a new GpmcpLayer instance with the given configurationconnect()- Start and connect to the MCP serverlist_tools()- Get available tools from the MCP servercall_tool(request)- Execute a tool with parameterslist_prompts()- Get available promptsget_prompt(request)- Retrieve a specific promptlist_resources()- Get available resourcesread_resource(request)- Read a specific resourceis_healthy()- Check server health with retriesis_healthy_quick()- Quick health check without retriespeer_info()- Get server informationcancel()- Gracefully shutdown the layer
cargo build --workspaceFor CI environments or when you only need specific platform support:
# Unix only (Linux, macOS)
cargo build --workspace --exclude gpmcp-layer-windows
# Windows only
cargo build --workspace --exclude gpmcp-layer-unix# Run all tests
cargo test --workspace
# Platform-specific testing
cargo test --workspace --exclude gpmcp-layer-windows # Unix
cargo test --workspace --exclude gpmcp-layer-unix # Windows# Integration tests
cargo test --test integration_tests| Platform | Status | Process Manager | Notes |
|---|---|---|---|
| Linux | ✅ Full | Unix | Native process groups, signals |
| macOS | ✅ Full | Unix | Native process groups, signals |
| Windows | ✅ Full | Windows | Job objects, process trees |
The library uses anyhow::Result for error handling and provides detailed error context:
asyncfncall(layer:&GpmcpLayer,request:CallToolRequest) -> anyhow::Result<()>{match layer.call_tool(request).await{Ok(result) => println!("Success: {:?}", result),Err(e) => {eprintln!("Error: {}", e);// Error chain provides detailed contextfor cause in e.chain(){eprintln!(" Caused by: {}", cause);}}}}Enable logging to see detailed operation information:
use tracing_subscriber;fnmain(){
tracing_subscriber::fmt().with_env_filter("gpmcp_layer=debug").init();}- Process spawning is optimized for each platform
- Retry strategies use exponential backoff to avoid overwhelming servers
- Health checks are lightweight and non-blocking
- Resource cleanup is automatic and thorough
- Process isolation using platform-specific mechanisms
- Secure environment variable handling
- Proper cleanup of sensitive data
- No hardcoded credentials or secrets