ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

15分钟从零开发生产级MCP服务器:Python实战指南

15分钟从零开发生产级MCP服务器:Python实战指南 1. 项目缘起为什么我们需要一个MCP服务器最近在折腾一些AI辅助编程的工具链发现一个挺有意思的现象无论是Cursor、Claude Code还是其他一些集成开发环境它们都在提一个叫MCPModel Context Protocol的东西。简单来说MCP就是一个标准协议它能让你的AI助手比如Claude安全、可控地访问和使用你本地的工具、数据源和API。你可以把它想象成给AI装上了一套“外挂”或“插件系统”让它不再只是一个聊天窗口而是能真正操作你的文件系统、数据库甚至调用你写的脚本。但问题来了官方提供的MCP服务器Server就那么几个像文件系统、网络搜索之类的。如果你想让你的大模型助手能帮你操作公司内部的Jira看板、查询特定的数据库报表或者调用一个私有的天气API怎么办答案就是自己动手丰衣足食——开发一个自定义的MCP服务器。网上关于MCP的概念介绍不少但真正手把手教你从零写一个、再到能稳定部署的实战教程却不多。很多人卡在环境配置、协议理解或者不知道如何打包发布。今天我就以Python为例带你用15分钟当然这是理想情况实际加上思考和调试时间会稍长走完从零开发到“生产级”部署的全过程。这里的“生产级”指的是代码结构清晰、有错误处理、日志记录并且能方便地通过Docker等方式运行而不是一个跑在本地命令行里、一关就没了的一次性脚本。2. 环境准备与核心依赖安装在开始敲代码之前我们得先把台子搭好。MCP协议本质上是一个基于JSON-RPC的通信规范所以我们的服务器就是一个实现了特定JSON-RPC接口的程序。2.1 Python环境与虚拟环境首先确保你有一个Python环境版本3.8或以上都行。我强烈建议使用虚拟环境来管理项目依赖避免污染全局环境。# 创建项目目录并进入 mkdir my-mcp-server cd my-mcp-server # 创建虚拟环境这里用venv你也可以用conda python -m venv .venv # 激活虚拟环境 # 在Windows上 .venv\Scripts\activate # 在Mac/Linux上 source .venv/bin/activate激活后你的命令行提示符前应该会出现(.venv)的标识。2.2 安装MCP核心SDK开发MCP服务器最省事的办法就是使用官方或社区维护的SDK。对于Pythonmcp这个库是目前最主流的选择。它提供了构建服务器所需的所有基础工具和类型定义。pip install mcp除了核心库我们通常还需要一些辅助工具pydantic用于数据验证和设置管理mcp库内部已经依赖了它但明确安装可以确保版本。uvicorn一个轻量级的ASGI服务器我们将用它来运行我们的服务器应用。python-dotenv用于从.env文件加载环境变量这在配置生产环境参数时非常有用。我们可以一次性安装pip install mcp uvicorn python-dotenv注意mcp库的API可能还在快速迭代中。如果本文的某些代码示例在你实践时出现报错建议查看其GitHub仓库的文档或源码以获取最新的使用方法。不过核心概念和流程是稳定的。3. 第一个MCP服务器实现一个“时间查询”工具为了快速理解MCP服务器的结构我们先来实现一个最简单的功能让AI助手能查询当前服务器时间。这个例子不涉及外部API纯粹演示协议流程。3.1 项目结构规划一个结构清晰的项目是“生产级”的第一步。我们这样组织文件my-mcp-server/ ├── .env # 环境变量配置文件可选 ├── .gitignore # Git忽略文件 ├── pyproject.toml # 项目依赖和配置或setup.py ├── src/ │ └── mcp_server_demo/ │ ├── __init__.py │ ├── main.py # 服务器主入口 │ ├── servers/ # 存放不同的服务器实现 │ │ ├── __init__.py │ │ └── time_server.py │ └── config.py # 配置管理 └── Dockerfile # Docker镜像构建文件3.2 编写时间服务器核心逻辑现在我们来填充src/mcp_server_demo/servers/time_server.py。一个MCP服务器主要做两件事声明工具Tools告诉客户端比如Claude Code“我有哪些能力”。每个工具需要定义名称、描述、输入参数。实现工具调用Call当客户端请求使用某个工具时执行相应的代码并返回结果。# src/mcp_server_demo/servers/time_server.py import asyncio from datetime import datetime from typing import Any from mcp import ClientSession, StdioServerParameters from mcp.server import Server from mcp.server.models import InitializationOptions import mcp.server.stdio # 创建Server实例 server Server(time-query-server) # 1. 声明工具定义一个名为 get_current_time 的工具 server.list_tools() async def handle_list_tools() - list: 返回服务器提供的工具列表 return [ { name: get_current_time, description: 获取当前的服务器时间可以指定时区例如 Asia/Shanghai或格式。, inputSchema: { type: object, properties: { timezone: { type: string, description: 可选的时区名称如 UTC 或 America/New_York。默认为服务器本地时区。 }, format: { type: string, description: 可选的时间格式字符串例如 %Y-%m-%d %H:%M:%S。默认为 ISO 8601 格式。 } } } } ] # 2. 实现工具调用 server.call_tool() async def handle_call_tool(name: str, arguments: dict[str, Any] | None) - list: 处理工具调用请求 if name ! get_current_time: # 理论上由于我们只声明了一个工具这里不会进入。 # 但良好的实践是做好错误处理。 raise ValueError(f未知的工具: {name}) # 获取参数提供默认值 timezone_str arguments.get(timezone) if arguments else None format_str arguments.get(format) if arguments else None # 这里是核心逻辑获取当前时间 # 注意为了简化这里没有真正实现时区转换需要pytz库。 # 生产环境中你应该使用 pytz 或 zoneinfo (Python 3.9) 来处理时区。 now datetime.now() if format_str: try: result_text now.strftime(format_str) except Exception as e: result_text f时间格式错误: {e} 当前时间为: {now.isoformat()} else: result_text now.isoformat() # 模拟时区参数的影响仅作演示 if timezone_str: result_text f[时区: {timezone_str}] {result_text} # MCP协议要求返回一个列表里面是“文本”或“图像”等内容块。 # 我们返回一个文本块。 return [{ type: text, text: f当前服务器时间是: {result_text} }] # 3. 可选的实现资源Resources和提示Prompts相关功能 # 本例只演示工具所以留空或返回空列表。 server.list_resources() async def handle_list_resources() - list: return [] server.read_resource() async def handle_read_resource(uri: str) - str: raise ValueError(f未知的资源: {uri}) server.list_prompts() async def handle_list_prompts() - list: return [] server.get_prompt() async def handle_get_prompt(name: str, arguments: dict[str, Any] | None) - list: raise ValueError(f未知的提示: {name})代码解读与避坑点工具声明是关键server.list_tools()装饰器下的函数必须返回一个列表里面是工具的描述字典。inputSchema字段遵循JSON Schema规范它定义了AI在调用工具时需要或可以提供的参数。写得越清晰AI用得越准。错误处理在handle_call_tool中我们对未知工具名做了检查。在实际工具逻辑中你也应该用try...except包裹核心代码返回友好的错误信息而不是让整个服务器崩溃。返回格式MCP协议要求call_tool返回一个内容块列表。最常用的是{type: text, text: ...}。未来你可能还会返回image或embedded_resource。异步编程MCP SDK大量使用async/await。确保你的工具处理函数是异步的并且在执行可能阻塞的操作如网络请求、文件IO时使用异步库或asyncio.to_thread。3.3 创建服务器主入口接下来我们在src/mcp_server_demo/main.py中创建启动逻辑。# src/mcp_server_demo/main.py import asyncio import sys from mcp.server import Server from mcp.server.stdio import stdio_server import logging # 导入我们刚才写的服务器逻辑 from .servers.time_server import server as time_server # 配置日志便于调试和生产监控 logging.basicConfig( levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[logging.StreamHandler(sys.stderr)] ) logger logging.getLogger(__name__) async def main(): 主异步函数启动stdio服务器 logger.info(Starting MCP Time Server...) # 使用stdio_server包装我们的server实例 # 这会将服务器的输入/输出重定向到标准流stdin/stdout这是MCP客户端期望的通信方式。 async with stdio_server(time_server) as (read_stream, write_stream): await time_server.run( read_stream, write_stream, InitializationOptions( server_nametime-query-server, server_version0.1.0, capabilitiestime_server.get_capabilities() ) ) if __name__ __main__: asyncio.run(main())为什么用StdioMCP服务器与客户端如Claude Desktop最常见的通信方式是通过标准输入输出stdio。客户端会启动我们的服务器进程然后通过管道pipe进行JSON-RPC消息的交换。这种方式简单、通用不依赖网络端口安全性也相对较好。4. 本地测试与调试让服务器“跑起来”写完代码当然要立刻测试。我们有几种测试方法。4.1 方法一使用MCP CLI工具推荐首先安装MCP命令行工具它可以模拟客户端来测试你的服务器。# 使用npm全局安装需要Node.js环境 npm install -g modelcontextprotocol/inspector然后我们需要创建一个服务器配置文件告诉MCP CLI如何启动我们的服务器。在项目根目录创建mcp-server-config.json{ mcpServers: { my-time-server: { command: python, args: [ -m, mcp_server_demo.main ], env: { PYTHONPATH: ${PYTHONPATH}:./src } } } }注意PYTHONPATH这里需要指向你的src目录确保Python能找到我们的模块。-m mcp_server_demo.main表示以模块方式运行。现在启动MCP Inspectormcp-inspector mcp-server-config.json如果一切正常Inspector会启动一个本地Web界面通常是http://localhost:5173。在界面中你应该能看到你的服务器my-time-server已连接并且列出了get_current_time这个工具。你可以手动输入参数如{timezone: UTC}来调用工具并查看返回结果。4.2 方法二编写简易测试脚本对于快速验证逻辑也可以写一个简单的Python脚本直接调用服务器函数。在项目根目录创建test_server.pyimport asyncio import sys sys.path.insert(0, ./src) # 临时添加路径 from mcp_server_demo.servers.time_server import handle_call_tool async def test(): # 测试不带参数 result await handle_call_tool(get_current_time, None) print(测试1无参数:, result) # 测试带参数 result await handle_call_tool(get_current_time, {format: %Y年%m月%d日 %H时%M分}) print(测试2带格式:, result) # 测试错误工具名 try: result await handle_call_tool(wrong_tool, {}) except ValueError as e: print(测试3错误工具名:, e) if __name__ __main__: asyncio.run(test())运行这个脚本可以快速检查工具调用逻辑是否正确而无需启动完整的Stdio服务器。4.3 常见调试问题与解决ModuleNotFoundError: No module named mcp_server_demo原因Python解释器找不到你的模块。解决确保在正确的目录下运行并且PYTHONPATH设置正确。使用mcp-inspector时配置文件中的env和args是关键。在本地测试脚本中需要手动sys.path.append。工具调用无反应或超时原因通常是handle_call_tool函数内部有同步的阻塞操作或者发生了未捕获的异常。解决在函数内部添加详细的日志logger.info(fCalling tool {name} with {arguments})。确保所有可能出错的代码都有try...except包裹并打印错误日志。Inspector连接失败原因配置文件路径错误或服务器启动命令有误。解决在终端手动执行配置中的command和args看能否成功启动Python脚本。检查虚拟环境是否激活。5. 迈向生产级配置、日志与Docker化一个能在开发机器上跑通的脚本离“生产级”还有距离。生产级意味着可配置、可观测、可扩展、易于部署。5.1 集中化管理配置我们将配置信息如服务器名称、版本、日志级别抽离到配置文件和环境中。创建src/mcp_server_demo/config.py# src/mcp_server_demo/config.py import os from pydantic_settings import BaseSettings from typing import Optional class Settings(BaseSettings): 应用配置优先从环境变量读取 server_name: str my-mcp-server server_version: str 0.1.0 log_level: str INFO # 你可以在这里添加更多配置比如数据库连接字符串、API密钥等 # some_api_key: Optional[str] None class Config: env_file .env # 从项目根目录的.env文件加载 env_file_encoding utf-8 settings Settings()然后在main.py中使用这个配置# src/mcp_server_demo/main.py (更新部分) from .config import settings # ... 其他导入 ... logging.basicConfig( levelgetattr(logging, settings.log_level.upper()), # 使用配置的日志级别 format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[logging.StreamHandler(sys.stderr)] ) async def main(): logger.info(fStarting {settings.server_name} v{settings.server_version}...) async with stdio_server(time_server) as (read_stream, write_stream): await time_server.run( read_stream, write_stream, InitializationOptions( server_namesettings.server_name, server_versionsettings.server_version, capabilitiestime_server.get_capabilities() ) )在项目根目录创建.env文件记得添加到.gitignore# .env SERVER_NAME生产时间查询服务 LOG_LEVELINFO5.2 结构化日志与错误处理生产服务必须有完善的日志方便排查问题。我们使用Python标准的logging模块但可以配置得更细致比如将日志输出到文件并区分不同级别。# 可以在config.py中扩展或单独创建 logging_config.py import logging.handlers def setup_logging(log_level: str, log_file: str None): logger logging.getLogger() # 获取根logger logger.setLevel(getattr(logging, log_level.upper())) # 控制台处理器 console_handler logging.StreamHandler(sys.stderr) console_format logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(message)s) console_handler.setFormatter(console_format) logger.addHandler(console_handler) # 文件处理器可选 if log_file: file_handler logging.handlers.RotatingFileHandler( log_file, maxBytes10*1024*1024, backupCount5 # 10MB一个文件保留5个备份 ) file_format logging.Formatter(%(asctime)s - %(name)s - %(levelname)s - %(module)s:%(lineno)d - %(message)s) file_handler.setFormatter(file_format) logger.addHandler(file_handler)在工具调用函数中积极记录日志server.call_tool() async def handle_call_tool(name: str, arguments: dict[str, Any] | None) - list: logger.info(f收到工具调用请求: {name}, 参数: {arguments}) try: # ... 业务逻辑 ... logger.info(f工具 {name} 执行成功) return result except Exception as e: logger.error(f工具 {name} 执行失败: {e}, exc_infoTrue) # exc_infoTrue会打印堆栈跟踪 # 即使出错也最好返回一个结构化的错误信息给客户端而不是抛出异常导致连接中断 return [{ type: text, text: f执行工具 {name} 时发生错误: {str(e)} }]5.3 使用Docker容器化部署容器化是保证环境一致性、简化部署流程的黄金标准。创建Dockerfile# Dockerfile # 使用官方Python轻量级镜像 FROM python:3.11-slim # 设置工作目录 WORKDIR /app # 设置环境变量防止Python输出缓冲使日志能实时输出 ENV PYTHONUNBUFFERED1 # 先复制依赖声明文件利用Docker层缓存 COPY pyproject.toml ./ # 安装依赖 RUN pip install --no-cache-dir -e . # 复制应用源代码 COPY src/ ./src/ # 创建一个非root用户来运行应用增强安全性 RUN useradd -m -u 1000 appuser chown -R appuser:appuser /app USER appuser # 设置容器启动命令 # 这里假设我们通过 pip install -e . 后可以直接以模块方式运行 CMD [python, -m, mcp_server_demo.main]创建pyproject.toml来管理依赖替代旧的requirements.txt# pyproject.toml [project] name mcp-server-demo version 0.1.0 dependencies [ mcp, uvicorn[standard], python-dotenv, pydantic-settings, ] [build-system] requires [setuptools61.0, wheel] build-backend setuptools.build_meta现在你可以构建并运行Docker镜像了# 在项目根目录构建镜像 docker build -t my-mcp-server:latest . # 运行容器测试Stdio模式通常由MCP客户端管理容器生命周期 # 但我们可以先交互式运行看看有没有明显错误 docker run --rm -it my-mcp-server:latest如果一切正常容器会启动并等待标准输入这就是MCP服务器的工作状态。要停止按CtrlC。生产环境运行在实际使用中你不会直接docker run这个服务器。而是由MCP客户端如配置了Docker运行方式的Claude Desktop来启动和管理这个容器。客户端配置中会指定镜像名和启动命令。6. 进阶实战连接真实API以查询天气为例只会报时的服务器显然不够酷。让我们升级一下连接一个真实的公开API——比如天气查询来演示如何处理外部请求和复杂参数。6.1 设计天气查询工具我们计划调用一个免费的天气API例如 Open-Meteo。工具需要接收latitude纬度和longitude经度参数。首先添加新的依赖。修改pyproject.toml在dependencies列表中添加httpx一个优秀的异步HTTP客户端dependencies [ mcp, uvicorn[standard], python-dotenv, pydantic-settings, httpx, # 新增 ]然后重新安装依赖在虚拟环境中pip install -e .6.2 实现天气服务器创建src/mcp_server_demo/servers/weather_server.py# src/mcp_server_demo/servers/weather_server.py import asyncio from typing import Any import httpx from mcp.server import Server import logging logger logging.getLogger(__name__) server Server(weather-api-server) # 免费的天气API端点示例请查看其使用条款 WEATHER_API_URL https://api.open-meteo.com/v1/forecast server.list_tools() async def handle_list_tools() - list: return [ { name: get_current_weather, description: 根据经纬度查询当前天气情况。, inputSchema: { type: object, properties: { latitude: { type: number, description: 纬度例如 52.52 }, longitude: { type: number, description: 经度例如 13.41 } }, required: [latitude, longitude] # 标记为必填参数 } } ] server.call_tool() async def handle_call_tool(name: str, arguments: dict[str, Any] | None) - list: if name ! get_current_weather: raise ValueError(f未知的工具: {name}) if not arguments or latitude not in arguments or longitude not in arguments: return [{ type: text, text: 错误必须提供 latitude 和 longitude 参数。 }] lat arguments[latitude] lon arguments[longitude] # 构建API请求参数 params { latitude: lat, longitude: lon, current_weather: true, # 只获取当前天气 timezone: auto } logger.info(f查询天气经纬度: ({lat}, {lon})) async with httpx.AsyncClient(timeout10.0) as client: # 设置超时 try: response await client.get(WEATHER_API_URL, paramsparams) response.raise_for_status() # 如果状态码不是2xx抛出异常 data response.json() except httpx.TimeoutException: logger.error(天气API请求超时) return [{type: text, text: 请求天气服务超时请稍后重试。}] except httpx.HTTPStatusError as e: logger.error(f天气API返回错误状态码: {e.response.status_code}) return [{type: text, text: f天气服务暂时不可用错误码: {e.response.status_code}}] except Exception as e: logger.error(f调用天气API时发生未知错误: {e}) return [{type: text, text: 获取天气信息时发生未知错误。}] # 解析响应 current data.get(current_weather, {}) temperature current.get(temperature) windspeed current.get(windspeed) weathercode current.get(weathercode) # 简单映射天气码到描述可根据API文档完善 weather_map { 0: 晴空, 1: 基本晴朗, 2: 局部多云, 3: 阴天, # ... 可以补充更多 } weather_desc weather_map.get(weathercode, f未知天气码({weathercode})) result_text ( f坐标 ({lat}, {lon}) 的当前天气\n f- 温度{temperature}°C\n f- 风速{windspeed} km/h\n f- 天气状况{weather_desc} ) logger.info(f天气查询成功: {result_text}) return [{type: text, text: result_text}] # 同样实现其他必要的空方法list_resources, read_resource等 server.list_resources() async def handle_list_resources() - list: return [] server.read_resource() async def handle_read_resource(uri: str) - str: raise ValueError(f未知的资源: {uri}) server.list_prompts() async def handle_list_prompts() - list: return [] server.get_prompt() async def handle_get_prompt(name: str, arguments: dict[str, Any] | None) - list: raise ValueError(f未知的提示: {name})6.3 整合多个服务器到主入口一个MCP进程可以同时承载多个“逻辑服务器”。我们可以修改main.py将时间服务器和天气服务器组合起来。# src/mcp_server_demo/main.py (更新版) import asyncio import sys from mcp.server import Server from mcp.server.stdio import stdio_server import logging from mcp.server.models import InitializationOptions from .config import settings from .servers.time_server import server as time_server from .servers.weather_server import server as weather_server logging.basicConfig( levelgetattr(logging, settings.log_level.upper()), format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[logging.StreamHandler(sys.stderr)] ) logger logging.getLogger(__name__) async def main(): 组合多个服务器的示例 logger.info(fStarting {settings.server_name} v{settings.server_version}...) # 创建一个“根”服务器或者选择其中一个作为主服务器。 # 这里我们创建一个新的Server实例但实际运行时客户端只会连接一个Server进程。 # 更常见的做法是一个物理进程只运行一个逻辑Server但该Server可以提供多个工具。 # 因此更好的架构是创建一个“聚合”服务器将两个工具集合并。 # 为了简化我们这里以weather_server为主但实际开发中你应该设计一个统一的server。 # 以下演示如何合并工具高级用法需要理解MCP Server内部结构 # 实际上mcp库的Server实例目前不支持简单的合并。生产环境中更推荐的做法是 # 1. 要么在一个server.py文件中定义所有工具适合工具不多时。 # 2. 要么使用路由或工厂模式根据工具名前缀分发到不同的处理模块。 # 本例为了清晰我们暂时只运行weather_server。你可以通过修改导入和下面的server变量来切换。 active_server weather_server # 切换为 time_server 或 weather_server 进行测试 async with stdio_server(active_server) as (read_stream, write_stream): await active_server.run( read_stream, write_stream, InitializationOptions( server_namesettings.server_name, server_versionsettings.server_version, capabilitiesactive_server.get_capabilities() ) ) if __name__ __main__: asyncio.run(main())关键进阶点网络请求与超时一定要为外部HTTP请求设置超时timeout并使用异步客户端如httpx.AsyncClient避免阻塞整个服务器的事件循环。错误处理网络服务不稳定必须对超时、状态码错误、JSON解析失败等情况做全面处理并返回用户友好的信息而不是抛出未处理的异常。API密钥管理如果使用需要认证的API务必不要将密钥硬编码在代码中。通过pydantic-settings从环境变量.env文件读取并在Docker运行时通过-e参数或Kubernetes Secret注入。工具合并上述例子展示了两个独立的服务器。在实际项目中如果你的工具彼此相关最好在一个Server实例内定义所有工具。如果工具模块确实需要物理分离可以考虑更高级的模式如使用mcp库的CompositeServer如果支持或自己实现一个简单的路由分发。7. 部署与集成让AI客户端认识你的服务器开发测试完成最后一步就是让像Claude Desktop这样的客户端能够使用你的服务器。7.1 为Claude Desktop配置自定义MCP服务器Claude Desktop允许通过配置文件添加自定义MCP服务器。配置文件通常位于macOS:~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:%APPDATA%\Claude\claude_desktop_config.jsonLinux:~/.config/Claude/claude_desktop_config.json你需要创建一个这样的JSON配置如果文件不存在就新建{ mcpServers: { my-awesome-server: { command: docker, args: [ run, --rm, -i, my-mcp-server:latest ] } } }解释my-awesome-server你给服务器起的名字会在客户端里显示。command: docker告诉Claude使用Docker运行。argsDocker的运行参数。--rm运行后自动清理容器。-i保持标准输入打开这是MCP通信所必需的。my-mcp-server:latest你的Docker镜像名。更安全的配置对于生产环境你可能需要映射卷、设置环境变量等。例如传递API密钥{ mcpServers: { my-awesome-server: { command: docker, args: [ run, --rm, -i, --env-file, /path/to/your/.env.production, my-mcp-server:latest ] } } }或者如果你不想用Docker也可以直接指向本地Python解释器和脚本路径确保环境一致{ mcpServers: { my-awesome-server: { command: /absolute/path/to/your/project/.venv/bin/python, args: [ -m, mcp_server_demo.main ], env: { PYTHONPATH: /absolute/path/to/your/project/src } } } }7.2 验证与使用保存配置文件。完全重启Claude Desktop应用。在Claude Desktop中打开设置你应该能在MCP服务器部分看到你配置的服务器名称。新建一个对话尝试让Claude使用你的工具。例如你可以说“帮我用my-awesome-server查一下东京的天气经纬度大概是35.68, 139.76。”如果配置正确Claude会识别出服务器提供的工具并尝试调用它。你可以在Claude的回复中看到工具调用的过程和结果。7.3 持续集成与部署CI/CD思路对于团队协作或频繁更新可以考虑设置CI/CD流水线代码仓库将项目代码包括Dockerfile推送到Git仓库如GitHub, GitLab。自动化测试在CI中运行你的单元测试和集成测试例如用pytest测试工具函数。构建镜像CI任务根据最新代码构建Docker镜像。推送镜像将构建好的镜像推送到容器镜像仓库如Docker Hub, GitHub Container Registry, 私有Harbor。更新配置最后一步是更新客户端机器的配置文件指向新版本的镜像标签。这一步可以手动也可以通过配置管理工具如Ansible或容器编排平台如Kubernetes自动完成。整个过程走下来从最初一个简单的想法到最终形成一个可以通过标准协议被AI助手调用的、容器化的、可配置的微服务其核心并不复杂。MCP协议的价值在于它提供了一个清晰的边界和通信标准让你能够以可扩展、可维护的方式安全地将自定义能力赋予大模型。剩下的就是发挥你的想象力去开发那些真正能提升你或你团队工作效率的“AI外挂”了。
返回列表