Sign up for your FREE personalized newsletter featuring insights, trends, and news for America's Active Baby Boomers

Newsletter
New

Mcp – Model Context Protocol: The New Standard For Ai Data Connectivity

Card image cap

In the rapidly evolving landscape of artificial intelligence, Large Language Models (LLMs) have revolutionized how we approach tasks like coding, question answering, and content creation. However, these LLMs do not have access to external data sources to get real-time and domain-specific data. Even though we use RAG and tools to update their knowledge, a significant challenge has persisted: each AI system typically requires a custom integration approach, with specific APIs, databases, or unique setups. This fragmentation has limited the ability of LLM-powered agents to access external information such as your files, emails, project documents, and APIs.

Introducing Model Context Protocol (MCP)

Recognizing this challenge, Anthropic has developed the Model Context Protocol (MCP) – an open standard for AI that enables models to dynamically connect with tools, files, and APIs.

Think of MCP as the USB-C for AI connectivity – a universal interface for feeding context to AI systems, allowing them to seamlessly integrate with external data sources. This breakthrough means developers and end users no longer need different interfaces to connect to various AI systems, whether they're working with an AI-powered IDE, chatbot, agent, or application. As a result, retrieving and acting on real-time information is becoming more standardized than ever before.

MCP servers offer separation of concerns from AI agents and LLM-powered applications, allowing tools and functionality to be integrated with any AI assistant or agent. The protocol promises a unified standard to connect any tool or service.

How MCP Works

MCP utilizes a client-server model with two main components:

  • MCP Server: Provides structured context to AI models, functioning as a database, file system, cloud services data storage, or API that AI can query.
  • MCP Host/Client: The AI application (such as Claude for Desktop, Cursor IDE, or Windsurf) or custom AI-powered applications that request context from the MCP Server.

Practical Applications

In this blog, we'll explore three different MCP Server implementations:

  1. Database Operations – Query, delete, update, and insert user profile data in an SQLite database
  2. File System Access – List, delete, and rename files from a given directory
  3. Real-time Data with SSE (Server-Sent Events) – Expose endpoints to retrieve all cities and get weather information for specific cities
  4. Cloud Storage Integration – List all file or blob names from Azure storage

We'll then build custom AI agents or chatbots to query real-time information from these MCP servers, demonstrating the versatility and power of this new protocol.

Architecture

Multi MCP Servers and MCP Client Implementation

1. FastMCP server (SSE)

import asyncio 
import json 
import random 
from datetime import datetime 
from typing import List, AsyncGenerator 
from mcp.server.fastmcp import FastMCP 
 
 
# Cities from India and USA 
cities = { 
    "India": [ 
        "Mumbai", "Delhi", "Bangalore", "Hyderabad", "Chennai",  
        "Kolkata", "Pune", "Ahmedabad", "Jaipur", "Lucknow" 
    ], 
    "USA": [ 
        "New York", "Los Angeles", "Chicago", "Houston", "Phoenix",  
        "Philadelphia", "San Antonio", "San Diego", "Dallas", "San Jose" 
    ] 
} 
 
# Temperature ranges for different cities (°C) 
temp_ranges = { 
    "India": (-5, 45),   # India can get very hot in summer 
    "USA": (-20, 40)     # USA can get colder in northern states 
} 
 
