Read-only knowledge should be an MCP resource, not another executable tool

Agentic AI SeedlingPlanted Sep 2026

I expose stable read-only knowledge as an MCP resource before I wrap it in an executable tool. Files, schemas, policy manuals, build outputs, and reference records are context. Presenting every one of them as a callable function collapses the difference between learning about the world and changing it — exactly the distinction an agent host should preserve.

The current MCP specification makes that split operational. Resources are application-driven and identified by URIs; a client can list them, read their text or binary contents, present them for explicit selection, or include them by host policy. Tools are model-controlled operations with input schemas and a call lifecycle. A server may expose both, but the primitives communicate different intent. A database service can expose its schema as a resource while reserving a query or mutation for a tool.

That intent matters before security enters the discussion. A resource has stable identity. Its URI can appear in logs, citations, caches, subscriptions, and freshness checks. MIME type describes interpretation; annotations can indicate audience, priority, and modification time. In the latest protocol revision, list and read results can also carry cache information. These are useful properties for knowledge because they let the host decide what to load and when. A generic get_document(name) tool hides the same object behind an invocation and forces the model to rediscover identity through arguments.

Tool-wrapping also consumes scarce control-plane attention. The model sees another operation, chooses whether to call it, constructs arguments, handles execution errors, and interprets a result. Multiply that pattern across repositories, runbooks, tables, and records, and the tool catalogue becomes a badly designed retrieval index. I would rather let the host offer navigable resources, then reserve tool selection for genuine computation or effects. This complements the argument that tool retrieval should optimize capability coverage: the cleanest way to cover a read-only capability may be not to advertise it as a tool at all.

A read-only annotation does not repair the category mistake. MCP tool annotations, including readOnlyHint, are hints and must be treated as untrusted unless the server is trusted. They help a client choose confirmation and display behavior; they do not enforce authorization or prove that an implementation has no side effects. Keeping a document a resource narrows the semantic surface. The server still must validate the URI and enforce access control, but the client no longer has to pretend that an executable interface is harmless because metadata says so.

The split also improves governance. I can authorize a principal to read a bounded URI namespace without granting a broad query function. I can record which version entered context and distinguish stale context from failed execution. If a resource changes, subscriptions or list-change signals can invalidate the host’s assumptions. That supports treating MCP servers as supply chain: resource identity, version, and provenance become reviewable inputs rather than opaque text returned by whichever function the model happened to call.

I concede that some read paths genuinely deserve tools. Search with ranked results, a parameterized database query, expensive aggregation, or access that requires a multi-step challenge is computation, not merely retrieval. The latest MCP resource flow can itself request additional input, so even that boundary is becoming more expressive. My rule is not “reads are never tools.” It is that stable knowledge should not acquire executable semantics without a concrete reason.

I want an MCP surface to tell the truth at a glance: resources are things the application may place in context; prompts are reusable interaction structures; tools are operations the model may invoke. Preserving that vocabulary reduces catalogue noise, makes authorization narrower, and keeps capability reduction visible in the protocol design instead of postponing it to runtime policy.