How to Create Custom MCP Server Plugins in Reasonix: A Complete Guide for Developers

Developers create custom MCP server plugins in Reasonix by adding a configuration entry, implementing an MCP-compliant server, registering tools, and placing skill markdown files—enabling the AI to invoke custom functions and prompts.

Reasonix uses the Multi-Channel Protocol (MCP) to load external capabilities as plugins. These plugins extend the AI with tools (callable functions) and skills (prompt templates) that integrate seamlessly into the reasoning engine. This guide walks through the complete implementation workflow based on the esengine/DeepSeek-Reasonix source code.


MCP Plugin Architecture Overview

Reasonix treats every plugin as an MCP server—either a local executable or remote HTTP endpoint. The system follows a six-stage lifecycle from configuration to runtime invocation.

Stage What Happens Key Source File
1. Configuration Add [[plugins]] entry with name, type, and launch command [internal/config/plugin_entry.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/config/plugin_entry.go)
2. Server Implementation Write MCP-compliant JSON-RPC server with initialize, tool handlers [sdk/go/examples/fullsidecar/main.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/sdk/go/examples/fullsidecar/main.go)
3. Tool Registration Register tools with isolated namespace mcp__plugin_<id>_<name>__ [internal/tool/tool.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/tool.go)
4. Skill Definition Add markdown files with front-matter declaring allowed tools [internal/skill/skill.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/skill/skill.go)
5. Startup Wiring Controller launches servers and binds capabilities to session [internal/control/controller.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/control/controller.go)
6. Runtime Invocation AI requests tools by prefixed name or invokes skills that grant tool access [internal/skill/skill_test.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/skill/skill_test.go)

Step 1: Configure Your Plugin Entry

Every plugin starts with a configuration block in reasonix.toml or ~/.config/reasonix/config.toml. The [[plugins]] table defines how Reasonix launches and identifies your server.

[[plugins]]
name = "myplugin"          # Stable identifier—used in all tool/skill names

type = "command"           # "command" for local executable, "http" for remote

command = "./plugins/myplugin/main"   # Path to binary (absolute or relative)

tier = "eager"             # "eager" (startup), "lazy" (first use), or "on-demand"

The name field is critical—Reasonix uses it to generate isolated namespaces for your tools. According to [internal/config/plugin_entry.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/config/plugin_entry.go), this structure supports both command (stdio-based) and http (network-based) server types.


Step 2: Implement the MCP Server

Your server must implement the MCP JSON-RPC protocol. The Initialize method negotiates capabilities, while handler methods process tool calls and prompt interception.

Minimal Server Skeleton

package main

import (
    "context"
    "encoding/json"
    "github.com/esengine/DeepSeek-Reasonix/sdk/go/extension"
)

type plugin struct {
    id string
}

func (p *plugin) Initialize(
    _ context.Context,
    params extension.InitializeParams,
) (*extension.InitializeResult, error) {
    return &extension.InitializeResult{
        Provider: p.id + "/demo",   // e.g., "plugin/myplugin/demo"
        Model:    "demo-1",
        Tools:    true,             // Advertise tool support
    }, nil
}

// Implement other required handlers:
// - InterceptInput: modify user messages
// - InterceptTool: handle tool execution
// - InterceptSystemPrompt: modify system prompts

The full reference implementation lives in [sdk/go/examples/fullsidecar/main.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/sdk/go/examples/fullsidecar/main.go). This example demonstrates proper request/response streaming and graceful shutdown handling—copy it as your starting template.


Step 3: Register Tools with Namespaced Identifiers

Tools must be registered through the Reasonix SDK. The runtime automatically prefixes tool names to prevent collisions between plugins.

import "github.com/esengine/DeepSeek-Reasonix/sdk/go/tool"

func (p *plugin) registerTools() {
    tool.Register(&tool.Tool{
        Name: "search",
        Run: func(
            ctx context.Context,
            args json.RawMessage,
        ) (json.RawMessage, error) {
            // Parse args, execute search, return results
            var req SearchRequest
            if err := json.Unmarshal(args, &req); err != nil {
                return nil, err
            }
            result := performSearch(req.Query)
            return json.Marshal(result)
        },
    })
}

After registration, this tool becomes available as:


mcp__plugin_myplugin_myplugin__search

The naming convention follows the pattern mcp__plugin_<plugin-id>_<plugin-name>__<tool-name>. As implemented in [internal/tool/tool.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/tool.go), this guarantees plugin isolation—no plugin can accidentally or maliciously invoke another plugin's tools.


Step 4: Create Skill Markdown Files

