# mcp-glimpse — full text > mcp-glimpse is an open-source MCP server that lets any agent — and its human — see its own environment: every connected MCP server, every tool and its declared annotations, the negotiated capabilities, the context window, and the wire. Pitch: "Point your agent at itself." Open-source (MIT) MCP server. Connect (hosted): https://mcp.mcpglimpse.com/mcp Connect (stdio): uvx mcp-glimpse Then run: introspect_mcp_context Source: https://github.com/CrankingAI/mcp-glimpse This file inlines every Learn article in full. The link index is at https://www.mcpglimpse.com/llms.txt. ================================================================================ # What is MCP? Tools vs prompts vs resources URL: https://www.mcpglimpse.com/learn/what-is-mcp Published: 2026-06-16 Tags: mcp, primitives, fundamentals Answer: MCP (the Model Context Protocol) is an open standard that lets an AI agent connect to external servers and use what they expose. A server can expose three core primitives: tools (functions the model calls), prompts (templates a person selects), and resources (readable content the app loads). The difference is who's in control — the model, the user, or the application. The Model Context Protocol (MCP) is an open standard — originally from Anthropic, now with a broad implementer community — for connecting AI agents to external capabilities. Instead of every tool integration being a bespoke plugin, MCP defines a common wire protocol: an agent's **host** (Claude Desktop, an IDE, a custom agent) speaks to one or more **MCP servers**, each of which advertises what it can do. The word that trips people up is "server." An MCP server is usually a small local process or a remote HTTP endpoint that publishes a handful of capabilities. It is not a monolith. A well-designed agent might have a dozen of them connected at once — one for your files, one for a database, one for GitHub, one that introspects the agent itself (that's what [mcp-glimpse](/) does). ## The three core primitives Every MCP server can expose up to three kinds of things. What separates them is **who decides when they're used**. | Primitive | Controlled by | What it is | Example | | --- | --- | --- | --- | | **Tools** | the model | Functions the model can invoke, each with a JSON-Schema input | `introspect_mcp_context` | | **Prompts** | the user | Parameterized message templates a person selects | `full_context_dump` | | **Resources** | the application | Readable content published at a URI | `glimpse://primitives` | ### Tools — model-invoked functions A tool is a function the server exposes and the model chooses to call. Each tool carries a name, a description, and a JSON-Schema for its input. When the model decides a tool is relevant, the host sends a `tools/call` request; the server runs it and returns a result. Tools are the primitive most people mean when they say "MCP" — they're how an agent takes action in the world. Because the model reads the name and description to decide *whether* to call a tool, those strings are part of the contract. Rename a tool and every agent that learned to call it breaks. ### Prompts — user-selected templates A prompt is a reusable, parameterized message template the server offers for a **person** to pick — think of the slash-command menu in a chat client. The user selects it; it isn't auto-invoked by the model. Prompts are how a server ships expert phrasing: instead of hoping the model asks the right question, the server hands the user a ready-made one. ### Resources — application-loaded content A resource is addressable, readable content published at a URI like `glimpse://primitives`. The client **application** reads it to build context — resources aren't "called," they're loaded, the way a program reads a file. They're ideal for reference material, schemas, and documentation the agent may want in context without spending a tool call to fetch it. ## Beyond the core three Later protocol revisions added a second class of primitives that flow the *other* direction — from server to client. **Sampling** lets a server ask the client's model to generate text; **elicitation** lets a server prompt the user for input mid-call; **roots** let the client advertise workspace folders to the server. These require an interactive, stateful session and are covered in [Elicitation, sampling, and roots](/learn/server-to-client-capabilities). mcp-glimpse itself uses the first three primitives to teach the rest: a single tool (`introspect_mcp_context`), a set of prompts, and a small library of `glimpse://` resources that explain the very concepts on this page. ## FAQ Q: What are the three MCP primitives? A: Tools (model-invoked functions), prompts (user-selected message templates), and resources (application-loaded readable content). Later revisions add server-to-client capabilities — sampling, elicitation, and roots — but tools, prompts, and resources are the core three. Q: What is the difference between an MCP tool and an MCP resource? A: A tool is a function the model decides to call, with a JSON-Schema input and a returned result. A resource is addressable content published at a URI that the client application reads for context — it isn't called, it's read. Q: Who controls each MCP primitive? A: Tools are model-controlled (the model chooses when to call them), prompts are user-controlled (a person picks one), and resources are application-controlled (the client reads them to build context). ## Call to action Connect https://mcp.mcpglimpse.com/mcp (or run `uvx mcp-glimpse`) and run `introspect_mcp_context`. ================================================================================ # What can an MCP server see about you? URL: https://www.mcpglimpse.com/learn/what-can-an-mcp-server-see Published: 2026-06-18 Tags: mcp, security, vantage-gap, privacy Answer: Surprisingly little. An MCP server can see its own tools, prompts, and resources, the protocol version it negotiated, the transport, and per-request arguments — plus whatever the host chose to surface at initialize (like the client's name). It cannot see your other connected servers, their tools, your model's identity, your context window, your working directory, or your active skills. That panoramic view belongs only to you, the agent. There is a common, quiet assumption that when you connect an MCP server, it can "see your setup." It can't. A server's vantage point is **narrow by design**, and understanding exactly how narrow is one of the most useful things you can know about your own agent's security. ## What a server CAN see - Its **own** tools, prompts, and resources — the things it published. - The **negotiated protocol version** and the client's declared `clientInfo` and capabilities *at initialize* — but only when the host chooses to surface them. - The **transport** it's running over (Streamable HTTP, or stdio) and, on HTTP, request-level detail like headers and a coarse client IP. - **Per-request arguments** and the session id for the current call. That's essentially the list. Everything a server knows about you, it knows because either it published it or you sent it. ## What a server CANNOT see - Your host's **other connected MCP servers** — or any of *their* tools. - Your **model's identity** (Claude vs GPT vs something local). - Your **context-window budget** — how big it is or how much is used. - Your **working directory**, the **date**, your **persona/system prompt**, or your **active skills**. None of that is in the protocol a server receives. A server is like a shop that can see the customer standing at *its* counter — but not the other shops the customer visited, not what's in their bag, not where they live. ## Why the vantage gap matters This asymmetry is the whole reason [mcp-glimpse](/) exists. The **panoramic view** — every server, every tool, the model, the context window — belongs to **you, the agent**. You are the only party that can see the whole board. That's why the `introspect_mcp_context` tool takes a `snapshot_json` you fill in: the server can't enumerate your other servers, so *you* report them, and the server renders the picture. Call the same tool with **no** snapshot and you see the server-only slice for contrast — often a handful of things next to your hundreds. Seeing four next to two hundred is the lesson landing. ## The security reading The vantage gap cuts two ways. The reassuring half: a random MCP server you connect **cannot** silently inventory your other tools or read your environment. The protocol doesn't hand it that. The cautionary half: anything you *do* pass — tool arguments, file contents you feed a tool, a snapshot you volunteer — is visible to that server. And on HTTP, the transport reveals request metadata (User-Agent, a coarse IP → geo) even without your agent saying a word. The honest framing, which mcp-glimpse's "This Connection" view states outright: > This is everything an MCP server can know about you without your agent telling > it — and nothing more. Knowing where that line sits is the difference between trusting a server blindly and trusting it accurately. For how the tools themselves can *mislead* about what they do, read [Tool annotations explained](/learn/tool-annotations-explained). ## FAQ Q: Can an MCP server see my other connected servers? A: No. Each MCP server is connected to the host independently and has no visibility into the host's other servers or their tools. Only the agent (the client) can see the full set of connected servers at once. Q: Can an MCP server see my model, context window, or working directory? A: No. None of that is in the protocol a server receives. A server sees its own capabilities, the negotiated protocol version, the transport, and request arguments — not your model identity, token budget, cwd, or skills. Q: Why does introspect_mcp_context ask the agent to fill in a snapshot? A: Because the agent is the only party that can see the whole board. The server structurally cannot enumerate your other servers or your model, so the panoramic view has to come from the client that can. ## Call to action Connect https://mcp.mcpglimpse.com/mcp (or run `uvx mcp-glimpse`) and run `introspect_mcp_context`. ================================================================================ # Tool annotations explained — and why so few tools declare them URL: https://www.mcpglimpse.com/learn/tool-annotations-explained Published: 2026-06-21 Tags: mcp, annotations, security, tools Answer: MCP tool annotations are optional hints on a tool definition — readOnlyHint, destructiveHint, idempotentHint, openWorldHint, and a human title — that tell a host how a tool behaves before it's called, so the host can auto-approve a read but confirm a write. Very few tools in the wild declare any of them, which means a tool that writes durable data can look, on the wire, identical to one that only reads. When a host decides whether to let a tool run — auto-approve it, or stop and ask you first — it would love to know one thing up front: *does this tool just read, or can it change something?* MCP's answer is **tool annotations**: optional hints an author can attach to a tool definition. ## The five annotations | Annotation | Meaning | A host uses it to… | | --- | --- | --- | | `readOnlyHint` | The tool does not modify its environment | Auto-approve safely | | `destructiveHint` | The tool may make irreversible changes | Require explicit confirmation | | `idempotentHint` | Calling twice has the same effect as once | Safely retry on failure | | `openWorldHint` | The tool reaches external systems (e.g. the network) | Reason about data exfiltration | | `title` | A human-readable display name | Show a friendly label in UI | The critical word is **hint**. These are declarations by the author, not guarantees enforced by the protocol. A tool can *claim* `readOnlyHint: true` and still write to a database — nothing stops it. That gap between what a tool *does* and what it *declares* is exactly where the interesting risk lives. ## Where annotations live — and why that matters Annotations sit on the tool definition returned by `tools/list`, **not** in the result of a tool call. Two consequences follow: 1. A host can only reason about a tool's behavior **before** calling it — which is the whole point, since after the destructive call it's too late. 2. A tool inspector can only *show* you a tool's annotations if it has access to the `tools/list` entry. Because [an MCP server can't see your other servers' tools](/learn/what-can-an-mcp-server-see), a lens like mcp-glimpse can only report annotation coverage across your whole agent if **you** include each tool's declared hints in your snapshot. ## Why so few tools declare them Walk through a real agent's connected servers and tally the annotations, and the number is startling: a large fraction of tools declare **none**. Two reasons: **Adoption is early.** Annotations are optional, newer than tools themselves, and most authors simply don't set them — the same slow-adoption curve that `outputSchema` is on now. **Some stacks can't emit them at all.** This isn't always the author's choice. As a pointed example, mcp-glimpse's *own* tools declared no annotations in an early build — not deliberately, but because the Azure Functions MCP binding it first ran on (`Extensions.Mcp` 1.5.0) exposed only a tool's name and description and offered **no way** to emit annotations. On that binding, a tool that writes durable data (`submit_feedback`) was, on the wire, indistinguishable from the read-only `introspect_mcp_context`. ## The "shadow write" problem Put those two facts together and you get the pattern worth scanning for: a tool whose name and description imply it changes state — `create_`, `delete_`, `set_`, `send_`, `submit_` — but which declares `readOnlyHint`, or declares nothing at all. The host has no signal to prompt you before it runs. mcp-glimpse calls these **shadow writes** and flags them by comparing each tool's declared hints against a word-boundary read of its own name and description. The takeaway isn't "annotations are broken." It's that annotations are a young, under-adopted contract, and until coverage improves, *absence of a destructive hint is not evidence a tool is safe*. The best thing an MCP author can do is declare all five, honestly — which is why an exemplary server aims to be the best-annotated server its users have. ## FAQ Q: What are the MCP tool annotations? A: readOnlyHint (the tool doesn't modify state), destructiveHint (it can make irreversible changes), idempotentHint (calling it twice is the same as once), openWorldHint (it reaches external systems like the network), plus a human-readable title. They are hints, not guarantees. Q: Where do MCP tool annotations live? A: On the tool definition returned by tools/list — not in a tool's result. So a host can only reason about them before calling, and a lens can only report them if the agent includes each tool's declared annotations in its snapshot. Q: Why do so few tools declare annotations? A: Adoption is early and annotations are optional, so most authors skip them. Some SDKs and hosting bindings can't even emit them — for example the Azure Functions MCP binding exposes only a tool's name and description, giving the author no way to declare annotations at all. ## Call to action Connect https://mcp.mcpglimpse.com/mcp (or run `uvx mcp-glimpse`) and run `introspect_mcp_context`. ================================================================================ # Elicitation, sampling, and roots: MCP's server→client capabilities URL: https://www.mcpglimpse.com/learn/server-to-client-capabilities Published: 2026-06-24 Tags: mcp, capabilities, elicitation, sampling, roots Answer: Most MCP primitives flow from client to server, but three flow the other way. Elicitation lets a server pause a tool call to ask the user for input. Sampling lets a server ask the client's model to generate text. Roots let the client advertise its workspace folders to the server. All three require an interactive, stateful session and are advertised by the client at initialize — a stateless HTTP server cannot use them. The primitives most people learn first — [tools, prompts, and resources](/learn/what-is-mcp) — all flow from the client to the server: the agent calls a tool, reads a resource, picks a prompt. But MCP also defines three capabilities that flow the **other** direction, from server to client. They're the ones that make an MCP session feel genuinely interactive rather than request/response. ## Capability negotiation, briefly At `initialize`, the client and server each advertise what they support, and each side uses only what the other offers. Servers advertise `tools`, `prompts`, and `resources`. **Clients** advertise the three below. If your client doesn't advertise `sampling`, no server can sample from your model — the capability simply isn't there to use. | Capability | Advertised by | Meaning | | --- | --- | --- | | `sampling` | client | Server may ask the client's model to generate | | `elicitation` | client | Server may prompt the user mid-call | | `roots` | client | Client advertises its workspace roots | ## Elicitation — the server asks the user Elicitation lets a server **pause a tool call** and ask the user for input: confirm a destructive action, fill in a missing parameter, choose among options. The server sends a structured request; the host renders a prompt; the answer flows back and the tool call resumes. This is how a well-behaved write tool earns trust. mcp-glimpse's `submit_feedback`, for instance, elicits a confirmation before it persists anything — and when the client doesn't support elicitation, it degrades gracefully: it records the feedback and labels it "unconfirmed" rather than failing. ## Sampling — the server asks your model Sampling inverts the usual arrangement: the **server** asks the **client's model** to generate a completion. The server ships no model of its own; it borrows the one the user already trusts and pays for. A server might use sampling to summarize a large result into a sentence, or to turn structured data into prose. Sampling is powerful and therefore gated: the client must advertise the capability, the user's host mediates every request, and it only works in a stateful session. ## Roots — the client shares its workspace Roots are the filesystem or workspace folders the client advertises to the server, scoping "which directories are you allowed to think about." The client declares the `roots` capability and the server calls `roots/list` to read them — for example, a code tool learning which repositories are open. ## Why all three need a stateful session Elicitation, sampling, and roots each require a **back-and-forth mid-operation**: a server issues a request and waits for the client to respond while a tool call is still in flight. That's only possible when the session persists across messages. A **stateless** HTTP server — one that treats every request independently and keeps no session — structurally can't do it. It can *report* that these capabilities were negotiated, but it can't *use* them. This is the single biggest practical reason to choose a stateful transport, covered in [Stateless vs stateful MCP transports](/learn/stateless-vs-stateful-transports). mcp-glimpse uses the core three primitives to teach these three, and demonstrates elicitation, sampling, and roots live so you can see the difference rather than take it on faith. ## FAQ Q: What is elicitation in MCP? A: Elicitation is a server asking the user for input in the middle of a tool call — for example, confirming an action or collecting a missing parameter. It requires an interactive, stateful session and is only available when the client advertises the elicitation capability. Q: What is sampling in MCP? A: Sampling is a server asking the client's model to generate a completion. It lets a server use the model's intelligence without shipping its own, but requires the client to advertise the sampling capability and to be in a stateful session. Q: What are roots in MCP? A: Roots are filesystem or workspace folders the client advertises to the server, telling the server which directories are in scope. The client declares the roots capability and the server can call roots/list to read them. ## Call to action Connect https://mcp.mcpglimpse.com/mcp (or run `uvx mcp-glimpse`) and run `introspect_mcp_context`. ================================================================================ # Stateless vs stateful MCP transports (what each can and cannot do) URL: https://www.mcpglimpse.com/learn/stateless-vs-stateful-transports Published: 2026-06-27 Tags: mcp, transports, http, stateful, architecture Answer: A stateful MCP transport keeps a session alive across messages, so the server can hold context, push notifications, and do mid-call back-and-forth like elicitation, sampling, and roots. A stateless transport treats every request independently — it's simpler and scales trivially, but it can only report those interactive capabilities, never use them. If you want an interactive MCP server, statefulness is a gate, not an option. "Transport" in MCP means how the client and server actually exchange bytes. There are two common ones — **stdio** (a local process over standard input/output) and **Streamable HTTP** (a remote endpoint) — but the distinction that changes what your server can *do* isn't stdio-vs-HTTP. It's **stateful vs stateless**. ## What "stateful" buys you A stateful transport keeps a **session** alive across many messages. The server can remember what happened earlier in the conversation, push messages to the client on its own initiative, and carry on a mid-operation exchange. That single property unlocks a whole tier of the protocol: - **Elicitation** — pause a tool call to ask the user a question. - **Sampling** — ask the client's model to generate mid-call. - **Roots** — read the client's advertised workspace folders. - **Progress notifications** — stream "37% done" during a long operation. - **Server-initiated logging** — emit log lines to the client as work happens. - **`listChanged`** — tell the client the tool list changed, live. Every one of these needs the server to speak *while a request is in flight* or *between* requests — which requires the session to persist. ## What "stateless" gives up — and gains A stateless transport handles each request in complete isolation. There's no session to hold, so: - It **cannot** use elicitation, sampling, roots, progress, or live `listChanged`. It can *report* that the client advertised these capabilities, but it has no channel to exercise them. - In exchange, it's dramatically **simpler to operate**. Any replica can serve any request, so it scales horizontally without sticky sessions, and a cold start costs nothing in correctness. Stateless isn't wrong — for a pure read-only tool server it's an excellent, cheap choice. It's just a ceiling: you've capped the server at the request/response subset of MCP. ## The mapping to real transports | Transport | Typically | Notes | | --- | --- | --- | | **stdio** | Stateful | One long-lived process with an open pipe — inherently a session. | | **Streamable HTTP** | Either | The design decision. With a session id it's stateful; without, it's stateless. | Note the nuance: HTTP is where you actually *choose*. Streamable HTTP can be run stateful (issuing a session id the client returns on each request, pinned to one replica or backed by sticky sessions) or stateless (every request independent). ## Operational cost of "stateful" — verified the hard way Choosing stateful HTTP has real deployment consequences, and they tend to surface only in production: - **Session affinity.** A session-bearing server needs requests to land on the same replica — a single replica, or sticky sessions. Round-robin across replicas drops the session. - **No scale-to-zero for interactive use.** If the platform scales the server to zero between requests, an interactive connector-add times out on the cold start. Keep at least one replica warm. - **Host allowlists.** SDKs guard against DNS-rebinding by checking the `Host` header; behind a public domain you must allowlist that host or every request returns a 421. ## The verdict If your server only reads, stateless is a fine, cheap default. But the moment you want the *interactive* half of MCP — confirmations, model sampling, workspace awareness, live progress — **statefulness is a gate, not an option.** That's exactly why mcp-glimpse runs a stateful Streamable HTTP session: the interactive capabilities it teaches, it also demonstrates live. See [Elicitation, sampling, and roots](/learn/server-to-client-capabilities) for what those capabilities actually do. ## FAQ Q: What is the difference between a stateless and a stateful MCP server? A: A stateful server keeps a session alive across requests, enabling server-initiated messages and mid-call interaction (elicitation, sampling, roots, progress, logging). A stateless server handles each request independently — simpler and infinitely scalable, but unable to use those interactive capabilities. Q: Can a stateless MCP server use elicitation or sampling? A: No. Elicitation, sampling, and roots require a mid-operation back-and-forth, which needs a persistent session. A stateless server can report that those capabilities were negotiated, but it cannot actually use them. Q: Does stdio count as stateful? A: Yes. A stdio connection is a single long-lived process with an open pipe, so it's inherently stateful. Streamable HTTP can be run either way — stateful (with a session id) or stateless — which is the choice that matters. ## Call to action Connect https://mcp.mcpglimpse.com/mcp (or run `uvx mcp-glimpse`) and run `introspect_mcp_context`. ================================================================================ # How big is your context window — and what do 178 tool definitions cost? URL: https://www.mcpglimpse.com/learn/context-window-tool-cost Published: 2026-06-30 Tags: mcp, context-window, tokens, cost Answer: Your context window is the total number of tokens your model can hold at once — often 200K for a current frontier model. Every connected tool spends part of it before you type a word: each tool's name, description, and input schema are serialized into the model's context. A heavily-connected agent with ~178 tools can burn roughly 30–45K tokens — 15–25% of a 200K window — purely on tool definitions. Your **context window** is the model's working memory: the maximum number of tokens it can hold and reason over in a single request. Everything — the system prompt, your messages, retrieved documents, and every connected tool's definition — has to fit inside it. A current frontier model commonly has a window around **200K tokens**. Big, but finite. Here's the part that surprises people: **a large chunk of that window can be gone before you say a word.** ## Where the tokens go When a host connects an MCP server, it takes each tool's definition — the **name**, the **description**, and the **JSON-Schema for its input** — and serializes all of it into the model's context so the model knows the tool exists and how to call it. That's not free. A single richly-documented tool with a nested input schema can easily be a few hundred tokens. Multiply by the number of connected tools and the bill adds up fast. > A heavily-connected agent with ~178 tools can spend roughly **30–45K tokens** — > **15–25%** of a 200K window — purely on tool definitions, before the first user > message. That's the headline mcp-glimpse renders: *"your 178 tools consume ~40K of your 200K before you say a word."* It's computable from the snapshot alone, because the snapshot already contains every tool's name, description, and schema. ## How to estimate it — honestly Token counting is approximate, and being honest about *how* approximate is part of doing it right. - **Tokenizers differ by model family.** Claude, tiktoken (OpenAI), and SentencePiece (many open models) split text differently — but on prose and JSON the spread is roughly **±10–25%**, not orders of magnitude. A sound estimator uses one computational base (e.g. tiktoken's `o200k_base`, which is cheap and pure-Python) and applies a per-family correction, then shows the result as a **range** ("~38–46K") with a method footnote — never a false-precision single number. - **Hosts reformat definitions before the model sees them.** The host wraps tool definitions in its *own* prompt syntax, so any estimate is approximate regardless of tokenizer. State that caveat rather than hide it. - **Caching reduces cost, not occupancy.** Prompt caching makes re-sending unchanged tokens cheaper and faster — but those tokens still **occupy** window space. A cache hit doesn't give you the room back. ## Why the number matters Every token spent on a tool you never call is a token unavailable for the actual task — the document you're analyzing, the conversation history, the reasoning room the model needs. Context-cost accounting turns "I connected a lot of servers" into a concrete, per-server number you can act on: prune the servers you don't use, and you get real window back. To see your own figure, connect mcp-glimpse and run `introspect_mcp_context` with your full inventory. It renders a headline tile — total estimated cost against your window — plus a per-server breakdown, so you can see exactly which connectors are the expensive ones. For how that fits into the whole report, see [Reading an introspection report](/learn/reading-an-introspection-report). ## FAQ Q: What is a context window? A: The context window is the maximum number of tokens a model can process in a single request — its working memory. Everything the model reasons over (system prompt, tool definitions, conversation, documents) has to fit inside it. A common current size is around 200K tokens. Q: How much of my context window do tool definitions consume? A: Each tool contributes its name, description, and JSON input schema, which the host serializes into the model's context. Summed across a heavily connected agent — say 178 tools — that can be roughly 30–45K tokens, or 15–25% of a 200K window, spent before the first user message. Q: Does prompt caching make tool definitions free? A: No. Caching reduces the latency and dollar cost of re-sending unchanged tokens, but those tokens still occupy space in the context window. Occupancy is real whether or not the request was cache-hit. ## Call to action Connect https://mcp.mcpglimpse.com/mcp (or run `uvx mcp-glimpse`) and run `introspect_mcp_context`. ================================================================================ # MCP protocol versions and capability negotiation URL: https://www.mcpglimpse.com/learn/protocol-versions-and-negotiation Published: 2026-07-02 Tags: mcp, protocol, versioning, capabilities Answer: MCP is date-versioned as YYYY-MM-DD. At initialize, client and server negotiate the highest revision both support, and the server echoes the agreed version back. Alongside the version, each side advertises its capabilities — the server its tools/prompts/resources, the client its sampling/elicitation/roots — and each side uses only what the other declared. Notable revisions include 2024-11-05, 2025-03-26, and 2025-06-18. MCP evolves, and it does so in a way that's easy to reason about: the protocol is **date-versioned**. Every revision is identified by its release date in `YYYY-MM-DD` form — no semantic-version guessing about what "2.3" means, just the date the spec shipped. ## Negotiation at initialize The first thing a client and server do when they connect is `initialize`. In that handshake two things get settled: 1. **The protocol version.** The client proposes a version; the server responds with the highest version *both* support, and echoes that agreed version back. From then on, both speak that revision. 2. **Capabilities.** Each side advertises what it can do. The server declares `tools`, `prompts`, and/or `resources` (with sub-flags like `listChanged` or `subscribe`). The client declares `sampling`, `elicitation`, and/or `roots`. Each side then uses **only** what the other advertised — see [capability negotiation](/learn/server-to-client-capabilities) for what those client-side capabilities unlock. The elegance is that a newer client and an older server (or vice versa) can still talk: they simply meet at the highest revision they share and use the intersection of their capabilities. ## Notable revisions | Version | What it brought | | --- | --- | | **2024-11-05** | The first widely-adopted revision. | | **2025-03-26** | Streamable HTTP transport; authorization guidance. | | **2025-06-18** | Refinements and a broader capability set. | ## A live example of the vantage gap Here's a subtle point that connects back to [what a server can see](/learn/what-can-an-mcp-server-see): the negotiated version is agreed at `initialize`, but whether a server can *report* it back to you depends on the host surfacing it. When mcp-glimpse's `introspect_mcp_context` runs with no snapshot, it reports the negotiated protocol version **when the host surfaces it** — and when the host doesn't, the field honestly reads *"not surfaced."* That "not surfaced" is not a bug; it's the vantage limit made visible. A server knows the version it negotiated, but it can only tell *you* what the host chose to pass along. It's a small, concrete reminder that a server's view of your environment is exactly as wide as the host lets it be — and no wider. To see which version your own client actually negotiated, connect mcp-glimpse and run `introspect_mcp_context`; the "This Connection" view reports the wire-level facts a server can observe first-hand. ## FAQ Q: How is the MCP protocol versioned? A: By date, in YYYY-MM-DD form. Each revision is identified by its release date, and client and server negotiate the highest version both support during initialize, with the server echoing the agreed version back. Q: What happens during MCP initialize? A: The client and server exchange protocol versions and capabilities. They settle on the highest shared protocol version, and each advertises what it supports so the other only uses features that are actually available. Q: What are the notable MCP protocol revisions? A: 2024-11-05 was the first widely-adopted revision; 2025-03-26 introduced the Streamable HTTP transport and auth guidance; 2025-06-18 brought refinements and a broader capability set. ## Call to action Connect https://mcp.mcpglimpse.com/mcp (or run `uvx mcp-glimpse`) and run `introspect_mcp_context`. ================================================================================ # What is an MCP App (ui:// / SEP-1865)? URL: https://www.mcpglimpse.com/learn/what-is-an-mcp-app Published: 2026-07-04 Tags: mcp, mcp-apps, ui, sep-1865 Answer: An MCP App is a small, self-contained HTML interface a server ships alongside a tool so its result renders as a real UI — a rectangle in the host — instead of plain text. The server publishes the interface as a ui:// resource and links a tool to it via _meta, and the host renders it in a locked-down iframe. It's the proposal tracked as SEP-1865, and the security model is the interesting part: the iframe makes no external requests. Most MCP tools return text. That's fine for a lot of things, but a report — a table of servers, a capability matrix, a token-cost breakdown — wants to be *looked at*, not read as a wall of JSON. **MCP Apps** are the answer: a server can ship a small interface that the host renders as a genuine UI rectangle when a tool returns. The proposal is tracked as **SEP-1865**. ## How it fits together An MCP App has three moving parts: 1. **A `ui://` resource.** The server publishes the interface as a resource with a `ui://` URI — a self-contained HTML document — marked with an HTML content type profiled for MCP apps (e.g. `text/html;profile=mcp-app`). 2. **A tool that links to it.** The tool references that resource through its `_meta` (for example, `_meta.ui.resourceUri`), so the host knows *this tool's result should render in that view*. The tool can also hint at presentation, like `prefersBorder`. 3. **A host that renders it.** When the tool returns, the host loads the `ui://` document into an iframe and hands it the tool's result data to display. The result: instead of a paragraph of text, the user sees a rendered rectangle — [mcp-glimpse](/)'s two-tab report of the agent's whole context is exactly this. ## The security model — a locked-down iframe The most important thing to understand about MCP Apps is the sandbox. The host renders the view in an **iframe with a strict Content-Security-Policy that blocks external network requests**. The view cannot phone home, load a remote script, fetch a tracker, or exfiltrate the data it's showing. Everything it needs must be **inlined** — one self-contained HTML file, no runtime external requests. That constraint shapes how you build the view: - **Self-contained by construction.** Bundle CSS, JS, and assets into the single file. A common toolchain is Vite with a single-file plugin, producing one HTML document with no external references. - **Never `innerHTML` on tool data.** The tool's result is data, and rendering it with `innerHTML` would open a cross-site-scripting hole *inside* the sandbox. Set text with safe DOM APIs instead. ## A useful side effect: sharing must be deliberate Because the iframe can't make external requests, an MCP App **cannot** silently upload anything — which is great for privacy but means a "share this" feature can't just POST from the view. It has to round-trip through the server via an explicit tool call. That constraint conveniently forces a consent moment: the user has to approve the share (often confirmed by [elicitation](/learn/server-to-client-capabilities)) before anything leaves the sandbox. The security limitation becomes a feature. To see a real MCP App, connect mcp-glimpse and run `introspect_mcp_context` in a host that supports MCP Apps — the report renders as a live rectangle. In a host that doesn't, the same tool degrades to readable text, so nothing is lost. ## FAQ Q: What is an MCP App? A: An MCP App is a self-contained HTML view a server publishes as a ui:// resource and links to a tool, so the tool's result renders as an interactive UI inside the host rather than as plain text. It's the interface proposal tracked as SEP-1865. Q: How does a tool link to its MCP App view? A: The tool references the view's resource URI through its _meta (for example a _meta.ui.resourceUri pointing at the ui:// resource), and marks the resource with an HTML content type profiled for MCP apps. The host reads that link and renders the view when the tool returns. Q: Is an MCP App view sandboxed? A: Yes. The host renders it in a locked-down iframe with a strict content policy that blocks external network requests, so the view must be entirely self-contained. Never inject tool data with innerHTML — that would open an XSS hole inside the sandbox. ## Call to action Connect https://mcp.mcpglimpse.com/mcp (or run `uvx mcp-glimpse`) and run `introspect_mcp_context`. ================================================================================ # Is my agent environment safe? Reading an introspection report URL: https://www.mcpglimpse.com/learn/reading-an-introspection-report Published: 2026-07-05 Tags: mcp, security, introspection, safety Answer: An introspection report is a snapshot of everything your agent can see — servers, tools, capabilities, context cost — read for the things that carry risk. The three highest-signal checks: shadow writes (tools that can change state but declare no destructive hint), name collisions (two servers exposing the same tool name), and tool-poisoning (injection-style text hidden in a tool's description). None alone means "unsafe," but together they tell you how much of your setup is trustworthy by evidence rather than by assumption. Connecting a lot of MCP servers is easy; knowing whether that pile of tools is *trustworthy* is the hard part. An introspection report — like the one [mcp-glimpse](/) renders from `introspect_mcp_context` — turns your setup into a readable inventory so you can check it against a few high-signal patterns instead of hoping for the best. Here's how to read one. ## The one framing to keep No single flag below means "your agent is compromised." These are **heuristics** — they tell you *where to look*, not *what's true*. The value is turning invisible assumptions ("this tool probably just reads") into visible evidence you can actually check. ## 1. Shadow writes — the highest-signal check Scan for tools whose **name or description implies a write** — `create_`, `delete_`, `set_`, `send_`, `submit_`, `update_` — but which declare `readOnlyHint`, or declare no [annotations](/learn/tool-annotations-explained) at all. These are **shadow writes**: the host has no signal to prompt you before they run, so a tool that changes durable state can execute as quietly as a read. A report flags these by comparing each tool's declared hints against a word-boundary read of its own name and description. A pile of unannotated write-shaped tools isn't proof of malice — but it *is* proof that your host can't protect you from them automatically. ## 2. Name collisions Do any two connected servers expose the **same tool name**? Collisions are worth knowing about because the model picks a tool by name, and two `search` tools from different servers create genuine ambiguity — including the possibility that a lower-trust server **shadows** a higher-trust one's tool. Enumerate every tool with its owning server and the duplicates surface immediately. ## 3. Tool-poisoning heuristics The text of a tool's description is fed to your model, which makes it an attack surface. A tool-poisoning scan reads descriptions for: - **Injection-style directives** — "ignore previous instructions," "always call this tool first." - **Exfiltration urges** — descriptions that coax the model into sending data somewhere. - **Invisible or bidi Unicode** — hidden characters that don't render but do reach the model. - **Suspiciously long descriptions** — a lot of text is a lot of room to hide instructions. These are explicitly heuristics, and a report should label them as such — but a description that says "always call this first" is worth a hard look no matter who shipped it. ## 4. Annotation coverage and context cost Two more numbers round out the read: - **Annotation coverage** — what fraction of your tools declare *any* hints. Low coverage means "absence of a destructive hint tells you nothing," which reframes every unannotated tool as unverified rather than safe. - **Context cost** — how many tokens your tool definitions consume before you say a word (see [context-window cost](/learn/context-window-tool-cost)). Not a safety issue exactly, but a budget one: tools you never use still cost you window. ## The privacy stance behind the report One reassurance about the report itself: mcp-glimpse analyzes your snapshot **in memory and never persists it**. The only things that ever get written are what you explicitly submit (feedback) or explicitly choose to share (an anonymized card). Introspecting your environment doesn't create a record of it. Read this way, "is my agent safe?" stops being a vibe and becomes a checklist. To run it on your own setup, connect the hosted server and run `introspect_mcp_context` with your full inventory. ## FAQ Q: How do I tell if my MCP setup is safe? A: Introspect it and read for signals: tools that can write but declare no destructive hint (shadow writes), duplicate tool names across servers (name collisions), and injection-style directives hidden in tool descriptions (tool-poisoning). These are heuristics that tell you where to look, not verdicts. Q: What is a shadow write? A: A tool whose name or description implies it changes state — create, delete, set, send, submit — but which declares readOnlyHint or no annotations at all. The host gets no signal to prompt you before it runs, so it can write without confirmation. Q: What is tool-poisoning? A: Tool-poisoning is malicious instruction text hidden in a tool's description — for example "ignore previous instructions" or "always call this tool first" — meant to manipulate the model that reads it. A heuristic scan can flag injection-style directives, exfiltration urges, and invisible Unicode. ## Call to action Connect https://mcp.mcpglimpse.com/mcp (or run `uvx mcp-glimpse`) and run `introspect_mcp_context`. ================================================================================