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.