12 MCP Servers的介绍

MCP(模型上下文协议)是一项开放标准,简化了AI模型(特别是大语言模型LLMs)与外部数据源、工具和服务之间的交互方式。MCP服务器充当这些AI模型与外部工具之间的桥梁。以下是一些主流的MCP服务器:

image

文件系统MCP服务器

允许大语言模型直接访问本地文件系统,进行读取、写入和创建目录等操作。

GitHub MCP服务器

将Claude连接到GitHub仓库,支持文件更新和代码搜索功能。

Slack MCP服务器

用于Slack API的MCP服务器,使Claude能够与Slack工作区进行交互。

Google Maps MCP服务器

用于Google Maps API的MCP服务器。

Docker MCP服务器

与Docker集成,用于管理容器、镜像、卷和网络。

Brave MCP服务器

使用Brave的搜索API实现网页和本地搜索功能。

PostgreSQL MCP服务器

一种MCP服务器,使大语言模型能够查看数据库结构并执行只读查询。

Google Drive MCP服务器

与Google Drive集成的MCP服务器,支持对文件进行读取和搜索。

Redis MCP服务器

提供对Redis数据库访问的MCP服务器。

Notion MCP服务器

该项目实现了针对Notion API的MCP服务器。

Stripe MCP服务器

用于与Stripe API交互的MCP服务器。

Perplexity MCP服务器

连接到Perplexity的Sonar API以实现实时搜索的MCP服务器。

MCP服务器代码示例

根据搜索结果,Model Context Protocol (MCP) 是一套允许大语言模型与外部系统交互的协议实现。以下是对您请求的各类MCP服务器的详细代码示例:

1. 文件系统MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import os
import json

app = FastAPI(title="File System MCP Server")

class FileSystemRequest(BaseModel):
    operation: str  # read, write, mkdir, list
    path: str
    content: str = None

@app.post("/tool_call")
async def tool_call(request: FileSystemRequest):
    """处理文件系统操作请求"""
    try:
        if request.operation == "read":
            if not os.path.exists(request.path):
                raise HTTPException(status_code=404, detail="File not found")
            with open(request.path, 'r') as f:
                content = f.read()
            return {"status": "success", "content": content}
            
        elif request.operation == "write":
            os.makedirs(os.path.dirname(os.path.abspath(request.path)), exist_ok=True)
            with open(request.path, 'w') as f:
                f.write(request.content)
            return {"status": "success", "message": f"File written to {request.path}"}
            
        elif request.operation == "mkdir":
            os.makedirs(request.path, exist_ok=True)
            return {"status": "success", "message": f"Directory created at {request.path}"}
            
        elif request.operation == "list":
            if not os.path.exists(request.path):
                raise HTTPException(status_code=404, detail="Directory not found")
            items = os.listdir(request.path)
            return {"status": "success", "items": items}
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "file_system",
                "description": "Access and manipulate the local file system",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (read, write, mkdir, list)"},
                    "path": {"type": "string", "description": "File or directory path"},
                    "content": {"type": "string", "description": "Content for write operations (optional)"}
                }
            }
        ]
    }

这是一个基础的文件系统MCP服务器实现,允许大语言模型安全地执行基本文件操作。

2. GitHub MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import os
from github import Github

app = FastAPI(title="GitHub MCP Server")

class GitHubRequest(BaseModel):
    operation: str  # get_repo, search_code, update_file
    repo: str
    path: str = None
    content: str = None
    commit_message: str = "Update via MCP"

def get_github_client():
    token = os.getenv("GITHUB_TOKEN")
    if not token:
        raise HTTPException(status_code=401, detail="GitHub token not configured")
    return Github(token)

@app.post("/tool_call")
async def tool_call(request: GitHubRequest, gh: Github = Depends(get_github_client)):
    """处理GitHub操作请求"""
    try:
        repo = gh.get_repo(request.repo)
        
        if request.operation == "get_repo":
            return {
                "name": repo.name,
                "description": repo.description,
                "stars": repo.stargazers_count,
                "forks": repo.forks_count
            }
            
        elif request.operation == "search_code":
            results = repo.search_code(request.path)  # path used as query here
            return [{"path": item.path, "sha": item.sha} for item in results]
            
        elif request.operation == "update_file":
            if not request.path or not request.content:
                raise HTTPException(status_code=400, detail="Path and content required for update")
                
            contents = repo.get_contents(request.path)
            repo.update_file(
                request.path,
                request.commit_message,
                request.content,
                contents.sha
            )
            return {"status": "success", "message": f"Updated {request.path}"}
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "github",
                "description": "Interact with GitHub repositories",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (get_repo, search_code, update_file)"},
                    "repo": {"type": "string", "description": "Repository name (owner/repo)"},
                    "path": {"type": "string", "description": "File path or search query"},
                    "content": {"type": "string", "description": "Content for file updates"},
                    "commit_message": {"type": "string", "description": "Commit message for updates"}
                }
            }
        ]
    }