mcp = FastMCP("weather", port=5023, host="localhost") 
 
 
async def weather_generator(location: str | None = None) -> AsyncGenerator[str, None]: 
    """Generate simulated weather data for cities in India and USA.""" 
    weather_conditions = ["Sunny", "Partly Cloudy", "Cloudy", "Rainy", "Thunderstorm", "Windy", "Snowy", "Foggy"] 
 
    while True: 
        # Generate data for a random city from each country 
        india_city = random.choice(cities["India"]) 
        usa_city = random.choice(cities["USA"]) 
 
        city_data = [] 
 
        # If location is specified, only return data for that city's country 
        if location: 
            target_cities = [] 
            if location.upper() in [city.upper() for city in cities["India"]]: 
                target_cities = [location] 
                temp_range = temp_ranges["India"] 
            elif location.upper() in [city.upper() for city in cities["USA"]]: 
                target_cities = [location] 
                temp_range = temp_ranges["USA"] 
            else: 
                # If location not found, use default behavior 
                target_cities = [india_city, usa_city] 
 
            for city in target_cities: 
                country = "India" if city in cities["India"] else "USA" 
                temp_range = temp_ranges[country] 
 
                city_data.append({ 
                    "country": country, 
                    "city": city, 
                    "timestamp": datetime.now().isoformat(), 
                    "temperature": round(random.uniform(*temp_range), 1), 
                    "condition": random.choice(weather_conditions), 
                    "humidity": random.randint(20 if country == "USA" else 30, 95 if country == "USA" else 100), 
                    "wind_speed": round(random.uniform(0, 30 if country == "USA" else 25), 1) 
                }) 
        else: 
            # Default behavior - one city from each country 
            india_data = { 
                "country": "India", 
                "city": india_city, 
                "timestamp": datetime.now().isoformat(), 
                "temperature": round(random.uniform(*temp_ranges["India"]), 1), 
                "condition": random.choice(weather_conditions), 
                "humidity": random.randint(30, 100), 
                "wind_speed": round(random.uniform(0, 25), 1) 
            } 
            city_data.append(india_data) 
 
            usa_data = { 
                "country": "USA", 
                "city": usa_city, 
                "timestamp": datetime.now().isoformat(), 
                "temperature": round(random.uniform(*temp_ranges["USA"]), 1), 
                "condition": random.choice(weather_conditions), 
                "humidity": random.randint(20, 95), 
                "wind_speed": round(random.uniform(0, 30), 1) 
            } 
            city_data.append(usa_data) 
 
        # Format as SSE message 
        yield f"data: {json.dumps(city_data)}\n\n" 
 
        # Wait before sending next update 
        await asyncio.sleep(3)  # Update every 3 seconds 
 
@mcp.tool("stream_weather") 
async def stream_weather(location: str | None = None): 
    """SSE endpoint for streaming weather updates from India and USA cities. 
 
    Args: 
        location: Optional city name to filter weather data for a specific city 
    """ 
    return weather_generator(location) 
 
@mcp.tool() 
async def get_cities(): 
    """Get the list of all available cities grouped by country.""" 
    india_cities = "\n".join(f"- {city}" for city in cities["India"]) 
    usa_cities = "\n".join(f"- {city}" for city in cities["USA"]) 
 
    return f"""Cities in India: 
{india_cities} 
 
Cities in USA: 
{usa_cities}""" 
 
if __name__ == "__main__": 
    mcp.run(transport="sse") 
 

2.MCP Server exposes Database SQLite data and FileSystems

import os 
import sqlite3 
from mcp.server.fastmcp import FastMCP 
from mcp.types import ImageContent 
from typing import List, Dict, Optional 
from PIL import Image as PILImage 
from io import BytesIO 
import base64 
 
mcp = FastMCP("Sreeni's File and Friend Management System") 
 
