🖍️
Developer Note
  • Welcome
  • Git
    • Eslint & Prettier & Stylelint & Husky
  • Programming Language
    • JavaScript
      • Script Async vs Defer
      • Module
      • Const VS Let VS Var
      • Promise
      • Event Loop
      • Execution Context
      • Hoisting
      • Closure
      • Event Buddling and Capturing
      • Garbage Collection
      • This
      • Routing
      • Debounce and Throttle
      • Web Component
      • Iterator
      • Syntax
      • String
      • Array
      • Object
      • Proxy & Reflect
      • ProtoType
      • Class
      • Immutability
      • Typeof & Instanceof
      • Npm (Node package manager)
    • TypeScript
      • Utility Type
      • Type vs Interface
      • Any vs Unknown vs Never
      • Void and undefined
      • Strict Mode
      • Namespace
      • Enum
      • Module
      • Generic
    • Python
      • Local Development
      • Uv
      • Asyncio & Event loop
      • Context Manager
      • Iterator & Generator
      • Fast API
      • Pydantic & Data Class
    • Java
      • Compilation and Execution
      • Data Type
      • Enumeration
      • Data Structure
      • Try Catch
      • InputStream and OutputStream
      • Concurrent
      • Unicode Block
      • Build Tools
      • Servlet
      • Java 8
  • Coding Pattern
    • MVC vs MVVM
    • OOP vs Functional
    • Error Handling
    • MVC vs Flux
    • Imperative vs Declarative
    • Design Pattern
  • Web Communication
    • REST API
      • Web Hook
      • CORS issue
    • HTTPS
    • GraphQL
      • REST API vs GraphQL
      • Implementation (NodeJS + React)
    • Server-Sent Event
    • Web Socket
    • IP
    • Domain Name System (DNS)
  • Frontend
    • Progressive Web App (PWA)
    • Single Page & Multiple Page Application
    • Search Engine Optimiaztion (SEO)
    • Web bundling & Micro-frontend
      • Webpack
        • Using Webpack to build React Application
        • Using Webpack to build react library
      • Vite
      • Using rollup to build react library
      • Implementing micro frontend
    • Web Security
      • CSRF & Nonce
      • XSS
      • Click hijacking
    • Cypress
    • CSS
      • Core
        • Box Model
        • Inline vs Block
        • Flexbox & Grid
        • Pseudo Class
        • Position
      • Tailwind CSS
        • Shadcn
      • CSS In JS
        • Material UI
    • React
      • Core
        • Component Pattern
        • React Lazy & Suspense
        • React Portal
        • Error Boundary
        • Rendering Methods
        • Environment Variable
        • Conditional CSS
        • Memo
        • Forward Reference
        • High Order Component (HOC) & Custom Hook
        • TypeScript
      • State Management
        • Redux
        • Recoil
        • Zustand
      • Routing
        • React Router Dom
      • Data Fetching
        • Axios & Hook
        • React Query
        • Orval
      • Table
        • React Table
      • Form & Validation
        • React Hook Form
        • Zod
      • NextJS
        • Page Router
        • App Router
      • React Native
    • Angular
    • Svelte
      • Svelte Kit
  • Backend
    • Cache
      • Browser Cache
      • Web Browser Storage
      • Proxy
      • Redis
    • Rate limit
    • Load Test
    • Encryption
    • Authentication
      • Password Protection
      • Cookie & Session
      • JSON Web Token
      • SSO
        • OAuth 2.0
        • OpenID Connect (OIDC)
        • SAML
    • Payment
      • Pre-built
      • Custom
    • File Handling
      • Upload & Download (Front-end)
      • Stream & Buffer
    • Microservice
      • API Gateway
      • Service Discovery
      • Load Balancer
      • Circuit Breaker
      • Message Broker
      • BulkHead & Zipkin
    • Elastic Search
    • Database
      • SQL
        • Group By vs Distinct
        • Index
        • N + 1 problem
        • Normalization
        • Foreign Key
        • Relationship
        • Union & Join
        • User Defined Type
      • NOSQL (MongoDB)
      • Transaction
      • Sharding
      • Lock (Concurrency Control)
    • NodeJS
      • NodeJS vs Java Spring
      • ExpressJS
      • NestJS
        • Swagger
        • Class Validator & Validation Pipe
        • Passport (Authentication)
      • Path Module
      • Database Connection
        • Integrating with MYSQL
        • Sequalize
        • Integrating with MongoDB
        • Prisma
        • MikroORM
        • Mongoose
      • Streaming
      • Worker Thread
      • Passport JS
      • JSON Web Token
      • Socket IO
      • Bull MQ
      • Pino (Logging)
      • Yeoman
    • Spring
      • Spring MVC
      • Spring REST
      • Spring Actuator
      • Aspect Oriented Programming (AOP)
      • Controller Advice
      • Filter
      • Interceptor
      • Concurrent
      • Spring Security
      • Spring Boot
      • Spring Cloud
        • Resilience 4j
      • Quartz vs Spring Batch
      • JPA and Hibernate
      • HATEOS
      • Swagger
      • Unit Test (Java Spring)
      • Unit Test (Spring boot)
  • DevOp
    • Docker
    • Kubernetes
      • Helm
    • Nginx
    • Observability
      • Logging
        • Loki
        • PLG Setup
      • Distributed Tracing
        • OpenTelemetry
        • Tempo
    • File System
    • Cloud
      • AWS
        • EC2 (Virtual Machine)
        • Network
        • IAM
          • Role-Service Binding
        • Database
        • Route 53
        • S3
        • Message Queue
        • Application Service
        • Serverless Framework
        • Data Analysis
        • Machine Learning
        • Monitoring
        • Security
      • Azure
        • Identity
        • Compute Resource
        • Networking
        • Storage
        • Monitoring
      • Google Cloud
        • IAM
          • Workload Identity Federation
        • Compute Engine
        • VPC Network
        • Storage
        • Kubernetes Engine
        • App Engine
        • Cloud function
        • Cloud Run
        • Infra as Code
        • Pub/Sub
    • Deployment Strategy
    • Jenkins
    • Examples
      • Deploy NextJS on GCP
      • Deploy Spring on Azure
      • Deploy React on Azure
  • Domain Knowledge
    • Web 3
      • Blockchain
      • Cryptocurrency
    • AI
      • Prompt
      • Chain & Agent
      • MCP
      • LangChain
      • Chunking
      • Search
      • Side Products
      • Crawl4AI
