When connecting file systems, databases, or internal APIs to AI applications like ChatGPT or Claude, you often hear the term “MCP server.” Because “protocol” is in its name, it might seem like a new network standard replacing TCP or HTTP, or simply a REST API with a list of tools attached.
More precisely, MCP (Model Context Protocol) is an application-layer RPC specification between AI applications and external functionalities. It uses standard process I/O or HTTP, familiar in existing operating environments, for transport, JSON-RPC 2.0 for message envelopes, and JSON Schema for tool input/output contracts.
This article, based on the latest stable specification released on July 28, 2026, organizes the role of an MCP server, actual byte streams, HTTP headers and body, SSE responses, schema standards, authentication, and error handling to a level where existing IT personnel can draw packet flows.

Figure: Structure separating MCP’s message layer and transport layer
First, the Conclusion: What MCP Is and What It Is Not
MCP can be summarized as follows when compared to existing technologies:
| Question | Accurate Answer |
| — | — |
| Does MCP replace HTTP? | No. It uses HTTP for remote transport. |
| Does MCP have its own data format? | Yes. It puts MCP-defined method, params, result, and _meta inside a JSON-RPC 2.0 envelope. |
| What is the serialization format? | UTF-8 JSON. Images and audio can be embedded as MIME type and Base64 data within JSON. |
| What is the input parameter specification? | JSON Schema. If $schema is omitted, 2020-12 is considered the default dialect. |
| Is WebSocket required? | No. Standard transports are stdio and Streamable HTTP. WebSocket is only an option when creating a custom transport. |
| Is it a REST API? | No. It’s an RPC that calls methods like tools/list, tools/call, not a resource-centric HTTP API. |
| Is it the same as gRPC? | The purpose is somewhat similar, but it does not mandate Protobuf binaries and HTTP/2 streams. |
| Is an MCP server an LLM? | No. It’s an adapter or service that exposes tools, resources, and prompts for an LLM to call. |
The important distinction is between the data layer and the transport layer.
MCP 데이터 계층
JSON-RPC 2.0
MCP 메서드와 메시지 의미
도구·리소스·프롬프트 스키마
오류와 메타데이터
MCP 전송 계층
stdio
Streamable HTTP
또는 의미를 보존하는 custom transport

Figure: Relationship between MCP’s Host, Client, Server, and Data/Transport Layers · Reconstructed based on official MCP Architecture documentation
Therefore, the answer to the question “Does MCP use HTTP?” is: Remote MCP uses HTTP, but the meaning of MCP itself is not dependent on HTTP.
Roles of Host, Client, and Server
Three roles appear in the MCP structure:
사용자
↓
Host 애플리케이션
├─ MCP Client A ── MCP Server: 파일 시스템
├─ MCP Client B ── MCP Server: GitHub
└─ MCP Client C ── MCP Server: 사내 데이터베이스
The Host is the overall application, including the conversational UI, LLM, and authorization screen. An MCP Client is a protocol component that communicates with a specific MCP Server. An MCP Server exposes external systems as MCP functionalities such as tools, resources, and prompts.
For example, an MCP server providing a tool called `query_database` might not be the database itself. It’s closer to an adapter that applies authentication and SQL policies, calls existing DB drivers, and then returns the results in MCP format.
The Common Message Envelope is JSON-RPC 2.0
Regardless of whether the transport method is stdio or HTTP, the body message uses JSON-RPC 2.0. A request typically has the following structure:
{
"jsonrpc": "2.0",
"id": 42,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"location": "Seoul"
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "example-client",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
The role of each field is clear:
| Field | Meaning |
| — | — |
| jsonrpc | JSON-RPC version. MCP uses “2.0”. |
| id | Correlation ID linking requests and responses. Must be unique among in-flight requests. |
| method | Name of the MCP method to execute |
| params | Method arguments |
| _meta | MCP metadata such as protocol version, client capabilities |
A response returns the same `id`.
{
"jsonrpc": "2.0",
"id": 42,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "서울의 현재 기온은 27°C입니다."
}
],
"isError": false
},
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "weather-server",
"version": "2.1.0"
}
}
}
Notifications do not have an `id` because they are messages for which the recipient does not send a response.
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progress": 70,
"total": 100
}
}

