How to Create and Register MCP Server Plugins in Reasonix

To create and register MCP server plugins in Reasonix, implement the MCP metadata interfaces in your Go type, register the tool using tool.Register() in an init function, and expose the binding through the session store's ConfigureToolBindings hook.

Reasonix supports Model-Controlled Plugin (MCP) servers that extend AI capabilities through external tools. Creating an MCP server plugin requires implementing specific metadata interfaces defined in the internal/tool package and registering your tool with the central registry. This guide walks through the exact implementation steps using the DeepSeek-Reasonix source code.

Implementing MCP Metadata Interfaces

Every MCP server plugin must satisfy the interface requirements defined in internal/tool/tool.go. These interfaces provide the metadata necessary for Reasonix to generate portable tool bindings and capability identifiers.

Required Interface Methods

Your tool type must implement the MCPMetadata interface, which defines two essential methods:

  • MCPServerName() string – Returns the logical server name (e.g., "myserver").
  • MCPRawToolName() string – Returns the raw tool identifier (e.g., "do_something").

Optional Metadata Methods

For enhanced visibility and package management, implement these optional interfaces:

  • MCPVisibleMetadata – Provides MCPVisibleToolName() string for user-facing display names.
  • MCPPackageMetadata – Provides MCPPackageName() string to identify the plugin package for alias generation.

Example implementation skeleton:

package myplugin

import "github.com/esengine/DeepSeek-Reasonix/internal/tool"

type DoSomething struct{}

func (DoSomething) MCPServerName() string      { return "myserver" }
func (DoSomething) MCPRawToolName() string     { return "do_something" }
func (DoSomething) MCPVisibleToolName() string { return "Do Something" }
func (DoSomething) MCPPackageName() string     { return "myplugin" }

Registering Tools with the Global Registry

After defining your tool, register it with Reasonix’s global registry located in internal/tool/registry.go. The registry creates canonical callable names and maintains the mapping between portable references and concrete implementations.

The Registration Flow

  1. Call tool.Register() – Pass your tool instance to this function inside your package's init() function.

  2. Canonical Name Generation – The registry constructs the callable name using the pattern:

    
    mcp__<server>__<tool>
    

    For the example above, this generates mcp__myserver__do_something.

  3. Alias Creation – The registry automatically generates compatibility aliases using the MCPBindingAliases function. These follow the pattern:

    
    mcp__plugin_<package>_<server>__<tool>
    

    If your package is "myplugin", the alias becomes mcp__plugin_myplugin_myserver__do_something.

Registration code:

func init() {
    tool.Register(DoSomething{})
}

The Register method in internal/tool/registry.go inserts the tool into the global Registry and builds the MCPBinding record containing the server name, raw name, visible name, callable name, capability ID, and package identifier.

Exposing Plugins to the Runtime Session

To make registered tools available during a Reasonix session, you must configure the tool bindings in the skill store. The store implementation in internal/skill/skill.go manages the runtime exposure of MCP capabilities.

Configuring Tool Bindings

Use the ConfigureToolBindings hook on the skill.Store to inject your MCP bindings into the session resolver. This function should return a slice of tool.MCPBinding structures that match your registered tools.

Example configuration:

store.ConfigureToolBindings(func(sk skill.Skill) []tool.MCPBinding {
    return []tool.MCPBinding{
        {
            Server:       "myserver",
            RawName:      "do_something",
            VisibleName:  "Do Something",
            CallableName: "mcp__myserver__do_something",
            CapabilityID: "mcp-tool:myserver/do_something",
            Package:      "myplugin",
        },
    }
})

Runtime MCP Tool Bindings Section

When a skill is prepared, the Store.Prepare method writes a "## Runtime MCP tool bindings" section into the skill body. This section lists the concrete callable names and capability IDs, enabling the model to resolve short references to authoritative binding records. The model can then invoke tools using either the direct callable name (mcp__myserver__do_something) or the stable capability ID (mcp-tool:myserver/do_something).

Complete Implementation Example

Here is a complete, runnable example combining all three stages:

// myplugin/tool.go
package myplugin

import (
    "github.com/esengine/DeepSeek-Reasonix/internal/tool"
)

type DoSomething struct{}

func (DoSomething) MCPServerName() string      { return "myserver" }
func (DoSomething) MCPRawToolName() string     { return "do_something" }
func (DoSomething) MCPVisibleToolName() string { return "Do Something" }
func (DoSomething) MCPPackageName() string     { return "myplugin" }

func init() {
    tool.Register(DoSomething{})
}
// main.go
package main

import (
    "github.com/esengine/DeepSeek-Reasonix/internal/skill"
    "github.com/esengine/DeepSeek-Reasonix/internal/tool"
    _ "github.com/esengine/DeepSeek-Reasonix/myplugin" // Import for side effects
)

func main() {
    store := skill.NewStore()
    
    store.ConfigureToolBindings(func(sk skill.Skill) []tool.MCPBinding {
        return []tool.MCPBinding{
            {
                Server:       "myserver",
                RawName:      "do_something",
                VisibleName:  "Do Something",
                CallableName: "mcp__myserver__do_something",
                CapabilityID: "mcp-tool:myserver/do_something",
                Package:      "myplugin",
            },
        }
    })
    
    // Continue with session initialization...
}

When the model issues use_tool "mcp__myserver__do_something", Reasonix resolves the call through the registry, invokes the DoSomething implementation, and returns the result.

Summary

  • Implement metadata interfaces – Satisfy MCPMetadata (required) and optionally MCPVisibleMetadata and MCPPackageMetadata in internal/tool/tool.go.
  • Register during initialization – Call tool.Register() inside your package's init() function to add the tool to the global registry in internal/tool/registry.go.
  • Generate canonical names – The registry automatically creates callable names (mcp__<server>__<tool>) and package aliases.
  • Expose via session store – Use ConfigureToolBindings in internal/skill/skill.go to make tools available to the model runtime.
  • Runtime resolution – The skill body includes a "## Runtime MCP tool bindings" section mapping portable names to concrete tool implementations.

Frequently Asked Questions

What is the difference between the callable name and the capability ID in Reasonix MCP plugins?

The callable name (e.g., mcp__myserver__do_something) is the direct function reference the model uses to invoke the tool, while the capability ID (e.g., mcp-tool:myserver/do_something) provides a stable, URI-style identifier for capability-based invocation systems. Both resolve to the same tool implementation through the registry.

Where does Reasonix store the global tool registry?

The global tool registry is implemented in internal/tool/registry.go as the Registry variable. This centralized store maintains all registered MCP tools and generates the MCPBinding structures that connect server names and tool names to their concrete Go implementations.

Can I register multiple tools from the same MCP server package?

Yes. You can define multiple types in the same package, each implementing the metadata interfaces with the same MCPServerName() return value but different MCPRawToolName() values. Register each type in the same init() function or separate init() functions within the package; the registry in internal/tool/registry.go handles multiple registrations from the same source.

How does Reasonix handle tool name collisions between different MCP server plugins?

The registry constructs unique callable names using the pattern mcp__<server>__<tool>, which namespaces tools by their server name. If two different packages register tools with identical server and tool names, the later registration will overwrite the earlier one in the global registry. To avoid collisions, use distinct server names or leverage the MCPPackageMetadata interface to generate unique aliases via MCPBindingAliases.

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 →