Skills bundle prompts with metadata about which tools they may use. Place these in your plugin's skills/ directory.

---
description: Summarize a document using the plugin's search tool
allowedTools:
  - "mcp__plugin_myplugin_myplugin__search"
---

You are a research assistant. Your task is to summarize the following text.

Use the search tool to verify any factual claims before including them in your summary.

The front-matter fields control skill behavior:

  • description: Shown in skill selection UI
  • allowedTools: List of tool name patterns the skill may invoke

Reasonix scans plugin directories at startup and loads skills into the prompt library, per [internal/skill/skill.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/skill/skill.go). The allowedTools pattern matching is tested in [internal/skill/skill_test.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/skill/skill_test.go), which includes examples of skills calling plugin-owned tools.


Step 5: Controller Wires Everything at Startup

When Reasonix boots, the controller orchestrates plugin initialization. Located in [internal/control/controller.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/control/controller.go), it executes:

  1. AddMCPServer: Parses configuration entries and prepares launch parameters
  2. mcpSpec: Builds a plugin.Spec defining the server's capabilities
  3. WireCapabilityRouting: Connects tools and skills to the session's request router

The controller respects the tier setting:

  • eager: Server starts immediately with Reasonix
  • lazy: Server starts on first tool invocation
  • on-demand: Server starts only when explicitly requested by user or skill

Step 6: Invoke Plugin Tools and Skills

After startup, the AI accesses your plugin through two mechanisms:

Direct Tool Calling

The model requests tools by their fully-qualified name:

// AI generates this tool call:
request := extension.ToolCall{
    Name: "mcp__plugin_myplugin_myplugin__search",
    Arguments: json.RawMessage(`{"query": "quantum computing"}`),
}

Skill-Based Invocation

Skills grant implicit tool access when invoked:

// User or system selects the "summarize" skill
request := extension.Request{
    ProviderRef: "plugin/myplugin/demo",
    Model:       "demo-1",
    Prompt:      "Summarize the article about quantum computing.",
    // The skill's allowedTools permits the AI to call search automatically
}

Complete Plugin Directory Structure


plugins/
└─ myplugin/
   ├─ main.go              # MCP server entry point

   ├─ tools/
   │   └─ search.go        # Tool implementations (optional organization)

   ├─ skills/
   │   └─ summarize.md     # Skill definition with front-matter

   └─ go.mod               # Module dependencies


Debugging and Verification

The Reasonix desktop client provides visibility into MCP server status. Reference [desktop/plugin_mcp_server_view.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/desktop/plugin_mcp_server_view.go) to understand:

  • Connection state indicators
  • Tool registration confirmation
  • Skill indexing status
  • Runtime error logs

Summary

  • Configure plugins via [[plugins]] entries in TOML with stable names and launch commands
  • Implement MCP servers following the JSON-RPC spec—start from the full-sidecar example
  • Register tools through the SDK; receive automatic mcp__plugin_<id>_<name>__ prefixing
  • Define skills as markdown with front-matter declaring allowedTools
  • Restart Reasonix to trigger controller wiring via AddMCPServer, mcpSpec, and WireCapabilityRouting

The full implementation examples and core logic are available in the esengine/DeepSeek-Reasonix repository under sdk/go/examples/ and internal/control/.


Frequently Asked Questions

What programming languages can I use to write MCP server plugins?

Reasonix communicates via JSON-RPC over stdin/stdout or HTTP, so any language works. The Go SDK in sdk/go/ provides convenience wrappers, but you can implement the protocol in Python, TypeScript, Rust, or others. The fullsidecar example demonstrates the message format you must support.

How do I prevent tool name collisions between plugins?

The runtime handles this automatically. As defined in [internal/tool/tool.go](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/internal/tool/tool.go), every tool is prefixed with mcp__plugin_<plugin-id>_<plugin-name>__. This namespace isolation ensures that a tool named "search" in "myplugin" becomes distinct from "search" in "otherplugin".

Can I update plugin tools without restarting Reasonix?

Currently, tool registration and skill loading occur during controller initialization at startup. The tier setting controls when servers launch, but runtime re-registration requires a restart. For development, use tier = "lazy" or tier = "on-demand" to minimize restart overhead.

How do skills differ from direct tool calling?

Skills are high-level prompt templates that bundle:

  • Pre-written instructions for the AI
  • Declared tool permissions (allowedTools)
  • Metadata for discovery and UI display

Direct tool calling gives the model raw function access without the structured prompting that skills provide. Skills are preferred for complex workflows where the AI needs guided reasoning.

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 →