How MCP Servers and Plugins Are Integrated into the Reasonix System

Reasonix treats external MCP (Model-Capability-Protocol) servers as first-class plugins by spawning them as stdio-bound processes, registering their tools in a global registry with normalized naming patterns, and injecting capability bindings into skills via the ConfigureToolBindings resolver.

The DeepSeek-Reasonix project implements a modular plugin architecture that allows any executable implementing the MCP protocol to integrate seamlessly with the core system. This design enables external tools to expose capabilities through a standardized handshake while the host manages validation, portable naming, and authorization. Understanding this integration requires examining the configuration layer, process lifecycle, and registry binding mechanisms.

Configuration and Validation Layer

Plugin registration begins in the user-editable TOML configuration file under the [[plugins]] array. Each entry requires a unique name, type (currently restricted to "mcp"), and the command string used to launch the executable. Optional fields include tier, which controls lazy versus eager initialization.

Validation logic resides in internal/repair/diagnose.go (lines 172-186), where the system ensures plugin names are unique and commands are non-empty before startup. This prevents runtime failures from malformed declarations.


# Example plugin declaration in config.toml

[[plugins]]
name = "figma"
type = "mcp"
command = "figma-mcp-server --port 0"
tier = "eager"

MCP Server Process Lifecycle

When Reasonix initializes, the host process—whether launched via cmd/reasonix/main.go for desktop or server modes—spawns each MCP plugin as a separate process using exec.Command. The host establishes a bidirectional stdio channel for JSON-RPC communication.

During the MCP handshake, the server advertises its available tools. Each tool must implement metadata interfaces defined in internal/tool/tool.go (lines 119-125), specifically MCPMetadata, MCPVisibleMetadata, or MCPPackageMetadata. These interfaces provide the server name, raw tool name, visible name, and optional package prefix required for registry insertion.

// Minimal MCP server implementation satisfying Reasonix interfaces
type FigMCP struct{}

func (FigMCP) MCPServerName() string      { return "figma" }
func (FigMCP) MCPRawToolName() string     { return "search" }
func (FigMCP) MCPVisibleToolName() string { return "search" }
func (FigMCP) MCPPackageName() string     { return "figma" }

Tool Registry and Portable Naming

After the handshake, the system registers every advertised tool in the global tool.Registry. The registry mixes built-in tools with plugin-provided MCP tools while enforcing a strict naming convention to prevent collisions.

Portable names follow the pattern mcp__<server>__<tool>. For plugin-specific isolation, the system generates aliases using the package prefix: mcp__plugin_<pkg>_<server>__<tool>. This logic is implemented in internal/tool/tool.go (lines 306-478).

// Simplified alias construction from the registry
func mcpBindingAliases(b tool.MCPBinding) []string {
    aliases := []string{
        "mcp__" + portableMCPPart(b.Server) + "__" + portableMCPPart(b.RawName),
        "mcp__" + portableMCPPart(b.Server) + "__" + portableMCPPart(b.VisibleName),
    }
    // Plugin-specific variant includes package name
    prefix := "mcp__plugin_" + portableMCPPart(b.Package) + "_" + 
              portableMCPPart(b.Server) + "__"
    aliases = append(aliases,
        prefix+portableMCPPart(b.RawName),
        prefix+portableMCPPart(b.VisibleName))
    return aliases
}

Skill Binding and Capability Resolution

Skills loaded from plugin packages receive their MCP bindings through Store.ConfigureToolBindings in internal/skill/skill.go (lines 242-251). This resolver maps portable MCP names to concrete, host-generated aliases and injects them into the skill's runtime environment.

The system automatically enriches skill markdown with a "Runtime MCP tool bindings" section that lists exact callable names and stable capability IDs. When the LLM invokes a tool via use_capability, the dispatcher looks up the binding, verifies authorization through MCPServerAuthorization and HasNonDestructiveMCPExecutionIntent, and forwards the call to the appropriate MCP process.


## Runtime MCP tool bindings

These host-generated bindings are authoritative for this invocation.
Use the exact direct name below; if only `use_capability` is available, 
use the stable capability ID.

use_capability mcp__figma__search

UI Integration and Model Discovery

The HTTP and desktop front-ends discover plugin-provided models through the ProviderCatalog. When a model reference uses the format plugin/<plugin>/<provider>/<model>, Reasonix pulls the entry from the catalog populated during MCP server initialization. This integration logic lives in internal/serve/serve.go (lines 1000-1030), enabling the model picker to display both built-in providers and external plugin models uniformly.

Summary

  • Configuration Validation: Plugins are declared in TOML and validated in internal/repair/diagnose.go to ensure unique names and executable commands.
  • Process Isolation: MCP servers run as separate stdio-bound processes, advertising capabilities via the MCP handshake protocol.
  • Registry Abstraction: The tool.Registry normalizes tool names using mcp__ prefixes and package-specific aliases to avoid namespace collisions.
  • Dynamic Binding: ConfigureToolBindings in internal/skill/skill.go injects plugin capabilities into skills at runtime with stable capability IDs.
  • Unified Interface: The UI model picker in internal/serve/serve.go exposes plugin models using the plugin/<plugin>/<provider>/<model> URI pattern.

Frequently Asked Questions

What configuration fields are required to register an MCP plugin in Reasonix?

The TOML configuration requires three mandatory fields under [[plugins]]: name (unique identifier), type (must be "mcp"), and command (the executable path). An optional tier field controls initialization timing. The validation logic in internal/repair/diagnose.go (lines 172-186) enforces these constraints during startup.

How does Reasonix handle naming collisions between built-in tools and MCP plugin tools?

The system uses a hierarchical naming convention implemented in internal/tool/tool.go. All MCP tools receive the prefix mcp__<server>__<tool>, while plugin-specific tools additionally support the format mcp__plugin_<package>_<server>__<tool>. This ensures that tools from different MCP servers remain isolated in the global registry.

Can MCP plugins expose custom models to the Reasonix UI?

Yes. When an MCP server advertises models, Reasonix populates the ProviderCatalog and exposes entries using the URI pattern plugin/<plugin>/<provider>/<model>. The model picker handler in internal/serve/serve.go (lines 1000-1030) integrates these alongside built-in providers, allowing users to select plugin-exposed models directly from the interface.

What authorization checks exist before executing an MCP tool?

Before forwarding calls to an MCP process, Reasonix verifies MCPServerAuthorization and checks HasNonDestructiveMCPExecutionIntent to ensure the operation complies with safety policies. These checks occur during the dispatch phase after the LLM invokes a capability via use_capability, preventing unauthorized or destructive operations from executing on external servers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →