MCP 协议与 Skill 开发架构培训文档

核心原理、环境搭建、自定义Skill封装与智能体(Agent)闭环集成

目录

[一、 MCP (Model Context Protocol) 核心原理剖析](#一、 MCP (Model Context Protocol) 核心原理剖析)

[1.1 什么是 MCP 协议?](#1.1 什么是 MCP 协议?)

[1.2 MCP 的三层架构模型](#1.2 MCP 的三层架构模型)

[1.3 核心概念深度解析](#1.3 核心概念深度解析)

[1.4 MCP 国内平台及应用服务](#1.4 MCP 国内平台及应用服务)

[二、 MCP 服务器开发环境搭建 (Python SDK)](#二、 MCP 服务器开发环境搭建 (Python SDK))

[2.1 环境准备与依赖配置](#2.1 环境准备与依赖配置)

[2.2 基础服务器框架代码实现](#2.2 基础服务器框架代码实现)

[2.3 运行与协议通道解析 (Stdio vs. SSE)](#2.3 运行与协议通道解析 (Stdio vs. SSE))

[三、 自定义 Skill 开发实践](#三、 自定义 Skill 开发实践)

[3.1 场景一:天气查询 Skill 封装 (外部 API 型)](#3.1 场景一:天气查询 Skill 封装 (外部 API 型))

[3.2 场景二:数据库操作 Skill 封装 (状态感知型)](#3.2 场景二:数据库操作 Skill 封装 (状态感知型))

[3.3 场景三:本地文件读写 Skill](#3.3 场景三:本地文件读写 Skill)

[3.4 场景四:内部 API 查询 Skill (综合业务型)](#3.4 场景四:内部 API 查询 Skill (综合业务型))

[3.5 场景五:外部 API 查询 Skill](#3.5 场景五:外部 API 查询 Skill)

[3.6 场景六:MCP调用SearXNG搜索引擎智能体](#3.6 场景六:MCP调用SearXNG搜索引擎智能体)

[四、 Skill 封装、注册与客户端调用契约](#四、 Skill 封装、注册与客户端调用契约)

[4.1 工具与资源的 Schema 自动化生成](#4.1 工具与资源的 Schema 自动化生成)

[4.2 使用 mcp dev 命令行进行本地独立调试与热加载](#4.2 使用 mcp dev 命令行进行本地独立调试与热加载)

[4.3 日志重定向技巧 (Stderr 隔离)](#4.3 日志重定向技巧 (Stderr 隔离))


一、 MCP (Model Context Protocol) 核心原理剖析

Anthropic 公司(就是发布 Claude 大模型的公司),在 2024 年 11 月,发布了 Model Context Protocol 协议,简称 MCP。

MCP 协议就像 Type-C 扩展坞,让海量的软件和工具,能够插在大语言模型上,供大模型调用。

MCP 协议是连接【大模型(客户端)】和【各种工具应用(服务端)】的统一接口。

它的目标是:

✨ 给 AI 一个可以"使用工具"的万能接口

🔌 统一模型与服务间的数据调用协议

💡 像 USB-C 一样为 AI 打造"标准连接规范"

1.1 什么是 MCP 协议?

MCP 是一套轻量级、安全、面向上下文交换的双向通信协议。它从设计之初就确立了"解耦、内聚、标准"的原则。它允许开发人员构建一套标准服务(MCP Server),该服务无需关心最终对接的是 Claude、GPT 还是企业自研的垂直领域大模型,只要客户端适配了 MCP 协议,就能以结构化、安全可控的方式读取服务器提供的文件、执行特定的数据库命令或调用受保护的内部 API。

1.2 MCP 的三层架构模型

MCP 的技术生态由严密的解耦三层架构组成,各层分工明确,通过标准的通道建立信任和数据交换:

  • **1. MCP Client(客户端):**大模型应用的寄宿骨架或 Agent 运行时环境(如自研 Agent 框架、Claude Desktop 等)。Client 负责维护与 MCP Server 的进程级或网络级连接,向 Server 获取可用的工具和资源清单(Schema),并在接收到 LLM 的指令时中转调度请求,最后组装上下文再次反馈给 LLM。
  • 2. MCP Server **(服务器):**企业核心资产与业务能力的真正承载者。Server 属于高度内聚的微服务,通过 MCP 标准协议安全地向外公开 Tools、Resources 以及 Prompts。Server 本身不包含任何 LLM 逻辑,它只被动响应来自 Client 的 JSON-RPC 请求,这极大地保证了企业私有环境的安全边界。
  • 3. LLM **(大语言模型):**系统的"大脑"。LLM 本身不感知 MCP 协议的底层技术细节,它通过 Client 传递而来的、符合标准 JSON Schema 规范的工具描述来进行推理决策。当模型判断需要调用某种能力时,它会输出一个结构化的 Tool Call 指令给 Client。
  • 4. MCP Host:人类电脑上安装的客户端软件,一般是 Dify、Cursor、Claude Desktop、Cherry Studio、Cline,软件里带了大语言模型。

1.3 核心概念深度解析

MCP 将大模型所需的能力与信息提炼为三大核心抽象:

  • 1. Tools **(工具):**带有明显"副作用(Side Effects)"或需要进行动态实时计算的操作。模型通过"主动调用(Invoke)"工具来直接改变外部系统状态或读取动态变化的数据。每个 Tool 必须声明其唯一的 Name、清晰的 Text Description 以及严谨的 JSON Schema 入参定义。例如:向数据库写入一条订单、调用短信关口、操作本地文件等。
  • **2. Resources(资源):**供大模型查阅的"只读(Read-Only)"数据源。资源采用类似于 Web URL 的 URI(统一资源标识符)进行标识(例如:`db://cluster/tables/users` 或 `file:///var/log/sys.log`)。模型可以通过 Read 请求读取资源的快照,或者通过 Subscribe 协议订阅资源的变更流,实现上下文的实时感知。
  • 3. Prompts **(提示词模板):**预先定义好、带有动态占位符参数的提示词模板。它能降低用户与 AI 交互的门槛。例如定义一个名为 `bug-analysis` 的模板,接收 `language` 与 `stack_trace` 参数,Server 负责组装最高效的系统提示词结构返回给客户端。

1.4 MCP 国内平台及应用服务

|--------------------------|--------|-------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
| 平台 | 服务规模 | 核心特点 | 官网 |
| **魔搭社区 MCP 广场(阿里云)** | 9227+ | 国内最大中文 MCP 社区,独家首发支付宝 MCP、MiniMax 多模态服务,支持可视化调试 | ModelScope - MCP 广场 |
| **百度智能云 MCP World** | 56757+ | 国内首个企业级 MCP 服务,百度搜索流量扶持,免费托管 | 海量 MCP Servers 导航网站 |
| **阿里云百炼 MCP 服务** | 184+ | 业界首个全生命周期托管,5 分钟快速搭建智能体,沙箱隔离 | 大模型服务平台百炼控制台 |
| **腾讯云 MCP 广场** | 1089+ | MCP+Agent+小程序一体化,一键发布到微信生态 | 腾讯云开发者社区-腾讯云开发者 MCP广场_开发者MCP服务_MCP 服务器- 腾讯云 |
| **讯飞星辰 MCP 广场** | 16318+ | 深度整合讯飞语音技术,支持语音识别/合成、星火大模型 | 讯飞星辰 |

MCP 目前国外的平台较多,国内比较头部的 MCP 平台目前是魔搭社区。

二、 MCP 服务器开发环境搭建 (Python SDK)

2.1 环境准备与依赖配置

本实操项目推荐在 Python 3.10+ 环境下运行。我们将使用 Anthropic 官方推出的高层封装框架 `FastMCP`。 首先,在独立的虚拟环境或开发目录中,安装核心 SDK 依赖以及本地开发调试所需的 CLI 工具链:

复制代码
# 安装 MCP 核心 SDK 及其命令行扩展组件
pip install mcp mcp[cli] uvicorn pydantic requests

# 检查安装状态,确保 mcp 命令在系统 PATH 中可用
mcp --help

2.2 基础服务器框架代码实现

创建一个名为 `mcp_server.py` 的文件。以下是搭建一个 MCP 服务所需的最简闭环代码。我们通过初始化 `FastMCP` 实例,来自动化管理整个协议握手与通信生命周期:

复制代码
from mcp.server.fastmcp import FastMCP
import sys

# 初始化 FastMCP 实例,指定该 MCP 服务的全局名称
server = FastMCP("Corporate-Skill-Platform", stateless_http=True, json_response=True)

@server.tool()
async def ping() -> str:
    """
    基础的心跳检测工具,用于验证 MCP 协议通道是否完全畅通。
    """
    return "pong! MCP Server is alive and operational."

if __name__ == "__main__":
    # 用 HTTP 模式,监听 0.0.0.0:8000,让 Dify 能访问    
    app = server.sse_app()
    uvicorn.run( app, host="0.0.0.0", port=8000 )

2.3 运行与协议通道解析 (Stdio vs. SSE)

MCP 支持两种主要的底层的传输通道(Transport Channels):

  • 1. Stdio 通信通道: 基于子进程的标准输入输出管道。Client 通过拉起 Python 解释器进程执行 `mcp dev mcp_server.py`,两者通过 stdout 和 stdin 传输结构化的 JSON-RPC 2.0 数据帧。这种方式完全不需要本地暴露任何网络端口,极为安全,是本地/单机 Agent 的标准配置。
  • **2. SSE 通信通道:**基于 Server-Sent Events(服务器发送事件)和 HTTP POST 组合的网络通道。适用于分布式部署、云端 Agent 框架对接局域网内 MCP 服务的场景,通过持久的 HTTP 长连接保持能力的在线发布。

uv run mcp_server.py

三、 自定义 Skill 开发实践

对比项 @server.tool() @server.resource() @server.prompt()
核心作用 执行操作 提供上下文数据 提供提示词模板
本质 Function Call Context Provider Prompt Template
是否有输入参数 ✅ 支持 ⚠️ 通常不支持业务参数 ✅ 支持
是否有返回值 ✅ 有 ✅ 有 ✅ 有
Agent是否主动调用 ✅ 是 ⚠️ 视框架而定 ⚠️ 视框架而定
是否改变外部状态 ✅ 可以 ❌ 不应该 ❌ 不应该
是否执行业务逻辑 ✅ 是 ❌ 否 ❌ 否
是否属于工具能力
是否属于上下文能力
Dify是否显示
Dify工作流是否可直接调用
LangGraph支持

3.1 场景一:天气查询 Skill 封装 (外部 API 型)

为了展示外部 API 通信工具的定义,我们编写一个具备入参校验的天气查询 Skill。请注意:FastMCP 会自动将 Python 的函数文档字符串(Docstring)提取为 LLM 的工具描述,将类型提示(Type Hints)转化为严格的 JSON Schema 字段约束。因此,规范的注释是 Skill 开发的重中之重!

天气查询工具Open-Meteo

Open-Meteo 是一个完全免费、无需注册 API Key 的开源天气数据服务,由瑞士开发者维护,提供全球范围内的实时天气、逐小时/逐日预报以及长达 40 年的历史气象数据。它整合了欧洲中期天气预报中心(ECMWF)、德国气象局(DWD)等多家权威机构的模型数据,支持分钟级降雨预报、空气质量、海浪、土壤湿度等多种专业气象参数,并通过简洁的 REST API 和友好的文档降低了接入门槛,非常适合个人开发者、开源项目和小型应用快速集成天气功能。

复制代码
import requests
import json
from typing import Optional

@server.tool()
async def get_weather(city: str, date: Optional[str] = None) -> str:
    """
    查询城市天气,返回JSON字符串
    
    参数:
        city: 城市名(如"北京"、"上海")
        date: 日期,格式"YYYY-MM-DD"。None表示当前天气
    """
    
    # 1. 获取城市坐标
    geo_url = "https://geocoding-api.open-meteo.com/v1/search"
    geo_resp = requests.get(geo_url, params={"name": city, "count": 1})
    geo_resp.raise_for_status()
    geo_data = geo_resp.json()
    
    if not geo_data.get("results"):
        raise ValueError(f"未找到城市: {city}")
    
    city_info = geo_data["results"][0]
    lat, lon = city_info["latitude"], city_info["longitude"]
    
    # 2. 请求天气数据
    url = "https://api.open-meteo.com/v1/forecast"
    params = {
        "latitude": lat,
        "longitude": lon,
        "current": "temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m"
    }
    
    if date:
        params["start_date"] = date
        params["end_date"] = date
        params["daily"] = "temperature_2m_max,temperature_2m_min,weather_code"
        del params["current"]
    resp = requests.get(url, params=params)
    resp.raise_for_status()
    data = resp.json()
    
    # 3. 天气代码映射
    weather_map = {
        0: "晴", 1: "多云", 2: "多云", 3: "阴",
        45: "雾", 48: "雾凇",
        51: "毛毛雨", 53: "小雨", 55: "中雨",
        61: "小雨", 63: "中雨", 65: "大雨",
        71: "小雪", 73: "中雪", 75: "大雪",
        95: "雷雨", 96: "雷雨伴冰雹", 99: "强雷雨伴冰雹"
    }
    
    # 4. 字符串拼接生成结果
    city_name = city_info["name"]
    if date:
        # 指定日期
        daily = data["daily"]
        idx = 0
        weather = weather_map.get(daily["weather_code"][idx], "未知")
        result = \
            "城市: " + city_name + "\n" + \
            "日期: " + date + "\n" + \
            "最高温度: " + str(daily["temperature_2m_max"][idx]) + "°C\n" + \
            "最低温度: " + str(daily["temperature_2m_min"][idx]) + "°C\n" + \
            "天气: " + weather
    else:
        # 当前实时天气
        current = data["current"]
        weather = weather_map.get(current["weather_code"], "未知")
        result = \
            "城市: " + city_name + "\n" + \
            "温度: " + str(current["temperature_2m"]) + "°C\n" + \
            "湿度: " + str(current["relative_humidity_2m"]) + "%\n" + \
            "天气: " + weather + "\n" + \
            "风速: " + str(current["wind_speed_10m"]) + " km/h"
    return result

3.2 场景二:数据库操作 Skill 封装 (状态感知型)

在企业级应用中,我们常需要向大模型暴露只读的数据字典,同时提供特定查询的工具。下面我们将"用户表结构"暴露为 MCP 资源(Resource),将"查询细节"暴露为工具(Tool):

复制代码
import pymysql
from pymysql.cursors import DictCursor

# MySQL 数据库配置
MYSQL_HOST = "192.168.0.11"
MYSQL_PORT = 3306
MYSQL_USER = "root"
MYSQL_PASSWORD = "root"
MYSQL_DB = "yuejuan"

def get_db_connection():
    """建立并返回数据库连接"""
    return pymysql.connect(
        host=MYSQL_HOST,
        port=MYSQL_PORT,
        user=MYSQL_USER,
        password=MYSQL_PASSWORD,
        database=MYSQL_DB,
        cursorclass=DictCursor,
        charset='utf8mb4'
    )

@server.resource("db://schema/users")
def get_users_table_schema() -> str:
    """
    [只读资源] 获取企业核心用户资产表的底层字段元数据定义 Schema。
    通过连接数据库动态获取真实的表结构。
    """
    try:
        conn = get_db_connection()
        try:
            with conn.cursor() as cursor:
                cursor.execute("DESCRIBE user")
                columns = cursor.fetchall()
                
                result = ["Table: user", "Columns:"]
                for col in columns:
                    field = col['Field']
                    dtype = col['Type']
                    extra = []
                    if col.get('Key') == 'PRI':
                        extra.append('PRIMARY KEY')
                    if col.get('Extra'):
                        if 'auto_increment' in col['Extra']:
                            extra.append('AUTO_INCREMENT')
                    if col.get('Null') == 'NO':
                        extra.append('NOT NULL')
                    if col.get('Default') is not None and col['Default'] != '':
                        extra.append(f"DEFAULT {col['Default']}")
                    
                    col_line = f"  - {field}: {dtype}"
                    if extra:
                        col_line += f" ({', '.join(extra)})"
                    result.append(col_line)
                
                return '\n'.join(result)
        finally:
            conn.close()
    except Exception as e:
        return f"[数据库连接失败] {str(e)}"

@server.tool()
async def query_user_privilege(email: str) -> str:
    """
    根据邮箱查询该用户是否为管理员。
    
    :param email: 用户的邮箱地址(例如:'admin@example.com')。
    """
    try:
        conn = get_db_connection()
        try:
            with conn.cursor() as cursor:
                sql = "SELECT id, email, is_superuser, is_active FROM user WHERE email = %s"
                cursor.execute(sql, (email,))
                result = cursor.fetchone()
                
                if result:
                    is_super = "是" if result['is_superuser'] else "否"
                    is_active = "活跃" if result['is_active'] else "禁用"
                    return f"[查询成功] 用户ID: {result['id']} | 邮箱: {result['email']} | 是否管理员: {is_super} | 账户状态: {is_active}"
                return f"[查询结果] 数据库中未找到邮箱为 '{email}' 的用户记录。"
        finally:
            conn.close()
    except Exception as e:
        return f"[数据库错误] 查询失败: {str(e)}"

3.3 场景三:本地文件读写 Skill

【核心实操任务定义】学员需开发一个能够深度切入本地运维场景的综合 Skill。该 Skill 能够完成读取本地系统的异常运行日志(本地文件读写)。

复制代码
import os

# 定义允许安全读取的本地工作根目录,防止路径穿越攻击(..)
SAFE_LOG_DIR = os.path.abspath(os.path.dirname(__file__))

@server.tool()
async def read_local_log_file(filename: str) -> str:
    """
    安全地读取本地指定相对路径的系统运行日志或配置文件内容,以便进行故障诊断。
    
    :param filename: 文件名称(例如:'error.log', 'sys_config.txt'),禁止使用绝对路径或带有 '..' 的非法穿透路径。
    """
    # 确保文件路径安全性
    clean_name = os.path.basename(filename)
    target_path = os.path.join(SAFE_LOG_DIR, clean_name)
    
    if not os.path.exists(target_path):
        # 如果文件不存在,为了方便实操演示,自动创建一个充满典型错误信息的日志,供 Agent 读取
        with open(target_path, 'w', encoding='utf-8') as f:
            f.write(
                "2026-05-29 09:15:22 [ERROR] [AuthModule] Database connection timeout after 5000ms.\n"
                "2026-05-29 09:15:25 [CRITICAL] [CoreEngine] Failed to initialize session for user 'zhangsan'.\n"
                "2026-05-29 09:15:30 [WARN] [Metrics] Push gateway unreachable, retrying...\n"
            )
    
    try:
        with open(target_path, 'r', encoding='utf-8') as f:
            content = f.read()
        return f"--- 本地文件读取成功 [{clean_name}] ---\n{content}"
    except Exception as e:
        return f"读取本地文件时发生未预期的系统级 I/O 异常: {str(e)}"

3.4 场景四:内部 API 查询 Skill (综合业务型)

【核心实操任务定义】学员需开发一个能够深度切入本地运维场景的综合 Skill。该 Skill 能够完成分析出故障后通过模拟的内部企业 ITIL 平台 API 进行紧急事件挂载与上报(内部 API 查询)。

复制代码
@server.tool()
async def submit_internal_itil_ticket(fault_module: str, level: str, details: str) -> str:
    """
    向企业内部核心 ITIL 运维调度控制台在线提交一份紧急故障工单。
    
    :param fault_module: 判定发生故障的核心模块名称(如 'AuthModule', 'Database')。
    :param level: 工单的严重性级别,必须为下列之一: 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'。
    :param details: 经过大模型分析、提炼后的故障详细日志片段或诊断结论。
    """
    # 模拟企业内部高效的 RESTful API 事务交互
    import random
    ticket_id = f"TK-20260529-{random.randint(1000, 9999)}"
    
    # 模拟 API 负载数据
    api_payload = {
        "sys_ticket_id": ticket_id,
        "target_service": fault_module,
        "urgency_matrix": level,
        "payload_description": details,
        "dispatch_status": "AUTOMATIC_ROUTING_TRIGGERED"
    }
    return (
        f"[内部API响应 200 SUCCESS]\n"
        f">> 工单挂载成功!分配单号: {ticket_id}\n"
        f">> 响应报文: {{'status': 'filed', 'assigned_group': 'SRE_Tier_2', 'sla_deadline': '15mins'}}\n"
        f">> 提报详情概要: 模块[{fault_module}]发生[{level}]级故障,SRE团队已被自动唤醒。"
    )

3.5 场景五:外部 API 查询 Skill

【核心实操任务定义】12306火车票查询(外部 API 查询)。

Mcp服务基于魔搭社区注册,ModelScope 魔搭社区

git clone GitHub - Joooook/12306-mcp: This is a 12306 ticket search server based on the Model Context Protocol (MCP). · GitHub

npm i

npx -y 12306-mcp --host 0.0.0.0 --port 8080

复制代码
async def query_12306(fromStation, toStation, date):
    """
    查询 12306 火车票信息
    参数:
        fromStation: 出发站(如"北京")
        toStation: 到达站(如"上海")
        date: 日期(格式: YYYY-MM-DD)
    返回:
        查询结果字符串
    """
    MCP_SERVER_URL = "https://mcp.api-inference.modelscope.net/c9ad9cb42dc242/sse"
    async with sse_client(MCP_SERVER_URL) as (read, write):
        async with ClientSession(read, write) as session:
            # 初始化连接
            await session.initialize()
            # 获取可用工具列表
            tools = await session.list_tools()
            print(f"可用工具: {[tool.name for tool in tools.tools]}")
            # 调用工具(工具名需根据实际情况调整)
            result = await session.call_tool(
                "get-tickets",  # 假设的工具名,实际可能需要修改
                arguments={
                    "fromStation": fromStation,
                    "toStation": toStation,
                    "date": date
                }
            )
            # 解析结果
            output_lines = [f"🚄 {fromStation} → {toStation} 列车查询结果 ({date})"]
            output_lines.append("=" * 50)
            
            for content in result.content:
                if content.type == "text":
                    output_lines.append(content.text)
            return "\n".join(output_lines)

3.6 场景六:MCP调用SearXNG搜索引擎智能体

这种结合让大语言模型具备了突破知识截止日期限制的能力------智能体可以在对话过程中动态调用搜索引擎获取实时信息,然后将搜索结果作为上下文整合到最终的回答中,从而提供更准确、更及时的响应。

复制代码
@server.tool()
async def search_searxng(query: str, language: str = "zh") -> str:
    """
    调用 SearXNG 搜索引擎进行搜索。
    :param query: 搜索关键词。
    :param language: 搜索语言,默认为中文 'zh',可选 'en' 英文。
    """
    searxng_url = "http://192.168.0.11:8080"
    try:
        params = {
            'q': query,
            'lang': language,
            'format': 'json'
        }
        
        response = requests.get(f"{searxng_url}/search", params=params, timeout=10)
        response.raise_for_status()
        results = response.json()
        if results.get('results'):
            output = [f"[SearXNG 搜索结果] 关键词: {query}"]
            for i, result in enumerate(results['results'][:5], 1):
                title = result.get('title', '无标题')
                url = result.get('url', '无链接')
                description = result.get('description', '无描述')
                output.append(f"\n{i}. {title}")
                output.append(f"   链接: {url}")
                output.append(f"   描述: {description}")
            return '\n'.join(output)
        return f"[搜索结果] 未找到与 '{query}' 相关的内容。"
    except requests.exceptions.RequestException as e:
        return f"[搜索失败] 无法连接到 SearXNG: {str(e)}"

四、 Skill 封装、注册与客户端调用契约

4.1 工具与资源的 Schema 自动化生成

当 FastMCP 服务加载上述代码后,它会在底层默默把这些带有装饰器的 Python 函数解析为 MCP 官方标准的控制协议结构。例如,`submit_internal_itil_ticket` 最终在协议握手中的 `tools/list` 请求返回里,体现为如下精简的契约 Schema:

复制代码
========== 测试 tools/list ==========
[可用工具列表]
🔧 ping
   描述:
    基础的心跳检测工具,用于验证 MCP 协议通道是否完全畅通。
🔧 get_weather
   描述:
    获取指定城市在特定日期的实时天气信息与气象指数。
    :param city: 目标城市名称,必须为标准的英文或拼音(例如:'Beijing', 'Shanghai')。
    :param date: 查询日期字符串,默认为 'today'。
🔧 query_user_privilege
   描述:
    根据邮箱查询该用户是否为管理员。
    :param email: 用户的邮箱地址(例如:'admin@example.com')。
🔧 read_local_log_file
   描述:
    安全地读取本地指定相对路径的系统运行日志或配置文件内容,以便进行故障诊断。
    :param filename: 文件名称(例如:'error.log', 'sys_config.txt'),禁止使用绝对路径或带有 '..' 的非法穿透路径。
🔧 submit_internal_itil_ticket
   描述:
    向企业内部核心 ITIL 运维调度控制台在线提交一份紧急故障工单。
    :param fault_module: 判定发生故障的核心模块名称(如 'AuthModule', 'Database')。
    :param level: 工单的严重性级别,必须为下列之一: 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'。
    :param details: 经过大模型分析、提炼后的故障详细日志片段或诊断结论。
🔧 search_searxng
   描述:
    调用 SearXNG 搜索引擎进行搜索。
    :param query: 搜索关键词。
    :param language: 搜索语言,默认为中文 'zh',可选 'en' 英文。

4.2 使用 mcp dev 命令行进行本地独立调试与热加载

在编写完成代码后,我们不需要急于启动复杂的 Agent 整体服务。MCP 生态提供了极为优秀的开发者沙箱工具 `mcp dev`。 它可以作为一个虚拟的 MCP 客户端,拉起你的服务器并提供一个可视化、支持"热加载(Hot Reloading)"的交互式控制台:

复制代码
# 使用 mcp dev 工具在沙箱环境中调试本地的 mcp_server.py
mcp dev mcp_server.py

# 运行后控制台会显示输出:
# ── MCP Dev Console ──
# ⚙️  Server: Corporate-Skill-Platform
# 🛠️  Available Tools: ping, get_weather, query_user_privilege, read_local_log_file, submit_internal_itil_ticket
# 📂  Available Resources: db://schema/users
# 🔄  Watching 'mcp_server.py' for changes... (热加载处于激活状态)

此时,你在 `mcp_server.py` 中修改任何一行业务逻辑代码并保存,`mcp dev` 会自动捕获文件系统变化、杀掉旧子进程、重载服务器,彻底免去了反复手动重启的低效开发操作。

特点:

  • 自动监听文件变化
  • 自动重启 MCP Server
  • 自动刷新 Tool 列表
  • 调试体验最佳

4.3 日志重定向技巧 (Stderr 隔离)

这是初学者在进行 MCP 协议开发时最容易踩中、且导致整个系统崩溃的"头号大坑":由于在标准 Stdio 通信模式下,客户端和服务器完全依赖系统的 `stdout`(标准输出流)和 `stdin`(标准输入流)作为传输 JSON-RPC 协议消息的物理介质。如果在编写 MCP Server 的代码中,不小心留下了原生的 `print('正在计算结果...')` 语句,该文本会直接混入通信通道,导致 MCP Client 无法将该非 JSON 格式的字符串解析为合法的 RPC 帧,从而引发连接断开崩溃。

【黄金准则】所有在服务器端进行的调试信息、业务日志、排查记录,必须强制重定向输出到 `sys.stderr`(标准错误流)。MCP Client 会默默捕获服务器进程的 stderr,并安全地在客户端控制台中打印,绝不会干扰核心的控制流数据层。

复制代码
import logging
import sys

# 规范的 MCP 服务器日志初始化配置示例
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.StreamHandler(sys.stderr) # 极其重要:强制指定将日志流推向 stderr 管道!
    ]
)
logger = logging.getLogger("MCPServer")

# 在工具内部调用时进行安全日志输出
logger.info("当前正在执行本地文件读取安全策略验证...")
相关推荐
做萤石二次开发的哈哈1 小时前
AI 陪护机器人硬件如何接入萤石ERTC 实现实时通话?
人工智能·音视频·实时音视频·萤石开放平台
@insist1231 小时前
系统架构设计师-嵌入式处理器核心知识体系:从分类到架构选型全解析
架构·分类·系统架构·软考·系统架构设计师·软件水平考试
Luhui Dev1 小时前
Anthropic 的 Claude Code 翻车经验
人工智能·luhuidev
DataX_ruby821 小时前
2026年数据中台厂商市场份额分析
大数据·人工智能·数据治理·数据中台
Luchang-Li1 小时前
GPU传输带宽等信息监控nvidia-smi
人工智能·gpu·监控·性能·带宽
冬奇Lab1 小时前
Skill 平台的五个深坑:企业 AI 能力体系的质量治理
人工智能·agent
码农小白AI1 小时前
生鲜农产品来料验收提质,IACheck AI 报告文档审核比对农残兽残合格证书
人工智能
禹亮科技1 小时前
上海临港100㎡大型跨国会议室音视频集成方案(思科Webex+思必驰AI音频)
人工智能·音视频·思必驰吸顶麦·禹亮科技
海兰1 小时前
【web应用】Excel 项目数据自动化分析系统(AI 驱动分析)详细设计与部署指南(附源代码)
前端·人工智能·自动化·excel