# Initialize SQLite database 
def init_db(): 
    conn = sqlite3.connect('sreeni_friends.db') 
    c = conn.cursor() 
    c.execute(''' 
        CREATE TABLE IF NOT EXISTS SreeniFriend ( 
            id INTEGER PRIMARY KEY AUTOINCREMENT, 
            first_name TEXT NOT NULL, 
            last_name TEXT NOT NULL, 
            email TEXT UNIQUE NOT NULL, 
            phone TEXT, 
            city TEXT, 
            state TEXT, 
            country TEXT 
        ) 
    ''') 
 
    # Insert sample data 
    sample_data = [ 
        ('Pradeep', 'Sethi', 'pradeep.sethi@email.com', '123-456-7890', 'Bangalore', 'Karnataka', 'India'), 
        ('Harithosh', 'Tewari', 'harithosh.tewari@email.com', '987-654-3210', 'Delhi', 'Delhi', 'India'), 
        ('Manohar', 'Reddy', 'manohar.reddy@email.com', '555-123-4567', 'Hyderabad', 'Telangana', 'India'), 
        ('Amith', 'Shah', 'amith.shah@email.com', '444-555-6666', 'Mumbai', 'Maharashtra', 'India'), 
        ('Pankaj', 'Jainani', 'pankaj.jainani@email.com', '777-888-9999', 'Jaipur', 'Rajasthan', 'India'), 
        ('Prodip', 'Shah', 'prodip.shah@email.com', '111-222-3333', 'Kolkata', 'West Bengal', 'India'), 
        ('Subburaj', 'Sundaraj', 'subburaj.sundaraj@email.com', '999-888-7777', 'Chennai', 'Tamil Nadu', 'India'), 
        ('Vinny', 'Davi', 'vinny.davi@email.com', '222-333-4444', 'Chennai', 'Tamil Nadu', 'India'), 
        ('Parthasarathy', 'Gurusamy', 'parthasarathy.g@email.com', '333-444-5555', 'Bangalore', 'Karnataka', 'India'), 
        ('Jayachandran', 'Ramadurai', 'jayachandran.r@email.com', '444-555-6666', 'Chennai', 'Tamil Nadu', 'India') 
    ] 
 
    try: 
        c.executemany(''' 
            INSERT OR IGNORE INTO SreeniFriend  
            (first_name, last_name, email, phone, city, state, country) 
            VALUES (?, ?, ?, ?, ?, ?, ?) 
        ''', sample_data) 
        conn.commit() 
    finally: 
        conn.close() 
 
# Initialize database on startup 
init_db() 
 
@mcp.tool() 
def add_friend(first_name: str, last_name: str, email: str, phone: str = "",  
               city: str = "", state: str = "", country: str = "") -> Dict: 
    """Add a new friend to the database.""" 
    try: 
        conn = sqlite3.connect('sreeni_friends.db') 
        c = conn.cursor() 
        c.execute(''' 
            INSERT INTO SreeniFriend  
            (first_name, last_name, email, phone, city, state, country) 
            VALUES (?, ?, ?, ?, ?, ?, ?) 
        ''', (first_name, last_name, email, phone, city, state, country)) 
        conn.commit() 
        return {"message": "Friend added successfully", "id": c.lastrowid} 
    except sqlite3.IntegrityError: 
        return {"error": "Email already exists"} 
    except Exception as e: 
        return {"error": str(e)} 
    finally: 
        conn.close() 
 
@mcp.tool() 
def get_all_friends() -> List[Dict]: 
    """Get all friends from the database.""" 
    try: 
        conn = sqlite3.connect('sreeni_friends.db') 
        c = conn.cursor() 
        c.execute('SELECT * FROM SreeniFriend') 
        columns = [description[0] for description in c.description] 
        friends = [dict(zip(columns, row)) for row in c.fetchall()] 
        return friends 
    except Exception as e: 
        return {"error": str(e)} 
    finally: 
        conn.close() 
 
@mcp.tool() 
def search_friends(query: str) -> List[Dict]: 
    """Search friends by name, email, city, or country.""" 
    try: 
        conn = sqlite3.connect('sreeni_friends.db') 
        c = conn.cursor() 
        search_query = f"%{query}%" 
        c.execute(''' 
            SELECT * FROM SreeniFriend  
            WHERE first_name LIKE ?  
            OR last_name LIKE ?  
            OR email LIKE ? 
            OR city LIKE ? 
            OR country LIKE ? 
        ''', (search_query, search_query, search_query, search_query, search_query)) 
        columns = [description[0] for description in c.description] 
        friends = [dict(zip(columns, row)) for row in c.fetchall()] 
        return friends 
    except Exception as e: 
        return {"error": str(e)} 
    finally: 
        conn.close() 
 