Figure: Fields and correlation of JSON-RPC requests, responses, and notifications · Reconstructed based on official MCP Architecture documentation
In other words, MCP does not freely place data on top of JSON without any rules. It adheres to the JSON-RPC 2.0 request, response, and notification formats, and the MCP methods and data types within them must follow the MCP specification and official schemas.
Key Change in 2026 Specification: Request is the Unit, Not Connection
In past MCP documentation, a flow often appeared where the client initialized a connection with an `initialize` request, the server issued a session ID, and the server then sent JSON-RPC requests back to the client. If explaining the 2025 specification, this would have been correct at the time.
However, the 2026-07-28 specification has changed to a stateless, per-request model.
과거 모델
연결 수립 → initialize → capability 협상 → 세션 상태 유지 → 여러 호출
현재 모델
각 요청 = 프로토콜 버전 + capability + 필요한 인증·메타데이터를 자체 포함
Servers must not infer protocol versions, client identities, or capabilities simply because the TCP connection or stdio process is the same. If long-lived operational states are required, they must be expressed with explicit identifiers such as `requestState` or `subscription ID`.
Currently, the two mandatory request metadata fields are:
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
}
`clientInfo` and log levels are optional. If mandatory metadata is missing, the server rejects with a JSON-RPC -32602 Invalid params error, and for HTTP transport, it also uses HTTP 400.
This change has the advantage of making it easier to send requests to different instances behind a load balancer or handle them serverlessly. On the other hand, if older SDKs and newer servers are mixed, their behavior can differ significantly, so implementers must verify the supported specification date.
stdio Transport: One JSON Message Per Line
The simplest method for a local MCP server is stdio. The client runs the MCP server as a child process and uses the following channels:
Client ── child stdin ──> MCP Server
Client <── child stdout ── MCP Server
Client <── child stderr ── 로그
The wire format is one UTF-8 JSON-RPC message per line over a reliable bidirectional byte stream.
{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{"_meta":{...}}}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search","arguments":{"q":"MCP"},"_meta":{...}}}
The rules are strict:
- Messages are delimited by newline characters, and actual newlines must not be present within the message. Newlines in JSON strings are escaped as `n`.
- Only valid MCP messages should be written to the server’s stdout.
- Logs, debug output, and stack traces are sent to stderr.
- All responses arrive mixed on a single stdout channel, so requests and responses are matched by `id`.
- Progress notifications also arrive on the same channel and are linked to in-flight requests or subscription IDs.
- Cancellations specify the request ID via `notifications/cancelled` notifications.
The stdio framing is not limited to operating system standard streams. Custom transports can also be created that apply the same “one JSON per line” rule to Unix Domain Sockets or TCP. However, that would be a user-defined transport reusing the same framing, not the standard stdio transport.

