sequenceDiagram
participant AI as AI Agent
participant Server as MCPR Server
participant Session as R Session
Note over Session: User runs mcpr_session_start()
Session->>Session: Creates mcprSession instance & finds an open port
Session->>Session: Starts an asynchronous listener on a nanonext socket
Note over AI: User asks agent to connect to R
AI->>Server: Launches MCPR Server process
Server->>Server: Initializes and scans local ports for active sessions
Server->>Session: Sends discovery ping via socket
Session->>Server: Responds with session metadata (ID, PID, etc.)
Server->>AI: Forwards available session list (result of 'manage_r_sessions("list")')
Note over AI: User asks agent to join a specific session
AI->>Server: Sends 'manage_r_sessions("join", session=ID)'
Server->>Session: Establishes persistent connection for message routing
Session->>Server: Acknowledges connection
Server->>AI: Confirms the agent is now connected to the R session
The MCPR framework is built on a robust client-server architecture designed to bridge the gap between stateless AI agents and the stateful, interactive nature of R programming. This article delves into the technical design, communication flow, and core principles that enable this integration.
At its heart, MCPR implements a client-server model with a unique session-joining paradigm, distinguishing it from typical stateless execution environments.
┌─────────────┐ JSON-RPC 2.0 ┌─────────────┐ Socket Comm ┌─────────────┐
│ AI Agent │<──────────────────>│ MCPR Server │<─────────────────>│ R Session │
│ (Client) │ via stdin/ │ (Proxy) │ via nanonext │ (Provider) │
└─────────────┘ stdout └─────────────┘ sockets └─────────────┘
This architecture consists of three primary components:
-
The AI Agent (Client): This is the large language model operating within its environment (e.g., Claude Desktop, a VS Code extension). It communicates using a standardized JSON-RPC 2.0 protocol over
stdin/stdout. -
The MCPR Server (Proxy): A transient, lightweight
Rscriptprocess that acts as a bridge. Its main roles are to discover active R sessions on the local machine and route messages between the AI Agent and the chosen R Session. -
The R Session (Provider): This is the user’s interactive R session where the data analysis occurs. By running
mcpr_session_start(), the user turns their R session into a service provider, listening for connections and executing tool calls within its persistent environment.
Communication Workflow
The entire workflow is designed to be seamless from the user’s perspective, but it involves a sophisticated sequence of events for discovery, connection, and execution.
Session Discovery and Connection
Before an agent can execute code, it must first discover and connect to a running R session. This process ensures that the agent interacts with the correct R environment intended by the user.
Tool Execution
Once connected, the agent can use the provided tools (execute_r_code, create_plot, etc.). Each tool call follows a structured path from the agent to the R session and back, with careful handling of data types.
sequenceDiagram
participant AI as AI Agent
participant Server as MCPR Server
participant Session as R Session
participant Tool as Tool Function
AI->>Server: JSON-RPC Request: {tool: "execute_r_code", args: {code: "..."}, ...}
Server->>Server: Validates tool exists
Server->>Session: Forwards the request via the established socket connection
Session->>Session: Deserializes arguments, reconstructing R objects from JSON
Session->>Tool: Executes the target R function (e.g., execute_r_code) with reconstructed arguments
Tool->>Session: Returns a standard R object (list, data.frame, etc.)
Session->>Session: Serializes the R result into a type-preserving JSON structure
Session->>Server: Sends JSON-RPC response containing the serialized result
Server->>AI: Forwards the final JSON response via stdout
Key Design Principles
The architecture is guided by several modern R development practices to ensure it is robust, maintainable, and extensible.
R6 Class-Based System
MCPR heavily utilizes the R6 class system to manage state and behavior.
-
BaseMCPR: A foundational class providing shared utilities like logging, state management, and resource cleanup. -
mcprServer&mcprClient: Concrete implementations for the server (proxy) and client (session) roles, inheriting common functionality fromBaseMCPR. -
mcprSession: Manages the lifecycle of a single R session listener, including handling timeouts and ensuring proper resource cleanup on exit.
Layered Communication
The communication stack is divided into distinct layers, each with a specific responsibility:
- Protocol Layer: Handles the JSON-RPC 2.0 message structure, including requests, responses, and error notifications.
-
Transport Layer: Manages asynchronous, non-blocking communication using the
nanonextpackage, which provides a robust socket-based messaging implementation. - Execution Layer: Dispatches requests to the appropriate local tool functions within the R session.
- Type Conversion Layer: A critical component that handles the serialization (R to JSON) and deserialization (JSON to R) of data, preserving R’s specific data types across the wire.
Advanced Type Preservation
A significant challenge in cross-language communication is preserving data fidelity. A data.frame in R is not the same as a generic JSON array of objects. MCPR solves this by using a custom serialization system.
When an R object is converted to JSON, a special _mcp_type marker is added to annotate the data. When the JSON is received, this marker is used to reconstruct the original R object with its correct class and attributes (e.g., factor, Date, data.frame). This ensures that code executed by the agent behaves exactly as if it were run directly in the R console.
sequenceDiagram
participant R_Side as R Environment
participant JSON_Transport as JSON Payload
participant Target_Side as Receiving Environment
Note over R_Side: Has a data.frame object
R_Side->>R_Side: to_mcpr_json() serializes it
R_Side->>JSON_Transport: Sends JSON with {"_mcp_type": "data.frame", "value": [...] }
JSON_Transport->>Target_Side: Receives JSON with type metadata
Target_Side->>Target_Side: from_mcpr_json() uses "_mcp_type" to reconstruct the data.frame
Note over Target_Side: Now has a native data.frame object
This bidirectional, type-preserving communication is fundamental to MCPR’s ability to maintain the integrity of the R workspace throughout a long and complex human-AI collaborative session.
