mcp实践:用python开发并部署到服务器

1. MCP简要介绍

大家好,我是JS-Man

2025年的MCP十分火热,我目前觉得最好用的就是Mysql了,评论区可以推荐下其他的。

先简单介绍下MCP:

如今的AI工具已经不是简单的一问一答,它变得更趋于"自动化",通过"某种"技术,已经能连接并且控制很多工具了,而这个技术就是MCP,Model Context Protocol,模型上下文协议。

  • 以前的AI大模型功能比较局限,例如我现在问gpt,我是谁,我是谁这个用户输入就是User Prompt,而我们常说的要优化提示词,其实就是System Prompt,也就是我们会给User Prompt加入前提条件System Prompt,但是不论我们怎么加提示词,AI也只是给我们答案,无法帮助我们去做。

这个时候AI Agent就出现了

  • AI Agent是处于大模型和Agent Tools之间的,大模型我们都知道,那Agent Tools是什么呢,其实就是一些工具函数,比如我想让AI帮我整理下桌面,那我就写几个函数:read_files、organize_desktop,我将这俩函数的功能、使用方法都注册到AI Agent里,AI Agent就会根据这些信息生成一个System Prompt,这样AI就可以告诉AI Agent,我要调用某某函数,从而达到自动化的效果,其实AI Agent就可以看作是一个中间人,用于联动用户、AI大模型和Agent Tools。

而MCP就是AI Agent和Agent Tools的通信协议,运行Tool的服务就叫MCP Server。通过MCP这个统一的规范协议,那不同的Agent可以调用不同的Tools,可以形成一个多对多的关系。

了解了MCP后,下面开始进入开发。

2. 本地开发调试

下面我们添加一个简单的tool进行测试。

python 复制代码
# server.py
from mcp.server.fastmcp import FastMCP

# Create an MCP server
mcp = FastMCP("Demo")


# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b


# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"
    
if __name__ == "__main__":
    # Initialize and run the server
    mcp.run(transport='stdio')

直接uv run server.py就可以本地跑起来,再看下cursor里的MCP配置:

json 复制代码
"test-mcp":{
  "command": "uv run /Users/huangfan/Downloads/MySelf/mcp-server/server.py",
  "transport": "stdio"
}

成功的跑起来了,在cursor里就可以直接用了。

3. sse部署

部署到服务器就不能使用stdio的传输方式了,要使用sse或者streamable-http,我们先演示下sse的:

python 复制代码
# server.py
import uvicorn
from mcp.server.fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount, Route
from starlette.responses import JSONResponse
import datetime

# Create an MCP server
mcp = FastMCP("Demo")

# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b

# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"

async def health_check():
    """健康检查端点"""
    return JSONResponse({
        "status": "healthy",
        "timestamp": datetime.datetime.now().isoformat(),
    })

app = Starlette(
    routes=[
        Route("/health", health_check, methods=["GET"]),
        Mount('/xixi', app=mcp.sse_app()),
    ]
)

if __name__ == '__main__':
    uvicorn.run(app,host='0.0.0.0', port=8000)

使用Starlette将sse的mcp路由跑起来,配置文件如下:

json 复制代码
 "test-mcp-sse":{
  "url": "http://0.0.0.0:8000/xixi/sse",
  "type": "sse"
}

实测可以直接用vercel部署,白嫖实在太爽了,但是在国内用不太稳定。

4. streamable-http部署

有时候服务器不支持sse或者不想折腾配置的,可以使用streamableHttp,官方表明sse已弃用:

使用streamableHttp的时候我踩了很多的坑,uvicorn.run的时候,怎么都跑不起来mcp,换了几个服务器都不行,一开始还以为streamableHttp要啥特殊配置,后来仔细观察发现,一个路由里的/health路径倒是访问的了,原来是要在lifespan里启动mcp,代码如下:

python 复制代码
# server.py
import uvicorn
from mcp.server.fastmcp import FastMCP
import contextlib
from fastapi import FastAPI
from starlette.responses import JSONResponse
import datetime

# Create an MCP server
mcp = FastMCP("Demo")

# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
    """Add two numbers"""
    return a + b

# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"

# 创建FastAPI应用并管理MCP session manager的生命周期
@contextlib.asynccontextmanager
async def lifespan(app: FastAPI):
    """管理MCP服务器的生命周期"""
    # 启动时初始化session manager
    async with mcp.session_manager.run():
        yield

async def health_check():
    """健康检查端点"""
    return JSONResponse({
        "status": "healthy",
        "timestamp": datetime.datetime.now().isoformat(),
    })

def create_app():
    """创建FastAPI应用"""
    app = FastAPI(
        title="test-mcp",
        description="使用sse协议的MCP服务器",
        version="1.0.0",
        lifespan=lifespan
    )

    # 添加健康检查端点
    app.get("/health")(health_check)

    # 挂载MCP服务到 /xixi 路径
    app.mount("/xixi", mcp.streamable_http_app())

    return app

def main():
    app = create_app()

    # 启动uvicorn服务器
    uvicorn.run(
        app,
        host="0.0.0.0",
        port=8000,
        log_level="info"
    )

if __name__ == '__main__':
    main()

使用streamableHttp成功部署MCP。

总结

以上,是对MCP三种传输协议部署实践,如果只是想试试MCP,使用stdio就行了,我们使用的MCP Tool大部分都是node写的,使用npx方式先拉到本地缓存再执行,使用部署的方式也比较少,我想这是因为本地的方式MCP功能会更加强大,线上部署的比较局限,只能调用接口。

本文只是实践了MCP的部署方式,没有详细写Tool的实现,在公司内部已经使用MCP落地一些实际场景了,我相信下半年MCP会是一种趋势,

相关推荐
今晚打老虎z4 分钟前
dotnet-env: .NET 开发者的环境变量加载工具
前端·chrome·.net
用户3802258598249 分钟前
vue3源码解析:diff算法之patchChildren函数分析
前端·vue.js
烛阴15 分钟前
XPath 进阶:掌握高级选择器与路径表达式
前端·javascript
小鱼小鱼干18 分钟前
【JS/Vue3】关于Vue引用透传
前端
JavaDog程序狗20 分钟前
【前端】HTML+JS 实现超燃小球分裂全过程
前端
独立开阀者_FwtCoder25 分钟前
URL地址末尾加不加 "/" 有什么区别
前端·javascript·github
独立开阀者_FwtCoder28 分钟前
Vue3 新特性:原来watch 也能“暂停”和“恢复”了!
前端·javascript·github
snakeshe101029 分钟前
优化 Mini React:实现组件级别的精准更新
前端
前端小盆友29 分钟前
从零实现一个GPT 【React + Express】--- 【2】实现对话流和停止生成
前端·gpt·react.js
京东云开发者35 分钟前
行云前端重构之路:从单体应用到 Monorepo 的血泪史
前端