这个GitHub MCP服务器实现了基本的仓库信息获取、代码搜索和文件更新功能,使Claude能够与GitHub仓库进行交互。

3. Slack MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError

app = FastAPI(title="Slack MCP Server")

class SlackRequest(BaseModel):
    operation: str  # send_message, get_channels, get_messages
    channel: str = None
    message: str = None
    limit: int = 10

def get_slack_client():
    token = os.getenv("SLACK_BOT_TOKEN")
    if not token:
        raise HTTPException(status_code=401, detail="Slack token not configured")
    return WebClient(token=token)

@app.post("/tool_call")
async def tool_call(request: SlackRequest, slack: WebClient = Depends(get_slack_client)):
    """处理Slack操作请求"""
    try:
        if request.operation == "send_message":
            if not request.channel or not request.message:
                raise HTTPException(status_code=400, detail="Channel and message required")
                
            response = slack.chat_postMessage(
                channel=request.channel,
                text=request.message
            )
            return {"status": "success", "ts": response["ts"]}
            
        elif request.operation == "get_channels":
            response = slack.conversations_list()
            return [{"id": c["id"], "name": c["name"], "is_channel": c["is_channel"]} 
                   for c in response["channels"]]
            
        elif request.operation == "get_messages":
            if not request.channel:
                raise HTTPException(status_code=400, detail="Channel required")
                
            response = slack.conversations_history(
                channel=request.channel,
                limit=request.limit
            )
            return [{
                "user": m["user"],
                "text": m["text"],
                "ts": m["ts"]
            } for m in response["messages"]]
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except SlackApiError as e:
        raise HTTPException(status_code=400, detail=f"Slack API error: {e.response['error']}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "slack",
                "description": "Interact with Slack workspace",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (send_message, get_channels, get_messages)"},
                    "channel": {"type": "string", "description": "Slack channel ID or name"},
                    "message": {"type": "string", "description": "Message content to send"},
                    "limit": {"type": "integer", "description": "Number of messages to retrieve (for get_messages)"}
                }
            }
        ]
    }

这个Slack MCP服务器实现了与Slack工作区的基本交互功能,使AI模型能够发送消息、获取频道列表和读取消息历史。

4. Google Maps MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import os
import googlemaps
from datetime import datetime

app = FastAPI(title="Google Maps MCP Server")

class MapsRequest(BaseModel):
    operation: str  # directions, geocode, places
    origin: str = None
    destination: str = None
    address: str = None
    query: str = None
    location: str = None  # lat,lng

def get_gmaps_client():
    api_key = os.getenv("GOOGLE_MAPS_API_KEY")
    if not api_key:
        raise HTTPException(status_code=401, detail="Google Maps API key not configured")
    return googlemaps.Client(key=api_key)

@app.post("/tool_call")
async def tool_call(request: MapsRequest, gmaps: googlemaps.Client = Depends(get_gmaps_client)):
    """处理Google Maps操作请求"""
    try:
        if request.operation == "directions":
            if not request.origin or not request.destination:
                raise HTTPException(status_code=400, detail="Origin and destination required")
                
            now = datetime.now()
            directions_result = gmaps.directions(
                request.origin,
                request.destination,
                mode="driving",
                departure_time=now
            )
            
            # 简化返回结果
            return {
                "status": "success",
                "routes": [{
                    "summary": route["summary"],
                    "distance": route["legs"][0]["distance"]["text"],
                    "duration": route["legs"][0]["duration"]["text"],
                    "steps": [{
                        "html_instructions": step["html_instructions"],
                        "distance": step["distance"]["text"],
                        "duration": step["duration"]["text"]
                    } for step in route["legs"][0]["steps"]]
                } for route in directions_result]
            }
            
        elif request.operation == "geocode":
            if not request.address:
                raise HTTPException(status_code=400, detail="Address required")
                
            geocode_result = gmaps.geocode(request.address)
            return {
                "status": "success",
                "results": [{
                    "formatted_address": result["formatted_address"],
                    "location": result["geometry"]["location"],
                    "types": result["types"]
                } for result in geocode_result]
            }
            
        elif request.operation == "places":
            if not request.query or not request.location:
                raise HTTPException(status_code=400, detail="Query and location required")
                
            places_result = gmaps.places(
                query=request.query,
                location=request.location,
                radius=1000
            )
            
            return {
                "status": "success",
                "results": [{
                    "name": place["name"],
                    "formatted_address": place.get("formatted_address"),
                    "rating": place.get("rating"),
                    "geometry": place["geometry"]["location"]
                } for place in places_result["results"]]
            }
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "google_maps",
                "description": "Access Google Maps routing, geocoding, and places data",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (directions, geocode, places)"},
                    "origin": {"type": "string", "description": "Starting point for directions"},
                    "destination": {"type": "string", "description": "Destination for directions"},
                    "address": {"type": "string", "description": "Address to geocode"},
                    "query": {"type": "string", "description": "Search query for places"},
                    "location": {"type": "string", "description": "Location for places search (lat,lng)"}
                }
            }
        ]
    }