Figure: Request, response, and log channels of stdio transport and newline framing · Reconstructed based on official MCP stdio specification
Streamable HTTP: One POST Per Request
The standard transport for remote MCP servers is Streamable HTTP. The core of the latest specification is as follows:
POST /mcp ── JSON-RPC 요청 1 ──> JSON 한 개 또는 요청 범위 SSE
POST /mcp ── JSON-RPC 요청 2 ──> JSON 한 개 또는 요청 범위 SSE
POST /mcp ── JSON-RPC 알림 ──> 202 Accepted
The server provides a single MCP endpoint, and all client messages are sent as new HTTP POST requests. The request body contains only one JSON-RPC object. Do not consider using JSON arrays for batching or putting multiple JSON-RPC messages in a single POST.
An actual request looks similar to this:
POST /mcp HTTP/1.1
Host: mcp.example.com
Content-Type: application/json
Accept: application/json, text/event-stream
Authorization: Bearer eyJ...
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: get_weather
{
"jsonrpc": "2.0",
"id": 42,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {"location": "Seoul"},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
What stands out here is that some values are duplicated in HTTP headers and the JSON body.
| HTTP Header | Body Source | Purpose |
| — | — | — |
| MCP-Protocol-Version | _meta.io.modelcontextprotocol/protocolVersion | Specification version selection |
| Mcp-Method | method | Proxy, WAF, observation tools route without parsing body |
| Mcp-Name | params.name or params.uri | Identify target tool, resource, or prompt |
The body is the source of truth for meaning, and the server verifies that the header and body match. If versions differ, it returns HTTP 400 and a HeaderMismatch JSON-RPC error.
Specific primitive type fields in the tool schema can declare `x-mcp-header` to be duplicated as `Mcp-Param-{Name}` headers. This is useful for load balancers to route based on values like region or tenant, but passwords, tokens, and personal information should not be put in headers as they are easily exposed to intermediate devices and logs.
Values that cannot be expressed as safe ASCII header values, such as Korean characters, use Base64 encoding of UTF-8 bytes and the following sentinel format:
Mcp-Name: =?base64?{Base64EncodedValue}?=
Why is it called Streamable HTTP?
The server responds in one of two ways depending on the nature of the request:
Short Response: application/json
HTTP/1.1 200 OK
Content-Type: application/json
{"jsonrpc":"2.0","id":42,"result":{"resultType":"complete",...}}
Responses with Progress: text/event-stream
HTTP/1.1 200 OK
Content-Type: text/event-stream
data: {"jsonrpc":"2.0","method":"notifications/progress","params":{"progress":50}}
data: {"jsonrpc":"2.0","id":42,"result":{"resultType":"complete","content":[...]}}
SSE is a response stream dependent on that POST request. It must end with a final JSON-RPC response after sending progress notifications. If the client closes this SSE connection, the server must treat that request as cancelled.
If you want to receive long-term tool list changes or resource changes, you maintain the response stream by sending a `subscriptions/listen` request, rather than opening a separate GET stream. In the 2026 specification, the previous independent GET SSE endpoint and protocol sessions have been removed. The ability to resume an SSE stream with `Last-Event-ID` is also not supported.
Therefore, in an operational environment, it is necessary to check the reverse proxy’s SSE buffering, idle timeout, maximum request time, and connection termination propagation. While possible with HTTP/1.1, considering multiple concurrent streams and connection efficiency, HTTP/2 support is also worth checking from an infrastructure perspective. However, the MCP specification does not mandate HTTP/2 itself.

Figure: JSON response per request and SSE streaming branch in Streamable HTTP · Reconstructed based on official MCP Streamable HTTP specification
How to Discover and Call Tools
Clients do not need to hardcode the tools provided by an MCP server in advance. They discover them at runtime using `tools/list`.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
The server returns the tool name, description, and input schema.
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"tools": [
{
"name": "get_weather",
"description": "지역의 현재 날씨를 조회합니다.",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "도시 이름"
}
},
"required": ["location"],
"additionalProperties": false
}
}
]
}
}
The Host informs the LLM of this description and schema, and if the model suggests a tool call, it sends `tools/call` after policy and user approval. MCP does not mandate the model’s judgment or the approval UI.
To What Extent is JSON Schema Standardized?
The question “Does MCP have a format?” should be divided into two layers:
First, the MCP protocol message types have an official TypeScript schema as the source of truth, from which JSON Schema is generated. SDK implementers can match request and response types based on this schema.
Second, each tool’s `inputSchema` and optional `outputSchema` are also JSON Schema. If `$schema` is omitted, it is interpreted as JSON Schema 2020-12. Implementations must support 2020-12, and if using a different dialect, it must be explicitly stated with a `$schema` URI.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100
}
},
"required": ["limit"],
"additionalProperties": false
}
JSON Schema can validate not only types but also required fields, ranges, string patterns, enumerations, and nested structures. However, having a schema does not automatically make it secure. Automatically fetching `$ref` from external URLs can lead to SSRF or supply chain issues, and excessive `oneOf`, `allOf`, or recursive references can consume validator resources. The official specification also prohibits automatic dereferencing of external network `$ref`s and recommends limiting depth, time, and the number of subschemas.
Is Result Data Only Text?
The `content` of tool results can mix multiple types:
{
"resultType": "complete",
"content": [
{"type": "text", "text": "분석 결과입니다."},
{
"type": "image",
"data": "iVBORw0KGgoAAA...",
"mimeType": "image/png"
},
{
"type": "resource_link",
"uri": "file:///reports/result.json",
"name": "result.json",
"mimeType": "application/json"
}
],
"structuredContent": {
"riskScore": 82,
"severity": "high"
},
"isError": false
}
Text is a JSON string, images and audio are Base64 data with MIME types, and files or web resources are represented by URI links or embedded resources. Machine-processable results can be returned as JSON values in `structuredContent` and validated with `outputSchema`.
Here, `structuredContent` is a different concept from “structured output” created by an LLM using schema-constrained decoding. It is simply the tool result data returned by the MCP server.
Embedding large binaries as Base64 in the body every time increases size by approximately 33% and consumes more memory. For large files, it may be more appropriate to return an access-controlled resource URI or a separate object storage URL and have the client read it when needed.
HTTP Status Codes and JSON-RPC Errors are Different Layers
In Streamable HTTP, errors exist on two layers:
HTTP 계층
인증 실패, 잘못된 Origin, 지원하지 않는 endpoint,
헤더 불일치, 전송 자체의 실패
JSON-RPC/MCP 계층
파싱 실패, 잘못된 요청, 존재하지 않는 method,
잘못된 params, tool 실행 오류
Typical JSON-RPC standard errors include:
| Code | Meaning |
| — | — |
| -32700 | Parse error |
| -32600 | Invalid Request |
| -32601 | Method not found |
| -32602 | Invalid params |
| -32603 | Internal error |
MCP also defines errors such as HeaderMismatch -32020, missing required client capability -32021, and unsupported protocol version -32022.
If a tool itself executed successfully but an business error occurred, HTTP 200 and a normal JSON-RPC response can be used with `isError: true`. For example, “payment card declined” is different from a network transmission failure. In monitoring, relying solely on HTTP success rates might miss business failures of MCP tools.
Authentication Uses OAuth 2.1 Family in HTTP
MCP authentication is optional, but if an HTTP-based transport supports authentication, it is recommended to follow the latest MCP Authorization specification. The core idea is that the MCP server acts as an OAuth resource server.
MCP Client
├─ Protected Resource Metadata 조회
├─ Authorization Server Metadata 조회
├─ OAuth 2.1 + PKCE로 사용자 승인
└─ Authorization: Bearer <access-token>
↓
MCP Server
The specification combines OAuth 2.1 draft, RFC 6750 Bearer Token, RFC 8414 Authorization Server Metadata, RFC 9728 Protected Resource Metadata, RFC 8707 Resource Indicators, and others. Clients must not put tokens in query strings and must include an `Authorization: Bearer` header in all protected HTTP requests. Servers must verify that the token’s audience is themselves.
stdio does not follow this HTTP OAuth flow and recommends receiving credentials in the process environment. This does not mean that API keys can be left in plain text in configuration files or logs. Separate operational controls such as OS keychains, secret managers, and least-privilege environment variable injection are required.
Comparison with REST, OpenAPI, gRPC, WebSocket
| Technology | Primary Role | Transport/Encoding | Difference from MCP |
| — | — | — | — |
| REST API | HTTP resource manipulation | HTTP + primarily JSON | MCP provides defined RPC methods and AI tool discovery conventions |
| OpenAPI | Static specification of HTTP APIs | YAML or JSON document | MCP defines runtime tools/list and call/result messages |
| JSON-RPC 2.0 | RPC message envelope | Transport-independent JSON | MCP standardizes methods and semantics on top of this envelope |
| gRPC | Strongly typed remote calls | HTTP/2 + Protobuf | MCP focuses on human-readable JSON and JSON Schema |
| WebSocket | Full-duplex connection transport | Frame-based | Not MCP’s default transport; a candidate for custom transport |
| SSE | Server-to-client streaming | HTTP text/event-stream | Used in Streamable HTTP for per-request progress notifications and final responses |
When connecting existing REST APIs to MCP, there’s no need to abandon the APIs. It’s common to use an MCP server as a thin adapter that internally calls existing REST or gRPC.
LLM Host
→ MCP Client
→ MCP Server
→ 기존 REST/gRPC/DB/Queue
MCP is less about creating new backend systems and more about providing a common interface for AI applications to discover and call the functionalities of those systems.
Candidates to Check Before Actual Adoption
When an existing IT organization reviews an MCP server, it’s good to check the following items first:
1. Transport Selection
- If the Host runs the process directly on one computer, stdio is simpler.
- If connecting multiple users and remote servers, Streamable HTTP is suitable.
- For custom transports, first calculate the cost of losing standard client compatibility and observation tools.
2. Specification Version and SDK Compatibility
- Verify that both server and client support the 2026-07-28 stateless model.
- Distinguish between older implementations that rely on `initialize`, `MCP-Session-Id`, and GET SSE.
- Test for protocol version mismatches in headers and body.
3. Schema Quality
- Define concrete `inputSchema` for all tools.
- If possible, use `additionalProperties: false`, length/range/enum constraints.
- Provide `outputSchema` and `structuredContent` for important machine-processable results.
- Set resource limits for external `$ref`s, recursion, and complex combinatorial schemas.
4. Permissions and Safeguards
- Minimize the tool list according to token scope.
- Separate read and write tools, and require user approval for deletion, payment, and permission changes.
- Do not trust LLM-generated arguments; re-validate them on the server.
- Check environment variables and file permissions inherited by the stdio server.
5. HTTP Operational Items
- Prevent DNS rebinding with Origin validation and localhost bind.
- Validate OAuth audience, scope, and token expiration.
- Test SSE buffering, idle timeout, and connection termination/cancellation propagation.
- Log `Mcp-Method` and `Mcp-Name`, but do not log sensitive `Mcp-Param-*`.
6. Reliability and Observability
- Connect end-to-end traces with JSON-RPC `id`.
- Aggregate HTTP errors, JSON-RPC errors, and `isError: true` as separate metrics.
- Distinguish between retriable read operations and write operations that are dangerous to duplicate.
- Test timeouts, cancellations, and failures after partial progress notifications.
Summary
Looking at an MCP server at a low level, it’s not a mysterious AI-specific network.
의미와 메시지
MCP method + JSON-RPC 2.0
도구 계약
JSON Schema 2020-12 기본
로컬 전송
UTF-8 newline-delimited JSON over stdio
원격 전송
HTTP POST + application/json 또는 request-scoped SSE
인증
HTTP는 OAuth 2.1 계열, stdio는 실행 환경의 자격증명
The value of MCP does not lie in inventing new sockets or serialization formats. It lies in combining existing standards to create a common contract for AI Hosts to discover, understand types, call, and receive results from tools.
Three key points for operators to remember are: separate the MCP data layer and transport layer, do not confuse the latest specification’s stateless request model with older session models, and enforce permissions, validation, approval, and observability both externally and internally to the server, even with schemas in place.
Leave a Reply