The setup
Resources and prompts are where teams accidentally rebuild shadow APIs—keep them narrow. If every read is a tool, you lose caching, ACL clarity, and my patience. Tools are for verbs with side effects; resources are for nouns you can read without setting the building on fire.
Picture this
Mental model
Resources answer “what exists to read?” Prompts answer “what instruction recipe should we apply?” Do not make tools answer both unless you enjoy incident reports.
Walkthrough
- Use URI templates for parameterized reads. Stable patterns beat ad-hoc string IDs in tool args.
- Treat prompt bodies like versioned code—review changes. Prompts are not “just text”; they are executable intent for models.
Hall of Shame
Hall of shame: Tool-shaped readsdesign
tool("get_doc", { id: z.string() }, ...)
Fix: prefer docs://{id} resource unless reads must be side-effecting (they should not). Tool-shaped reads are shadow APIs with worse caching and the same auth mistakes.
Why this matters in production
Resources are easier to cache, scan, and ACL than tools—use that. Prompts belong in change control like code, not in a shared doc someone edits during a demo. I am magnificent; your prompt library should not be a surprise box.
Mini challenge
Pick one read tool and convert it to a resource—what auth checks move where? If you cannot answer, you do not understand your own surface yet.
Reflection
Which prompts in your org should require human approval to publish, not just to run? Publishing poisoned templates hurts every session; running them once hurts one meeting. Both are bad. One scales.
You can now brag that…
You can explain why your docs are resources without sounding like you reinvented HTTP GET (even if you kinda did, but politely). Progress.