这个Google Maps MCP服务器提供了路线规划、地理编码和地点搜索功能,为AI模型提供地图和位置数据支持。

5. Docker MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import docker
from typing import List, Dict, Any

app = FastAPI(title="Docker MCP Server")

class DockerRequest(BaseModel):
    operation: str  # list_containers, run_container, stop_container, list_images
    image: str = None
    command: str = None
    container_id: str = None
    name: str = None
    environment: Dict[str, str] = None
    volumes: List[str] = None
    ports: Dict[str, int] = None

def get_docker_client():
    try:
        return docker.from_env()
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Could not connect to Docker: {str(e)}")

@app.post("/tool_call")
async def tool_call(request: DockerRequest, client: docker.DockerClient = Depends(get_docker_client)):
    """处理Docker操作请求"""
    try:
        if request.operation == "list_containers":
            containers = client.containers.list(all=True)
            return {
                "status": "success",
                "containers": [{
                    "id": c.id[:12],
                    "name": c.name,
                    "status": c.status,
                    "image": c.image.tags[0] if c.image.tags else str(c.image.id)
                } for c in containers]
            }
            
        elif request.operation == "run_container":
            if not request.image:
                raise HTTPException(status_code=400, detail="Image name required")
                
            container = client.containers.run(
                image=request.image,
                command=request.command,
                name=request.name,
                environment=request.environment,
                volumes=request.volumes,
                ports=request.ports,
                detach=True
            )
            return {
                "status": "success",
                "container_id": container.id[:12],
                "message": f"Container started with ID {container.id[:12]}"
            }
            
        elif request.operation == "stop_container":
            if not request.container_id:
                raise HTTPException(status_code=400, detail="Container ID required")
                
            try:
                container = client.containers.get(request.container_id)
                container.stop()
                return {
                    "status": "success",
                    "message": f"Container {request.container_id} stopped"
                }
            except docker.errors.NotFound:
                raise HTTPException(status_code=404, detail="Container not found")
                
        elif request.operation == "list_images":
            images = client.images.list()
            return {
                "status": "success",
                "images": [{
                    "id": i.id[:20],
                    "tags": i.tags,
                    "created": i.attrs['Created'],
                    "size": f"{i.attrs['Size'] / 1024 / 1024:.2f} MB"
                } for i in images]
            }
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except docker.errors.APIError as e:
        raise HTTPException(status_code=400, detail=f"Docker API error: {e.explanation}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "docker",
                "description": "Manage Docker containers, images, and networks",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (list_containers, run_container, stop_container, list_images)"},
                    "image": {"type": "string", "description": "Docker image name"},
                    "command": {"type": "string", "description": "Command to run in container"},
                    "container_id": {"type": "string", "description": "Container ID for operations"},
                    "name": {"type": "string", "description": "Name for new container"},
                    "environment": {"type": "object", "description": "Environment variables"},
                    "volumes": {"type": "array", "description": "Volume mappings"},
                    "ports": {"type": "object", "description": "Port mappings"}
                }
            }
        ]
    }

这个Docker MCP服务器实现了容器、镜像和网络的基本管理功能,使大语言模型能够与Docker环境进行交互。

6. Brave MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import os
import requests

app = FastAPI(title="Brave Search MCP Server")

class BraveRequest(BaseModel):
    operation: str  # search, news
    query: str
    count: int = 10
    country: str = "US"
    language: str = "en"

def get_brave_api_key():
    api_key = os.getenv("BRAVE_API_KEY")
    if not api_key:
        raise HTTPException(status_code=401, detail="Brave API key not configured")
    return api_key

