|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working |
| 4 | +with code in this repository. |
| 5 | + |
| 6 | +## Overview |
| 7 | + |
| 8 | +plumber2mcp is an R package that adds Model Context Protocol (MCP) |
| 9 | +support to Plumber APIs. It transforms existing Plumber endpoints into |
| 10 | +MCP tools that AI assistants can discover and call via JSON-RPC. |
| 11 | + |
| 12 | +## Core Architecture |
| 13 | + |
| 14 | +### Main Components |
| 15 | + |
| 16 | +**R/pr_mcp.R** - Core implementation with three key functions: - |
| 17 | +[`pr_mcp()`](https://armish.github.io/plumber2mcp/reference/pr_mcp.md) - |
| 18 | +Main user-facing function that adds MCP capabilities to a Plumber |
| 19 | +router - `create_mcp_handler()` - Creates JSON-RPC message handlers for |
| 20 | +MCP protocol - `extract_plumber_tools()` - Converts Plumber endpoints to |
| 21 | +MCP tool definitions |
| 22 | + |
| 23 | +**Protocol Implementation**: - HTTP transport layer (Plumber endpoints |
| 24 | +at `/mcp` and `/mcp/messages`) - JSON-RPC 2.0 protocol handlers for |
| 25 | +`initialize`, `tools/list`, and `tools/call` methods - Automatic |
| 26 | +endpoint discovery and schema generation from function signatures |
| 27 | + |
| 28 | +**Transport Bridge**: - `inst/examples/stdio-wrapper.py` - Python bridge |
| 29 | +that converts stdio transport (expected by MCP clients) to HTTP calls - |
| 30 | +Handles R’s jsonlite serialization quirks (single-element arrays, empty |
| 31 | +objects) |
| 32 | + |
| 33 | +### Key Design Patterns |
| 34 | + |
| 35 | +1. **Endpoint Transformation**: Plumber endpoints become MCP tools with |
| 36 | + naming pattern `{METHOD}__{path}` (e.g., `GET__echo`, `POST__add`) |
| 37 | + |
| 38 | +2. **Schema Generation**: Function parameters automatically converted |
| 39 | + to JSON Schema with roxygen comment parsing for descriptions |
| 40 | + |
| 41 | +3. **Transport Abstraction**: Core R implementation uses HTTP; stdio |
| 42 | + wrapper enables compatibility with standard MCP clients |
| 43 | + |
| 44 | +## Development Workflow |
| 45 | + |
| 46 | +### Testing |
| 47 | + |
| 48 | +``` bash |
| 49 | +# Run all tests |
| 50 | +R -e "devtools::test()" |
| 51 | + |
| 52 | +# Run specific test |
| 53 | +R -e "testthat::test_file('tests/testthat/test-pr_mcp.R')" |
| 54 | + |
| 55 | +# Run with coverage |
| 56 | +R -e "covr::package_coverage()" |
| 57 | +``` |
| 58 | + |
| 59 | +### Package Development |
| 60 | + |
| 61 | +``` bash |
| 62 | +# Install dev version |
| 63 | +R -e "devtools::install()" |
| 64 | + |
| 65 | +# Generate documentation |
| 66 | +R -e "devtools::document()" |
| 67 | + |
| 68 | +# Check package |
| 69 | +R -e "devtools::check()" |
| 70 | +``` |
| 71 | + |
| 72 | +### Testing MCP Integration |
| 73 | + |
| 74 | +``` bash |
| 75 | +# Start example server |
| 76 | +R -e "source('inst/examples/run_mcp_server.R')" |
| 77 | + |
| 78 | +# Test HTTP endpoints directly |
| 79 | +curl -X POST http://localhost:8000/mcp/messages \ |
| 80 | + -H 'Content-Type: application/json' \ |
| 81 | + -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' |
| 82 | + |
| 83 | +# Test with MCP client (requires stdio wrapper) |
| 84 | +cd inst/examples |
| 85 | +mcp-cli --config-file server_config.json tools |
| 86 | +``` |
| 87 | + |
| 88 | +## JSON-RPC Protocol Flow |
| 89 | + |
| 90 | +1. **Initialize**: Client sends `initialize` with protocol version, |
| 91 | + receives server capabilities |
| 92 | +2. **Tool Discovery**: Client calls `tools/list`, receives array of |
| 93 | + available tools with schemas |
| 94 | +3. **Tool Execution**: Client calls `tools/call` with tool name and |
| 95 | + arguments, receives results |
| 96 | + |
| 97 | +## Known Issues & Workarounds |
| 98 | + |
| 99 | +**R Serialization**: jsonlite creates single-element arrays for scalars. |
| 100 | +The stdio wrapper (`stdio-wrapper.py`) handles these conversions: - |
| 101 | +`["2.0"]` → `"2.0"` for protocol fields - |
| 102 | +[`{}`](https://rdrr.io/r/base/Paren.html) → `null` for empty id fields - |
| 103 | +Ensures `content` is always an array of content items |
| 104 | + |
| 105 | +**Transport Mismatch**: R implementation uses HTTP, but most MCP clients |
| 106 | +expect stdio. The Python wrapper bridges this gap. |
| 107 | + |
| 108 | +## CI/CD |
| 109 | + |
| 110 | +GitHub Actions workflows: - `R-CMD-check.yaml` - Multi-platform R |
| 111 | +package testing - `test-coverage.yaml` - Code coverage reporting via |
| 112 | +Codecov |
0 commit comments