Repository navigation
Resource Templates
A resource template names a family of resources with one URI template1. The SDK matches the URI of a resources/read request against the templates and gives the variables to the handler. The template syntax is a subset of RFC 65702. This page tells you how to register a template, which syntax the SDK accepts and how the match works.
Applies to: MCP 2026-07-28, Zig 0.16.0, zig-sdk 0.1.0. The length limits of templates and URIs, and the check of the completion reference: zig-sdk 0.2.0.
Server.addResourceTemplate(def, handler) registers a template. The first registration of a resource or a template declares the resources capability with listChanged and subscribe.
fn readUser(ctx: *mcp.RequestContext, uri: []const u8, vars: []const mcp.UriTemplate.Variable) anyerror!mcp.Outcome(mcp.types.ReadResourceResult) {
const contents = try ctx.arena.alloc(mcp.types.ResourceContents, 1);
contents[0] = .{ .text = .{ .uri = uri, .mimeType = "text/plain", .text = vars[0].value } };
return .{ .complete = .{ .contents = contents } };
}
try server.addResourceTemplate(.{
.uri_template = "users://{id}/profile",
.name = "User profile",
.mime_type = "text/plain",
}, readUser);The fields of the definition:
| Field | Meaning |
|---|---|
uri_template |
The URI template. |
name |
The name of the template. |
title, description, mime_type, annotations
|
The optional metadata of the template. |
list |
An optional function that gives the concrete resources of the template for resources/list. |
userdata |
A pointer that the handler gets in ctx.userdata. |
A template with a syntax error, or with more than limits.uri_template.max_expressions (256) expressions, gives error.InvalidUriTemplate at registration. A template that is longer than limits.uri_template.max_template_bytes (64 KiB) gives the same error.
| Expression | Name in RFC 6570 | Value |
|---|---|---|
{var} |
Simple expansion | Text without /, ? and #. |
{+var} |
Reserved expansion | Any text, also with /. |
{#var} |
Fragment expansion | Text after #. |
{.var} |
Label expansion | Text after ., without ., /, ? and #. |
{/var} |
Path segment expansion | Text after /, without /, ? and #. |
{?var} |
Form-style query | Text after ?. |
{&var} |
Form-style query continuation | Text after &. |
A variable name has letters, digits, _, . and %. The SDK rejects these parts of RFC 6570:
- A list of variables in one expression, such as
{a,b}. - The explode modifier, such as
{list*}. - The prefix modifier, such as
{name:3}. - The operators
;,=,,,!,@and|.
The match goes from left to right and never goes back. A literal part must occur at the current position. The value of an expression ends at the next literal part, or at the end of the URI. The full URI must match. A URI that is longer than limits.uri_template.max_uri_bytes (64 KiB) matches no template.
The value of a variable is a slice of the URI. It stays percent-encoded. Decode it in the handler when you need the decoded text.
Some examples with the template users://{id}/profile:
| URI | Result |
|---|---|
users://42/profile |
A match with id = 42. |
users://42/profile/x |
No match: text follows the last literal part. |
users://4/2/profile |
No match: a simple value cannot contain /. |
For resources/read, the server first looks for a resource with the exact URI. Then it tries the templates in the order of registration. The first template that matches gets the request. When no resource and no template matches, the server answers -32602 with the message "Resource not found: URI" and the URI in data.uri. A handler that returns no contents gets the same error.
The handler can return .input_required for a multi round-trip request, like a tool handler. A resource handler cannot start a task.
resources/templates/list gives every template, with pages of limits.page_size (100) entries3. resources/list gives the static resources and the resources that the list function of each template returns.
A client can ask for completions of a template variable with completion/complete and a ref/resource reference4. The reference has the template URI, or a URI that the template matches. A reference to an unknown template gets -32602 before the handler runs. Server.setCompletionHandler(handler) sets one handler for all prompts and templates. The server gives at most limits.completion_max_values (100) values and sets hasMore when there are more.
- MCP-RESOURCES-2026-07-28: Resources and resource templates.
- RFC6570: "URI Template".
- MCP-PAGINATION-2026-07-28: Pagination with cursors.
- MCP-COMPLETION-2026-07-28: Completion of arguments.
zig-sdk uses the Apache License 2.0. The wiki uses the project profile of ASD-STE100 Simplified Technical English. The Bibliography lists the sources.
zig-sdk
- Home
- Getting Started
- Concepts
- Server Guide
- Client Guide
- Transports
- Transport stdio
- Transport Streamable HTTP
- Transport gRPC
- Transport Unix Socket
- Transport WebSocket
- TLS and Certificates
- Deploy Reverse Proxy
- Authorization
- Authorization Server
- JSON Schema Support
- Resource Templates
- Tasks Extension
- Skills Extension
- Apps Extension
- Conformance
- Examples
- API Reference
- Interoperability
- Threat Model
- Limits and Security
- Deprecated Features
- Roadmap
- Release Notes
- Versioning
- Contributing
- FAQ
Style and words