Skip to contents

Introduction

The Model Context Protocol (MCP) allows Large Language Models like Claude to interact with external tools and data sources. However, R’s stdin handling in subprocess contexts requires special handling. The mcpr package solves this by providing Node.js wrapper templates that properly manage communication between MCP clients and R servers.

Quick Start

Generating a Simple Server

library(mcpr)

# Generate a basic MCP server
generate_mcp_server(
  name = "hello-world",
  title = "Hello World Server",
  description = "A simple MCP server that greets users"
)

This creates a complete server package in ./mcp-hello-world/ with: - wrapper.js - Node.js wrapper that handles stdin/stdout - server.R - R server implementation - package.json - NPM package configuration - test.js - Test script to validate the server - README.md - Documentation

Testing Your Server

cd mcp-hello-world
npm install
npm test

Adding to Claude Desktop

Add to your Claude Desktop configuration:

{
  "mcpServers": {
    "hello-world": {
      "command": "node",
      "args": ["/path/to/mcp-hello-world/wrapper.js"]
    }
  }
}

Creating Servers with Tools

Basic Example

# Define tools
tools <- list(
  greet = list(
    description = "Greet a person by name",
    parameters = list(
      name = list(type = "string", description = "Name to greet")
    )
  ),
  calculate = list(
    description = "Evaluate an R expression",
    parameters = list(
      expression = list(type = "string", description = "R expression to evaluate")
    )
  )
)

# Generate server with tools
generate_mcp_server(
  name = "my-tools",
  title = "My R Tools",
  description = "Useful R tools for data analysis",
  tools = tools
)

Using the Programmatic API

# Create server programmatically
server <- mcp(name = "Data Analyzer", version = "1.0.0")

# Add tools
server$mcp_tool(
  name = "summarize",
  fn = function(data) {
    summary(data)
  },
  description = "Summarize a dataset"
)

server$mcp_tool(
  name = "correlation",
  fn = function(x, y) {
    cor(x, y)
  },
  description = "Calculate correlation"
)

# Generate standalone package
server$generate(path = "./servers", template = "full")

Working with Resources

Resources provide read-only access to data:

resources <- list(
  list(
    uri = "data://iris",
    name = "Iris Dataset",
    description = "Classic iris dataset"
  ),
  list(
    uri = "info://system",
    name = "System Information",
    description = "R system information"
  )
)

generate_mcp_server(
  name = "data-provider",
  title = "Data Provider",
  description = "Provides access to datasets",
  resources = resources
)

Using Configuration Files

YAML Configuration

Create server-config.yaml:

name: analysis-server
title: Statistical Analysis Server
description: Comprehensive statistical analysis tools
version: 1.0.0
author: Your Name

tools:
  t_test:
    description: Perform t-test
    parameters:
      x:
        type: array
        description: First sample
      y:
        type: array
        description: Second sample
      
  regression:
    description: Linear regression
    parameters:
      formula:
        type: string
        description: Model formula
      data:
        type: object
        description: Data frame
        
resources:
  - uri: "data://example"
    name: "Example Data"
    description: "Sample datasets"

Generate from configuration:

generate_from_config("server-config.yaml")

JSON Configuration

# Create example configuration
create_example_config("server-config.json", format = "json")

# Generate from JSON
generate_from_config("server-config.json")

Templates

Full Template

The default “full” template includes: - Complete MCP protocol implementation - Support for tools, resources, and prompts - Comprehensive error handling - Detailed comments and documentation

Minimal Template

For simple use cases:

generate_mcp_server(
  name = "simple",
  title = "Simple Server",
  description = "Minimal MCP server",
  template = "minimal"
)

Advanced Usage

Exposing R Packages

server <- mcp(name = "Stats Server", version = "1.0.0")

# Expose specific functions from stats package
server$mcp_package(
  package = "stats",
  include = c("lm", "glm", "t.test", "cor.test")
)

# Generate server
server$generate()

Custom Wrapper Configuration

The Node.js wrapper filters stderr to prevent R output from breaking the MCP connection. You can customize the filtering:

// In wrapper.js
const filterPatterns = [
  /^Attaching package:/,
  /^The following objects are masked/,
  /^Loading required package:/,
  // Add custom patterns
];

HTTP Transport (New!)

As of version 0.1.0, mcpr supports HTTP transport as an alternative to stdio. HTTP transport offers several advantages:

  • Multiple concurrent clients: Unlike stdio which is limited to one client, HTTP servers can handle multiple connections
  • Easier debugging: Use standard HTTP tools like curl or Postman
  • Better deployment options: Deploy to cloud platforms, containers, or behind load balancers
  • No subprocess complexity: Avoids R’s stdin handling limitations

Creating an HTTP Server