@app.post("/tool_call")
async def tool_call(request: BraveRequest, api_key: str = Depends(get_brave_api_key)):
    """处理Brave搜索操作请求"""
    try:
        headers = {
            "Accept": "application/json",
            "X-Subscription-Token": api_key
        }
        
        if request.operation == "search":
            url = "https://api.search.brave.com/res/v1/web/search"
            params = {
                "q": request.query,
                "count": request.count,
                "country": request.country,
                "language": request.language
            }
            
            response = requests.get(url, headers=headers, params=params)
            response.raise_for_status()
            data = response.json()
            
            # 简化结果
            results = []
            for result in data.get("web", {}).get("results", []):
                results.append({
                    "title": result["title"],
                    "url": result["url"],
                    "description": result["description"],
                    "domain": result["domain"]
                })
                
            return {"status": "success", "results": results}
            
        elif request.operation == "news":
            url = "https://api.search.brave.com/res/v1/news/search"
            params = {
                "q": request.query,
                "count": request.count,
                "country": request.country,
                "language": request.language
            }
            
            response = requests.get(url, headers=headers, params=params)
            response.raise_for_status()
            data = response.json()
            
            # 简化结果
            results = []
            for result in data.get("news", {}).get("results", []):
                results.append({
                    "title": result["title"],
                    "url": result["url"],
                    "description": result["description"],
                    "source": result["source"]["name"],
                    "published": result["published"]
                })
                
            return {"status": "success", "results": results}
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except requests.exceptions.RequestException as e:
        raise HTTPException(status_code=500, detail=f"Request failed: {str(e)}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "brave_search",
                "description": "Use Brave Search API for web and news search",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (search, news)"},
                    "query": {"type": "string", "description": "Search query"},
                    "count": {"type": "integer", "description": "Number of results to return"},
                    "country": {"type": "string", "description": "Country code for results"},
                    "language": {"type": "string", "description": "Language code for results"}
                }
            }
        ]
    }

这个Brave MCP服务器实现了使用Brave搜索API进行网页和新闻搜索的功能,为AI模型提供实时搜索能力。

7. PostgreSQL MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import os
import psycopg2
from psycopg2 import sql
from typing import List, Dict, Any

app = FastAPI(title="PostgreSQL MCP Server")

class PostgresRequest(BaseModel):
    operation: str  # describe, query
    query: str = None
    params: List[Any] = None

def get_db_connection():
    conn_str = os.getenv("DATABASE_URL")
    if not conn_str:
        raise HTTPException(status_code=401, detail="Database connection string not configured")
    try:
        return psycopg2.connect(conn_str)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Database connection failed: {str(e)}")

@app.post("/tool_call")
async def tool_call(request: PostgresRequest, conn=Depends(get_db_connection)):
    """处理PostgreSQL操作请求"""
    try:
        if request.operation == "describe":
            with conn.cursor() as cur:
                # 获取所有表
                cur.execute("""
                    SELECT table_name 
                    FROM information_schema.tables 
                    WHERE table_schema = 'public'
                """)
                tables = [row[0] for row in cur.fetchall()]
                
                # 获取每个表的结构
                table_info = {}
                for table in tables:
                    cur.execute(sql.SQL("""
                        SELECT column_name, data_type, is_nullable 
                        FROM information_schema.columns 
                        WHERE table_name = %s
                    """), [table])
                    columns = [{
                        "name": row[0],
                        "type": row[1],
                        "nullable": row[2] == "YES"
                    } for row in cur.fetchall()]
                    table_info[table] = columns
                
                return {"status": "success", "schema": table_info}
                
        elif request.operation == "query":
            if not request.query:
                raise HTTPException(status_code=400, detail="Query required")
                
            # 确保是只读查询
            if not request.query.strip().lower().startswith(("select", "explain", "with")):
                raise HTTPException(status_code=403, detail="Only read-only queries are allowed")
                
            with conn.cursor() as cur:
                cur.execute(request.query, request.params or ())
                columns = [desc[0] for desc in cur.description]
                rows = [dict(zip(columns, row)) for row in cur.fetchall()]
                
                return {"status": "success", "results": rows, "count": len(rows)}
                
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except psycopg2.Error as e:
        raise HTTPException(status_code=400, detail=f"Database error: {e.pgerror or str(e)}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    finally:
        conn.close()

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "postgres",
                "description": "Query PostgreSQL database with read-only access",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (describe, query)"},
                    "query": {"type": "string", "description": "SQL query to execute"},
                    "params": {"type": "array", "description": "Query parameters"}
                }
            }
        ]
    }

这个PostgreSQL MCP服务器实现了数据库结构查看和只读查询功能,使大语言模型能够安全地访问数据库信息。

8. Google Drive MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import os
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
import pickle
from typing import List, Dict, Any

app = FastAPI(title="Google Drive MCP Server")

class DriveRequest(BaseModel):
    operation: str  # list_files, search, get_file
    query: str = None
    file_id: str = None
    folder_id: str = None
    page_size: int = 10