@mcp.tool() 
def update_friend(email: str, updates: Dict) -> Dict: 
    """Update friend information by email. 
 
    Args: 
        email: Email of the friend to update 
        updates: Dictionary of fields to update 
    """ 
    valid_fields = {'first_name', 'last_name', 'phone', 'city', 'state', 'country'} 
    update_fields = {k: v for k, v in updates.items() if k in valid_fields and v} 
 
    if not update_fields: 
        return {"error": "No valid fields to update"} 
 
    try: 
        conn = sqlite3.connect('sreeni_friends.db') 
        c = conn.cursor() 
 
        set_clause = ', '.join(f"{field} = ?" for field in update_fields) 
        query = f"UPDATE SreeniFriend SET {set_clause} WHERE email = ?" 
 
        values = list(update_fields.values()) + [email] 
        c.execute(query, values) 
        conn.commit() 
 
        if c.rowcount > 0: 
            return {"message": "Friend updated successfully"} 
        return {"error": "Friend not found"} 
    except Exception as e: 
        return {"error": str(e)} 
    finally: 
        conn.close() 
 
@mcp.tool() 
def delete_friend(email: str) -> Dict: 
    """Delete a friend by email.""" 
    try: 
        conn = sqlite3.connect('sreeni_friends.db') 
        c = conn.cursor() 
        c.execute('DELETE FROM SreeniFriend WHERE email = ?', (email,)) 
        conn.commit() 
 
        if c.rowcount > 0: 
            return {"message": "Friend deleted successfully"} 
        return {"error": "Friend not found"} 
    except Exception as e: 
        return {"error": str(e)} 
    finally: 
        conn.close() 
 
@mcp.tool() 
def get_friends_by_country(country: str) -> List[Dict]: 
    """Get all friends from a specific country.""" 
    try: 
        conn = sqlite3.connect('sreeni_friends.db') 
        c = conn.cursor() 
        c.execute('SELECT * FROM SreeniFriend WHERE country = ?', (country,)) 
        columns = [description[0] for description in c.description] 
        friends = [dict(zip(columns, row)) for row in c.fetchall()] 
        return friends 
    except Exception as e: 
        return {"error": str(e)} 
    finally: 
        conn.close() 
 
@mcp.tool() 
def read_file(path: str) -> str: 
    with open(path, "r") as f: 
        return f.read() 
 
 
@mcp.tool() 
def list_files(path: str) -> list[str]: 
    return os.listdir(path) 
 
 
@mcp.tool() 
def create_file(path: str, content: str): 
    with open(path, "w") as f: 
        f.write(content) 
 
@mcp.tool() 
def delete_file(path: str): 
    os.remove(path) 
 
@mcp.tool() 
def rename_file(old_path: str, new_path: str): 
    os.rename(old_path, new_path) 
 
@mcp.resource("config://app") 
def get_config() -> Dict: 
    """Static configuration data""" 
    return { 
        "name": "Sreeni's Friend Management System", 
        "version": "1.0.0", 
        "description": "A system to manage friends and their contact information", 
        "supported_countries": ["India", "USA", "UK"], 
        "max_friends": 1000 
    } 
 
@mcp.resource("users://{user_id}/profile") 
def get_user_profile(user_id: str) -> Dict: 
    """Get user profile from the friends database. 
 
    Args: 
        user_id: Email of the friend to fetch profile for 
 
    Returns: 
        Dict containing the friend's profile information 
    """ 
    try: 
        conn = sqlite3.connect('sreeni_friends.db') 
        c = conn.cursor() 
        c.execute('SELECT * FROM SreeniFriend WHERE email = ?', (user_id,)) 
        columns = [description[0] for description in c.description] 
        row = c.fetchone() 
 
        if row: 
            profile = dict(zip(columns, row)) 
            # Add additional profile information 
            profile.update({ 
                "role": "friend", 
                "permissions": ["view", "contact"], 
                "added_date": "2024-03-20", 
                "status": "active", 
                "connection_type": "direct" 
            }) 
            return profile 
        return { 
            "error": "Profile not found", 
            "user_id": user_id 
        } 
    except Exception as e: 
        return {"error": str(e)} 
    finally: 
        conn.close() 
 
 
