mcpField
A
ActionMCP

ActionMCP

本地服务
github.com/seuros开发工具1241 天前更新

关于 ActionMCP

ActionMCP 是一个 Ruby gem,为 Rails 应用提供作为 MCP 服务的能力。它面向需要网络化部署的生产 Rails 环境,不支持 STDIO 传输。开发者可以专注于业务逻辑,框架负责 MCP 协议的样板代码。

主要功能

  1. 01基于 Rails Engine 的 MCP 服务基类与辅助工具
  2. 02支持 MCP 2025-11-25 协议与 Streamable HTTP 端点
  3. 03Tool、Prompt、ResourceTemplate 三类核心抽象
  4. 04工具调用的同意(consent)管理与 -32002 错误码
  5. 05支持 Tasks 异步执行与进度上报

适用场景

  1. 01将 Rails 应用的业务功能以工具形式暴露给 LLM
  2. 02为 Rails 应用提供可供 LLM 检索的资源模板
  3. 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

同意流程:

  1. 未经同意调用需要同意的工具时,工具会返回错误代码为 -32002 的 JSON-RPC 错误
  2. 客户端必须明确授予对特定工具的同意
  3. 授予同意后,该工具即可在当前会话中正常执行
  4. 同意仅对当前会话有效,且可随时撤销

管理同意:

# 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 提供了多份专门指南,涵盖全面的文档内容。每份指南都聚焦于特定方面,让信息更有条理,避免上下文过载:

入门与设置
组件开发
  • 📋 TOOLS.MD — MCP 工具开发完整指南

    • 生成器的使用方法和最佳实践
    • 属性定义、验证和同意管理
    • 用于结构化响应的输出架构
    • 错误处理、测试和安全注意事项
    • 附加属性和身份验证上下文等高级功能
  • 📝 PROMPTS.MD — 提示词模板开发指南

    • 创建可复用的提示词模板
    • 多步骤对话和混合内容类型
    • 参数验证和提示词串联
  • 🔗 RESOURCE_TEMPLATES.md — 资源模板实现

    • URI 模板模式和参数提取
    • 动态资源解析和集合
    • 回调和验证模式
客户端与集成
  • 🔌 CLIENTUSAGE.MD — 客户端实现完整指南
    • 会话管理和恢复能力
    • 传输配置和连接处理
    • 工具、提示词和资源集合
    • 生产环境部署模式
  • 🔐 GATEWAY.md — 身份验证 Gateway 指南
    • 实现 ApplicationGateway
    • 通过 ActionMCP::Current 处理标识符
    • 身份验证模式、错误处理和加固技巧
协议与技术细节
  • 🚀 MCP 入门指南 - 协议版本与迁移
    • 历史协议对比及当前 2025-11-25 的行为
    • 设计决策与架构原理
    • 迁移路径与兼容性考量
    • 功能演进与技术规范(别慌!)
高级配置
开发与测试
故障排除与生产环境

💡 专业提示:动手开发时,先阅读各组件专属指南(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 包含三种会话存储实现:

  1. :volatile - 使用 Concurrent::Hash 的内存存储

    • 开发和测试环境的默认设置
    • 服务器重启后会话会丢失
    • 适用于本地开发,快速且轻量
    • 无外部依赖
  2. :active_record - 数据库支持的存储

    • 生产环境的默认设置
    • 服务器重启后会话仍会保留
    • 支持会话恢复
    • 需要数据库迁移
  3. :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
常见问题
  1. 找不到会话:确保会话已正确创建并保存到会话存储中
  2. 工具未注册:确认工具定义正确,且继承自 ApplicationMCPTool
  3. 需要用户同意:使用 session.grant_consent(tool_name) 授予同意
  4. 中间件冲突:使用 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

配置档案检查任务会指出任何问题,例如配置了应用中实际不存在的工具、提示词或资源。

使用场景

配置档案尤其适用于:

  1. 多租户应用:使用 Dorp 或其他 gem 为不同客户层级配置不同的配置档案
  2. 访问控制:为不同用户角色(管理员、员工、公众)创建配置档案
  3. 性能优化:为高流量端点使用最小配置档案
  4. 测试环境:在测试环境中使用专用的测试配置档案
  5. 渐进式增强:从最小配置档案开始,逐步添加功能

借助配置档案,你可以维护单一的 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 以避免中间件冲突

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。