def get_drive_service():
    """获取已认证的Google Drive服务客户端"""
    SCOPES = ['https://www.googleapis.com/auth/drive.readonly']
    
    creds = None
    # 尝试从pickle文件加载凭证
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    
    # 如果凭证无效,需要重新认证
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        
        # 保存凭证以备将来使用
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)
    
    service = build('drive', 'v3', credentials=creds)
    return service

@app.post("/tool_call")
async def tool_call(request: DriveRequest, service=Depends(get_drive_service)):
    """处理Google Drive操作请求"""
    try:
        if request.operation == "list_files":
            params = {
                'pageSize': request.page_size,
                'fields': 'nextPageToken, files(id, name, mimeType, modifiedTime)'
            }
            if request.folder_id:
                params['q'] = f"'{request.folder_id}' in parents and trashed=false"
            
            results = service.files().list(**params).execute()
            items = results.get('files', [])
            
            return {
                "status": "success",
                "files": [{
                    "id": item["id"],
                    "name": item["name"],
                    "mimeType": item["mimeType"],
                    "modifiedTime": item["modifiedTime"]
                } for item in items]
            }
            
        elif request.operation == "search":
            if not request.query:
                raise HTTPException(status_code=400, detail="Search query required")
                
            query = f"({request.query}) and trashed=false"
            results = service.files().list(
                q=query,
                pageSize=request.page_size,
                fields='files(id, name, mimeType, modifiedTime)'
            ).execute()
            items = results.get('files', [])
            
            return {
                "status": "success",
                "files": [{
                    "id": item["id"],
                    "name": item["name"],
                    "mimeType": item["mimeType"],
                    "modifiedTime": item["modifiedTime"]
                } for item in items]
            }
            
        elif request.operation == "get_file":
            if not request.file_id:
                raise HTTPException(status_code=400, detail="File ID required")
                
            # 获取文件元数据
            file = service.files().get(
                fileId=request.file_id,
                fields='id, name, mimeType, modifiedTime, webViewLink'
            ).execute()
            
            # 对于文本文件,尝试获取内容
            content = None
            if file["mimeType"] == "text/plain":
                request = service.files().get_media(fileId=request.file_id)
                content = request.execute().decode('utf-8')
            
            return {
                "status": "success",
                "file": {
                    "id": file["id"],
                    "name": file["name"],
                    "mimeType": file["mimeType"],
                    "modifiedTime": file["modifiedTime"],
                    "webViewLink": file["webViewLink"],
                    "content": content
                }
            }
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "google_drive",
                "description": "Access Google Drive files with read-only permissions",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (list_files, search, get_file)"},
                    "query": {"type": "string", "description": "Search query"},
                    "file_id": {"type": "string", "description": "File ID for specific file operations"},
                    "folder_id": {"type": "string", "description": "Folder ID to list files from"},
                    "page_size": {"type": "integer", "description": "Number of results to return"}
                }
            }
        ]
    }

这个Google Drive MCP服务器实现了文件列表、搜索和内容读取功能,使AI模型能够与Google Drive进行交互。

9. Redis MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import os
import redis
from typing import List, Dict, Any, Optional

app = FastAPI(title="Redis MCP Server")

class RedisRequest(BaseModel):
    operation: str  # get, set, keys, info, hgetall
    key: str = None
    value: str = None
    pattern: str = "*"
    hash_key: str = None

def get_redis_client():
    redis_url = os.getenv("REDIS_URL", "redis://localhost:6379/0")
    try:
        return redis.Redis.from_url(redis_url, decode_responses=True)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Redis connection failed: {str(e)}")