@mcp.tool() 
def create_thumbnail(image_path: str) -> ImageContent: 
    """Create a thumbnail from an image""" 
    try: 
        img = PILImage.open(image_path) 
        img.thumbnail((100, 100)) 
        # Convert to PNG bytes using BytesIO 
        img_byte_arr = BytesIO() 
        img.save(img_byte_arr, format='PNG') 
        img_byte_arr = img_byte_arr.getvalue() 
        return ImageContent(type='image', data=base64.b64encode(img_byte_arr).decode('utf-8'), mimeType='image/png') 
    except Exception as e: 
        print(f"Error creating thumbnail: {e}") 
        return ImageContent(type='error', data=str(e), mimeType='text/plain') 
 
 
if __name__ == "__main__": 
    print("Starting MCP server with Friend Management System...") 
    mcp.run(transport="stdio") 
 

3. MCP Custom Client

from  langchain_mcp_adapters.client import MultiServerMCPClient 
from langgraph.prebuilt import create_react_agent 
from langchain_openai import AzureChatOpenAI 
from langchain_core.prompts import ChatPromptTemplate 
from dotenv import load_dotenv 
import asyncio 
import os 
load_dotenv() 
# Azure OpenAI Configuration 
AZURE_OPENAI_ENDPOINT = os.getenv("AZURE_OPENAI_ENDPOINT") 
AZURE_OPENAI_KEY = os.getenv("AZURE_OPENAI_KEY") 
AZURE_OPENAI_DEPLOYMENT = os.getenv("AZURE_OPENAI_DEPLOYMENT", "gpt-4") 
AZURE_OPENAI_MODEL = os.getenv("AZURE_OPENAI_MODEL", "gpt-4") 
AZURE_OPENAI_VERSION = os.getenv("AZURE_OPENAI_VERSION", "2023-05-15") 
 
llm = AzureChatOpenAI( 
                        azure_deployment="gpt-4o-mini", 
                        azure_endpoint=AZURE_OPENAI_ENDPOINT, 
                        api_key=AZURE_OPENAI_KEY, 
                        api_version=AZURE_OPENAI_VERSION, 
                        temperature=0, 
                    ) 
 
async def main(): 
    async with MultiServerMCPClient( 
        { 
            "math": { 
                "command": "python", 
                "args": ["mcpserver.py"], 
                "transport": "stdio", 
            }, 
            "weather": { 
                "url": "http://localhost:5023/sse", 
                "transport": "sse", 
            }, 
            "azure_blob": { 
                "command": "python", 
                "args": ["azure_blob.py"], 
                "transport": "stdio", 
            } 
        } 
    ) as client: 
        try: 
            tools = client.get_tools() 
            agent = create_react_agent( 
                model=llm, 
                tools=tools, 
 
            ) 
 
            print("\nAgent initialized successfully. Type 'exit' to quit.") 
 
            while True: 
                try: 
                    query = input("\nEnter a query: ").strip() 
 
                    if query.lower() == 'exit': 
                        print("Exiting...") 
                        break 
 
                    if not query: 
                        continue 
 
                    result = await agent.ainvoke({ 
                        "messages": [{"role": "user", "content": query}], 
                        "agent_scratchpad": "" 
                    }) 
 
                    for res in result["messages"]: 
                        print(res.pretty_print()) 
 
                    if isinstance(result, dict): 
                        response = result.get('output', str(result)) 
                    else: 
                        response = str(result) 
 
                    print("\nAgent response:") 
                    print(response) 
 
                except KeyboardInterrupt: 
                    print("\nReceived interrupt, shutting down...") 
                    break 
                except Exception as e: 
                    print(f"\nError processing query: {e}") 
 
        except Exception as e: 
            print(f"Error initializing agent: {e}") 
 
if __name__ == "__main__": 
    try: 
        asyncio.run(main()) 
    except KeyboardInterrupt: 
        print("\nShutting down gracefully...") 
 

4.MCP Client & Host Invoking MCPServer and Response or output

(sreenisub) (base) sreenir@Seenivasaragavans-MacBook-Pro sreeni-sup-agent % python multi_server_client.py
Processing request of type ListToolsRequest
Processing request of type ListToolsRequest

Agent initialized successfully. Type 'exit' to quit.

Enter a query: List all friends
Processing request of type CallToolRequest
================================ Human Message =================================

