How MCP Plugin Resources Are Referenced in Chat: DeepSeek-Reasonix Implementation

MCP plugin resources are referenced in chat using the @<server>:<uri> syntax, which the controller detects, validates against connected servers, and injects into the conversation context after fetching the content via RPC calls.

DeepSeek-Reasonix treats MCP (Multi-Channel Plugin) resources as first-class references that can be injected directly into any chat turn. When a user types a token matching the @server:uri pattern, the system automatically resolves the reference by communicating with the connected MCP server and inserting the retrieved content into the model's prompt.

The Reference Syntax Pattern

Reasonix uses a concise, mention-style syntax for resource references that mirrors familiar social media patterns. A valid reference follows the format @<server>:<uri>, where the server name identifies the connected MCP plugin and the URI specifies the resource path.

For example, when a user writes:

Please summarise the API spec: @docs:file://README.md

The controller identifies @docs:file://README.md as a potential MCP resource reference. The prefix before the colon (docs) must match a connected MCP server name stored in the controller's known map, while the suffix (file://README.md) represents the resource URI that the server understands.

Detection and Classification Pipeline

The reference detection logic resides in internal/control/refs.go and operates in two distinct phases to ensure only valid MCP resources are processed.

Token Detection

The detectRefs routine scans each line of chat input for tokens beginning with @. When it finds a candidate, it extracts the server name and URI by splitting on the first colon:

// inside detectRefs (internal/control/refs.go)
if i := strings.Index(tok, ":"); i > 0 && i+1 < len(tok) && known[tok[:i]] {
    // → token matches a connected server name
    refs = append(refs, ref{
        kind:   refResource,
        server: tok[:i],
        uri:    tok[i+1:],
        raw:    tok,
    })
}

This creates a ref struct with kind set to refResource (defined at line 39 of internal/control/refs.go), capturing both the server identifier and the specific resource URI.

Server Validation

The classifyRef function validates references against the known map of currently connected MCP servers (see line 74 of internal/control/refs.go). If the server prefix does not match an active connection, the token is ignored or treated as plain text, preventing invalid RPC calls to disconnected plugins.

MCP Resource Lifecycle

Once a reference is validated, Reasonix coordinates with the MCP plugin through a three-stage lifecycle: enumeration, retrieval, and injection.

Listing Available Resources

When an MCP server connects, the Host queries the plugin to discover available resources via the listResources method in internal/plugin/resources.go. This method invokes the RPC method resources/list and unmarshals the response into a slice of plugin.Resource objects:

// internal/plugin/resources.go
func (c *Client) listResources(ctx context.Context) ([]Resource, error) {
    res, err := c.call(ctx, "resources/list", map[string]any{})
    // … unmarshal JSON into []Resource …
}

The resource list is aggregated at the host level through internal/plugin/plugin.go (specifically the Resources() and fetchResources methods), making discovered resources available to the UI for auto-completion and status displays.

Reading Resource Content

When the controller needs to resolve a specific reference, it calls readResource (line 50 of internal/plugin/resources.go) to fetch the actual content:

// internal/plugin/resources.go
func (c *Client) readResource(ctx context.Context, uri string) (string, error) {
    res, err := c.call(ctx, "resources/read", map[string]any{"uri": uri})
    // … concatenate text portions, omit binary blobs …
    return sb.String(), nil
}

This method invokes the resources/read RPC method. The response may contain text or binary blobs. Text content is concatenated and preserved for injection, while binary data is summarized (e.g., "[binary resource …]") to prevent token bloat in the model's context window.

Content Injection into Chat Context

The ResolveRefs method in internal/control/controller.go orchestrates the final injection. It replaces the original @server:uri token with the fetched content, prepending the resource text to the user's prompt:

func (c *Controller) ResolveRefs(line string) string {
    for _, r := range c.detectRefs(line) {
        if r.kind == refResource {
            txt, _ := c.mcp.client(r.server).readResource(context.Background(), r.uri)
            line = strings.Replace(line, "@"+r.raw, txt, 1)
        }
    }
    return line
}

The resolved content is sent to the LLM as part of the conversation history, allowing the model to reason about external documents, code files, or web-accessible resources without manual copy-pasting.

Key Implementation Files

The end-to-end flow spans several components within the Reasonix codebase:

Summary

  • Reference syntax follows the pattern @<server>:<uri>, where the server prefix must match a connected MCP plugin.
  • Detection occurs in internal/control/refs.go via detectRefs, which creates refResource structs for valid tokens.
  • Validation checks the server name against the known map in classifyRef before attempting RPC calls.
  • Resource enumeration uses listResources (RPC resources/list) to discover available items when servers connect.
  • Content retrieval happens through readResource (RPC resources/read), which handles both text and binary data.
  • Injection replaces the original token with fetched content via ResolveRefs in the controller, prepending resource data to the model prompt.

Frequently Asked Questions

What happens if I reference an MCP server that isn't connected?

If the server prefix in your @server:uri token does not match an entry in the controller's known map, the classifyRef function treats the token as plain text. The system does not attempt to resolve the reference via RPC, and the literal text remains in your chat message without triggering a resource fetch.

Can MCP resources contain binary data like images or PDFs?

Yes, but with limitations. The readResource implementation in internal/plugin/resources.go detects binary responses and summarizes them (e.g., "[binary resource …]") rather than injecting raw bytes into the chat context. This prevents token overflow while still informing the model that a binary resource exists at the referenced location.

How does Reasonix handle multiple resource references in a single message?

The ResolveRefs method iterates over all detected references in the input line, fetching content for each valid @server:uri token sequentially. Each reference is replaced with its corresponding content, and the fully resolved string is then sent to the LLM. The order of resolution follows the left-to-right appearance of tokens in the original message.

Where can I see which MCP resources are available before referencing them?

The internal/cli/mcp_manager_view.go file renders the MCP status interface, which displays the number of discovered resources for each connected server. Additionally, the Resources() method in internal/plugin/plugin.go aggregates available resources from all connections, making them accessible to the UI for browse-and-select functionality or auto-completion hints.

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 →