MCP Servers Explained
Understand MCP servers, clients, tools, transports, security, and how to connect AI applications to them with practical examples.
An MCP server is a local program or remote service that connects to an AI application’s MCP client and provides capabilities such as tools, resources, and prompts. The Model Context Protocol (MCP) standardizes how the client and server exchange those capabilities; it does not dictate how the AI application uses them.
MCP is useful when an AI assistant needs controlled access to external actions or context: querying a database, reading files, calling an internal API, taking a screenshot, or using a reusable prompt template.
What MCP means
MCP has two layers:
- Data layer: JSON-RPC 2.0 messages, capability discovery, and client/server features.
- Transport layer: the communication channel, framing, connection handling, and authorization details.
The MCP architecture guide describes an MCP host as the AI application, such as Claude Code or Claude Desktop. The host creates an MCP client for each server connection. Each server supplies capabilities to its corresponding client. MCP architecture overview.
MCP host, client, and server
| Component | Role |
|---|---|
| Host | The AI application that coordinates conversations, models, permissions, and one or more MCP connections. |
| Client | The protocol component created by the host to communicate with one MCP server. |
| Server | A program or service that exposes tools, resources, and prompts. |
A host can connect to several servers at once. The client discovers what each server offers, then the model can request an available capability subject to the host’s permission rules.
What can an MCP server provide?
Tools
Tools let an AI application request an action. Examples include running a database query, creating a ticket, fetching a report, or capturing a web page. A tool normally declares a name, description, input schema, and result.
Resources
Resources supply contextual data. A server might expose a database schema, a document, a file, or another readable data object. Resources provide information; they are not interchangeable with action-oriented tools.
Prompts
Prompts are reusable interaction templates. A server can offer a prompt that structures a recurring task, supplies examples, or asks for the inputs needed by a tool.
Servers do not have to expose all three primitives. The official architecture guide’s database example uses a query tool, a schema resource, and a prompt, but that combination is illustrative rather than mandatory.
How an MCP request flows
- The host starts or connects to an MCP server.
- The client and server exchange protocol messages and discover capabilities.
- The model decides that a tool, resource, or prompt is relevant.
- The host asks the client to call or read that capability.
- The server validates the request, performs its permitted work, and returns a structured result.
- The host gives the result to the model, which can continue the task or ask for another operation.
MCP standardizes the exchange. The host still decides how to present results, request user approval, limit tools, and handle errors.
Local stdio versus remote Streamable HTTP
| Characteristic | stdio | Streamable HTTP |
|---|---|---|
| Where it runs | A local process started by the host. | A remote HTTP service. |
| Communication | Standard input and output. | HTTP POST, with optional Server-Sent Events for streaming. |
| Network overhead | No network hop between host and process. | Requires network reachability, TLS, routing, and service operations. |
| Credentials | Environment-provided credentials. | MCP HTTP authorization framework when authorization is used. |
| Scaling | Managed per local host. | Can be routed across service instances. |
The 2026-07-28 specification makes protocol requests stateless. A server should process each request from the information in that request rather than infer context from an earlier connection. If an application needs continuity, pass an explicit identifier in later calls. This allows requests to be routed across instances without shared protocol-level session state. See the 2026-07-28 basic specification and the release announcement.
Calling a remote MCP endpoint with JSON-RPC
The exact endpoint and authorization method come from the server you operate. Replace the placeholders below with values supplied by that server. Do not send credentials in source control.
curl -X POST "$YOUR_MCP_SERVER_URL" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MCP_ACCESS_TOKEN" \
--data '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}'
A tool call uses the same JSON-RPC envelope, with the server’s tool name and schema-defined arguments:
curl -X POST "$YOUR_MCP_SERVER_URL" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MCP_ACCESS_TOKEN" \
--data '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "YOUR_TOOL_NAME",
"arguments": {}
}
}'
Python example: send a JSON-RPC request
This standard-library example lists tools from a remote HTTP server. It deliberately leaves the endpoint, token, and tool arguments as environment variables because every deployment exposes different capabilities.
import json
import os
import urllib.request
endpoint = os.environ["MCP_SERVER_URL"]
token = os.environ["MCP_ACCESS_TOKEN"]
payload = {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {},
}
request = urllib.request.Request(
endpoint,
data=json.dumps(payload).encode("utf-8"),
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {token}",
},
method="POST",
)
with urllib.request.urlopen(request, timeout=30) as response:
result = json.load(response)
print(json.dumps(result, indent=2))
Node.js example: send a JSON-RPC request
const endpoint = process.env.MCP_SERVER_URL;
const token = process.env.MCP_ACCESS_TOKEN;
if (!endpoint || !token) {
throw new Error('Set MCP_SERVER_URL and MCP_ACCESS_TOKEN');
}
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'tools/list',
params: {}
})
});
if (!response.ok) {
throw new Error(`MCP server returned ${response.status}`);
}
console.log(JSON.stringify(await response.json(), null, 2));
Connecting an AI application to an MCP server
- Identify whether the server uses local stdio or remote Streamable HTTP.
- Read its capability list and input schemas before enabling it.
- For stdio, configure the host to start the process and provide credentials through its environment.
- For HTTP, configure the service URL, TLS, and the authorization method required by that server.
- Restrict the enabled tools to the smallest set needed for the task.
- Run a harmless discovery request, then test one low-risk operation.
- Log request IDs, server errors, and authorization failures without logging secrets.
Configuration syntax differs among hosts, so use the target application’s documentation for the exact config file or settings screen. The protocol concepts remain the same.
Security and authorization
Security depends on the particular server, host, credentials, and permissions. MCP is a protocol, not a universal security boundary.
- For HTTP transports, follow the MCP authorization framework when authorization is used.
- A protected resource server must validate that an access token is intended for that server.
- Do not pass a token received from the MCP client through to an upstream API. Use a separate upstream credential.
- For stdio, retrieve credentials from the process environment rather than applying the HTTP authorization flow.
- Review every tool’s side effects, allowed destinations, filesystem scope, and data exposure.
- Use separate credentials for development and production, rotate them, and grant only required permissions.
These requirements come from the MCP authorization specification. Provider-specific controls, such as Google Cloud IAM, apply to that provider’s services and should not be generalized to every MCP server.
The 2026-07-28 MCP revision
The current reviewed specification is dated July 28, 2026. It introduces a stateless protocol core, optional server/discover capability discovery, header-based routing for Streamable HTTP, cache hints for list results, authorization hardening, and a formal extensions framework. The announcement says the revision retires the previous initialize/initialized exchange and Mcp-Session-Id header. Check the implementation status of your chosen client and SDK before applying migration advice.
ScreenshotNeo as an MCP server for web screenshots
ScreenshotNeo is a website screenshot API and MCP server. Its MCP tools include take_screenshot, get_page_info, and capture_pdf, so an AI agent can inspect a page or request an image or PDF through an MCP client.
Its capture service can load lazy images, capture a CSS-selected element or a full page, set a device or viewport, emulate dark mode, run custom CSS or JavaScript, click an element, wait for a selector, delay, or network idle, block ads or selected request types, set headers, cookies, a user agent, authorization, timezone, or geolocation, resize images, cache with a chosen TTL, create signed image links, submit asynchronous jobs with signed webhooks, and capture up to 100 URLs per bulk call.
Or skip the browser setup
Use the ScreenshotNeo HTTP endpoint when you want a screenshot without managing a browser process. See the ScreenshotNeo documentation for options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' }); const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
- Cookie banners, newsletter popups, and chat widgets are removed before the shot.
- Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; response headers report the page verdict and billing result.
- The MCP server lets AI agents take screenshots.
- 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 shots.
Create a free ScreenshotNeo account to get started.
Performance, reliability, and cost planning
- Latency: stdio avoids a network hop; remote HTTP adds DNS, TLS, routing, and server processing time.
- Throughput: stateless requests can be routed across instances, but your application still needs rate limits and retries.
- Retries: retry only safe or idempotent operations, use request IDs where supported, and apply exponential backoff.
- Timeouts: set client timeouts that match the tool’s real work, especially for browser automation or large data queries.
- Costs: account for host compute, remote service fees, model tokens, and any downstream API charges. Cache read-heavy resources when valid.
- Observability: record duration, status, request ID, tool name, and structured error data while redacting tokens and sensitive arguments.
Troubleshooting MCP connections
| Symptom | Likely cause | Fix |
|---|---|---|
| Server never appears | Wrong transport or host configuration. | Confirm whether the server expects stdio or Streamable HTTP and verify the executable path or URL. |
| JSON parse errors | Logs or other text were written to the protocol stream. | For stdio, write diagnostics to stderr and keep stdout reserved for protocol messages. |
| 401 or 403 response | Missing, expired, incorrectly scoped, or wrongly targeted token. | Issue a token for the MCP server, send it in the required form, and validate its audience and expiry. |
| Tool call rejected | Arguments do not match the discovered schema. | Call tools/list, then send the exact required property names and types. |
| Request times out | Slow upstream work, unreachable service, or an overly short client timeout. | Check server logs and network access, then set a bounded timeout and safe retry policy. |
| State is missing between calls | The server follows the stateless 2026-07-28 model. | Pass an explicit workflow or conversation identifier in each request, if the server defines one. |
| Unexpected upstream authorization failure | The MCP token was forwarded to another API. | Configure a separate upstream credential and keep token exchange within the server. |
Checklist for evaluating an MCP server
- Which tools, resources, and prompts are exposed?
- Can the host enable only the capabilities required for a task?
- Is the server local stdio or remote Streamable HTTP?
- Where are credentials stored, and how are tokens validated?
- What data can each tool read, change, or send externally?
- Does the implementation support the protocol revision used by your host?
- How are timeouts, retries, rate limits, logs, and updates handled?
- What happens when an upstream system is unavailable?
FAQ
Is an MCP server the same as an API?
No. An API exposes application operations. An MCP server exposes capabilities through the MCP protocol so an MCP client can discover and use them consistently. A server may call APIs internally.
Does every MCP server run locally?
No. Local servers commonly use stdio; remote servers commonly use Streamable HTTP.
Can one host use multiple MCP servers?
Yes. The host creates a separate MCP client connection for each server.
Do MCP servers always need tools?
No. A server may provide resources or prompts without exposing action tools.
Does stateless mean the application cannot keep state?
No. It means protocol requests should carry the information needed for processing. Application state can still exist when represented explicitly and passed between calls.
Is an MCP server automatically safe?
No. Review the server’s code or provider, credentials, permissions, network access, and tool side effects.