@app.post("/tool_call")
async def tool_call(request: RedisRequest, client: redis.Redis = Depends(get_redis_client)):
    """处理Redis操作请求"""
    try:
        if request.operation == "get":
            if not request.key:
                raise HTTPException(status_code=400, detail="Key required")
                
            value = client.get(request.key)
            if value is None:
                raise HTTPException(status_code=404, detail="Key not found")
                
            return {"status": "success", "key": request.key, "value": value}
            
        elif request.operation == "set":
            if not request.key or request.value is None:
                raise HTTPException(status_code=400, detail="Key and value required")
                
            client.set(request.key, request.value)
            return {"status": "success", "message": f"Key {request.key} set successfully"}
            
        elif request.operation == "keys":
            keys = client.keys(request.pattern)
            return {"status": "success", "keys": keys, "count": len(keys)}
            
        elif request.operation == "info":
            info = client.info()
            # 只返回部分关键信息
            safe_info = {
                "server": {
                    "redis_version": info.get("redis_version"),
                    "os": info.get("os"),
                    "arch_bits": info.get("arch_bits")
                },
                "memory": {
                    "used_memory": info.get("used_memory"),
                    "used_memory_human": info.get("used_memory_human"),
                    "maxmemory": info.get("maxmemory"),
                    "maxmemory_human": info.get("maxmemory_human")
                },
                "clients": {
                    "connected_clients": info.get("connected_clients")
                },
                "stats": {
                    "total_commands_processed": info.get("total_commands_processed"),
                    "instantaneous_ops_per_sec": info.get("instantaneous_ops_per_sec")
                }
            }
            return {"status": "success", "info": safe_info}
            
        elif request.operation == "hgetall":
            if not request.key:
                raise HTTPException(status_code=400, detail="Key required")
                
            value = client.hgetall(request.key)
            if not value:
                raise HTTPException(status_code=404, detail="Hash not found or empty")
                
            return {"status": "success", "key": request.key, "value": value}
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except redis.RedisError as e:
        raise HTTPException(status_code=400, detail=f"Redis error: {str(e)}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "redis",
                "description": "Access Redis database for key-value operations",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (get, set, keys, info, hgetall)"},
                    "key": {"type": "string", "description": "Redis key"},
                    "value": {"type": "string", "description": "Value for set operations"},
                    "pattern": {"type": "string", "description": "Pattern for keys search"},
                    "hash_key": {"type": "string", "description": "Hash key for hgetall operations"}
                }
            }
        ]
    }

这个Redis MCP服务器提供了基本的Redis数据库访问功能,使大语言模型能够执行键值操作。

10. Notion MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import os
from notion_client import Client

app = FastAPI(title="Notion MCP Server")

class NotionRequest(BaseModel):
    operation: str  # search, get_page, query_database
    query: str = None
    page_id: str = None
    database_id: str = None
    filter: dict = None
    sorts: list = None

def get_notion_client():
    token = os.getenv("NOTION_TOKEN")
    if not token:
        raise HTTPException(status_code=401, detail="Notion API token not configured")
    return Client(auth=token)

@app.post("/tool_call")
async def tool_call(request: NotionRequest, notion: Client = Depends(get_notion_client)):
    """处理Notion操作请求"""
    try:
        if request.operation == "search":
            if not request.query:
                raise HTTPException(status_code=400, detail="Search query required")
                
            results = notion.search(
                query=request.query,
                page_size=10
            )
            
            return {
                "status": "success",
                "results": [{
                    "id": item["id"],
                    "object": item["object"],
                    "title": item.get("title", [{"text": {"content": "No title"}}])[0]["text"]["content"] if item["object"] == "page" else None,
                    "url": item["url"],
                    "last_edited_time": item["last_edited_time"]
                } for item in results["results"]]
            }
            
        elif request.operation == "get_page":
            if not request.page_id:
                raise HTTPException(status_code=400, detail="Page ID required")
                
            page = notion.pages.retrieve(page_id=request.page_id)
            
            # 提取基本页面信息
            properties = {}
            for name, prop in page["properties"].items():
                if prop["type"] == "title":
                    properties[name] = prop["title"][0]["plain_text"] if prop["title"] else ""
                elif prop["type"] == "rich_text":
                    properties[name] = prop["rich_text"][0]["plain_text"] if prop["rich_text"] else ""
                elif prop["type"] == "number":
                    properties[name] = prop["number"]
                # 可以添加更多属性类型处理
            
            return {
                "status": "success",
                "page": {
                    "id": page["id"],
                    "url": page["url"],
                    "properties": properties,
                    "last_edited_time": page["last_edited_time"]
                }
            }
            
        elif request.operation == "query_database":
            if not request.database_id:
                raise HTTPException(status_code=400, detail="Database ID required")
                
            params = {"database_id": request.database_id}
            if request.filter:
                params["filter"] = request.filter
            if request.sorts:
                params["sorts"] = request.sorts
                
            results = notion.databases.query(**params)
            
            # 简化结果
            items = []
            for item in results["results"]:
                properties = {}
                for name, prop in item["properties"].items():
                    if prop["type"] == "title":
                        properties[name] = prop["title"][0]["plain_text"] if prop["title"] else ""
                    elif prop["type"] == "rich_text":
                        properties[name] = prop["rich_text"][0]["plain_text"] if prop["rich_text"] else ""
                    elif prop["type"] == "select":
                        properties[name] = prop["select"]["name"] if prop["select"] else None
                    # 可以添加更多属性类型处理
                
                items.append({
                    "id": item["id"],
                    "properties": properties,
                    "url": item["url"]
                })
                
            return {"status": "success", "items": items, "total": len(items)}
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "notion",
                "description": "Interact with Notion pages and databases",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (search, get_page, query_database)"},
                    "query": {"type": "string", "description": "Search query"},
                    "page_id": {"type": "string", "description": "Notion page ID"},
                    "database_id": {"type": "string", "description": "Notion database ID"},
                    "filter": {"type": "object", "description": "Query filters for databases"},
                    "sorts": {"type": "array", "description": "Sort criteria for database queries"}
                }
            }
        ]
    }

