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

> Learn how MCP plugin resources are referenced in chat using the @server:uri syntax in DeepSeek-Reasonix. Discover RPC calls and context injection.

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

---

**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:

```text
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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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:

```go
// 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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/plugin/resources.go). This method invokes the RPC method `resources/list` and unmarshals the response into a slice of `plugin.Resource` objects:

```go
// 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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/plugin/resources.go)) to fetch the actual content:

```go
// 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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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:

```go
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:

- **[`internal/control/refs.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/control/refs.go)** – Contains `detectRefs` and `classifyRef` for parsing `@` tokens and distinguishing MCP resources (`refResource`).
- **[`internal/plugin/resources.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/plugin/resources.go)** – Defines the `Resource` struct and implements `listResources` and `readResource` for RPC communication.
- **[`internal/plugin/plugin.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/plugin/plugin.go)** – Host-level aggregation via `Resources()` and `fetchResources` methods that collect resources from all connected servers.
- **[`internal/control/controller.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/control/controller.go)** – Session driver that calls `detectRefs` and injects resource content into chat turns.
- **[`internal/cli/mcp_manager_view.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/cli/mcp_manager_view.go)** – CLI helper that renders MCP status, including the number of discovered resources for each connection.

## 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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/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.