Skip to content

Extending MCP Tools

Optional plugins must register MCP tools through EasyMcp::ToolRegistry.register.

Core MCP code must not reference plugin constants at load time. Use a string service class name and an available_if predicate.

Example:

EasyMcp::ToolRegistry.register(
  name: "easy8_helpdesk_projects_list",
  service: "EasyHelpdesk::EasyMcp::Tools::ListProjects",
  definition: {
    "name" => "easy8_helpdesk_projects_list",
    "description" => "List visible Easy Helpdesk project settings.",
    "inputSchema" => {
      "type" => "object",
      "properties" => {
        "project_id" => { "type" => "integer" }
      },
      "additionalProperties" => false
    }
  },
  argument_keys: %w[project_id],
  available_if: -> { Redmine::Plugin.installed?(:easy_helpdesk) }
)

If a plugin is not installed, disabled, or its service class cannot be loaded, its tools are omitted from tools/list. Direct calls to unavailable tools return a controlled tool error instead of raising to the MCP client.

Naming

  • core tool names use easy8_<resource>_<verb>
  • plugin-owned tools should use easy8_<plugin_domain>_<resource>_<verb>
  • tools should be registered from the owning plugin

EasyMcp::ToolRegistry adds default MCP safety annotations from the tool name suffix. Tools ending in _list, _get, _search, _me, _read, _transition_options, or _analysis are advertised as read-only. Tools ending in _create, _add, _upload, or _copy are advertised as non-destructive write tools. Other write-like names are advertised as potentially destructive. If a tool does not follow these naming conventions, include explicit annotations in the registered definition.

Availability

Use available_if for plugin-specific conditions such as plugin installation, feature flags, or product-level enablement.

Do not make core MCP code depend on optional plugin constants. Keep cross-plugin coupling guarded and explicit.

Extending existing tools

Plugins can add arguments to an existing tool with EasyMcp::ToolRegistry.extend_tool.

If the new arguments must affect query execution or response payloads, also register hooks with EasyMcp::ToolExtensions.register.

Example: CRM extends easy8_issues_list with customer-account filters and optional account payloads.

Schemas

Each registered tool should publish an MCP-compatible JSON schema through its definition.

Clients should call tools/list and treat the returned schema as the source of truth for required arguments, supported filters, and allowed values.