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

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 implements separate methods for each discovery type:


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

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:


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


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

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.

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 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.

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 →