List all friends
None
================================== Ai Message ==================================
Tool Calls:
get_all_friends (call_xHe7eeKgZXPhUon9k6n0mHRH)
Call ID: call_xHe7eeKgZXPhUon9k6n0mHRH
Args:
None
================================= Tool Message =================================
Name: get_all_friends

["{\"id\": 1, \"first_name\": \"Pradeep\", \"last_name\": \"Sethi\", \"email\": \"pradeep.sethi@email.com\", \"phone\": \"123-456-7890\", \"city\": \"Boston\", \"state\": \"MA\", \"country\": \"USA\"}", "{\"id\": 2, \"first_name\": \"Harithosh\", \"last_name\": \"Tewari\", \"email\": \"harithosh.tewari@email.com\", \"phone\": \"987-654-3210\", \"city\": \"Delhi\", \"state\": \"Delhi\", \"country\": \"India\"}", "{\"id\": 3, \"first_name\": \"Manohar\", \"last_name\": \"Reddy\", \"email\": \"manohar.reddy@email.com\", \"phone\": \"555-123-4567\", \"city\": \"Hyderabad\", \"state\": \"Telangana\", \"country\": \"India\"}", "{\"id\": 4, \"first_name\": \"Amith\", \"last_name\": \"Shah\", \"email\": \"amith.shah@email.com\", \"phone\": \"444-555-6666\", \"city\": \"Mumbai\", \"state\": \"Maharashtra\", \"country\": \"India\"}", "{\"id\": 5, \"first_name\": \"Pankaj\", \"last_name\": \"Jainani\", \"email\": \"pankaj.jainani@email.com\", \"phone\": \"777-888-9999\", \"city\": \"Jaipur\", \"state\": \"Rajasthan\", \"country\": \"India\"}", "{\"id\": 6, \"first_name\": \"Prodip\", \"last_name\": \"Shah\", \"email\": \"prodip.shah@email.com\", \"phone\": \"111-222-3333\", \"city\": \"Kolkata\", \"state\": \"West Bengal\", \"country\": \"India\"}", "{\"id\": 7, \"first_name\": \"Subburaj\", \"last_name\": \"Sundaraj\", \"email\": \"subburaj.sundaraj@email.com\", \"phone\": \"999-888-7777\", \"city\": \"Chennai\", \"state\": \"Tamil Nadu\", \"country\": \"India\"}", "{\"id\": 688, \"first_name\": \"Vinny\", \"last_name\": \"Davi\", \"email\": \"vinny.davi@email.com\", \"phone\": \"222-333-4444\", \"city\": \"Chennai\", \"state\": \"Tamil Nadu\", \"country\": \"India\"}", "{\"id\": 689, \"first_name\": \"Parthasarathy\", \"last_name\": \"Gurusamy\", \"email\": \"parthasarathy.g@email.com\", \"phone\": \"333-444-5555\", \"city\": \"Bangalore\", \"state\": \"Karnataka\", \"country\": \"India\"}", "{\"id\": 690, \"first_name\": \"Jayachandran\", \"last_name\": \"Ramadurai\", \"email\": \"jayachandran.r@email.com\", \"phone\": \"444-555-6666\", \"city\": \"Chennai\", \"state\": \"Tamil Nadu\", \"country\": \"India\"}"]
None
================================== Ai Message ==================================

Here is the list of all friends:

  1. Pradeep Sethi

  2. Harithosh Tewari

  3. Manohar Reddy

  4. Amith Shah

  5. Pankaj Jainani

  6. Prodip Shah

  7. Subburaj Sundaraj

  8. Vinny Davi

  9. Parthasarathy Gurusamy

  10. Jayachandran Ramadurai

Agent response:
{'messages': [HumanMessage(content='List all friends', additional_kwargs={}, response_metadata={}, id='b43aad44-1b02-4c4e-8d5d-4302cc96274e'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_xHe7eeKgZXPhUon9k6n0mHRH', 'function': {'arguments': '{}', 'name': 'get_all_friends'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 12, 'prompt_tokens': 428, 'total_tokens': 440, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_ded0d14823', 'fin