# Reasonix Plugin System Architecture and MCP Server Integration: A Deep Dive

> Explore the Reasonix plugin system architecture and MCP server integration. Learn how Reasonix treats external MCP servers as first-class citizens for enhanced capabilities and UI model selection.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: architecture
- Published: 2026-08-07

---

**The Reasonix plugin system treats external MCP (Model-Capability-Protocol) servers as first-class citizens by spawning them as separate processes, discovering their tools through a stdio-based handshake, and registering them in a global registry that exposes portable aliases to the skill system and UI model picker.**

The DeepSeek-Reasonix repository implements a sophisticated plugin architecture that bridges external AI capabilities with its core reasoning engine. This system leverages the Model-Capability-Protocol (MCP) to standardize how external tools and models are discovered, registered, and invoked. Understanding the Reasonix plugin system architecture reveals how the platform maintains strict separation between core logic and extensible capabilities while providing seamless MCP server integration.

## Configuration Layer: Declaring MCP Plugins

### TOML Schema and Validation

Plugin declarations reside in the user-editable TOML configuration under the `[[plugins]]` array. Each entry requires three mandatory fields: **`name`** (unique identifier), **`type`** (currently restricted to `"mcp"`), and **`command`** (the executable launch string). An optional **`tier`** field controls initialization timing, with `"eager"` forcing immediate startup.

Validation logic in [`internal/repair/diagnose.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/repair/diagnose.go) (lines 172-186) enforces schema constraints before the host attempts process creation. This validator ensures plugin names are unique across the configuration and that the command string is non-empty, preventing runtime failures during the spawn phase.

```toml

# Example: Declaring a Figma MCP plugin in config.toml

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

```

## Process Management and the MCP Handshake

### Spawning External Processes

When Reasonix initializes, the host process—whether launched via [`cmd/reasonix/main.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/cmd/reasonix/main.go) into desktop mode or serve mode—spawns each configured plugin as a separate operating system process. The host establishes a bidirectional stdio channel using `exec.Command`, binding the plugin's standard input and output to the parent process for JSON-RPC communication.

### Tool Discovery and Metadata Interfaces

After process spawn, the MCP handshake protocol begins. The external server advertises its available tools by implementing metadata interfaces defined in [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go) (lines 119-125). Each tool must satisfy one or more of these contracts:

- **`MCPMetadata`**: Base interface providing server and tool identifiers
- **`MCPVisibleMetadata`**: Exposes human-readable tool names for UI rendering
- **`MCPPackageMetadata`**: Associates tools with specific plugin packages for namespacing

Once discovered, every tool registers in the global **`tool.Registry`**, mixing built-in capabilities with plugin-provided MCP tools under a unified access layer.

## Tool Registry and Portable Naming Conventions

### Canonical Alias Generation

The registry constructs portable, deterministic identifiers to ensure stable references across sessions. For each MCP tool, Reasonix generates canonical aliases following the pattern `mcp__<server>__<tool>`, where both components undergo normalization to handle special characters safely. This logic resides in [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go) (lines 306-478).

The system creates aliases for both the raw tool name and the visible display name, ensuring that skills can reference capabilities using either technical identifiers or human-readable labels.

### Plugin-Specific Namespacing

To prevent collisions between built-in tools and plugin-provided capabilities, Reasonix constructs plugin-specific aliases that incorporate the package name: `mcp__plugin_<pkg>_<server>__<tool>`. This prefixing strategy allows multiple plugins to expose tools with identical base names without namespace pollution, while the portable aliases provide a stable interface for skill authors.

```go
// Simplified alias generation from internal/tool/tool.go
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 adds package namespace
    prefix := "mcp__plugin_" + portableMCPPart(b.Package) + "_" + portableMCPPart(b.Server) + "__"
    aliases = append(aliases,
        prefix+portableMCPPart(b.RawName),
        prefix+portableMCPPart(b.VisibleName))
    return aliases
}

```

## Skill Integration and Capability Binding

### Runtime Binding Injection

When a skill loads from a plugin package, the system invokes **`Store.ConfigureToolBindings`** defined in [`internal/skill/skill.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/skill/skill.go) (lines 242-251). This resolver injects MCP bindings directly into the skill's markdown context, appending a "Runtime MCP tool bindings" section that enumerates available capabilities and their stable `use_capability` identifiers.

The binding process maps portable MCP names to concrete, host-generated aliases, ensuring that skills reference tools through deterministic IDs regardless of the underlying server implementation. Before execution, the dispatcher verifies authorization through **`MCPServerAuthorization`** and **`HasNonDestructiveMCPExecutionIntent`** checks to enforce safety boundaries.

```markdown

## 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 Exposure and Model Selection

### Provider Catalog Integration

The plugin architecture extends to the UI layer through model reference paths formatted as `plugin/<plugin>/<provider>/<model>`. The HTTP and desktop front-ends enumerate available models by querying the **`ProviderCatalog`**, which aggregates entries from both built-in providers and active MCP servers.

This integration logic in [`internal/serve/serve.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/serve/serve.go) (lines 1000-1030) parses plugin-prefixed model identifiers, resolving them to the appropriate MCP process capabilities. Users can select plugin-exposed models directly from the model picker alongside native Reasonix providers, creating a seamless experience where external AI services appear as first-class options.

## Summary

- **Three-layer architecture**: Configuration validation, process management, and registry binding work sequentially to initialize and expose MCP capabilities
- **Portable naming**: The `mcp__<server>__<tool>` pattern provides stable references, while plugin-specific prefixes prevent namespace collisions
- **Automatic skill enrichment**: The `ConfigureToolBindings` mechanism injects capability mappings into skill markdown without manual configuration
- **Unified UI integration**: The `ProviderCatalog` treats MCP-exposed models identically to built-in providers, supporting the `plugin/<plugin>/<provider>/<model>` reference format

## Frequently Asked Questions

### How does Reasonix validate plugin configurations before startup?

Validation occurs in [`internal/repair/diagnose.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/repair/diagnose.go) (lines 172-186), where the system checks that each plugin has a unique name, a valid type (currently limited to `"mcp"`), and a non-empty command string. This prevents runtime spawn failures and namespace collisions during the initialization phase.

### What is the difference between portable MCP names and plugin-specific aliases?

Portable names follow the pattern `mcp__<server>__<tool>` and provide a stable interface for skill authors, while plugin-specific aliases incorporate the package identifier as `mcp__plugin_<pkg>_<server>__<tool>`. The portable variant ensures consistency across different installations, whereas the plugin-specific variant prevents naming collisions when multiple plugins expose similar tools.

### How does the skill system resolve tool calls to MCP server processes?

When a skill invokes `use_capability`, the dispatcher consults the runtime bindings injected by `Store.ConfigureToolBindings` in [`internal/skill/skill.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/skill/skill.go). This resolver maps the capability ID to the specific MCP server process, verifies authorization via `MCPServerAuthorization`, and forwards the JSON-RPC call through the stdio channel established during process spawn.

### Can Reasonix integrate with non-MCP external tools?

Currently, the plugin system exclusively supports the MCP protocol as indicated by the `type = "mcp"` constraint in configuration validation. The architecture assumes stdio-based JSON-RPC communication and the specific metadata interfaces defined in [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go), making MCP the sole supported integration pattern for external capabilities.