MCPR: Rust implementation of Model Context Protocol

repository·master·Indexed 43 days ago

https://github.com/conikeec/mcpr

A Rust implementation of Anthropic's Model Context Protocol (MCP) for building AI-connected clients and servers. It supports multiple transport layers, including stdio and SSE, and provides a high-level API for registering tools and managing communication between AI assistants and data sources. Version 0.2.3.

Tokens
21.4K
Snippets
71
Records
96
Agent score
56%

What's inside MCPR

  1. The MCP Connection Lifecycle

    master

    An MCP connection follows a strict lifecycle of three main stages:

    1. Initialization: The Client sends an initialize request (containing protocol version and capabilities). The Server responds with its own capabilities and info. The Client then sends an initialized notification to acknowledge.
    2. Message Exchange: The active phase where tool_call requests, request_input requests, and optional progress notifications are exchanged.
    3. Termination: The connection is closed via a shutdown request and response to ensure a clean exit.
  2. How the MCP Client-Server architecture works

    master

    The Model Context Protocol (MCP) uses a client-server architecture to connect AI applications (Hosts) with tools and data sources.

    • Host: The parent application (e.g., Claude Desktop, an IDE) that initiates the connection.
    • Client: An entity embedded in the Host that maintains a 1:1 connection with a specific server.
    • Server: A service that provides tools, context, and capabilities to the client.
    • Tools: The specific functional units provided by the server (e.g., web search, code execution).
  3. MCP Message Formats (JSON-RPC 2.0)

    master

    MCP uses the JSON-RPC 2.0 specification for all communication. There are four primary message types:

    • Request: A message sent from Client to Server (or vice versa) that expects a response. Includes an id to track the request.
    • Response: The result of a Request. Can be a success containing a result object, or an error containing an error object.
    • Notification: A one-way message that does not require a response (e.g., progress updates).
    • Error: A specialized response used when a request fails.
    // Example Request
    {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "tool_call",
      "params": {
        "name": "web_search",
        "parameters": {
          "query": "weather in San Francisco"
        }
      }
    }
    
    // Example Success Response
    {
      "jsonrpc": "2.0",
      "id": 1,
      "result": {
        "temperature": "72°F",
        "conditions": "Partly cloudy"
      }
    }
    
    // Example Error Response
    {
      "jsonrpc": "2.0",
      "id": 1,
      "error": {
        "code": -32603,
        "message": "Internal error",
        "data": {
          "details": "Search service unavailable"
        }
      }
    }
    
    // Example Notification
    {
      "jsonrpc": "2.0",
      "method": "progress",
      "params": {
        "percent": 50,
        "message": "Processing query..."
      }
    }
  4. Supported MCP Transport Types

    master

    MCP supports different transport layers depending on whether the communication is local or over a network:

    • Stdio Transport (Local): Used for local communication where the Client writes to the Server's stdin and reads from the Server's stdout.
    • SSE Transport (Web): Used for web-based communication. The Client sends messages via HTTP POST /messages and the Server sends updates back via an SSE Event Stream.
  5. Run MCP projects with SSE transport

    master

    For SSE (Server-Sent Events) transport, the server runs as a web service. The generated project includes a mock SSE implementation for testing.

    1. Start the server (defaults to port 8080):
      ./server/target/debug/my-sse-project-server --port 8080
    2. Connect the client using the --uri flag:
      ./client/target/debug/my-sse-project-client --uri "http://localhost:8080"

    Clients also support an --interactive mode for manual testing and a one-shot mode using --name <name>.

  6. Install MCPR

    master

    To use MCPR in your Rust project, add it to your Cargo.toml dependencies.

    Important: Avoid version 0.2.0 as it has been yanked due to critical SSE transport issues. Use version 0.2.3 or later.

    To use the CLI tools (like the project generator), install the package globally using cargo install.

    [dependencies]
    mcpr = "0.2.3"
    cargo install mcpr
  7. Run MCP projects with Stdio transport

    master

    For stdio transport, the server communicates via standard input/output. You can run the server and pipe its output directly to the client, or run them in separate terminals using a URI.

    Piping method:

    ./server/target/debug/my-stdio-project-server | ./client/target/debug/my-stdio-project-client

    URI method:

    1. Run the server in one terminal.
    2. Run the client in another terminal using the --uri flag pointing to the server executable.
    ./client/target/debug/my-stdio-project-client --uri "stdio://./server/target/debug/my-stdio-project-server"
  8. Test stdio transport projects

    master

    To test a project using stdio transport, build both the server and client, then pipe the server's output directly into the client's input.

    Steps:

    1. Build the server and client using cargo build in their respective directories.
    2. Run the server and client together using a pipe: ./server/target/debug/[project-name]-server | ./client/target/debug/[project-name]-client

    Options:

    • Detailed Logging: Prepend RUST_LOG=debug to both commands.
    • Custom Name: Use the --name flag on the client command.
    • Interactive Mode: Use the --interactive flag on the client to manually enter tool names and parameters.
    # Build
    cd /tmp/test-stdio-project
    cd server && cargo build
    cd ../client && cargo build
    
    # Run with pipe
    ./server/target/debug/test-stdio-project-server | ./client/target/debug/test-stdio-project-client
    
    # Run with debug logging
    RUST_LOG=debug ./server/target/debug/test-stdio-project-server | RUST_LOG=debug ./client/target/debug/test-stdio-project-client
    
    # Run in interactive mode
    ./client/target/debug/test-stdio-project-client --interactive
  9. Debug and monitor MCP implementations

    master

    To maintain a reliable MCP system, focus on three primary areas: Logging, Diagnostics, and Testing.

    Logging

    • Log Protocol Events: Capture the sequence of MCP events to understand the system state.
    • Track Message Flow: Monitor how messages move between the client and server.
    • Monitor Performance: Identify latency or bottlenecks in message processing.
    • Record Errors: Log specific error codes and failure points.

    Diagnostics

    • Implement Health Checks: Ensure the server or client is responsive.
    • Monitor Connection State: Track whether the transport layer is active, disconnected, or in an error state.
    • Track Resource Usage: Monitor CPU and memory usage of the MCP processes.
    • Profile Performance: Use profiling tools to optimize the execution of tools or resources.

    Testing

    • Test Different Transports: Verify that your implementation works across both stdio and SSE transports.
    • Verify Error Handling: Ensure the system responds correctly to malformed messages or connection drops.
    • Check Edge Cases: Test boundary conditions in message sizes or tool arguments.
    • Load Test Servers: Evaluate how the server performs under high volumes of requests from an AI assistant.
  10. Run the GitHub Tools Server

    master

    The server can be run in two modes:

    1. Standalone process: Runs in the foreground.
    2. Background process: Runs in the background, redirecting output to a log file. This is useful for testing multiple clients connecting to a single server instance.
    # Option 1: Start the server as a standalone process
    cd server
    cargo run
    
    # Option 2: Start the server in the background
    cd server
    ./target/debug/github-tools-server < /dev/null > server_output.log 2>&1 &
  11. Enable debug logging

    master

    To see detailed information about the MCP protocol exchange and internal state, set the RUST_LOG environment variable to debug or trace when running your server or client.

    RUST_LOG=debug cargo run
  12. Generate an MCP Project from Template

    master

    You can use the github-tools structure as a template for your own MCP application.

    1. Scaffold the directory structure:
      mkdir -p my-mcp-project/{client,server}/src
      cp examples/github-tools/client/Cargo.toml my-mcp-project/client/
      cp examples/github-tools/server/Cargo.toml my-mcp-project/server/
    2. Customize the Client: Update Cargo.toml and create a new main.rs in my-mcp-project/client/src/.
    3. Implement Server Tools: Update the server's Cargo.toml and create a new main.rs in my-mcp-project/server/src/. To add new functionality, create new structs that implement the Tool trait.
    4. Test: Build the server, connect with your client, and verify tool execution.
    mkdir -p my-mcp-project/{client,server}/src
    cp examples/github-tools/client/Cargo.toml my-mcp-project/client/
    cp examples/github-tools/server/Cargo.toml my-mcp-project/server/