diff --git a/src/skillz/_server.py b/src/skillz/_server.py
index da56dd4..3456293 100644
--- a/src/skillz/_server.py
+++ b/src/skillz/_server.py
@@ -120,7 +120,6 @@ def read_body(self) -> str:
 class SkillResourceMetadata(TypedDict):
     """Metadata describing a registered skill resource."""
 
-    path: str
     relative_path: str
     uri: str
     runnable: bool
@@ -568,7 +567,6 @@ def _read_resource() -> str | bytes:
 
         metadata.append(
             {
-                "path": str(resource_path),
                 "relative_path": relative_display,
                 "uri": uri,
                 "runnable": runnable,
@@ -627,18 +625,14 @@ async def _skill_tool(  # type: ignore[unused-ignore]
             instructions = bound_skill.read_body()
             resource_entries = [
                 {
-                    "path": entry["path"],
                     "relative_path": entry["relative_path"],
                     "uri": entry["uri"],
                     "runnable": entry["runnable"],
                 }
                 for entry in bound_resources
             ]
-            resource_uris = [entry["uri"] for entry in resource_entries]
-            legacy_paths = [entry["path"] for entry in resource_entries]
             script_entries = [
                 {
-                    "path": entry["path"],
                     "relative_path": entry["relative_path"],
                     "uri": entry["uri"],
                 }
@@ -675,18 +669,24 @@ async def _skill_tool(  # type: ignore[unused-ignore]
                         """\
 Share the `suggested_prompt` with your assistant or embed the
 `instructions` text directly alongside the task so the model can apply
-the skill as authored. If the instructions mention supporting files,
-call `ctx.read_resource` with one of the URIs in `available_resources`
-before handing data to the model.
+the skill as authored.
+
+IMPORTANT: All skill resources MUST be accessed via the MCP protocol.
+If the instructions mention supporting files, use `ctx.read_resource(uri)`
+with one of the URIs from `available_resources` to read them. Do not
+attempt to access resources via filesystem paths.
 """
                     ).strip(),
                     "script_execution": {
                         "call_instructions": textwrap.dedent(
                             """\
-Invoke this tool again with the `script` parameter set to a path
-relative to the skill root (choose from `available_scripts`) and
-optionally include `script_payload` (keys: args, env, files, stdin,
-workdir).
+Invoke this tool again with the `script` parameter set to a relative
+path from the skill root (use the `relative_path` from
+`available_scripts`). Optionally include `script_payload` (keys: args,
+env, files, stdin, workdir).
+
+Use `ctx.read_resource(uri)` to access any non-script resources before
+invoking scripts.
 """
                         ).strip(),
                         "payload_fields": {
@@ -713,8 +713,7 @@ async def _skill_tool(  # type: ignore[unused-ignore]
                         },
                         "available_scripts": script_entries,
                         "available_resources": [
-                            *resource_uris,
-                            *legacy_paths,
+                            entry["uri"] for entry in resource_entries
                         ],
                     },
                 },
diff --git a/tests/test_run_script.py b/tests/test_run_script.py
index c5c9e48..280c8c1 100644
--- a/tests/test_run_script.py
+++ b/tests/test_run_script.py
@@ -86,7 +86,6 @@ async def test_registers_skill_resources(tmp_path: Path) -> None:
         )
         expected_entries.append(
             {
-                "path": str(resource_path),
                 "relative_path": relative.as_posix(),
                 "uri": uri,
                 "runnable": runnable,
@@ -99,9 +98,16 @@ async def test_registers_skill_resources(tmp_path: Path) -> None:
 
     for entry in expected_entries:
         uri = entry["uri"]
-        path = Path(entry["path"])
+        # Verify we can read the resource via URI
         content = await server._resource_manager.read_resource(uri)
-        file_bytes = path.read_bytes()
+        # Find the original path from skill.resources for validation
+        relative = Path(entry["relative_path"])
+        resource_path = next(
+            p
+            for p in skill.resources
+            if p.relative_to(skill.directory) == relative
+        )
+        file_bytes = resource_path.read_bytes()
         try:
             file_text = file_bytes.decode("utf-8")
         except UnicodeDecodeError:
@@ -124,7 +130,6 @@ async def test_registers_skill_resources(tmp_path: Path) -> None:
         ]
         assert available_scripts == [
             {
-                "path": entry["path"],
                 "relative_path": entry["relative_path"],
                 "uri": entry["uri"],
             }
@@ -133,12 +138,13 @@ async def test_registers_skill_resources(tmp_path: Path) -> None:
         ]
 
         available = payload["usage"]["script_execution"]["available_resources"]
-        assert available[: len(expected_entries)] == [
-            entry["uri"] for entry in expected_entries
-        ]
-        assert available[len(expected_entries) :] == [
-            entry["path"] for entry in expected_entries
-        ]
+        assert available == [entry["uri"] for entry in expected_entries]
+
+        # Regression test: ensure no absolute paths leak into the payload
+        import json
+
+        payload_json = json.dumps(payload)
+        assert '"path"' not in payload_json or "relative_path" in payload_json
 
 
 @pytest.mark.asyncio
diff --git a/uv.lock b/uv.lock
index b2b0d62..91f6ff3 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1116,7 +1116,7 @@ wheels = [
 
 [[package]]
 name = "skillz"
-version = "0.1.0"
+version = "0.1.5"
 source = { editable = "." }
 dependencies = [
     { name = "fastmcp" },