# Using the convenience function
server <- mcp_http(
  name = "My HTTP Server",
  version = "1.0.0",
  host = "127.0.0.1",
  port = 8080
)

# Add tools, resources, and prompts as usual
server$mcp_tool(
  name = "analyze",
  fn = function(data) { summary(as.numeric(strsplit(data, ",")[[1]])) },
  description = "Analyze comma-separated numbers"
)

# Start the server
server$mcp_run()  # Automatically uses HTTP transport

Quick Start with HTTP

# Start a hello world HTTP server
mcp_hello_world_http(port = 8080)

# Test it with curl
# curl -X POST http://localhost:8080/mcp \
#   -H "Content-Type: application/json" \
#   -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'

HTTP Server Features

  1. Built-in endpoints:

    • POST /mcp - Main MCP protocol endpoint
    • GET /health - Health check endpoint
    • GET / - Server information
  2. Logging support:

    server <- mcp_http(
      name = "Logged Server",
      log_file = "server.log",
      log_level = "debug"  # debug, info, warn, error
    )
  3. Swagger documentation (when enabled):

    server$mcp_run(docs = TRUE)
    # Visit http://localhost:8080/__docs__

Migrating from STDIO to HTTP

# Before (stdio)
server <- mcp(name = "My Server")
# ... add tools ...
server$mcp_run(transport = "stdio")

# After (HTTP)
server <- mcp(name = "My Server")
# ... add tools ...
server$mcp_run(transport = "http", port = 8080)

Using with Claude Desktop

For Claude Desktop configuration with HTTP servers:

{
  "mcpServers": {
    "my-http-server": {
      "command": "Rscript",
      "args": ["-e", "library(mcpr); server <- mcp_http('My Server'); server$mcp_tool('hello', function(name='World') paste('Hello', name)); server$mcp_run()"]
    }
  }
}

Or create a script file:

# my-server.R
library(mcpr)
server <- mcp_http("My Server", port = 8080)
# Add your tools here
server$mcp_run()
{
  "mcpServers": {
    "my-http-server": {
      "command": "Rscript",
      "args": ["path/to/my-server.R"]
    }
  }
}

Deployment Options

HTTP servers can be deployed to:

  1. Local development: Run on localhost for testing
  2. Docker containers: Package your server as a container
  3. Cloud platforms: Deploy to Heroku, Google Cloud Run, etc.
  4. Posit Connect: Deploy R-based HTTP APIs
  5. Corporate networks: Run behind firewalls with proper authentication

Security Considerations

When deploying HTTP servers:

  1. Authentication: The MCP spec requires OAuth 2.1 for remote servers
  2. HTTPS: Use TLS encryption for production deployments
  3. Rate limiting: Implement rate limiting for public endpoints
  4. CORS: Configure CORS policies appropriately

Troubleshooting

Common Issues

  1. Server doesn’t connect: Ensure no stderr output from R
  2. Tools not working: Check parameter definitions match function signature
  3. Resources empty: Verify resource functions return proper content

Debug Mode

Enable debug logging:

DEBUG=1 node wrapper.js

This writes debug information to mcp-debug.log.

Best Practices

  1. Always use the Node.js wrapper - Direct R execution won’t work with Claude Desktop
  2. Keep stderr clean - Use suppressMessages() and suppressWarnings() in your R code
  3. Test thoroughly - Use the included test script before deployment
  4. Document your tools - Provide clear descriptions for better LLM understanding

Example: Complete Data Analysis Server

# Create a comprehensive data analysis server
tools <- list(
  read_csv = list(
    description = "Read CSV file",
    parameters = list(
      path = list(type = "string", description = "File path")
    )
  ),
  
  summarize = list(
    description = "Generate summary statistics",
    parameters = list(
      data = list(type = "object", description = "Data frame")
    )
  ),
  
  plot_histogram = list(
    description = "Create histogram",
    parameters = list(
      data = list(type = "array", description = "Numeric data"),
      bins = list(type = "number", description = "Number of bins")
    )
  ),
  
  linear_model = list(
    description = "Fit linear model",
    parameters = list(
      formula = list(type = "string", description = "Model formula"),
      data = list(type = "object", description = "Data frame")
    )
  )
)

resources <- list(
  list(
    uri = "data://sample",
    name = "Sample Datasets",
    description = "Built-in R datasets"
  )
)

prompts <- list(
  analyze = list(
    description = "Analyze a dataset comprehensively"
  )
)

generate_mcp_server(
  name = "data-analysis",
  title = "R Data Analysis Server",
  description = "Complete data analysis toolkit",
  tools = tools,
  resources = resources,
  prompts = prompts,
  author = "Data Science Team"
)

Conclusion

The mcpr package makes it easy to create MCP servers that expose R functionality to LLMs. The Node.js wrapper ensures reliable communication, while the template system provides flexibility for different use cases.