This page looks best with JavaScript enabled

Model context protocol

 ·  ☕ 4 min read

Model Context Protocol

I installed so many MCP servers on my AI agnets and they have magic.
Just some short notes to help myself understand what MCP is.

What it is

MCP is something that helps the AI models nteract with external services, data sources in a structured, controlled way. Instead of letting the AI models to explore how to work with the external things itself, the MCP servers provide the safe and deterministic tools with descriptions so that AI models can easily understand and use them.

In a typical setup, an AI agent (like Cline) sits between the model and the MCP server, passing tool definitions to the model and executing tool calls on its behalf.

Let’s say sending an email, when we first started using AI, it’s just the chatGPT webiste that helped me write, I’d still need to copy the output and send the email myself in Gmail.

Now we’ve got a Gmail MCP, which contains all the tools, including the script to call the Gmail’s SendMail API. The model only needs to generate the text, then delegate the job to the MCP server, and an email is sent.

How does an AI model interact with MCP servers

Let’s us sending an email as an exmple, and we are using Cline (or some random AI agent).

Step 1

First we have our MCP server running (locally or remotely), and it knows how to do “the thing”, sending an email via Gmail properly.

# on the MCP server
@mcp.tool()
def send_email(to: str, subject: str, body: str):
    gmail_api.send(to, subject, body)

Step 2

The MCP server automatically exposes

{
  "name": "send_email",
  "description": "Send an email via Gmail",
  "parameters": {
    "to": "string",
    "subject": "string",
    "body": "string"
  }
}
...
// more tools

Step 3

Cline connects to the MCP server, getting the tool list, the json file describing what are available.

Step 4

Cline talks to the AI model with your message and the tool definitions.

User message: "I need to send an email via gmail to my grandma@gmail.com to congrate her birthday"


The available tools on the MCP server:
1. ("name": "send_email", "description": "Send an email via Gmail", "parameters": ...)
2. ("name": "read_emails", "description": "read the unread emails", "parameters": ...)

Step 5

The model considers and responses this to Cline

{
  "type": "tool_call", 
  "tool": "send_email",
  "arguments": {...}
}

Step 6

Cline catches it!
Cline has something like this implemented

if (response.type == "tool_call") {
  // intercept and interact with MCP server
} else if (response.type == "normal_text") {
  // ...
}

Step 7

Cline calls the MCP server to execute

send_email(arguments)

Usually it’s via JSON-RPC but it can vary.

Step 8

MCP executes, runs the function.
Calls Gmail API (or whatever).

Step 9

Cline gets the result from MCP and sends result back to model.
Then see how AI model responses, the loop continues.

When do we need to create our own MCP

We build our own MCP only when we need reusable, structured access to real systems across multiple AI workflows.

Let’s again use sending an email as an example, but this time we want to send a monthly sales report with some pre-defined data and AI generated text.

This is the previous MCP

@mcp.tool()
def send_email(to: str, subject: str, body: str):
    gmail_api.send(to, subject, body)

And we can implement the new MCP tool like this

@mcp.tool()
def get_monthly_sales_report(date):
    sales_data_raw = database.sales.query(date)
    sales_data = data_process(sales_data_raw) // critical business logic
    
    return {
        to: "leadership@company.com",
        subject: "Monthly Sales Summary" 
        sales_data: sales_data
    }
    
@mcp.tool()
def send_email(to: str, subject: str, body: str):
    gmail_api.send(to, subject, body)
    
    

When we tell our AI agent that we want to send out the monthly sales summary

  1. The AI is told about the available tools, then decide to fetch the data first to help generating summary
  2. call get_monthly_sales_report to get data
  3. Feed AI model with sales_data to generate a summary in text
  4. call send_email to send out the monthly report

With the get_monthly_sales_report implemented in our MCP, we made it reusable.
Without implementing the fixed procedure, the AI model will need to explore by itself, which can be really difficult and error prone even if we provide other tools like database_query, database_table_description, not to mention the business logic in data_process might even by critical, like removing user identification for privacy regulation.

We could even make it more fixed by

@mcp.tool()
def send_monthly_sales_report(date):
    sales_data_raw = database.sales.query(date)
    sales_data = data_process(sales_data_raw)

    summary = generate_summary(sales_data) # some LLM

    gmail_api.send(
        to="leadership@company.com",
        subject="Monthly Sales Summary",
        body=summary
    )

This does not rely on our local AI and agent to guess the flow, combining different tools.

Summary

What it is is the summary!

Share on

Marko Peng
WRITTEN BY
Marko Peng
Good man