Monitoring public SaaS earnings languagePress releases, transcripts, score drift, and evidence capture
SaaSocalypse
Resilience BoardDeath ClockCompaniesCompareProductsPartnersAnalysisMethodology
AI is rewriting SaaS. We track who survives.Rankings, evidence, and research on how AI is changing public SaaS companies.

Loading

Pulling the latest capture.

Fetching scores, snapshots, evidence trails, and company signal drift.

Public SaaS AI intelligence from earnings materials.

SaaSocalypse interprets public company reports and earnings materials based on our reading of the data. Take it with a pinch of salt: this is not investment advice and not a final judgment on the future of any company.

Privacy
Back to analysis

2026-06-16

I Finally Understood MCP After Ignoring the Tutorials and Opening curl -v

A practical deep dive into the Model Context Protocol (MCP) by reverse engineering a real MCP server with Python, curl, JSON-RPC and Server-Sent Events.

AIMCPLLMLangChainJSON-RPCEngineering

Related Analysis

2026-04-01

SaaSocalypse Raises $10M Series A To Build The System Of Record For SaaS Mortality

SaaSocalypse has raised a $10 million Series A to become the AI-native analytics firm for predicting SaaS collapse, consolidation, and strategic decay.

2026-03-26

Google's TurboQuant Could Shrink AI Memory Costs. The Bigger Story Is What Happens Next

Google's March 24, 2026 TurboQuant announcement points to a meaningful compression shift for KV cache memory and vector search, with broader consequences for AI app design.

2026-03-25

Token Burning Is The New OKR

Jensen Huang's March 2026 token-spend line captures a real management shift: AI usage is becoming visible, budgetable, and dangerously easy to mistake for productivity.

TL;DR: If you've ever wondered how an AI agent "magically" discovers tools exposed by an MCP server, forget the marketing diagrams for a moment. Grab curl, inspect the network traffic, and it all starts making sense.


When I first started reading about the Model Context Protocol (MCP), almost every explanation looked something like this:

User
   ↓
LLM
   ↓
MCP
   ↓
Tools

The explanation usually stopped at:

"The LLM discovers tools and calls them."

That wasn't satisfying.

I wanted to know:

  • Where are the tools actually exposed?
  • How does the agent know what tools exist?
  • Can I call an MCP server without an LLM?
  • Is an MCP server just another REST API?
  • What's actually happening on the wire?

So instead of reading more tutorials, I decided to reverse engineer a real MCP server.

I used LangChain's public MCP endpoint:

https://docs.langchain.com/mcp

Step 1: Ignore the LLM

The first thing I realized is that you don't need an LLM at all.

Using the Python MCP SDK:

tools = await session.list_tools()

The server replied with a list of tools.

This was my first "aha!" moment.

Unlike REST APIs, where developers typically read documentation to learn which endpoints exist, an MCP client simply asks the server:

tools/list

and the server replies with every available tool and its input schema.

Conceptually:

Client
   │
   │ tools/list
   ▼
MCP Server
   │
   ▼
Available tools

The MCP server itself becomes the source of truth.


Step 2: No LLM Is Required

Suppose the server advertises:

search_docs_by_lang_chain(query: string)

I can simply call it.

result = await session.call_tool(
    "search_docs_by_lang_chain",
    {
        "query": "How do I create a LangGraph agent?"
    }
)

No LLM.

No reasoning.

No AI.

Just:

Client
   │
tools/call
   │
   ▼
MCP Server
   │
Runs tool
   │
Returns result

This was probably the biggest realization:

MCP is fundamentally a protocol for discovering and invoking tools.

The LLM is just another client.


Step 3: Is the SDK Doing Something Magical?

The obvious next question was:

Is the Python SDK hiding some secret sauce?

Turns out...

Not really.

I replaced it with curl.

First, I listed the available tools.

curl -X POST https://docs.langchain.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"tools/list"
  }'

The server immediately returned the list of tools.

Then I called one.

{
  "jsonrpc":"2.0",
  "id":2,
  "method":"tools/call",
  "params":{
    "name":"search_docs_by_lang_chain",
    "arguments":{
      "query":"How do I create a LangGraph agent?"
    }
  }
}

It worked.

The SDK wasn't performing magic.

It was simply wrapping the protocol.


Step 4: curl -v Was More Educational Than the Docs

Running with verbose output:

curl -v ...

revealed far more than I expected.

MCP Runs Over Plain HTTPS

The first surprise:

Connected to docs.langchain.com

SSL connection using TLSv1.3

HTTP/2

Nothing exotic.

Just HTTPS.


MCP Uses JSON-RPC

Instead of REST endpoints like:

GET /tools

POST /search

everything goes through a single endpoint:

POST /mcp

The operation is encoded inside the request body.

{
  "jsonrpc":"2.0",
  "method":"tools/list"
}

or

{
  "jsonrpc":"2.0",
  "method":"tools/call"
}

This is JSON-RPC.

JSON vs JSON-RPC

This confused me initially.

JSON is just structured data.

{
    "query":"LangGraph"
}

JSON-RPC is a way of calling remote functions.

{
    "jsonrpc":"2.0",
    "method":"tools/list",
    "params":{}
}

Think of it this way:

JSON
↓

A document
JSON-RPC
↓

A function call encoded as JSON

The Response Wasn't JSON

The response headers included:

content-type: text/event-stream

Instead of returning:

{
    "result": ...
}

the server returned:

event: message

data:
{
   "result": ...
}

This is Server-Sent Events (SSE).


What Is Server-Sent Events?

Most REST APIs work like this:

Request

↓

Response

↓

Connection closes

SSE keeps the connection alive.

Instead of one response, the server can stream many events.

event: message
data: {"progress":10}

event: message
data: {"progress":20}

event: message
data: {"progress":30}

This is why AI APIs often stream tokens, and why MCP uses SSE as its transport.

Even though tools/list only returned a single event, the protocol supports long-running tools that stream progress back to the client.


Step 5: So Where Does the LLM Come In?

Suppose the MCP server advertises:

search_docs(query)

fetch_page(url)

list_examples(topic)

A user asks:

"How do I create a LangGraph agent?"

Who decides to call search_docs?

Not the server.

Instead:

  1. The client asks for the available tools.
  2. The tool definitions are shown to the LLM.
  3. The LLM decides which tool best answers the user's question.
  4. The client sends tools/call.
  5. The MCP server executes the tool.

The MCP server never interprets natural language.

It simply executes requested tools.


The Mental Model That Finally Clicked

Initially I thought of MCP as:

AI magic

After spending an hour with Python, curl and the network inspector, I now think of it as:

HTTPS
    +
JSON-RPC
    +
Runtime Tool Discovery
    +
Tool Invocation

The LLM is not MCP.

The tools are not MCP.

MCP is simply the protocol that allows clients to discover and invoke capabilities exposed by a remote service.


The Biggest Surprise

The biggest surprise wasn't that MCP exists.

It was how ordinary it is.

The SDK wasn't doing anything magical.

The protocol wasn't doing anything magical.

Everything ultimately boiled down to a few JSON-RPC messages sent over HTTPS.

Sometimes the fastest way to understand a protocol isn't another tutorial.

It's opening curl -v.


What's Next?

There are still a few things I'd like to explore:

  • How stateful MCP sessions work.
  • Resources vs Tools vs Prompts.
  • Authentication.
  • Building a minimal MCP server from scratch.
  • How different transports (stdio vs HTTP) compare.

Those will probably become future posts.