modelcontextprotocol/servers · error · Error
Unknown resource: ${uri.toString()}
Error message
Unknown resource: ${uri.toString()} What it means
Thrown by `parseResourceId` in the resource-template resolver when the URI neither starts with the text base nor the blob base. The first guard is a defensive check: a URI reaching this resolver is expected to match one of the two registered template prefixes (`demo://resource/dynamic/text` or `.../blob`). Reaching it with any other URI is treated as an unknown resource.
Source
Thrown at src/everything/resources/templates.ts:145
new URL(`${blobUriBase}/${resourceId}`);
/**
* Parses the resource identifier from the provided URI and validates it
* against the given variables. Throws an error if the URI corresponds
* to an unknown resource or if the resource identifier is invalid.
*
* @param {URL} uri - The URI of the resource to be parsed.
* @param {Record<string, unknown>} variables - A record containing context-specific variables that include the resourceId.
* @returns {number} The parsed and validated resource identifier as an integer.
* @throws {Error} Throws an error if the URI matches unsupported base URIs or if the resourceId is invalid.
*/
const parseResourceId = (uri: URL, variables: Record<string, unknown>) => {
const uriError = `Unknown resource: ${uri.toString()}`;
if (
uri.toString().startsWith(textUriBase) &&
uri.toString().startsWith(blobUriBase)
) {
throw new Error(uriError);
} else {
const idxStr = String((variables as any).resourceId ?? "");
const idx = Number(idxStr);
if (Number.isFinite(idx) && Number.isInteger(idx) && idx > 0) {
return idx;
} else {
throw new Error(uriError);
}
}
};
/**
* Register resource templates with the MCP server.
* - Text and blob resources, dynamically generated from the URI {resourceId} variable
* - Any finite positive integer is acceptable for the resourceId variable
* - List resources method will not return these resources
* - These are only accessible via template URIs
* - Both blob and text resources:View on GitHub (pinned to 76d64c822f)
Solutions
- Ensure the requested URI matches one of the registered templates: `demo://resource/dynamic/text/{id}` or `demo://resource/dynamic/blob/{id}`.
- Use the resources/templates/list response to obtain valid URI templates rather than constructing them by hand.
- Route static (non-templated) resource URIs to the static resource handler, not the dynamic template resolver.
Example fix
// before
readResource('demo://resource/static/text/1')
// after
readResource('demo://resource/dynamic/text/1') Defensive patterns
Strategy: validation
Validate before calling
const TEXT_BASE = 'demo://resource/dynamic/text';
const BLOB_BASE = 'demo://resource/dynamic/blob';
function isKnownDynamicUri(u: string): boolean {
return u.startsWith(TEXT_BASE) || u.startsWith(BLOB_BASE);
}
// only route URIs that pass this check to the dynamic template handler Type guard
function isDynamicResourceUri(uri: URL): boolean {
const s = uri.toString();
return s.startsWith('demo://resource/dynamic/text/') || s.startsWith('demo://resource/dynamic/blob/');
} Prevention
- Obtain URIs from resources/templates/list rather than constructing by hand.
- Route static resource URIs to the static handler, not the dynamic resolver.
- Match the exact template prefix before reading.
When it happens
Trigger: A resources/read or template-completion request whose URI does not begin with `demo://resource/dynamic/text` or `demo://resource/dynamic/blob` — e.g. a client constructs `demo://resource/dynamic/other/1` or sends a static resource URI to the dynamic template handler.
Common situations: Misrouting requests to the wrong template handler, typos in hand-built URIs, or a client that strips/rewrites the scheme. Note the logic uses `&&` (both startsWith checks), so in practice this branch is hard to hit unless the URI matches neither prefix — which then falls into the else and validates the id; this specific throw is reached only when the URI is entirely foreign to both bases.
Related errors
- Invalid resourceType: ${args?.resourceType}. Must be ${RESOU
- Invalid resourceId: ${args?.resourceId}. Must be a finite po
- Invalid resourceType: ${args?.resourceType}. Must be ${RESOU
- Invalid resourceId: ${args?.resourceId}. Must be a finite po
- Unknown outputType: ${outputType}
AI-assisted analysis of modelcontextprotocol/servers@76d64c822f (2026-08-12).
Data as JSON: /api/errors/b71605bbcaf2a97c.
Report an issue: GitHub.