Powered by GitBook
On this page
  • Introduction
  • Stdio
  • Server
  • Client
  • SSE Server
  • Server
  • Client
  • References

Was this helpful?

  1. Domain Knowledge
  2. AI

MCP

PreviousChain & AgentNextLangChain

Last updated 10 days ago

Was this helpful?

Introduction

  • MCP is an open protocol that standardizes how applications provide context to LLMs

  • MCP provides a standardized way to connect AI models to different data sources and tools.

Stdio

  • STDIO (Standard Input/Output) Transport is primarily used for inter-process communication within the same system. It allows a client application to send data to a server application through the standard input and receive responses via the standard output streams.

Server

server.py
from dataclasses import asdict, dataclass
import aiohttp
from mcp.server.fastmcp import FastMCP
from mcp.server.sse import SseServerTransport
from mcp.server import Server
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.routing import Mount, Route


# Create the MCP server
mcp = FastMCP("SSE")

@dataclass
class DisplayName:
    text: str
    languageCode: str

@dataclass
class Restaurant:
    id: str
    displayName: DisplayName
    rating: int
    primaryTypeDisplayName: str
    

@dataclass
class Location:
    latitude: float
    longitude: float
 
async def get_latitude_longitude(location_name):
    # Define the endpoint URL
    endpoint = "https://maps.googleapis.com/maps/api/geocode/json"
    
    # Set up the parameters for the request
    params = {
        'address': location_name,
        'key': "AIzaSyBUguvUNCxqha21BhH6r3bOcF48ckoxTz8"
    }
    async with aiohttp.ClientSession() as session:
        async with session.get(endpoint, params=params) as response:
            data = await response.json()
            
            # Check if the request was successful
            if data['status'] == 'OK':
                # Extract latitude and longitude
                latitude = data['results'][0]['geometry']['location']['lat']
                longitude = data['results'][0]['geometry']['location']['lng']
                return Location(latitude=latitude, longitude=longitude)
            else:
                return None    
    