这个Notion MCP服务器实现了与Notion API的基本交互功能,使AI模型能够搜索内容、获取页面和查询数据库。

11. Stripe MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import os
import stripe
from typing import List, Dict, Any

app = FastAPI(title="Stripe MCP Server")

class StripeRequest(BaseModel):
    operation: str  # list_customers, get_customer, create_customer, list_payments
    customer_id: str = None
    email: str = None
    name: str = None
    limit: int = 10

def get_stripe_client():
    stripe.api_key = os.getenv("STRIPE_SECRET_KEY")
    if not stripe.api_key:
        raise HTTPException(status_code=401, detail="Stripe API key not configured")
    return stripe

@app.post("/tool_call")
async def tool_call(request: StripeRequest, stripe_client: stripe = Depends(get_stripe_client)):
    """处理Stripe操作请求"""
    try:
        if request.operation == "list_customers":
            customers = stripe_client.Customer.list(limit=request.limit)
            return {
                "status": "success",
                "customers": [{
                    "id": c.id,
                    "name": c.name,
                    "email": c.email,
                    "created": c.created
                } for c in customers.data]
            }
            
        elif request.operation == "get_customer":
            if not request.customer_id:
                raise HTTPException(status_code=400, detail="Customer ID required")
                
            customer = stripe_client.Customer.retrieve(request.customer_id)
            return {
                "status": "success",
                "customer": {
                    "id": customer.id,
                    "name": customer.name,
                    "email": customer.email,
                    "description": customer.description,
                    "created": customer.created,
                    "metadata": customer.metadata
                }
            }
            
        elif request.operation == "create_customer":
            if not request.email:
                raise HTTPException(status_code=400, detail="Email required")
                
            customer = stripe_client.Customer.create(
                email=request.email,
                name=request.name
            )
            return {
                "status": "success",
                "customer": {
                    "id": customer.id,
                    "name": customer.name,
                    "email": customer.email
                }
            }
            
        elif request.operation == "list_payments":
            params = {"limit": request.limit}
            if request.customer_id:
                params["customer"] = request.customer_id
                
            payments = stripe_client.PaymentIntent.list(**params)
            return {
                "status": "success",
                "payments": [{
                    "id": p.id,
                    "amount": p.amount,
                    "currency": p.currency,
                    "status": p.status,
                    "customer": p.customer,
                    "created": p.created
                } for p in payments.data]
            }
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except stripe.error.StripeError as e:
        raise HTTPException(status_code=400, detail=f"Stripe error: {e.user_message or str(e)}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "stripe",
                "description": "Interact with Stripe payment API",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (list_customers, get_customer, create_customer, list_payments)"},
                    "customer_id": {"type": "string", "description": "Stripe customer ID"},
                    "email": {"type": "string", "description": "Customer email address"},
                    "name": {"type": "string", "description": "Customer name"},
                    "limit": {"type": "integer", "description": "Number of results to return"}
                }
            }
        ]
    }

这个Stripe MCP服务器实现了客户管理和支付操作的基本功能,使AI模型能够与Stripe支付系统进行交互。

12. Perplexity MCP服务器

python 复制代码
from fastapi import FastAPI, HTTPException, Depends
from pydantic import BaseModel
import os
import requests
from typing import List, Dict, Any

app = FastAPI(title="Perplexity MCP Server")

class PerplexityRequest(BaseModel):
    operation: str  # search, conversation
    query: str
    mode: str = "concise"  # concise, copilot
    conversation_id: str = None
    messages: List[Dict[str, str]] = None

def get_perplexity_api_key():
    api_key = os.getenv("PERPLEXITY_API_KEY")
    if not api_key:
        raise HTTPException(status_code=401, detail="Perplexity API key not configured")
    return api_key

