使用说明
水管2mcp
通过单个函数调用将模型上下文协议(MCP)支持添加到Plumber API中。
什么是MCP?
模型上下文协议(MCP)是一种标准协议,使AI助手(如Claude、ChatGPT等)能够与外部工具和服务进行交互。通过将MCP支持添加到您的Plumber API,您可以将R功能提供为:
- 工具:人工智能助手可以直接调用您的API端点
- 资源:AI助手可以读取文档、数据和分析结果
- 提示词:AI助手可以使用预定义的模板来指导交互
安装
# Install from GitHub
remotes::install_github("armish/plumber2mcp")
依赖项
此软件包要求:
- R(>=4.0.0)
- 水管工(>=1.0.0)
- Jsonlite
- 高温工程试验堆
快速开始
HTTP传输(默认)
library(plumber)
library(plumber2mcp)
# Create and run a Plumber API with MCP support via HTTP
pr("plumber.R") %>%
pr_mcp(transport = "http") %>%
pr_run(port = 8000)
您的API现在具有:
- 常规HTTP端点位于
http://localhost:8000/ - MCP服务器位于
http://localhost:8000/mcp
标准传输(本地MCP)
library(plumber)
library(plumber2mcp)
# Create and run a Plumber API with native stdio transport
pr("plumber.R") %>%
pr_mcp(transport = "stdio")
与mcp-cli或其他mcp客户端一起使用:
- 创建一个
server_config.json文件:
{
"mcpServers": {
"plumber2mcp": {
"command": "Rscript",
"args": ["-e", "plumber::pr('api.R') %>% plumber2mcp::pr_mcp(transport='stdio')"],
"cwd": "."
}
}
}
- 测试连接:
mcp-cli servers # Should show your server as "Ready"
mcp-cli tools # List available tools
mcp-cli cmd --tool GET__echo --tool-args '{"msg": "Hello!"}' # Call a tool
运作原理
这 pr_mcp() 自动功能:
- 发现您的端点:扫描Plumber API中的所有端点
- 创建MCP工具:将每个端点转换为具有适当架构的MCP工具
- 添加MCP端点:添加必要的MCP协议端点
- 处理JSON-RPC:通过JSON-RPC管理所有MCP通信
- 支持资源:允许AI助手从R环境中读取文档和数据
- 支持提示:公开可重用的提示模板,指导人工智能交互
- 生成丰富的模式:使用您的roxygen注释中的文档创建详细的输入/输出模式
增强的文档和模式生成
plumber2mcp通过分析您的roxygen注释和函数签名,自动为您的API端点生成丰富的JSON模式和详细的文档。此功能受FastAPI MCP的启发,使您的R API更容易被AI助手使用。
丰富的工具描述
当您使用roxygen注释记录端点时,管道工2mcp会创建全面的工具描述:
#* Calculate statistical operations on numeric data
#*
#* This endpoint performs various statistical calculations on a vector of numbers.
#* It supports multiple operations and handles missing values.
#*
#* @param numbers Numeric vector of values to calculate statistics for
#* @param operation Statistical operation to perform: "mean", "median", "sum", "sd" (default: "mean")
#* @param na_rm:bool Logical value indicating whether to remove NA values (default: TRUE)
#* @param digits:int Number of decimal places to round the result (default: 2)
#* @return List containing the calculated result and metadata
#* @post /calculate
function(numbers, operation = "mean", na_rm = TRUE, digits = 2) {
# Convert input to numeric
if (is.character(numbers)) {
numbers <- as.numeric(strsplit(numbers, ",")[[1]])
} else {
numbers <- as.numeric(numbers)
}
result <- switch(operation,
"mean" = mean(numbers, na.rm = na_rm),
"median" = median(numbers, na.rm = na_rm),
"sum" = sum(numbers, na.rm = na_rm),
"sd" = sd(numbers, na.rm = na_rm),
stop("Unknown operation: ", operation)
)
list(
result = round(result, digits),
operation = operation,
count = length(numbers[!is.na(numbers)]),
input_length = length(numbers)
)
}
这将创建一个MCP工具,其中包含:
增强描述:
Calculate statistical operations on numeric data
This endpoint performs various statistical calculations on a vector of numbers.
It supports multiple operations and handles missing values.
Parameters:
- numbers (string): Numeric vector of values to calculate statistics for
- operation (string) [default: mean]: Statistical operation to perform: "mean", "median", "sum", "sd"
- na_rm (boolean) [default: TRUE]: Logical value indicating whether to remove NA values
- digits (integer) [default: 2]: Number of decimal places to round the result
HTTP Method: POST
Path: /calculate
输入架构:
{
"type": "object",
"properties": {
"numbers": {
"type": "string",
"description": "Numeric vector of values to calculate statistics for"
},
"operation": {
"type": "string",
"description": "Statistical operation to perform: \"mean\", \"median\", \"sum\", \"sd\"",
"default": "mean"
},
"na_rm": {
"type": "boolean",
"description": "Logical value indicating whether to remove NA values",
"default": true
},
"digits": {
"type": "integer",
"description": "Number of decimal places to round the result",
"default": 2
}
},
"required": ["numbers"]
}
输出架构:
{
"type": "object",
"description": "Structured response object",
"properties": {
"result": {
"type": "number",
"description": "Response field: result"
},
"operation": {
"type": "string",
"description": "Response field: operation"
},
"count": {
"type": "number",
"description": "Response field: count"
},
"input_length": {
"type": "number",
"description": "Response field: input_length"
}
}
}
类型检测和模式特征
-
智能类型映射:自动将R类型映射到JSON模式类型:
logical→booleaninteger→integernumeric/double→numbercharacter→string- 并支持水管工类型的注释,如
:bool,:int,:array
-
默认值检测:从函数签名中提取默认值并将其包含在架构中
-
必需参数与可选参数:根据参数是否具有默认值自动确定需要哪些参数
-
输出模式生成:分析函数的返回语句以自动生成响应模式
-
丰富的参数文档:从roxygen中提取参数描述
@param标签
为什么这对人工智能助理很重要
借助增强的模式,AI助手可以:
- 更好地理解你的API:丰富的描述有助于AI助手理解每个端点的作用
- 提供更好的建议:详细的参数信息有助于AI助手建议适当的值
- 生成更好的代码:输出模式帮助人工智能助手了解API的预期
- 减少错误:类型信息和所需/可选参数检测减少了API调用错误
- 自我文档:您的API成为人类和人工智能的自主文档
AI助手交互示例
如果没有增强的模式:
User: "Can you help me calculate the mean of some numbers using this API?"
AI: "I can see there's a calculate endpoint, but I'm not sure what parameters it needs..."
使用增强的模式:
User: "Can you help me calculate the mean of some numbers using this API?"
AI: "I can see you have a calculate endpoint that performs statistical operations!
It needs a 'numbers' parameter (required) and optionally 'operation' (defaults to 'mean'),
'na_rm' (defaults to TRUE), and 'digits' (defaults to 2).
Let me call it for you:
POST /calculate with {"numbers": "1,2,3,4,5"}
This will return an object with the result, operation used, count of valid numbers,
and input length."
文档的最佳实践
要充分利用增强的模式生成:
- 使用描述性的roxygen注释:写清楚标题和描述
- 记录所有参数:使用
@param带有清晰描述的标签 - 在有帮助时指定类型:使用
:bool,:int,:array注释清晰 - 提供有意义的默认值:默认值出现在架构中
- 使用一致的返回结构:返回带有命名元素的列表,以获得更好的输出模式
- 在描述中包含示例:帮助AI助手理解预期的格式
MCP端点
曾经 pr_mcp() 应用时,您的API将公开:
GET /mcp-服务器信息和功能POST /mcp/messages-MCP协议的JSON-RPC消息处理程序
示例
给定一个简单的管道工API:
#* Echo back the input
#*
#* Simple endpoint that echoes back whatever message you send it
#*
#* @param msg:string The message to echo back (default: "Hello World")
#* @get /echo
function(msg = "Hello World") {
list(message = paste("Echo:", msg))
}
#* Add two numbers together
#*
#* Performs arithmetic addition on two numeric values
#*
#* @param a:number First number to add
#* @param b:number Second number to add
#* @param precision:int Number of decimal places to round result (default: 2)
#* @post /add
function(a, b, precision = 2) {
result <- as.numeric(a) + as.numeric(b)
list(
result = round(result, precision),
operation = "addition",
inputs = c(a, b)
)
}
这些端点成为具有完整模式的丰富MCP工具:
GET__echo-使用智能默认处理回显消息POST__add-添加两个具有可配置精度和结构化输出的数字
增强的文档为AI助手提供了有关参数类型、默认值、描述和预期响应格式的详细信息。
提示支持
提示是可重复使用的模板,人工智能助手可以发现并用于与您的API交互。它们为常见任务和工作流程提供结构化的指导。
什么是提示?
MCP中的提示是预定义的消息模板,它们:
- 帮助人工智能助手了解如何有效使用API
- 为复杂的工作流程提供结构化的指导
- 可以接受参数来自定义提示内容
- 支持多回合对话
添加提示
# Simple prompt with no arguments
pr %>%
pr_mcp(transport = "stdio") %>%
pr_mcp_prompt(
name = "r-help",
description = "Get help with R programming",
func = function() {
paste(
"I need help with R programming.",
"Please provide guidance on best practices and common patterns.",
sep = "\n"
)
}
)
# Prompt with arguments
pr %>%
pr_mcp(transport = "stdio") %>%
pr_mcp_prompt(
name = "analyze-dataset",
description = "Generate a comprehensive analysis plan for an R dataset",
arguments = list(
list(
name = "dataset",
description = "Name of the R dataset to analyze",
required = TRUE
),
list(
name = "focus",
description = "Specific aspect to focus on",
required = FALSE
)
),
func = function(dataset, focus = "general") {
sprintf(
paste(
"Please analyze the %s dataset in R.",
"Focus: %s",
"",
"Provide:",
"1. Summary statistics",
"2. Data quality assessment",
"3. Key insights",
sep = "\n"
),
dataset, focus
)
}
)
# Multi-turn conversation prompt
pr %>%
pr_mcp(transport = "stdio") %>%
pr_mcp_prompt(
name = "code-review",
description = "Review R code for quality and best practices",
arguments = list(
list(name = "code", description = "The R code to review", required = TRUE)
),
func = function(code) {
list(
list(
role = "user",
content = list(
type = "text",
text = paste("Please review this R code:", code, sep = "\n\n")
)
),
list(
role = "assistant",
content = list(
type = "text",
text = "I'll review your code for correctness, performance, and style."
)
),
list(
role = "user",
content = list(
type = "text",
text = "Please provide specific suggestions for improvement."
)
)
)
}
)
提示消息格式
提示函数可以以多种格式返回消息:
- 简单字符串 -自动转换为用户消息:
func = function() "Hello World"
- 结构化消息 -完全控制角色和内容:
func = function() {
list(
role = "user",
content = list(type = "text", text = "Your message")
)
}
- 多条消息 -对于多回合对话:
func = function() {
list(
list(role = "user", content = list(type = "text", text = "First message")),
list(role = "assistant", content = list(type = "text", text = "Second message"))
)
}
提示用例
工作流程指导
pr_mcp_prompt(
pr,
name = "data-pipeline",
description = "Guide for building data processing pipelines",
arguments = list(
list(name = "data_type", description = "Type of data to process", required = TRUE)
),
func = function(data_type) {
sprintf("Create a data processing pipeline for %s data...", data_type)
}
)
代码生成模板
pr_mcp_prompt(
pr,
name = "create-endpoint",
description = "Template for creating new Plumber endpoints",
func = function() {
paste(
"Generate a Plumber endpoint with:",
"1. Proper roxygen documentation",
"2. Input validation",
"3. Error handling",
"4. Example usage",
sep = "\n"
)
}
)
领域特定协助
pr_mcp_prompt(
pr,
name = "statistical-test",
description = "Choose and implement appropriate statistical tests",
arguments = list(
list(name = "research_question", description = "Research question", required = TRUE)
),
func = function(research_question) {
sprintf(
paste(
"Research Question: %s",
"",
"Help me:",
"1. Choose the appropriate statistical test",
"2. Check assumptions",
"3. Implement in R",
"4. Interpret results",
sep = "\n"
),
research_question
)
}
)
示例:使用提示完成设置
library(plumber)
library(plumber2mcp)
pr("api.R") %>%
pr_mcp(transport = "stdio") %>%
# Add analysis prompt
pr_mcp_prompt(
name = "analyze",
description = "Analyze data from the API",
func = function() {
"Guide me through analyzing the data available from this API."
}
) %>%
# Add troubleshooting prompt
pr_mcp_prompt(
name = "troubleshoot",
description = "Help troubleshoot API issues",
arguments = list(
list(name = "issue", description = "Description of the issue", required = TRUE)
),
func = function(issue) {
sprintf("I'm experiencing this issue with the API: %s\n\nHow can I resolve it?", issue)
}
)
资源支持
资源允许AI助手从R环境中读取内容,如文档、数据描述或分析结果。
添加自定义资源
# Create a Plumber API with resources
pr(...) %>%
pr_mcp(transport = "stdio") %>%
# Add a resource that provides dataset information
pr_mcp_resource(
uri = "/data/iris-summary",
func = function() {
paste(
"Dataset: iris",
paste("Dimensions:", paste(dim(iris), collapse = " x ")),
"",
capture.output(summary(iris)),
sep = "\n"
)
},
name = "Iris Dataset Summary",
description = "Statistical summary and structure of the iris dataset"
) %>%
# Add a resource that shows current memory usage
pr_mcp_resource(
uri = "/system/memory",
func = function() {
mem <- gc()
paste(
"R Memory Usage:",
paste("Used (Mb):", round(sum(mem[,2]), 2)),
paste("Gc Trigger (Mb):", round(sum(mem[,6]), 2)),
"",
"Object sizes in workspace:",
capture.output(print(object.size(ls.str()), units = "Mb")),
sep = "\n"
)
},
name = "R Memory Usage",
description = "Current R session memory statistics"
) %>%
# Add a resource with model diagnostics
pr_mcp_resource(
uri = "/models/latest-lm",
func = function() {
# Example: fit a model and return diagnostics
model <- lm(mpg ~ wt + hp, data = mtcars)
paste(
"Linear Model: mpg ~ wt + hp",
"",
capture.output(summary(model)),
"",
"Diagnostic plots saved to: /tmp/lm_diagnostics.png",
sep = "\n"
)
},
name = "Latest Linear Model",
description = "Diagnostics for the most recent linear model",
mimeType = "text/plain"
)
内置R帮助资源
pr(...) %>%
pr_mcp(transport = "stdio") %>%
pr_mcp_help_resources() # Adds help for common R functions
这会自动为以下内容添加资源:
- R帮助主题(
/help/mean,/help/lm等等) - R会话信息(
/r/session-info) - 已安装的软件包(
/r/packages)
带参数的动态资源
虽然当前的实现不支持URI模板,但您可以创建根据运行时条件进行调整的资源:
# Create resources based on available data files
data_files <- list.files("data/", pattern = "\\.csv$")
my_pr <- pr(...)
for (file in data_files) {
my_pr <- my_pr %>%
pr_mcp_resource(
uri = paste0("/data/", tools::file_path_sans_ext(file)),
func = local({
current_file <- file # Capture the file name
function() {
data <- read.csv(file.path("data", current_file))
paste(
paste("File:", current_file),
paste("Rows:", nrow(data)),
paste("Columns:", paste(names(data), collapse = ", ")),
"",
"First 5 rows:",
capture.output(print(head(data, 5))),
sep = "\n"
)
}
}),
name = paste("Dataset:", tools::file_path_sans_ext(file)),
description = paste("Contents of", file)
)
}
资源使用示例
一旦您的MCP服务器运行了资源,AI助手就可以:
- 浏览可用资源 -AI可以列出所有资源,以查看可用的信息
- 阅读特定资源 -AI可以读取资源内容以了解您的数据和环境
- 根据上下文使用资源 -AI在回答问题或编写代码时可以参考资源信息
与AI助手的交互示例:
You: "What datasets are available in this R session?"
AI: *Lists resources and reads relevant ones*
"I can see you have the iris dataset available. Based on the
/data/iris-summary resource, it has 150 observations of 5 variables..."
You: "Can you help me analyze the relationship between Sepal.Length and Petal.Length?"
AI: *Reads the iris summary resource for context*
"Based on the iris dataset summary, I can see that Sepal.Length ranges
from 4.3 to 7.9 and Petal.Length from 1.0 to 6.9. Let me create a
linear model to analyze their relationship..."
高级用法
自定义MCP路径
my_pr %>% pr_mcp(transport = "http", path = "/my-mcp-server")
筛选端点
# Include only specific endpoints
my_pr %>% pr_mcp(transport = "http", include_endpoints = c("GET__echo", "POST__add"))
# Exclude specific endpoints
my_pr %>% pr_mcp(transport = "stdio", exclude_endpoints = c("POST__internal"))
自定义服务器信息
my_pr %>% pr_mcp(
transport = "http",
server_name = "my-api-mcp",
server_version = "1.0.0"
)
完整示例
以下是创建启用MCP的API的分步示例:
- 创建水管工API文件(
my_api.R):
#* @apiTitle My MCP-Enabled API
#* @apiDescription API with MCP support for AI assistants
#* Get current time
#* @get /time
function() {
list(time = Sys.time())
}
#* Calculate factorial
#* @param n Integer to calculate factorial
#* @post /factorial
function(n) {
n <- as.integer(n)
if (n < 0) stop("n must be non-negative")
list(result = factorial(n))
}
- 创建并运行服务器:
library(plumber)
library(plumber2mcp)
pr("my_api.R") %>%
pr_mcp(transport = "http") %>%
pr_run(port = 8000)
- 您的API现在可以访问:
- HTTP API:
http://localhost:8000/ - MCP端点:
http://localhost:8000/mcp - API文件:
http://localhost:8000/__docs__/
- HTTP API:
测试
运行示例服务器:
source(system.file("examples/run_mcp_server.R", package = "plumber2mcp"))
使用MCP客户端进行测试:
source(system.file("examples/test_mcp_client.R", package = "plumber2mcp"))
使用AI助手
MCP服务器运行后,您可以配置AI助手来使用它:
克劳德桌面
添加到您的Claude配置文件中:
{
"mcpServers": {
"my-r-api": {
"url": "http://localhost:8000/mcp"
}
}
}
其他人工智能助理
查看AI助手的文档,了解MCP配置说明。
MCP协议详细信息
此包实现了 模型上下文协议 规范。MCP端点处理:
- 工具发现:将所有可用的Plumber端点作为MCP工具列出
- 工具执行:将MCP工具调用转换为Plumber端点请求
- 错误处理:正确格式化MCP响应格式中的错误
MCP检验员测试
MCP检查员 是用于测试和调试MCP服务器的工具。
在HTTP传输中使用MCP检查器
- 使用HTTP传输启动水管工API:
library(plumber)
library(plumber2mcp)
pr("api.R") %>%
pr_mcp(transport = "http") %>%
pr_run(port = 8000)
- 在新终端中,导航到示例目录:
cd /path/to/plumber2mcp/inst/examples
mcp-inspector --config http_wrapper_config.json --server plumber2mcp
这 stdio-wrapper.py 该脚本将MCP Inspector的stdio接口连接到您的HTTP服务器。
使用带标准传输的MCP检查器
直接使用stdio配置:
cd /path/to/plumber2mcp/inst/examples
mcp-inspector --config stdio_config.json --server plumber2mcp
故障排除
常见问题
- 端口已在使用中:更改中的端口号
pr_run(port = 8001) - 未找到MCP端点:确保你打过电话
pr_mcp()之前pr_run() - 工具未显示:检查Plumber端点是否具有正确的注释
- MCP检查器连接错误:
- 对于HTTP:在启动MCP检查器之前,确保服务器在端口8000上运行
- 检查一下
cwd配置文件中的路径指向正确的目录
调试模式
启用详细日志记录:
# For stdio transport
my_pr %>% pr_mcp(transport = "stdio", debug = TRUE)
# For HTTP transport (debug not available)
my_pr %>% pr_mcp(transport = "http") %>% pr_run(port = 8000)
贡献
欢迎投稿!请在GitHub上提交问题和拉取请求。
许可证
麻省理工学院