async def get_restaurants(max_result_count: int , location_info: Location):
    url='https://places.googleapis.com/v1/places:searchNearby'
    request_body = {
                "languageCode": "zh-HK",
                "regionCode": "HK",
                "includedTypes": ["restaurant"],
                "maxResultCount": max_result_count,
                "locationRestriction": {
                    "circle": {
                        "center": {
                            "latitude": location_info.latitude,
                            "longitude": location_info.longitude
                        },
                        "radius": 500.0
                    }                   
                }}
    if max_result_count > 20:
        request_body.pop('maxResultCount')
    async with aiohttp.ClientSession() as session:
        resp = await session.post(url,
            json=request_body,
            headers={
                "Content-Type": "application/json",
                "X-Goog-Api-Key": "AIzaSyBUguvUNCxqha21BhH6r3bOcF48ckoxTz8",
                "X-Goog-FieldMask": "places.id,places.displayName,places.rating,places.primaryTypeDisplayName"
            }
        )
        res = await resp.json()
        restaurants = []
        if(res.get('places')):
            restaurants = [ Restaurant(**restaurant) for restaurant in res.get('places')]
        else:
            print(res)
        return restaurants

@mcp.tool()
async def get_restaurant_list(location: str, result_count: int) -> list:
    """Get the list of restaurant
    Args:
        location: The location of the restaurant (e.g: Kwun tong)
        result_count: The number of restaurants to return, default is 10, if user want more restaurant, increase 10, if user want all the restaurants, set to 100
    """
    print(f"location: {location}, result_count: {result_count}")
    location_info = await get_latitude_longitude(location)
    if(location_info is None):
        print("Location not found")
        return []
    restaurants = await get_restaurants(max_result_count=result_count, location_info=location_info)
    return [asdict(restaurant) for restaurant in restaurants] 

if __name__ == "__main__":
    mcp.run(transport='stdio')

Client

# Create server parameters for stdio connection
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langchain_mcp_adapters.client import MultiServerMCPClient

from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import MemorySaver



model = ChatOpenAI(
    model="anthropic/claude-3.5-sonnet", 
    base_url="https://openrouter.ai/api/v1",
    api_key="xxxx"
)
server_params = StdioServerParameters(
    command="python",
    # Make sure to update to the full absolute path to your math_server.py file
    args=["server.py"],
)



async def main():
    tools = []
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            # Initialize the connection
            await session.initialize()
            # Get tools
            tools = await load_mcp_tools(session)
            print("tools:", tools)
            
if __name__ == "__main__":  
    asyncio.run(main())
mcp.json
{
    "mcpServers": {
        "Demo": {
            "command": "uv",
            "args": [
                "--directory",
                "/Users/petercheng/Desktop/my-mcp-server",
                "run",
                "server.py"
            ]
        }
    }
}

SSE Server

  • ​Server-Sent Events (SSE) is a technology that enables servers to push real-time updates to web clients over a single, long-lived HTTP connection. This allows for efficient, one-way communication from the server to the client, making it suitable for applications that require real-time data updates

Server

from dataclasses import asdict, dataclass
import aiohttp
from mcp.server.fastmcp import FastMCP
from mcp.server.sse import SseServerTransport
from mcp.server import Server
from starlette.applications import Starlette
from starlette.requests import Request
from starlette.routing import Mount, Route
import uvicorn

# Create the MCP server
mcp = FastMCP("SSE")

@dataclass
class DisplayName:
    text: str
    languageCode: str

@dataclass
class Restaurant:
    id: str
    displayName: DisplayName
    rating: int
    primaryTypeDisplayName: str
    

@dataclass
class Location:
    latitude: float
    longitude: float
 
async def get_latitude_longitude(location_name):
    # Define the endpoint URL
    endpoint = "https://maps.googleapis.com/maps/api/geocode/json"
    
    # Set up the parameters for the request
    params = {
        'address': location_name,
        'key': "AIzaSyBUguvUNCxqha21BhH6r3bOcF48ckoxTz8"
    }
    async with aiohttp.ClientSession() as session:
        async with session.get(endpoint, params=params) as response:
            data = await response.json()
            
            # Check if the request was successful
            if data['status'] == 'OK':
                # Extract latitude and longitude
                latitude = data['results'][0]['geometry']['location']['lat']
                longitude = data['results'][0]['geometry']['location']['lng']
                return Location(latitude=latitude, longitude=longitude)
            else:
                return None    
    

