# How Remote Tools Are Adapted to the Tool Interface in DeepSeek-Reasonix

> Discover how DeepSeek-Reasonix adapts remote tools to its interface using a lightweight proxy. Learn about schema metadata forwarding and RPC execution for seamless integration.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: how-to-guide
- Published: 2026-06-23

---

**DeepSeek-Reasonix adapts remote Model-Client-Protocol (MCP) tools to the Tool interface using a lightweight proxy that prefixes names with `mcp__`, forwards schema metadata, and executes RPC calls over the network.**

DeepSeek-Reasonix treats every capability that the model can invoke as a first-class `Tool`, including remote capabilities provided by external MCP servers. The adaptation layer implemented in [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go) creates proxy objects that satisfy the local interface while forwarding execution to remote endpoints. This design allows the planner, preview subsystem, and execution loop to handle remote and built-in tools identically without protocol-specific branching.

## The Tool Interface Abstraction

Every tool in DeepSeek-Reasonix implements the same interface, whether it is a built-in file writer or a remote search capability. The interface requires five methods: `Name()` for identification, `Description()` for the model's context, `Schema()` for JSON-Schema validation, `Execute(ctx, args)` for invocation, and `ReadOnly()` to indicate side effects. Because remote tools implement this exact contract, the engine treats them as native capabilities without modification to the planning or execution logic.

## Namespace Prefixing for Remote Tools

To prevent collisions between built-in and remote tools, DeepSeek-Reasonix applies a strict naming convention defined in [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go).

### The MCPNamePrefix Constant

In [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go) (lines 33-37), the system defines `MCPNamePrefix = "mcp__"`. Every remote tool receives a canonical name following the pattern `mcp__<server>__<tool>`, ensuring unique identification across the registry.

### Name Splitting and Routing

The helper function `SplitMCPName` (lines 40-49 in the same file) parses prefixed names to extract the server identifier and original tool name. It returns `ok = false` for non-MCP names, allowing the adapter to route calls to the correct remote endpoint or fall back to local execution.

## Remote Tool Proxy Implementation

When an MCP connection is established, the client builds a proxy struct that implements the `Tool` interface using the remote server's metadata.

### Proxy Method Behaviors

- **Name()** returns the prefixed identifier (`mcp__<server>__<tool>`).
- **Description()** forwards the string provided by the remote server unchanged.
- **Schema()** returns the JSON-Schema stored verbatim from the remote server's tool definition.
- **Execute(ctx, args)** marshals arguments and sends an RPC request to the remote MCP server, returning the server's JSON result as a string.
- **ReadOnly()** always returns **false** because the client cannot statically infer whether remote operations have side effects.

## Registry Lifecycle and Schema Canonicalization

Remote tools enter the system through the `Registry` type, which manages both discovery and cleanup.

### Schema Canonicalization

When `Registry.Add` inserts a proxy tool, `provider.CanonicalizeSchema` processes the schema once (lines 13-16 in [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go)). This guarantees that the registry exposes a stable, normalized list of tool definitions to the LLM, regardless of the source server.

### Dynamic Removal and Suspension

The registry supports lifecycle methods for volatile connections:

- `Registry.RemovePrefix(prefix)` deletes every tool whose name starts with a given prefix, invoked when an MCP server disconnects.
- `Registry.SuspendPrefix` and `Registry.ResumePrefix` (lines 52-78) temporarily block tools from being re-added while a session tears down, preventing race conditions during reconnection.

## Implementation Examples

The following patterns demonstrate how remote tools materialize in the codebase.

### Creating a Remote Tool Proxy

```go
func newMCPTool(server, name, desc string, schema json.RawMessage) tool.Tool {
    return &mcpTool{
        server:      server,
        toolName:    name,
        description: desc,
        schema:      schema,
    }
}

type mcpTool struct {
    server, toolName, description string
    schema                         json.RawMessage
}

func (t *mcpTool) Name() string        { return tool.MCPNamePrefix + t.server + "__" + t.toolName }
func (t *mcpTool) Description() string { return t.description }
func (t *mcpTool) Schema() json.RawMessage { return t.schema }
func (t *mcpTool) ReadOnly() bool      { return false }

func (t *mcpTool) Execute(ctx context.Context, args json.RawMessage) (string, error) {
    resp, err := mcpClient.Call(ctx, t.server, t.toolName, args)
    if err != nil {
        return "", err
    }
    return string(resp), nil
}

```

### Registering Remote Tools

```go
reg := tool.NewRegistry()
reg.Add(newMCPTool("my-server", "search", "Search the web", rawSchema))

```

### Executing Through the Generic Interface

```go
if t, ok := reg.Get("mcp__my-server__search"); ok {
    result, _ := t.Execute(ctx, json.RawMessage(`{"query":"golang interface"}`))
    fmt.Println(result)
}

```

## Summary

- Remote MCP tools are adapted to the local `Tool` interface via proxy objects in [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go).
- Names are prefixed with `mcp__<server>__<tool>` to ensure uniqueness and enable routing via `SplitMCPName`.
- The proxy implements all five interface methods, with `Execute` forwarding to the remote server and `ReadOnly` always returning false.
- Schema canonicalization happens once during `Registry.Add`, preparing stable definitions for the LLM.
- Lifecycle methods `RemovePrefix`, `SuspendPrefix`, and `ResumePrefix` handle dynamic server connections.

## Frequently Asked Questions

### How does the naming convention prevent conflicts between remote and local tools?

DeepSeek-Reasonix enforces the `MCPNamePrefix` constant defined in [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go) (lines 33-37). All remote tool names follow the pattern `mcp__<server>__<tool>`, while built-in tools omit this prefix, guaranteeing unique identifiers in the registry.

### Why does the ReadOnly method always return false for remote tools?

The `ReadOnly` method signals whether a tool modifies state. For remote tools, this always returns false because the client cannot statically verify side effects on the remote server, ensuring the planner treats all remote calls as potentially mutating.

### What happens to remote tools when an MCP server disconnects?

The `Registry.RemovePrefix` method removes all tools matching the disconnected server's prefix. Additionally, `SuspendPrefix` and `ResumePrefix` (lines 52-78 in [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go)) manage temporary blocking during session teardown to prevent stale tool registrations from reappearing.

### Is schema canonicalization necessary for every tool addition?

Yes. When `Registry.Add` is called, `provider.CanonicalizeSchema` processes the JSON-Schema once (as implemented in lines 13-16 of [`internal/tool/tool.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/tool.go)). This ensures the LLM receives consistent, normalized tool definitions regardless of variations in remote server implementations.