Published / 6 min
MCP explained: tools for agents and the WebMCP proposal
What the Model Context Protocol connects, how tools, resources, and prompts differ, and what WebMCP proposes for browsers.
Your assistant can reason about an order, but it does not know whether order 4312 has shipped. To answer, it needs to talk to the source of truth; attaching a screenshot or promising it "access to everything" will not do. MCP (Model Context Protocol) defines a way to discover capabilities and request data or actions from external systems.
What problem does it solve, and what does it NOT solve?
Without a shared contract, every AI app needs a different integration to query a service, read a document, or perform an action. MCP separates the host (the AI application), its MCP client (the connection), and the MCP server (the provider of capabilities). Think of a defined socket that connects pieces, not a guarantee that every plugged-in piece is safe or correct.
The protocol does not choose your model, grant unlimited permission, or decide when an operation needs confirmation. Those remain the responsibility of your application, its access policy, and the person using it.
A server can offer three main primitives:
- Tools: executable functions such as
find_orderorcreate_ticket. Their parameters describe valid inputs. A tool may have side effects. - Resources: contextual data, such as an API schema or a document. Reading a resource is not the same as editing it.
- Prompts: reusable templates that structure an interaction; they are not API calls by themselves.
Tip: start with a narrowly scoped, read-only tool. "Look up an authorized order" is easier to explain and test than "manage every order."
The path of a real request
Imagine someone asking "Where is my order?" The host connects to the MCP server, discovers find_order, presents its description to the model, validates arguments, and requests execution. The server queries the order system using the correct identity and permissions and returns a result. The assistant then interprets it. If the order does not belong to that person, the server must reject the request even if the model asks for it.
A conceptual tool definition might look like this; it is an illustrative contract, not a complete MCP server or a package you need to install:
{
"name": "find_order",
"description": "Return the status of an order visible to the current session",
"inputSchema": {
"type": "object",
"properties": { "orderId": { "type": "string" } },
"required": ["orderId"]
}
}
The description helps decide when to call the tool; the schema describes how to call it. Neither replaces backend authorization:
// Application logic behind a tool; the MCP SDK handles the protocol.
async function findOrder(orderId: string, userId: string) {
if (!/^[0-9]{1,12}$/.test(orderId)) throw new Error("Invalid ID");
const order = await db.orders.findById(orderId);
if (!order || order.ownerId !== userId) return { found: false };
return { found: true, status: order.status };
}
userId comes from the verified session, not from model-generated text. That detail separates a flashy demo from an integration ready for production. For a real server, use an SDK and protocol version compatible with your host; initialization and transport APIs evolve.
Local, remote, and trust boundaries
A local server commonly uses stdio to communicate with a client on the same machine. A remote server uses Streamable HTTP and needs appropriate authentication and network controls. In either case, treat tool results, documents, and descriptions as potentially untrusted data: they can contain malicious instructions (prompt injection) that must not become system instructions.
Log which tool was called and the outcome, but do not retain secrets or sensitive data without reason. Require human confirmation for actions like deleting, buying, or sending, and enforce authorization on the server. "The AI requested it" is never permission.
What about WebMCP? Bringing the browser into the picture
WebMCP is a Community Group draft, not a final W3C standard or an API shipped by default in every browser. It proposes letting a page expose JavaScript functions as tools for agents interacting with that same interface. Unlike a remote MCP server, the function lives in the page context and can reuse its existing state and workflows.
The draft describes document.modelContext.registerTool. This snippet is experimental and illustrative; check support and the current draft before using it:
if ("modelContext" in document) {
await document.modelContext.registerTool({
name: "read_cart",
description: "Summarize the cart the person is currently viewing",
inputSchema: { type: "object", properties: {} },
execute: async () => ({ items: cart.items.length, total: cart.total }),
});
}
This snippet does not make WebMCP work in browsers without an implementation. Nor does it automatically expose the cart to every origin: permissions, context, and security policies matter. The execution model and API can still change. WebMCP does not replace backend MCP when you need safe access to databases, server jobs, or credentials.
Which piece should you choose?
Use a skill when an agent needs to know how to work (a procedure); an MCP server when it needs to fetch data or perform actions across a clear boundary; and consider WebMCP if agents must use web-app functionality in an environment that supports this proposal. Keep privileged operations on the server and begin with testable reads.
If you are building something today, first try one query tool with real permissions, error cases, and useful logs. The best integration does not expose the most functions; it answers a real question without giving away more access than necessary.
Sources: MCP architecture · MCP specification · WebMCP draft.