async def get_restaurants(max_result_count: int , location_info: Location):
    url='https://places.googleapis.com/v1/places:searchNearby'
    request_body = {
                "languageCode": "zh-HK",
                "regionCode": "HK",
                "includedTypes": ["restaurant"],
                "maxResultCount": max_result_count,
                "locationRestriction": {
                    "circle": {
                        "center": {
                            "latitude": location_info.latitude,
                            "longitude": location_info.longitude
                        },
                        "radius": 500.0
                    }                   
                }}
    if max_result_count > 20:
        request_body.pop('maxResultCount')
    async with aiohttp.ClientSession() as session:
        resp = await session.post(url,
            json=request_body,
            headers={
                "Content-Type": "application/json",
                "X-Goog-Api-Key": "AIzaSyBUguvUNCxqha21BhH6r3bOcF48ckoxTz8",
                "X-Goog-FieldMask": "places.id,places.displayName,places.rating,places.primaryTypeDisplayName"
            }
        )
        res = await resp.json()
        restaurants = []
        if(res.get('places')):
            restaurants = [ Restaurant(**restaurant) for restaurant in res.get('places')]
        else:
            print(res)
        return restaurants

@mcp.tool()
async def get_restaurant_list(location: str, result_count: int) -> list:
    """Get the list of restaurant
    Args:
        location: The location of the restaurant (e.g: Kwun tong)
        result_count: The number of restaurants to return, default is 10, if user want more restaurant, increase 10, if user want all the restaurants, set to 100
    """
    print(f"location: {location}, result_count: {result_count}")
    location_info = await get_latitude_longitude(location)
    if(location_info is None):
        print("Location not found")
        return []
    restaurants = await get_restaurants(max_result_count=result_count, location_info=location_info)
    return [asdict(restaurant) for restaurant in restaurants] 



def create_starlette_app(mcp_server: Server, *, debug: bool = False) -> Starlette:
    """Create a Starlette application that can serve the MCP server with SSE."""
    sse = SseServerTransport("/messages/")

    async def handle_sse(request: Request) -> None:
        async with sse.connect_sse(
                request.scope,
                request.receive,
                request._send,
        ) as (read_stream, write_stream):
            await mcp_server.run(
                read_stream,
                write_stream,
                mcp_server.create_initialization_options(),
            )

    return Starlette(
        debug=debug,
        routes=[
            Route("/sse", endpoint=handle_sse),
            Mount("/messages/", app=sse.handle_post_message),
        ],
    )

if __name__ == "__main__":
    # # Get the underlying MCP server
    mcp_server = mcp._mcp_server
    # Create Starlette app with SSE support
    starlette_app = create_starlette_app(mcp_server, debug=True)
    port = 8080
    print(f"Starting MCP server with SSE transport on port {port}...")
    print(f"SSE endpoint available at: http://localhost:{port}/sse")
    # Run the server using uvicorn
    uvicorn.run(starlette_app, host="0.0.0.0", port=port)

Client

# Create server parameters for stdio connection
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langchain_mcp_adapters.client import MultiServerMCPClient

from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import MemorySaver



model = ChatOpenAI(
    model="anthropic/claude-3.5-sonnet", 
    base_url="https://openrouter.ai/api/v1",
    api_key="xxxx"
)
server_params = StdioServerParameters(
    command="python",
    # Make sure to update to the full absolute path to your math_server.py file
    args=["server.py"],
)
async def main():
    tools = []
    async with MultiServerMCPClient(
        {
            "demo": {
                # make sure you start your weather server on port 8000
                "url": "http://0.0.0.0:8080/sse",
                "transport": "sse",
            }
        }
    ) as client:
        tools = client.get_tools()
        print("tools:", tools)
mcp.json
{
    "mcpServers": {
        "server-name": {
            "url": "http://0.0.0.0:8080/sse"
        }
    }
}

References

MCP Clients : Stdio vs SSEMedium
Introduction - Model Context ProtocolModel Context Protocol
Logo
Logo