Unlock AI Agents with Model Context Protocol (MCP): Deep Dive & Code
This article explains the Model Context Protocol (MCP) introduced by Anthropic, detailing its client‑server architecture, protocol and transport layers, message types, lifecycle, and practical implementation in Python and TypeScript to build a custom AI agent that can both converse and perform tasks.
Introduction
MCP (Model Context Protocol) is an open protocol released by Anthropic at the end of 2024 to provide a safe, standardized way for AI systems—such as programming assistants or agents—to access data. It uses a client‑server architecture so that AI tools (e.g., Claude Desktop, IDE plugins) can interact with an MCP server to read local or remote data sources.
Basic Concepts
MCP Hosts (宿主程序) : applications like Claude Desktop or IDEs that use MCP to access data.
MCP Clients (客户端) : establish a 1:1 connection with the server and handle communication.
MCP Servers (服务端) : lightweight programs that expose standardized data or tool access.
Local Data Sources : files, databases, etc., accessed securely by the server.
Remote Services : APIs, cloud services, etc., proxied by the server.
Protocol Layer
Handles message framing, request/response correlation, and advanced communication modes.
Transport Layer
Supports two transport methods:
Stdio (standard input/output) for local inter‑process communication.
HTTP + SSE for remote network communication (server‑sent events for server→client, HTTP POST for client→server).
All transports use JSON‑RPC 2.0 for message exchange.
Message Types
Request (expects a response)
Result (successful response)
Error (error response)
Notification (one‑way, no response)
interface Request { method: string; params?: { ... } } interface Result { [key: string]: unknown; } interface Error { code: number; message: string; data?: unknown; } interface Notification { method: string; params?: { ... } }Lifecycle
The client and server perform a three‑step handshake similar to TCP:
Client sends initialize request with protocol version and capabilities.
Server replies with its version and capabilities.
Client sends initialized notification, then normal communication begins.
Message Exchange
After initialization, communication can use:
Request‑Response mode (bidirectional).
Notification mode (one‑way).
Termination
Explicit close via close().
Transport layer disconnect.
Error‑triggered termination.
Practical Implementation
The author builds a personal agent (myAgent) that can converse and perform tasks. The workflow:
User input is sent to the AI via the MCP client.
AI decides whether to answer directly or invoke a tool.
If a tool is needed, the client calls the MCP server (e.g., a search‑assistant tool get_offers).
Server returns structured data, which the client forwards back to the AI for summarization.
Two example interactions are shown: a simple greeting (no tool) and a product search for "手表" (watches) where the AI automatically selects the get_offers tool, passes arguments, receives results, and returns a polished answer.
Code Samples
Python MCP client (asyncio) implementation:
import asyncio
import json
import os
import traceback
from typing import Optional
from contextlib import AsyncExitStack
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
class MCPClient:
def __init__(self):
self.session: Optional[ClientSession] = None
self.exit_stack = AsyncExitStack()
self.client = OpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
base_url=os.getenv("OPENAI_BASE_URL")
)
self.model = os.getenv("OPENAI_MODEL")
self.messages = [{"role": "system", "content": "You are a versatile assistant capable of answering questions, completing tasks, and intelligently invoking specialized tools to deliver optimal results."}]
self.available_tools = []
# ... (connection, query processing, chat loop, cleanup) ...TypeScript MCP client implementation (Node.js):
/** MCP client implementation */
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import OpenAI from "openai";
import * as dotenv from "dotenv";
import * as readline from "readline";
dotenv.config();
class MCPClient {
private openai: OpenAI;
private client: Client;
private messages = [{ role: "system", content: "You are a versatile assistant capable of answering questions, completing tasks, and intelligently invoking specialized tools to deliver optimal results." }];
private availableTools: any[] = [];
constructor() {
if (!process.env.OPENAI_API_KEY) throw new Error("OPENAI_API_KEY not set");
this.openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, baseURL: process.env.OPENAI_BASE_URL });
this.client = new Client({ name: "my-mcp-client", version: "1.0.0" });
}
// ... (connectToServer, toolCalls, processQuery, chatLoop, cleanup) ...
}Server Example (TypeScript)
Implements a get_offers tool that fetches product offers via an external API and returns them as structured text.
class ProductOffersServer {
private server: Server;
private baseUrl = 'YOUR_API_URL';
constructor() {
this.server = new Server({ name: 'search-assistant-server', version: '0.1.0' }, { capabilities: { tools: {} } });
this.setupToolHandlers();
this.server.onerror = (error) => console.error('[MCP Error]', error);
process.on('SIGINT', async () => { await this.server.close(); process.exit(0); });
}
private async fetchOffers(keywords?: string, pageSize?: number): Promise<Product[]> { /* axios call */ }
private setupToolHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [{ name: 'get_offers', description: 'Get product offers from API', inputSchema: { type: 'object', properties: { keywords: { type: 'string', description: 'Keywords to search for products', default: '' }, pageSize: { type: 'number', description: 'Number of items per page', minimum: 1, maximum: 100, default: 10 } } } }])
}));
this.server.setRequestHandler(CallToolRequestSchema, async (request) => { /* call fetchOffers and return */ });
}
async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('Product Offers MCP server running on stdio'); }
}
const server = new ProductOffersServer();
server.run().catch(console.error);Conclusion
The article demonstrates how MCP enables AI agents to safely access heterogeneous data sources, automatically decide when to invoke tools, and optionally let the AI summarize results. By integrating MCP with OpenAI’s function‑calling API, developers can build agents that handle multi‑turn interactions, delegate tasks to external services, and return user‑friendly answers.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
