关于 ActionMCP
ActionMCP 是一个 Ruby gem,为 Rails 应用提供作为 MCP 服务的能力。它面向需要网络化部署的生产 Rails 环境,不支持 STDIO 传输。开发者可以专注于业务逻辑,框架负责 MCP 协议的样板代码。
主要功能
- 01基于 Rails Engine 的 MCP 服务基类与辅助工具
- 02支持 MCP 2025-11-25 协议与 Streamable HTTP 端点
- 03Tool、Prompt、ResourceTemplate 三类核心抽象
- 04工具调用的同意(consent)管理与 -32002 错误码
- 05支持 Tasks 异步执行与进度上报
适用场景
- 01将 Rails 应用的业务功能以工具形式暴露给 LLM
- 02为 Rails 应用提供可供 LLM 检索的资源模板
- 03基于 Tasks 运行耗时较长的批量任务
MCP 相关
ActionMCP 作为 MCP 服务,将 Rails 应用的工具、提示词和资源暴露给 MCP 客户端。它同时包含连接远程 MCP 服务的客户端部分,但不支持通过 STDIO 连接本地进程。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
ActionMCP
ActionMCP 是一个 Ruby gem,旨在为 Ruby on Rails 应用提供 Model Context Protocol(MCP)能力,具体来说是作为 MCP 服务。
ActionMCP 面向生产环境中的 Rails 应用,不支持 STDIO 传输。由于 STDIO 尚不适用于生产环境,只适合桌面或基于脚本的使用场景,因此 ActionMCP 不包含 STDIO 支持。相反,ActionMCP 专为稳健的网络部署而构建。
ActionMCP 的客户端功能旨在连接远程 MCP 服务,而非通过 STDIO 连接本地进程。
它提供了用于创建 MCP 应用的基类和辅助工具,让 Ruby/Rails 应用更容易集成 MCP 标准。
使用 ActionMCP,你可以专注于应用逻辑,同时由它处理符合 MCP 规范所需的样板代码。
介绍
Model Context Protocol(MCP) 是一种开放协议,用于规范应用向大模型(LLM)提供上下文的方式。
可以把它看作连接 AI 助手与外部数据源和工具的通用接口。
MCP 允许 AI 系统以一致、安全的方式接入各种资源,从而实现数据与 AI 驱动应用之间的双向集成。
这意味着 AI(例如大模型)可以通过定义明确的协议向你的应用请求信息或执行操作,而你的应用也可以向 AI 提供上下文或代为执行任务。
ActionMCP 面向构建支持 MCP 的 Rails 应用的开发者。它提供一组基类和易于使用的服务接口,简化 Ruby 和 Rails 应用与 MCP 标准的集成过程。
协议支持
ActionMCP 面向已发布的 MCP 2025-11-25 协议。不接受较旧的协议版本和未发布的草案版本。核心处理功能包括:
- JSON-RPC 2.0 传输层
- 初始化期间的能力协商
- 错误处理,包含适当的错误代码(找不到方法为 -32601,需要用户同意为 -32002)
- 有状态会话管理,支持显式终止
- 处理 Tasks、tools、prompts、resources、completion、logging、sampling、roots 和 elicitation 消息
内置的 Streamable HTTP 端点会为请求返回一条 application/json 消息,并有意对 GET 请求返回 HTTP 405,因为它不提供 SSE 流。这种行为符合传输规范。出站服务请求和通知会保留在会话消息存储中,但应用需要使用 SSE 或自定义传输,才能将这些消息推送给当前请求响应之外的客户端。
如需详细(且有趣)地了解协议版本、功能和我们的设计决策,请参阅 MCP 漫游指南。
别慌:这份指南包含了你了解 MCP 协议版本所需的一切。
注意: ActionMCP 不支持 STDIO 传输。此 gem 专注于适用于生产环境的网络部署。STDIO 只适合桌面或基于脚本的试验,因此我们有意排除对它的支持。
你无需从头实现 MCP 支持,只需继承并配置提供的 Prompt、Tool 和 ResourceTemplate 类,即可向大模型公开应用功能。
ActionMCP 会处理底层 MCP 消息格式和路由,让你以最少的工作量遵循开放标准。
简而言之,ActionMCP 能帮助你更快、更少出错地构建 MCP 服务(向 AI 开放功能的组件)。
客户端连接: ActionMCP 的客户端部分仅用于连接远程 MCP 服务。不支持连接本地进程(例如通过 STDIO 连接)。
要求
- Ruby:3.4.8+ 或 4.0.0+
- Rails:8.1.1+
- 数据库:PostgreSQL、MySQL 或 SQLite3
ActionMCP 已通过 Ruby 3.4.8 和 4.0.0,以及 Rails 8.1.1+ 的测试。
安装
要开始使用 ActionMCP,请将其添加到项目中:
# Add gem to your Gemfile
$ bundle add actionmcp
# Install dependencies
bundle install
# Copy migrations from the engine
bin/rails action_mcp:install:migrations
# Generate base classes and configuration
bin/rails generate action_mcp:install
# Create necessary database tables
bin/rails db:migrate
action_mcp:install 生成器将:
- 创建基础应用程序类(ApplicationGateway、ApplicationMCPTool 等)
- 生成 MCP 配置文件(
config/mcp.yml) - 设置 MCP 组件的基本目录结构(
app/mcp/)
数据库迁移文件需使用 bin/rails action_mcp:install:migrations 单独复制。
核心组件
ActionMCP 提供三种核心抽象,简化 MCP 服务开发:
ActionMCP::Prompt
ActionMCP::Prompt 支持创建可复用的提示词模板,供大模型发现和使用。每个提示词都定义为继承自 ApplicationMCPPrompt 的 Ruby 类。
主要功能:
- 定义带说明和验证规则的预期参数
- 使用混合内容类型构建多步对话
- 支持文本、图像、音频和资源附件
- 添加不同角色(user/assistant)的消息
示例:
class AnalyzeCodePrompt < ApplicationMCPPrompt
prompt_name "analyze_code"
description "Analyze code for potential improvements"
argument :language, description: "Programming language", default: "Ruby"
argument :code, description: "Code to explain", required: true
validates :language, inclusion: { in: %w[Ruby Python JavaScript] }
def perform
render(text: "Please analyze this #{language} code for improvements:")
render(text: code)
# You can add assistant messages too
render(text: "Here are some things to focus on in your analysis:", role: :assistant)
# Even add resources if needed
render(resource: "file://documentation/#{language.downcase}_style_guide.pdf",
mime_type: "application/pdf",
blob: get_style_guide_pdf(language))
end
private
def get_style_guide_pdf(language)
# Implementation to retrieve style guide as base64
end
end
可通过实例化提示词并调用 call 方法来执行:
analyze_prompt = AnalyzeCodePrompt.new(language: "Ruby", code: "def hello; puts 'Hello, world!'; end")
result = analyze_prompt.call
ActionMCP::Tool
ActionMCP::Tool 支持创建交互式函数,大模型可以通过传入参数调用这些函数以执行特定任务。每个工具都是继承自 ApplicationMCPTool 的 Ruby 类。
主要功能:
- 定义带有类型、说明和验证规则的输入属性
- 返回多种响应类型(文本、图像、错误)
- 通过多次 render 调用逐步返回响应
- 根据属性定义自动验证输入
- 敏感操作的同意管理
示例:
class CalculateSumTool < ApplicationMCPTool
tool_name "calculate_sum"
description "Calculate the sum of two numbers"
property :a, type: "number", description: "The first number", required: true
property :b, type: "number", description: "The second number", required: true
def perform
sum = a + b
render(text: "Calculating #{a} + #{b}...")
render(text: "The sum is #{sum}")
# You can report errors if needed
if sum > 1000
report_error("Warning: Sum exceeds recommended limit")
end
# Or even images
render(image: generate_visualization(a, b), mime_type: "image/png")
end
private
def generate_visualization(a, b)
# Implementation to create a visualization as base64
end
end
同意管理
对于执行敏感操作(文件系统访问、数据库修改、外部 API 调用)的工具,可以要求用户明确同意:
class FileSystemTool < ApplicationMCPTool
tool_name "read_file"
description "Read contents of a file"
# Require explicit consent before execution
requires_consent!
property :file_path, type: "string", description: "Path to file", required: true
def perform
# This code only runs after user grants consent
content = File.read(file_path)
render(text: "File contents: #{content}")
end
end
同意流程:
- 未经同意调用需要同意的工具时,工具会返回错误代码为
-32002的 JSON-RPC 错误 - 客户端必须明确授予对特定工具的同意
- 授予同意后,该工具即可在当前会话中正常执行
- 同意仅对当前会话有效,且可随时撤销
管理同意:
# Check if consent is granted
session.consent_granted_for?("read_file")
# Grant consent for a tool
session.grant_consent("read_file")
# Revoke consent
session.revoke_consent("read_file")
可通过实例化工具并调用 call 方法来执行:
sum_tool = CalculateSumTool.new(a: 5, b: 10)
result = sum_tool.call
结构化输出(output_schema)
为工具的 structuredContent 声明 JSON Schema,并返回经过机器验证的结果,同时也可返回文本输出。
class PriceQuoteTool < ApplicationMCPTool
tool_name "price_quote"
description "Return a structured price quote"
property :sku, type: "string", description: "SKU to price", required: true
output_schema do
string :sku, required: true, description: "SKU that was priced"
number :price_cents, required: true, description: "Total price in cents"
object :meta do
string :currency, required: true, enum: %w[USD EUR GBP]
boolean :cached, default: false
end
end
def perform
price_cents = lookup_price_cents(sku) # Implement your lookup
render structured: { sku: sku,
price_cents: price_cents,
meta: { currency: "USD", cached: false } }
end
end
该 Schema 会包含在工具定义中,structured 负载会在响应中作为 structuredContent 发出,同时仍兼容文本、音频和图像渲染。
从工具返回资源链接
如果要返回 URI 而不是嵌入负载,请使用内置的 render_resource_link,它会生成 MCP resource_link 内容类型。
class ReportLinkTool < ApplicationMCPTool
tool_name "report_link"
description "Return a downloadable report link"
property :report_id, type: "string", required: true
def perform
render_resource_link(
uri: "reports://#{report_id}.json",
name: "Report #{report_id}",
description: "Downloadable JSON for report #{report_id}",
mime_type: "application/json"
)
end
end
客户端可通过单独的 resources/read 调用解析 URI,从而在保持工具响应轻量的同时,确保资源仍可被发现。
任务增强型工具(异步执行并报告进度)
当工作可能需要几秒或几分钟时,请使用 MCP Tasks。使用 task_required!(或 task_optional!)声明支持任务,并允许调用方在 tools/call 请求中发送 _meta.task 选择启用。任务运行期间,可以使用 report_progress! 发送进度更新。
class BatchIndexTool < ApplicationMCPTool
tool_name "batch_index"
description "Index many items asynchronously with progress updates"
task_required! # advertise that this tool is intended to run as a task
property :items, type: "array_string", description: "Items to index", required: true
def perform
total = items.length
items.each_with_index do |item, idx|
index_item(item) # your indexing logic
percent = ((idx + 1) * 100.0 / total).round
report_progress!(percent: percent, message: "Indexed #{idx + 1}/#{total}")
end
render(text: "Indexed #{total} items")
end
private
def index_item(item)
# Implement your indexing logic here
end
end
客户端可以通过添加顶层 task 参数将调用作为任务执行(这会创建 Task 记录,并通过 ToolExecutionJob 运行工具):
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "batch_index",
"arguments": { "items": ["a", "b", "c"] },
"task": { "ttl": 120000 }
}
}
使用 tasks/get 轮询任务状态,或使用 tasks/result 获取结果。
根据 MCP 2025-11-25 的要求,若任务处于任何非终止状态(包括 input_required),tasks/result 都会等待;任务达到 completed、failed 或 cancelled 状态后才会返回。内部数据库轮询间隔必须为正值,并且可以针对 Rails 应用进行调整:
config.action_mcp.tasks_result_poll_interval = 0.25.seconds
使用 tasks/cancel 停止非终止状态的任务。tasks/list 按最近优先的顺序返回任务,并且始终进行分页(每页默认为 50 条,或使用配置的 pagination_page_size)。有更多结果时,响应会包含不透明的 nextCursor;请将游标视为不透明令牌。
ActionMCP::ResourceTemplate
ActionMCP::ResourceTemplate 便于创建 LLM 可访问的动态资源 URI 模板。
这样,模型就可以使用参数化 URI 请求特定数据。
模板支持两种 MCP 资源接口:
resources/templates/list— 参数化 URI 模式(现有行为)resources/list— URI 已知的具体资源(通过self.list)
注意: 并非所有 MCP 客户端都支持这两个资源端点。Claude Code(截至 v2.1.50)只调用
resources/list,而 Codex 完全不提供资源方法的存根。请在模板上实现self.list,确保所有客户端都能看到资源。Crush 和 VS Code 支持这两个端点。
示例:
class ProductResourceTemplate < ApplicationMCPResTemplate
uri_template "product/{id}"
description "Access product information by ID"
mime_type "application/json"
parameter :id, description: "Product identifier", required: true
validates :id, format: { with: /\A\d+\z/, message: "must be numeric" }
# Optional: enumerate concrete resources for resources/list
def self.list(session: nil)
Product.limit(50).map do |product|
build_resource(
uri: "product/#{product.id}",
name: product.name,
title: "Product ##{product.id}"
)
end
end
# Resolve a specific resource for resources/read
def resolve
product = Product.find_by(id: id)
return unless product
ActionMCP::Content::Resource.new(
"product/#{id}",
mime_type,
text: product.to_json
)
end
end
回调:
before_resolve do |template|
# Starting to resolve product: #{template.product_id}
end
after_resolve do |template|
# Finished resolving product resource for product: #{template.product_id}
end
around_resolve do |template, block|
start_time = Time.current
resource = block.call
resource
end
当 LLM 请求与其模式匹配的资源时,资源模板会自动注册并用于处理请求。 完整 API 参考(包括分页、去重和读取约定的详细信息),请参阅 RESOURCE_TEMPLATES.md。
📚 文档
ActionMCP 提供了多份专门指南,涵盖全面的文档内容。每份指南都聚焦于特定方面,让信息更有条理,避免上下文过载:
入门与设置
- 安装与配置 — 初始设置、数据库迁移和基本配置
- 使用 Gateway 进行身份验证 — 用户身份验证和授权模式
组件开发
-
📋 TOOLS.MD — MCP 工具开发完整指南
- 生成器的使用方法和最佳实践
- 属性定义、验证和同意管理
- 用于结构化响应的输出架构
- 错误处理、测试和安全注意事项
- 附加属性和身份验证上下文等高级功能
-
📝 PROMPTS.MD — 提示词模板开发指南
- 创建可复用的提示词模板
- 多步骤对话和混合内容类型
- 参数验证和提示词串联
-
🔗 RESOURCE_TEMPLATES.md — 资源模板实现
- URI 模板模式和参数提取
- 动态资源解析和集合
- 回调和验证模式
客户端与集成
- 🔌 CLIENTUSAGE.MD — 客户端实现完整指南
- 会话管理和恢复能力
- 传输配置和连接处理
- 工具、提示词和资源集合
- 生产环境部署模式
- 🔐 GATEWAY.md — 身份验证 Gateway 指南
- 实现
ApplicationGateway - 通过
ActionMCP::Current处理标识符 - 身份验证模式、错误处理和加固技巧
- 实现
协议与技术细节
- 🚀 MCP 入门指南 - 协议版本与迁移
- 历史协议对比及当前 2025-11-25 的行为
- 设计决策与架构原理
- 迁移路径与兼容性考量
- 功能演进与技术规范(别慌!)
高级配置
开发与测试
- 生成器 - 用于搭建组件的 Rails 生成器
- 使用 TestHelper 进行测试 - 全面的测试策略
- 开发命令 - 用于调试和检查的 Rake 任务
- MCP Inspector 集成 - 交互式测试与验证
故障排除与生产环境
💡 专业提示:动手开发时,先阅读各组件专属指南(TOOLS.MD、PROMPTS.MD、RESOURCE_TEMPLATES.md),再参考《MCP 入门指南》了解协议细节,并参考 CLIENTUSAGE.MD 了解集成模式。
配置
ActionMCP 通过 Rails 应用中的 config.action_mcp 进行配置。
默认情况下,名称设为应用名称,版本默认为 "0.0.1",除非应用有版本文件。
你可以在配置中覆盖这些设置(例如,在 config/application.rb 中):
module Tron
class Application < Rails::Application
config.action_mcp.name = "Friendly MCP (Master Control Program)" # defaults to Rails.application.name
config.action_mcp.version = "1.2.3" # defaults to "0.0.1"
config.action_mcp.logging_enabled = true # defaults to true
config.action_mcp.logging_level = :info # defaults to :info, can be :debug, :info, :warn, :error, :fatal
# Server instructions - helps LLMs understand the server's purpose
config.action_mcp.server_instructions = [
"Use this server to access and control Tron system programs",
"Helpful for managing system processes and user data"
]
end
end
如需动态版本控制,可考虑添加 rails_app_version gem。
分页
所有列表端点(tools/list、prompts/list、resources/list、resources/templates/list)都支持按照 MCP 规范进行基于游标的分页。分页默认关闭——设置 pagination_page_size 即可启用:
config.action_mcp.pagination_page_size = 10
也可以在 config/mcp.yml 中设置:
shared:
pagination_page_size: 10
启用后,如果还有更多项目,响应会包含不透明的 nextCursor。设为 nil(默认值)时,所有项目都会在单个响应中返回。仅在客户端支持基于游标的分页时启用。
无论此设置如何,tasks/list 始终使用分页(每页默认为 50 项;如果已配置 pagination_page_size,则使用该值)。
服务端说明
服务端说明可帮助大模型了解你的服务是做什么的以及何时使用它。它们描述服务的用途和目标,而非速率限制或身份验证等技术细节(工具会通过各自的描述进行自我说明)。
说明会在 MCP 初始化响应的顶层返回。
你可以在 config/mcp.yml 文件中配置服务端说明:
shared:
# Describe the server's purpose - helps LLMs know when to use this server
server_instructions:
- "Use this server to manage Fizzy project tickets and workflows"
- "Helpful for tracking bugs, features, and sprint planning"
development:
# Development-specific purpose description
server_instructions:
- "Development server for testing Fizzy integration"
- "Use for prototyping ticket management workflows"
production:
# Production-specific purpose description
server_instructions:
- "Production Fizzy server for managing live project data"
说明会以单个字符串的形式(以换行符连接)发送到初始化响应的顶层,帮助大模型了解服务的用途。
会话存储
ActionMCP 提供可插拔的会话存储系统,你可以根据环境和需求选择会话的持久化方式。
会话存储类型
ActionMCP 包含三种会话存储实现:
-
:volatile- 使用 Concurrent::Hash 的内存存储- 开发和测试环境的默认设置
- 服务器重启后会话会丢失
- 适用于本地开发,快速且轻量
- 无外部依赖
-
:active_record- 数据库支持的存储- 生产环境的默认设置
- 服务器重启后会话仍会保留
- 支持会话恢复
- 需要数据库迁移
-
:test- 专用于测试的存储- 跟踪通知和方法调用
- 提供断言辅助方法
- 使用 TestHelper 时,会在测试环境中自动启用
配置
你可以在 Rails 配置或 config/mcp.yml 中配置会话存储类型:
# config/application.rb or environment files
Rails.application.configure do
config.action_mcp.session_store_type = :active_record # or :volatile
end
也可以在 config/mcp.yml 中配置:
# Global session store type (used by both client and server)
session_store_type: volatile
# Client-specific session store type (falls back to session_store_type if not specified)
client_session_store_type: volatile
# Server-specific session store type (falls back to session_store_type if not specified)
server_session_store_type: active_record
默认设置如下:
- 生产环境:
:active_record - 开发环境:
:volatile - 测试环境:
:volatile(使用 TestHelper 时为:test)
分别配置客户端和服务端会话存储
你可以为客户端和服务端操作配置不同的会话存储类型:
session_store_type:客户端和服务端共用的全局设置,未设置专用类型时使用client_session_store_type:ActionMCP 客户端连接使用的会话存储(未设置时回退到全局设置)server_session_store_type:ActionMCP 服务端会话使用的会话存储(未设置时回退到全局设置)
这样可以分别优化各个组件。例如,你可以为客户端会话使用易失性存储(更快、临时),同时为服务端会话使用持久化存储(重启后仍保留状态)。
使用不同的会话存储
# The session store is automatically selected based on configuration
# You can access it directly if needed:
session_store = ActionMCP::Server.session_store
# Create a session
session = session_store.create_session(session_id, {
status: "initialized",
protocol_version: "2025-11-25",
# ... other session attributes
})
# Load a session
session = session_store.load_session(session_id)
# Update a session
session_store.update_session(session_id, { status: "active" })
# Delete a session
session_store.delete_session(session_id)
会话恢复
使用 :active_record 存储时,客户端可以在断开连接后恢复会话:
# Client includes session ID in request headers
# Server automatically resumes the existing session
headers["Mcp-Session-Id"] = "existing-session-id"
# If the session exists, it will be resumed
# If not, a new session will be created
自定义会话存储
你可以继承 ActionMCP::Server::SessionStore::Base 来创建自定义会话存储:
class MyCustomSessionStore < ActionMCP::Server::SessionStore::Base
def create_session(session_id, payload = {})
# Implementation
end
def load_session(session_id)
# Implementation
end
def update_session(session_id, updates)
# Implementation
end
def delete_session(session_id)
# Implementation
end
def exists?(session_id)
# Implementation
end
end
# Register your custom store
ActionMCP::Server.session_store = MyCustomSessionStore.new
线程池管理
ActionMCP 使用线程池高效处理消息回调。这可以防止系统在高负载下因线程过多而不堪重负。
线程池配置
你可以在 config/mcp.yml 中配置线程池:
production:
# Thread pool configuration
min_threads: 10 # Minimum number of threads to keep in the pool
max_threads: 20 # Maximum number of threads the pool can grow to
max_queue: 500 # Maximum number of tasks that can be queued
线程池会自动:
- 使用
min_threads个线程启动 - 按需扩展至
max_threads - 将任务排队,最多达到
max_queue限制 - 队列已满时使用调用方的线程(回退策略)
优雅关闭
应用关闭时,应调用:
ActionMCP::Server.shutdown
这可确保所有线程池都正确终止,并完成所有任务。
引擎与挂载
警告:不要在
routes.rb中挂载 ActionMCP::Engine。 ActionMCP 是独立的 Rack 应用,通过mcp/config.ru在自己的端口上运行。将其作为 Rails 引擎路由挂载将无法正常工作。
在 mcp/config.ru 中使用 run ActionMCP.server 时,MCP 端点默认位于根路径(/),也可以通过 config.action_mcp.base_path 配置。始终使用 ActionMCP.server(不要直接使用 ActionMCP::Engine)——它会初始化所需的子系统。
安装 ActionMCP
ActionMCP 提供生成器,帮助你快速设置项目。安装生成器会创建所有必要的基类和配置文件:
# Install ActionMCP with base classes and configuration
bin/rails generate action_mcp:install
这会创建:
app/mcp/prompts/application_mcp_prompt.rb- 提示词基类app/mcp/tools/application_mcp_tool.rb- 工具基类app/mcp/resource_templates/application_mcp_res_template.rb- 资源模板基类app/mcp/application_gateway.rb- 用于身份验证的网关config/mcp.yml- 配置文件,包含所有环境的示例设置mcp/config.ru- 独立的 Rack 服务配置bin/mcp- 服务启动脚本(优先使用 Falcon,若不可用则回退到 Puma)
注意: 不包含身份验证和授权功能。你需要自行确保端点安全。
使用 Gateway 进行身份验证
ActionMCP 提供了用于处理身份验证的 Gateway 系统。Gateway 可用于验证用户身份,并让用户信息在所有 MCP 组件中可用。如需查看完整的 Gateway 参考,包括标识符类、会话持久化、配置文件切换和生产环境加固技巧,请参阅 GATEWAY.md。
ActionMCP 使用 Gateway 模式,并支持可插拔的身份标识符。你可以使用基于会话的身份验证、API 密钥、Bearer 令牌实现自定义身份验证策略,也可以与 Warden、Devise 等现有身份验证系统或外部 OAuth 提供方集成。
注意: 配置 Gateway 后,它会对每个 MCP HTTP 请求进行身份验证,包括
initialize、GET 和 DELETE。身份验证失败时会返回 HTTP 401,并附带WWW-Authenticate: Bearer质询和 JSON-RPC 错误正文。
创建 ApplicationGateway
运行安装生成器时,它会创建一个 ApplicationGateway 类:
# app/mcp/application_gateway.rb
class ApplicationGateway < ActionMCP::Gateway
# Specify what attributes identify a connection
identified_by :user
protected
def authenticate!
token = extract_bearer_token
raise ActionMCP::UnauthorizedError, "Missing token" unless token
payload = ActionMCP::JwtDecoder.decode(token)
user = resolve_user(payload)
raise ActionMCP::UnauthorizedError, "Unauthorized" unless user
# Return a hash with all identified_by attributes
{ user: user }
end
private
def resolve_user(payload)
user_id = payload["user_id"] || payload["sub"]
User.find_by(id: user_id) if user_id
end
end
使用多个标识符
你可以通过多个属性识别连接:
class ApplicationGateway < ActionMCP::Gateway
identified_by :user, :organization
protected
def authenticate!
# ... authentication logic ...
{
user: user,
organization: user.organization
}
end
end
在组件中访问当前用户
完成身份验证后,当前用户(以及其他标识符)便可在你的工具、提示词和资源模板中使用:
class MyTool < ApplicationMCPTool
def perform
# Access the authenticated user
if current_user
render text: "Hello, #{current_user.name}!"
else
render text: "Hi Stranger! It's been a while "
end
end
end
当前属性
ActionMCP 使用 Rails 的 CurrentAttributes 存储已验证的上下文。ActionMCP::Current 类提供:
ActionMCP::Current.user- 已验证的用户ActionMCP::Current.gateway- Gateway 实例- 你通过
identified_by定义的其他属性
在会话中持久化上下文
在 Gateway 中重写 configure_session,即可将身份验证上下文(user_id、tenant_id、roles)持久化到会话中,用于审计追踪、后台作业和跨请求场景:
class ApplicationGateway < ActionMCP::Gateway
identified_by UserIdentifier
def configure_session(session)
session.session_data = { "user_id" => user.id, "tenant_id" => user.tenant_id }
end
end
工具通过 session_data["user_id"] 访问这些信息。详情请参阅 GATEWAY.md。
1. 创建 mcp/config.ru
安装生成器(rails generate action_mcp:install)会自动创建此文件。如果需要手动创建:
# Load the full Rails environment to access models, DB, Redis, etc.
require_relative "../config/environment"
$stdout.sync = true
# Eager load so all tools, prompts, and resources are registered.
Rails.application.eager_load!
# IMPORTANT: Use ActionMCP.server — it initializes required subsystems.
# Do NOT use ActionMCP::Engine directly.
run ActionMCP.server
2. 启动服务
bin/mcp # Uses Falcon (recommended)
bundle exec rails s -c mcp/config.ru -p 62770 # Uses Puma (fallback)
处理中间件冲突
如果 Rails 应用使用了会干扰 MCP 服务运行的中间件(例如 Devise、Warden、Ahoy、Rack::Cors 等),请改用 mcp_vanilla.ru:
# mcp_vanilla.ru - A minimal Rack app with only essential middleware
# This avoids conflicts with authentication, tracking, and other web-specific middleware
# See the file for detailed documentation on when and why to use it
bundle exec rails s -c mcp_vanilla.ru -p 62770
# Or with Falcon:
bundle exec falcon serve --bind http://127.0.0.1:62770 --config mcp_vanilla.ru
可能导致问题的常见中间件:
- Devise/Warden - 需要 Cookie 和会话,会引发
Devise::MissingWarden错误 - Ahoy - 会拦截请求的分析追踪中间件
- Rack::Attack - 面向 Web 流量的速率限制中间件
- Rack::Cors - 面向浏览器的 CORS 标头中间件
- 任何假定响应为 HTML 或使用基于 Cookie 的身份验证的中间件
dummy app 中的 test/dummy/mcp_vanilla.ru 文件提供了一个最小 mcp_vanilla.ru 示例。
此文件是一个最小 Rack 应用,仅包含运行 MCP 服务所需的基本中间件,可避免与 Web 专用中间件发生冲突。
但请记得添加所需的检测或日志记录中间件,因为默认情况下,此最小配置不包含这些中间件。
## Production Deployment of MCPS0
In production, **MCPS0** (the MCP server) is a standard Rack application. You can run it using any Rack-compatible server (such as Puma, Unicorn, or Passenger).
> **For best performance and concurrency, it is highly recommended to use a modern, synchronous server like [Falcon](https://github.com/socketry/falcon)**. Falcon is optimized for streaming and concurrent workloads, making it ideal for MCP servers. You can still use Puma, Unicorn, or Passenger, but Falcon will generally provide superior throughput and responsiveness for real-time and streaming use cases.
You have several main options for exposing the server:
### 1. Dedicated Port
Run MCPS0 on its own TCP port (commonly `62770`):
**With Falcon:**
```bash
bundle exec falcon serve --bind http://0.0.0.0:62770 --config mcp/config.ru
使用 Puma:
bundle exec rails s -c mcp/config.ru -p 62770
使用 Passenger:
passenger start --rackup mcp/config.ru --port 62770
然后,使用 Web 服务(Nginx、Apache 等)将请求反向代理到此端口。
2. Unix Socket
或者,你也可以在 Unix socket 上运行 MCPS0,以提升性能和安全性(尤其是在 Web 服务和应用服务位于同一台机器上时):
使用 Falcon:
bundle exec falcon serve --bind unix:/tmp/mcps0.sock mcp/config.ru
使用 Puma:
bundle exec puma -C config/puma.rb -b unix:///tmp/mcps0.sock -c mcp/config.ru
使用 Passenger:
passenger start --rackup mcp/config.ru --socket /tmp/mcps0.sock
并将 Web 服务配置为代理到此 socket:
location /mcp/ {
proxy_pass http://unix:/tmp/mcps0.sock:;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
3. 使用 Passenger 配置 Nginx
你可以通过 Nginx 中的 Passenger 进程同时运行主应用和 MCP 应用。
location / {
root /path/to/current/public;
passenger_app_root /path/to/current;
passenger_enabled on;
# ... additional configuration for the main Rails app
}
location ~* ^/mcp {
root /path/to/current/public;
passenger_app_root /path/to/current;
passenger_enabled on;
passenger_startup_file mcp/config.ru;
passenger_app_group_name mcp;
}
你必须将 config.action_mcp.base_path 设置为与上述 Nginx 配置一致,即 config.action_mcp.base_path = '/mcp'。
要点:
- MCPS0 是独立的 Rack 应用——请将它与主 Rails 服务分开运行。
- 你可以通过 TCP 端口(例如 62770)或 Unix 套接字公开它。
- 按需使用反向代理(Nginx、Apache 等)将请求路由到 MCPS0。
- 这种分离可确保主应用和 MCP 服务的可靠性与可扩展性。
生成器
ActionMCP 包含 Rails 生成器,可帮助你快速设置 MCP 服务组件。
首先,安装 ActionMCP 以创建基类和配置:
bin/rails action_mcp:install:migrations # to copy the migrations
bin/rails generate action_mcp:install
这将在你的应用目录中创建基应用类、配置文件、身份验证网关、mcp/config.ru rackup 文件和 bin/mcp binstub。
生成新的提示词
bin/rails generate action_mcp:prompt AnalyzeCode
生成新的工具
bin/rails generate action_mcp:tool CalculateSum
使用 TestHelper 进行测试
ActionMCP 提供了 TestHelper 模块,可简化工具和提示词的测试:
require "test_helper"
require "action_mcp/test_helper"
class ToolTest < ActiveSupport::TestCase
include ActionMCP::TestHelper
test "CalculateSumTool returns the correct sum" do
assert_mcp_tool_findable("calculate_sum")
result = execute_mcp_tool("calculate_sum", a: 5, b: 10)
assert_mcp_tool_output("15.0", result)
end
test "AnalyzeCodePrompt returns the correct analysis" do
assert_mcp_prompt_findable("analyze_code")
result = execute_mcp_prompt("analyze_code", language: "Ruby", code: "def hello; puts 'Hello, world!'; end")
assert_mcp_prompt_output("Analyzing Ruby code: def hello; puts 'Hello, world!'; end", result)
end
end
TestHelper 提供了多种断言和执行方法:
工具:
assert_mcp_tool_findable(name)- 验证工具存在且已注册execute_mcp_tool(name, **args)- 使用参数执行工具并断言成功execute_mcp_tool_with_error(name, **args)- 执行工具但不断言成功(用于测试错误情况)assert_mcp_tool_output(expected, response)- 断言工具输出与预期内容一致
提示词:
assert_mcp_prompt_findable(name)- 验证提示词存在且已注册execute_mcp_prompt(name, **args)- 使用参数执行提示词assert_mcp_prompt_output(expected, response)- 断言提示词输出与预期内容一致
资源模板:
assert_mcp_resource_template_findable(name)- 验证资源模板存在且已注册resolve_mcp_resource(uri)- 解析资源 URI 并断言成功resolve_mcp_resource_with_error(uri)- 解析资源 URI,但不断言成功(用于测试错误情况)
常规:
assert_mcp_error_code(code, response)- 断言特定的 JSON-RPC 错误代码
测试资源模板
require "test_helper"
require "action_mcp/test_helper"
class ProductResourceTest < ActiveSupport::TestCase
include ActionMCP::TestHelper
test "product template is registered" do
assert_mcp_resource_template_findable("products")
end
test "resolves a product resource by URI" do
resp = resolve_mcp_resource("ecommerce://products/1")
assert resp.success?
assert_not_empty resp.contents
assert_equal "application/json", resp.contents.first.mime_type
end
test "returns error for nonexistent product" do
resp = resolve_mcp_resource_with_error("ecommerce://products/0")
assert resp.is_error
end
end
检查你的 MCP 服务
你可以使用 MCP Inspector 测试服务实现:
# Start your MCP server
bundle exec rails s -c mcp/config.ru -p 62770
# In another terminal, run the inspector
npx @modelcontextprotocol/inspector --url http://localhost:62770
MCP Inspector 提供了一个交互式界面,可用于:
- 使用自定义参数测试工具执行
- 验证提示词响应
- 检查资源模板及其输出
- 调试协议合规性和错误处理
开发命令
ActionMCP 包含多个用于开发和调试的 rake 任务:
# List all MCP components
bundle exec rails action_mcp:list
# List specific component types
bundle exec rails action_mcp:list_tools
bundle exec rails action_mcp:list_prompts
bundle exec rails action_mcp:list_resources
bundle exec rails action_mcp:list_widgets
bundle exec rails action_mcp:list_profiles
# Show configuration and statistics
bundle exec rails action_mcp:info
bundle exec rails action_mcp:stats
# Show profile configuration
bundle exec rails action_mcp:show_profile[profile_name]
代码检查
RuboCop 会作为 git 提交前钩子,对已暂存的 Ruby 文件运行。每个克隆仓库只需启用一次:
git config core.hooksPath .githooks
错误处理与故障排除
ActionMCP 根据 JSON-RPC 2.0 规范提供全面的错误处理:
错误代码
- -32601:找不到方法 - 请求的方法不存在
- -32002:需要用户同意 - 工具需要用户同意才能执行
- -32603:内部错误 - 服务遇到了意外错误
- -32600:无效请求 - 请求格式错误
上下文感知的错误消息
工具应使用 render 方法向大模型返回清晰的错误消息:
class MyTool < ApplicationMCPTool
def perform
# Check for error conditions and return clear messages
if some_error_condition?
report_error("Clear error message for the LLM")
return
end
# Normal processing
render(text: "Success message")
end
end
常见问题
- 找不到会话:确保会话已正确创建并保存到会话存储中
- 工具未注册:确认工具定义正确,且继承自 ApplicationMCPTool
- 需要用户同意:使用
session.grant_consent(tool_name)授予同意 - 中间件冲突:使用
mcp_vanilla.ru以避免特定于 Web 的中间件
调试提示
- 查看服务日志以获取详细的错误信息
- 使用
bundle exec rails action_mcp:info验证配置 - 使用 MCP Inspector 进行测试,以隔离协议问题
- 确保在生产环境中妥善管理会话
配置档案
ActionMCP 支持灵活的配置档案系统,可根据不同的使用场景选择性地公开工具、提示词和资源。这对于在不同上下文中需要不同 MCP 功能的应用尤其有用(例如,公共 API 与管理界面)。
了解配置档案
配置档案是命名配置,用于定义:
- 可用的工具
- 可访问的提示词
- 可访问的资源
- 配置选项,例如日志记录级别和更改通知
默认情况下,ActionMCP 包含两个配置档案:
primary:公开所有工具、提示词和资源minimal:默认不公开任何工具、提示词或资源
配置配置档案
在 Rails 应用中通过 config/mcp.yml 文件配置配置档案。如果此文件不存在,ActionMCP 将使用 gem 中的默认设置。
配置示例:
default:
tools:
- all # Include all tools
prompts:
- all # Include all prompts
resources:
- all # Include all resources
options:
list_changed: false
logging_enabled: true
logging_level: info
resources_subscribe: false
api_only:
tools:
- calculator
- weather
prompts: [] # No prompts for API
resources:
- user_profile
options:
list_changed: false
logging_level: warn
admin:
tools:
- all
options:
logging_level: debug
list_changed: true
resources_subscribe: true
每个配置档案都可以指定:
tools:要包含的工具名称数组(使用all可包含所有工具)prompts:要包含的提示词名称数组(使用all可包含所有提示词)resources:要包含的资源名称数组(使用all可包含所有资源)options:其他配置选项:list_changed:是否发送更改通知logging_enabled:是否启用日志记录logging_level:要使用的日志记录级别resources_subscribe:是否启用资源订阅
切换配置档案
你可以在代码中以编程方式切换配置档案:
# Permanently switch to a different profile
ActionMCP.configuration.use_profile(:only_tools) # Switch to a profile named "only_tools"
# Temporarily use a profile for a specific operation
ActionMCP.with_profile(:minimal) do
# Code here uses the minimal profile
# After the block, reverts to the previous profile
end
这样一来,你就能轻松控制应用在不同上下文中可用的 MCP 功能。
检查配置档案
ActionMCP 包含帮助你管理和检查配置档案的 rake 任务:
# List all available profiles with their configurations
bin/rails action_mcp:list_profiles
# Show detailed information about a specific profile
bin/rails action_mcp:show_profile[admin]
# List all tools, prompts, resources, UI widgets, and profiles
bin/rails action_mcp:list
配置档案检查任务会指出任何问题,例如配置了应用中实际不存在的工具、提示词或资源。
使用场景
配置档案尤其适用于:
- 多租户应用:使用 Dorp 或其他 gem 为不同客户层级配置不同的配置档案
- 访问控制:为不同用户角色(管理员、员工、公众)创建配置档案
- 性能优化:为高流量端点使用最小配置档案
- 测试环境:在测试环境中使用专用的测试配置档案
- 渐进式增强:从最小配置档案开始,逐步添加功能
借助配置档案,你可以维护单一的 ActionMCP 代码库,同时为不同上下文提供量身定制的 MCP 功能。
客户端用法
ActionMCP 包含一个用于连接远程 MCP 服务的客户端。该客户端负责会话管理和协议协商,并提供用于与 MCP 服务交互的简易 API。
有关客户端的完整文档,包括示例、会话管理、传输配置和 API 用法,请参阅 CLIENTUSAGE.md。
生产环境注意事项
安全
-
切勿通过 MCP 组件泄露敏感数据
-
在生产部署中通过 Gateway 使用身份验证
-
在工具和提示词中实施适当的授权
-
使用属性定义和 Rails 验证来验证所有输入
-
对敏感操作使用同意管理
-
防范 DNS 重绑定:ActionMCP 会在每个请求中验证
Origin标头,而不会信任请求的Host标头。默认允许环回源(localhost、127.0.0.1和::1)。除非其他浏览器源的主机已明确列入allowed_origins,否则这些源会收到 HTTP 403。省略Origin的非浏览器客户端不受影响:# config/initializers/action_mcp.rb ActionMCP.configure do |config| config.allowed_origins = ["app.example.com", "api.example.com"] end为了纵深防御,还应配置 Rails 的
ActionDispatch::HostAuthorization,限制接受哪些Host标头(这是针对主机标头注入的单独检查):# config/environments/production.rb config.hosts = ["api.example.com"]
性能
- 为高流量场景配置合适的线程池
- 在生产环境中使用 Redis 或 SolidMCP 进行发布/订阅
- 选择 ActiveRecord 会话存储来持久化会话
- 监控会话清理,以防止内存泄漏
- 使用配置档案来限制暴露的功能
监控
- 启用日志记录并配置合适的日志级别
- 使用
action_mcp:stats监控会话统计信息 - 跟踪工具使用情况和性能指标
- 针对错误率和响应时间设置警报
部署
- 对流式工作负载使用 Falcon,以获得最佳性能
- 部署在专用端口或 Unix 套接字上
- 使用反向代理(Nginx、Apache)终止 SSL
- 为 MCP 端点实施运行状况检查
- 使用
mcp_vanilla.ru以避免中间件冲突
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。