# Resource Templates vs Regular Resources in MCP Protocol: Key Differences Explained

> Understand the key differences between MCP protocol resource templates and regular resources. Learn how fixed URIs differ from parameterized URI patterns.

- Repository: [Junjie.M/dify-plugin-tools-mcp_sse](https://github.com/junjiem/dify-plugin-tools-mcp_sse)
- Tags: deep-dive
- Published: 2026-03-05

---

**Regular resources use fixed URIs discovered via `resources/list`, while resource templates use parameterized URI patterns via `resources/templates/list`, requiring runtime substitution before reading.**

The Model Context Protocol (MCP) implementation in the `junjiem/dify-plugin-tools-mcp_sse` repository distinguishes between two fundamental resource discovery patterns. Understanding the difference between resource templates and regular resources is essential for building efficient MCP clients that expose static assets and dynamic collections as callable tools.

## Core Architectural Differences

### Discovery Mechanisms

Regular resources are discovered through the `resources/list` endpoint, which returns concrete items with predetermined locations. In contrast, resource templates utilize the `resources/templates/list` endpoint, returning patterns that contain placeholders requiring substitution.

The `McpClient` class in [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-tools-mcp_sse/blob/main/utils/mcp_client.py) implements separate methods for each discovery type:

```python

# Regular resources - utils/mcp_client.py#L87-L104

def list_resources(self) -> list[Resource]:
    response = self._send_request("resources/list")
    return [Resource(**r) for r in response.get("resources", [])]

# Resource templates - utils/mcp_client.py#L123-L139  

def list_resources_templates(self) -> list[ResourceTemplate]:
    response = self._send_request("resources/templates/list")
    return [ResourceTemplate(**t) for t in response.get("resourceTemplates", [])]

```

### Data Structures

A regular resource object contains a concrete `uri` field along with metadata like `name`, `mimeType`, and `size`. Resource templates replace the `uri` field with a `uriTemplate` field containing a parameterized pattern such as `/files/{id}` or `/users/{user_id}/profile`.

## Implementation in the Dify MCP Client

### Action Type Classification

The client distinguishes these resource types internally using the `ActionType` enum defined at `utils/mcp_client.py#L13-L17`:

```python
class ActionType(Enum):
    RESOURCE = "resource"
    RESOURCE_TEMPLATE = "resource_template"
    TOOL = "tool"

```

This classification determines how the client processes each item during tool generation and execution phases.

### Listing Operations

When initializing the tool collection, the client queries both endpoints sequentially. Regular resources are fetched via `list_resources()`, which parses the `resources` array from the JSON-RPC response. Templates are fetched via `list_resources_templates()`, extracting the `resourceTemplates` array.

## Tool Generation and Runtime Behavior

### Schema Generation

The critical difference emerges during tool creation in `McpClient.fetch_tools()` at `utils/mcp_client.py#L512-L533`:

**Regular Resources** generate tools with empty input schemas because the URI is already known:

```python

# For regular resources with fixed URIs

tool = Tool(
    name=resource.name,
    description=f"Read resource: {resource.name}",
    inputSchema={
        "type": "object",
        "properties": {},
        "required": []
    }
)

```

**Resource Templates** generate tools requiring a `uri` parameter because the final address must be constructed at runtime:

```python

# For resource templates with uriTemplate

tool = Tool(
    name=template.name,
    description=f"Read resource template: {template.name}",
    inputSchema={
        "type": "object",
        "properties": {
            "uri": {
                "type": "string",
                "description": "The URI to read (must match template pattern)"
            }
        },
        "required": ["uri"]
    }
)

```

### Execution Flow

At runtime, regular resource tools invoke `resources/read` immediately with the stored URI. Resource template tools first validate that the provided URI matches the template pattern, then perform the read operation using the substituted value.

## Practical Use Cases

### When to Use Regular Resources

Regular resources excel for **static assets** that never change location. Examples include:

- Configuration files with fixed paths (e.g., [`/config/app-settings.json`](https://github.com/junjiem/dify-plugin-tools-mcp_sse/blob/main//config/app-settings.json))
- Static documentation files (e.g., [`/docs/readme.md`](https://github.com/junjiem/dify-plugin-tools-mcp_sse/blob/main//docs/readme.md))
- System information endpoints (e.g., `/system/status`)

These items require no parameterization because their identity and location are constant.

### When to Use Resource Templates

Resource templates are designed for **dynamic collections** where resource paths follow predictable patterns but require runtime parameters. Ideal scenarios include:

- User-specific profiles accessed via `/users/{user_id}/profile`
- Order details retrieved from `/orders/{order_id}/pdf`
- File repositories where items are stored under `/files/{file_id}`

A single template can represent thousands of concrete resources without requiring individual registration.

## Summary

- **Regular resources** expose fixed URIs via `resources/list`, require no input parameters, and suit static assets with constant locations.
- **Resource templates** expose parameterized patterns via `resources/templates/list`, require runtime URI construction, and handle dynamic resource collections efficiently.
- The `junjiem/dify-plugin-tools-mcp_sse` implementation distinguishes these types using `ActionType` enum values and generates appropriate input schemas in [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-tools-mcp_sse/blob/main/utils/mcp_client.py).

## Frequently Asked Questions

### Can a resource template be converted to a regular resource?

No, these are distinct conceptual categories in the MCP protocol. A resource template represents a potentially infinite set of resources defined by a pattern, while a regular resource represents a single concrete item. The client in [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-tools-mcp_sse/blob/main/utils/mcp_client.py) treats them as separate action types and does not convert between them.

### How does the MCP client handle URI template substitution?

The client does not perform server-side substitution. Instead, when `fetch_tools()` processes a resource template at `utils/mcp_client.py#L512-L533`, it creates a tool requiring the caller to provide the complete URI as a parameter. The caller must construct the final URI (e.g., replacing `{id}` with `123`) before invoking the tool.

### Are resource templates slower than regular resources?

Resource templates introduce negligible overhead in the discovery phase but require an additional parameter validation step at runtime. Regular resources execute immediately using pre-cached URIs, while template-based tools validate the provided URI against the pattern before calling `resources/read`. For high-throughput scenarios with known static assets, regular resources offer marginally faster execution paths.

### Which discovery method should I implement first?

Implement `resources/list` first if your server primarily serves static configuration files or fixed assets. Add `resources/templates/list` when your server manages dynamic entities identified by IDs or parameters. The `junjiem/dify-plugin-tools-mcp_sse` client automatically queries both endpoints during initialization, so implementing both ensures maximum compatibility with MCP clients.