Non-intuitive aspects of MCP servers

The first time I configured my coding agent to use an MCP server, the "command": "npx" part got me a bit weirded out. Is this going to run as a child process? Isn’t it an MCP “server” though!? So, I started exploring this fairly new world of MCP.
If you are an engineer who has been doing enterprise software development for a few years, you might have a certain mental model of the term “server”. It won’t take much time for us to understand the basics of MCP and what pain points it is trying to solve. But there are certain aspects of it that I found to be non-intuitive, and this article is about them.
It is a fairly new protocol that is being revised frequently, and rightfully so! Based on industry feedback and adoption signals, maintainers are continuously adding new features and also deprecating some. It has seen very strong adoption in LLM-based applications. Let’s talk about the not-so-obvious aspects of it and how some of them are converging back toward our intuition.
We can run the server as a subprocess of the client process
When we think of a server, we usually think of a process running on a remote machine, accessible over a network, commonly using HTTP. MCP aims to be transport-agnostic. As of today, it supports stdio and streamable HTTP as transport mechanisms. Using stdio, we can run it as a sub-process of the client process itself! In this mode, it uses stdin and stdout as a communication channel. Many of the MCP servers from the dev-tooling space are run over stdio.
Its design was inspired by the Language Server Protocol (LSP), the protocol governing the communication between a language server and your IDEs, used to power features such as auto-completion.
It doesn’t mean that everything that it needs is available on the same machine the client app is running on! E.g., if you are using an Azure MCP server in your app(or coding agent), it does need to communicate with remote servers to get all the data that your client app needs! Just that, that communication is handled within the subprocess itself; your client app communicates with the subprocess only. These MCP servers are provided by vendors as a packaged solution, so you are not the one writing the code for communicating (or authenticating) with remote servers, unless you are designing your own MCP server!
The client app is actually called host app, as per official terminology. And MCP client is the instance inside it which is holding the server connection. In this article, I will be using client app/client to cover both the host + MCP Client.
No remote server means no URL to point to, the server starts and stops with your client app, restarting the server is restarting your IDE, and N clients require N server instances!
A server can make LLM queries and ask questions to end users via the client
Sampling is a feature that lets the server make LLM calls via the client, without server having its own API key. Elicitation is also a similar feature that allows the server to request more input from the user via the client. These are useful when the server needs more information for processing the client request.
Sampling (along with roots and logging) was deprecated in the most recent spec revision, citing low adoption, complexity of implementation, and security concerns. Sampling and elicitation were based on stateful design principles, which are revised (more on this in the next point) now. Elicitation did survive these revisions and can be used through the new MRTR pattern.
Its (original) stateful design
It almost brought back sticky sessions for achieving server-to-client communication! Until very recently, when the server needed some data mid-processing, the way to make it ask the client was using stateful sessions. In the latest iteration of the specs(2026-07-28), touted to be the largest update ever, they have introduced “stateless core”.
We are so used to the stateless design of HTTP that we often forget how it makes scaling easy! Horizontal scaling using load balancers is easier because there is no state being maintained to route the client to the same server. Sticky sessions are almost a thing of the past!
The original MCP specs required an initialization handshake and a persistent SSE connection to be maintained for mid-processing server → client requests. SSE was replaced with Streamable HTTP and later deprecated, but Streamable HTTP used similar mechanisms and introduced Mcp-Session-Id header. SEP-2575 removed the initialization handshake. SEP-2567 removed Mcp-Session-Id header and protocol-level sessions.
As per the revision, each request will carry the client identity, capabilities and protocol version under _meta field. The client includes Mcp-Method and Mcp-Name headers for routing and rate-limiting to work without requiring reading the body. Multi Round-Trip Requests, which aims to replace this stateful behavior, doesn’t require holding a persistent connection or sticky sessions. Server sends an InputRequiredResult object as part of its normal response, which contains a list of requests the client must fulfill. It also returns a requestState field, which the client needs to pass back unmodified in the payload. The client collects the answers, attaches the answer to the same payload, and re-issues a new request. Basically, the state can now ride within the payload itself.
Servers can serve prompts
When we think of a prompt, we think of a user query. A user has a query; they write a prompt and send it to the LLM-powered chat application they are using, right?
Well, one of the things that MCP servers can serve is a prompt itself. As authors of MCP servers, we design a well-written, well-tested prompt (or a prompt template) and expose it using the server. Then the client app can provide a menu of some sort (e.g., slash commands, quick-action buttons) that users can choose from, each menu item pointing to a prompt template exposed by the server.
The goal is to provide users with ready-made, well-refined prompts for common queries/activities within your app. The team provisioning the GitHub MCP server knows what a good “Review this PR” prompt looks like. So instead of having every user who wants to use that functionality write their own prompts, they can expose it via the server itself. Then the client app can use it to provide some kind of quick action/command interface.
MCP servers can now ship UIs
MCP Apps is an MCP extension that allows us to return interactive HTML UI to the client. The client renders it within a sandboxed iframe. Apps are useful for implementing charts/dashboards, interactive forms, real-time monitoring UIs, authored within the server system itself. They help us embed UI within the conversational context, where it makes sense.
These Apps support bidirectional workflow; they can request tool calls and receive data from the client app using a secure postMessage channel over JSON-RPC. If you have ever worked on payment gateway integrations using hosted payment forms, this will sound a lot like it.
This is where things stand as of September 2026. Some aspects of it are moving closer to what we already understand, but it is also becoming unique in its own ways, as it should. The protocol development is part of the newly formed Agentic AI Foundation (AAIF). The roadmap looks exciting and already has developments planned related to the features that we talked about above.
Do share your own experiences with MCP servers in the comments.



