MCP(Model Context Protocol)
What? It is the opensource standard way how AI agents(like claude
CLI) interacts & gets information from outside world(eg: github, google
drive, postgres db reader etc)
Client Server Architecture: AI Agent(eg: Claude CLI) acts as the
client, and the service provider(eg: postgres DB reader) act as the
server.
Communication: Client and server uses Server-Sent Events (SSE) or
WebSockets over HTTP and uses HTTPS (SSL/TLS) to encrypt the JSON-RPC
messages.
MCP is Opensource/Vendor Agnostic: That means any agent can use
MCP to interact with MCP server and access tools/services
Claude-MCP-Client ---------|
MCP-Server <--> postgres-DB-reader
Cursor-MCP-Client ---------|
MCP Message Format: MCP always sends JSON-RPC with specific feilds (eg: method, params, id etc)
POST /mcp/v1/tools/call HTTP/1.1
Host: mcpserver.com
Content-Type: application/json
Authorization: Bearer <AI_Platform_JWT>
User-Agent: AI-Assistant-Client/1.0
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "fetch_webpage",
"arguments": {
"url": "http://www.google.com/"
}
},
"id": 42
}
How MCP Client Authenticate to Server? if human user want to access any service then they provide password, but for AI agent authenticate using OAuth.
Machine-1 Machine-2 Machine-3
Client(claude cli) (Auth Server) (Resource Server)
---- GET www.google.com -------------------->
<- 401 Unauthorized Challenge -----------
-- Authenticate ----->
my client_id: https://claude.ai/mcp-metadata.json
- Fetch public key > claude.ai
<--- Public key -------
Verify Signature
--- GET google.com Authorization Header: JWT -->
MCP Authorization
OAuth for HTTP/SSE client,server.
None for STDIO
Message Exchange
@startuml
title MCP Client-Server Sequence Diagram
participant "MCP Client" as Client
participant "MCP Server" as Server
== Connection Setup ==
Client <-> Server: HTTP 3 Way Handshake
Server <-> Client: TLS Tunnel established
== Initialize Handshake (id=1) ==
note over Client: Client Advertises its Capabilities
Client -> Server: POST /jsonrpc\nHost: mcp-server.example.com \nContent-Type: application/json\nMCP-Protocol-Version: 2025-11-25\nMCP-Session-Id: uuid\n initialize (id=1)\n{\n "jsonrpc": "2.0",\n "id": 1,\n "method": "initialize",\n "params": {\n "protocolVersion": "2024-11-05",\n "capabilities": {\n "roots": {"listChanged": false}\n },\n "clientInfo": {"name": "Test", "version": "0.1.0"}\n }\n}
note over Server: Server advertises its capabilities
Server -> Client: POST /jsonrpc\nHost: mcp-client.example.com \nContent-Type: application/json\nMCP-Protocol-Version: 2025-11-25\nMCP-Session-Id: uuid\n Response (id=1)\n{\n "jsonrpc": "2.0",\n "id": 1,\n "result": {\n "protocolVersion": "2024-11-05",\n "capabilities": {\n "tools": {"listChanged": false},\n "resources": {"listChanged": false},\n "prompts": {"listChanged": false}\n },\n "serverInfo": {"name": "Srv", "version": "0.1.0"}\n }\n}
note over Client: Client saves Server's Capabilites\nClient responds Initialized
Client -> Server: POST /jsonrpc\nHost: mcp-server.example.com \nContent-Type: application/json\nMCP-Protocol-Version: 2025-11-25\nMCP-Session-Id: uuid\nnotifications/initialized\n{\n "jsonrpc": "2.0",\n "method": "notifications/initialized"\n}
== Tools & Resource Discovery (id=2) ==
note over Client: Client asks Tools List
Client -> Server: POST /jsonrpc\nHost: mcp-server.example.com\nMCP-Protocol-Version: 2025-11-25\nMCP-Session-Id: uuid \nContent-Type: application/json\ntools/list (id=2)\n{\n "jsonrpc": "2.0",\n "id": 2,\n "method": "tools/list"\n}
note over Server: Server provides Tools List
Server --> Client: POST /jsonrpc\nHost: mcp-client.example.com\nMCP-Protocol-Version: 2025-11-25\nMCP-Session-Id: uuid \nContent-Type: application/json\nresult (id=2)\n{\n "jsonrpc": "2.0",\n "id": 2,\n "result": {\n "tools": [\n {"name": "add", "inputSchema": {"type": "object", "properties": {"a", "b"}}},\n {"name": "echo", "inputSchema": {"type": "object", "properties": {"type": "string"}}}\n ]\n }\n}
== Tools Invocation (id=3) ==
note over Client: Client invokes the Tool
Client -> Server: POST /jsonrpc\nHost: mcp-server.example.com\nMCP-Protocol-Version: 2025-11-25\nMCP-Session-Id: uuid \nContent-Type: application/json\ntools/call (id=3)\n{\n "jsonrpc": "2.0",\n "id": 3,\n "method": "tools/call",\n "params": {\n "name": "add",\n "arguments": {"a": 2, "b": 3}\n }\n}
note over Server: Server provides invocation result
Server --> Client: POST /jsonrpc\nHost: mcp-client.example.com\nMCP-Protocol-Version: 2025-11-25\nMCP-Session-Id: uuid \nContent-Type: application/json\nresult (id=3)\n{\n "jsonrpc": "2.0",\n "id": 3,\n "result": {\n "content": [\n {"type": "text", "text": "2+3 = 5"}\n ]\n }\n}
@enduml
|
- Initialize Handshake (Both sides exchange protocolVersion, advertise Capabilities) - C->S initialize (id=1) Request S->C result for id=1 (protocolVersion, capabilities, serverInfo) Response C->S Initialized. notification --------- Tools & Resouce Discovery ------------ C->S tools/list (id=2) Reqeuest S->C result for id=2 (tools list for inputs) Response ------- Tools Invocation ------------- C->S tools/call add(2,3) (id=3) Reqeust S->C result for id=3 Response C->S resources/list (id=5) Request S->C result for id=5 Response C->S resouces/read (id=6) Request S->C result for id=6 Response |
Modes of Operation
- There can be 2 modes of operation: Local, Remote
| Local / STDIO | Remote (HTTPS/SSE) | |
|---|---|---|
| What | Claude CLI runs on a machine and for all operations it need not to leave the machine | Claude CLI need to connect to MCP server over the netwrok or within company network and client need to auth via OAuth |
| Example |
1. git clone repo; Ans ask questions about repo 2. Shell commands 3. Spawning subagent 4. Searching Company's Jira, Google docs, confluence(if skill is imported to claude cli agent) |
|
| Authorization | Implementations using an STDIO transport SHOULD NOT follow this any protocol for authorization, and instead retrieve credentials from the environment. | OAuth recent standard |
Fields in Header
Session Id (non mandatory):
- Client can send MCP-Session-Id in initialization message, by including it in HTTP
header, if server support Session Id, it will return in Initialization response and client should use
it in all subsequent HTTP requests.
- if server does not support MCP-Session-Id, it should respond without MCP-Session-Id with HTTP 400 Bad response
Protocol Version Header (non mandatory):
- If using HTTP, the client MUST include the MCP-Protocol-Version: protocol-version HTTP header on all subsequent requests to the MCP server.
MCP server to respond based on the MCP protocol version. For example: MCP-Protocol-Version: 2025-11-25
- if protocol version is not sent, server SHOULD assume protocol version 2025-03-26. If the server receives a request with an invalid or
unsupported MCP-Protocol-Version, it MUST respond with 400 Bad Request.
We can use these(MCP-Session-Id, MCP-Protocol-Version) as strong hints, but not sufficient to detect MCP traffic
MCP vs HTTP
| Traditional Web Traffic | With MCP | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
Headers:- Are HTTP headers or WebSocket upgrade headers, SSE headers
|
|||||||||
| Destination Endpoint |
https://www.google.com/submit-form Reqeust is directed to final destination visible in HTTP Request |
api.external-mcp-provider.com HTTP Request sent MCP Server endpoint. method is present in json body |
||||||||
| Payload | Body contains the raw data intended for the destination | JSON-RPC object | ||||||||
| Json Structure Attached | No | Always | ||||||||
| Reaching endpoint | Directly reach | MCP client can reach resource via MCP Server |
MCP parsing in SWG
-
Netskope must look past the HTTP headers and parses the JSON body.
Earlier blocking policy was created by finding destination URL in HTTP header eg(https://google.com) but in MCP Json body has to be parsed.
Common MCP Request Examples
HTTP GET (same for SSE,)
|
DB Access
|
Filesystem Access
|
github access
|
Questions
1. Can existing tools(old postgres DB reader) talk over MCP directly, or
do they need an update?
They would need to be updated since every MCP server need to
expose some new endpoint eg: tools/list, execute_query.
Endpoint execute_query: MCP server provides a
endpoint(execute_query) which accepts the JSON-RPC payload, translates
it into an actual SQL query, executes it against the database, and
reformats the tabular SQL rows back into clean text/JSON for the AI
model.
2. Why couldn't we use an existing RPC protocol (like gRPC or
JSON-RPC)?
MCP is just AI specific way of getting information over existing
RPC protocols.
AI agent converts generic prompts to REST endpoint calls(eg:
code-review) and use these endpoints to perform the tasks
3. What would surely present in MCP Request
This is high probability that these fields would be present in MCP
request:
1. Method / Operation type: tools/call, action:invoke, op:call
2. Structured Json:
Capability Identifier(name in params)
Sensitive Payload Data(URLs, SQL, file paths, prompts, shell
commands, repo names)