@app.post("/tool_call")
async def tool_call(request: PerplexityRequest, api_key: str = Depends(get_perplexity_api_key)):
    """处理Perplexity操作请求"""
    try:
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
        
        if request.operation == "search":
            url = "https://api.perplexity.ai/chat/completions"
            
            payload = {
                "model": "pplx-7b-online" if request.mode == "copilot" else "pplx-7b-chat",
                "messages": [{"role": "user", "content": request.query}]
            }
            
            response = requests.post(url, json=payload, headers=headers)
            response.raise_for_status()
            data = response.json()
            
            # 提取回答和来源
            answer = data["choices"][0]["message"]["content"]
            
            # 尝试提取来源(Perplexity响应中可能包含)
            sources = []
            if "citations" in data:
                sources = [{"title": c["title"], "url": c["url"]} for c in data["citations"]]
            elif "references" in 
                sources = [{"title": r["title"], "url": r["url"]} for r in data["references"]]
            
            return {
                "status": "success",
                "answer": answer,
                "sources": sources,
                "model": data["model"]
            }
            
        elif request.operation == "conversation":
            url = "https://api.perplexity.ai/chat/completions"
            
            # 构建对话消息
            messages = []
            if request.conversation_id:
                # 在实际实现中,这里应该从数据库获取之前的对话历史
                # 为简化示例,我们假设消息已提供
                messages = request.messages or [{"role": "system", "content": "You are a helpful assistant."}]
            else:
                messages = [{"role": "system", "content": "You are a helpful assistant."}]
                
            messages.append({"role": "user", "content": request.query})
            
            payload = {
                "model": "pplx-7b-online" if request.mode == "copilot" else "pplx-7b-chat",
                "messages": messages
            }
            
            response = requests.post(url, json=payload, headers=headers)
            response.raise_for_status()
            data = response.json()
            
            # 提取回答
            answer = data["choices"][0]["message"]["content"]
            
            return {
                "status": "success",
                "answer": answer,
                "conversation_id": request.conversation_id or "new_conversation",
                "model": data["model"]
            }
            
        else:
            raise HTTPException(status_code=400, detail="Invalid operation")
            
    except requests.exceptions.RequestException as e:
        raise HTTPException(status_code=500, detail=f"Request failed: {str(e)}")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/tools")
async def get_tools():
    """返回此MCP服务器支持的工具列表"""
    return {
        "tools": [
            {
                "name": "perplexity",
                "description": "Use Perplexity AI for real-time web search and conversational responses",
                "parameters": {
                    "operation": {"type": "string", "description": "Operation to perform (search, conversation)"},
                    "query": {"type": "string", "description": "Search or conversation query"},
                    "mode": {"type": "string", "description": "Response mode (concise, copilot)"},
                    "conversation_id": {"type": "string", "description": "ID of existing conversation"},
                    "messages": {"type": "array", "description": "Conversation history for context"}
                }
            }
        ]
    }

这个Perplexity MCP服务器实现了连接到Perplexity的Sonar API,提供实时搜索和对话功能,使AI模型能够获取最新的网络信息。

总结

以上代码示例展示了各种MCP服务器的实现,这些服务器作为Model Context Protocol的实现,使大语言模型能够与外部系统安全交互。

每个MCP服务器都遵循类似的结构:

  1. 实现/tools端点,描述可用的工具
  2. 实现/tool_call端点,处理具体的工具调用请求
  3. 提供适当的错误处理和安全措施

这些实现都是基础示例,实际部署时需要考虑:

  • 更严格的认证和授权机制
  • 请求限制和配额管理
  • 详细的日志记录
  • 错误处理和重试策略
  • 性能优化

这些MCP服务器可以作为扩展AI能力的基础,通过文件访问、数据库连接和API集成等方式增强模型的功能。

相关推荐
猫头虎3 分钟前
猫头虎AI分享|一款Coze、Dify类开源AI应用超级智能体Agent快速构建工具:FastbuildAI
人工智能·开源·github·aigc·ai编程·ai写作·ai-native
0wioiw08 分钟前
Python基础(Flask①)
后端·python·flask
bug菌25 分钟前
还在为多平台开发头疼?看Trae如何让你一人顶一个团队!
aigc·ai编程·trae
bug菌30 分钟前
还在为团队协作扯皮?看字节Trae如何让代码评审变成"享受"!
aigc·ai编程·trae
风象南36 分钟前
SpringBoot 自研运行时 SQL 调用树,3 分钟定位慢 SQL!
spring boot·后端
Jenny40 分钟前
第九篇:卷积神经网络(CNN)与图像处理
后端·面试
大志说编程42 分钟前
LangChain框架入门16:智能客服系统RAG应用实战
后端·langchain·aigc
沸腾_罗强1 小时前
Redis内存爆了
后端
天天摸鱼的java工程师1 小时前
Snowflake 雪花算法优缺点(Java老司机实战总结)
java·后端·面试
海梨花2 小时前
【从零开始学习Redis】项目实战-黑马点评D2
java·数据库·redis·后端·缓存