您现在的位置是:网站首页> AI人工智能

AI模型调用MCP服务及实用MCP服务

摘要

AI模型调用MCP服务及实用MCP服务

***Agent让调用模型变得简单***

***Python编写MCP一般使用FastMCP,支持发布为studio sse streamable_http***

方便调用AI模型的Agent编程框架

AI入门编程推荐隔壁的程序员老王,点击进入


1.jpg


客户端将MCP工具列表和用户问题-》大语言模型-》需要调用MCP的信息返回给调用模型的客户端,客户端调用指定MCP->客户端获得MCP结果-》大语言模型-》返回给最终客户


AI辅助生成MCP例子

MCP协议:AI界的USB-C统一接口,从知识点到实践,从使用别人的MCP到自己编写部署MCP,cherry-studio使用链接MCP

UV与Conda工具使用收集

UVX NPX介绍

Awesome MCP Servers

mcp.so

Cherry Studio 新版本 1.2.9 一键式添加MCP服务器

CherryStudio的MCP配置

详细介绍NPX或UVX配置MCP服务

MCP客户端神器全收录

C# .NET4.5用 IHttpHandler如何编写SSE服务

MCP协议官网

MCP相关视频

MCP服务相关技术收集MCP

MCP协议详细讲解

AI 模型调用 MCP 服务的过程

AI 模型调用 MCP 服务的代码示例

C# 编写 Agent 调用 ollama 及 MCP 的方法

Trae+Chrome MCP Server 让AI接管你的浏览器

MCP典型服务

Chrome MCP Server

mcp2mqtt动动嘴就可以控制智能家居

excel-mcp-server使用 AI 代理创建、读取和修改 Excel 工作簿

Windows MCP.Net基于 .NET 的 Windows 桌面自动化 MCP (Model Context Protocol) 服务器

Windows-MCP用于 Windows 计算机的轻量级 MCP 服务器

AI辅助生成MCP例子



UVX NPX介绍

点击查看原文

UVX主要针对python编写的MCP, npx主要针对nodejs编写的MCP

直接使用UVX执行MCP命令(如uvx mcp-server-time)时,UVX会检查本地缓存或临时下载所需工具包。若MCP组件已存在于Python环境中,则直接调用;否则会触发下载安装过程

npx也会自动安装mcp

安装源

更换镜像源(国内用户常用

npm config set registry https://registry.npmmirror.com/



mcp server大多使用python和typescript编写,对应的启动命令分别为uvx和npx,下面将分别具体介绍一下这两种指令。熟悉指令的基础知识,有利于我们安装和调试mcp server

示例1:

{

  "mcpServers": {

    "fetch": {

      "command": "uvx",

      "args": [

        "mcp-server-fetch"

      ]

    }

  }

}


示例2:

{

  "mcpServers": {

    "amap-maps": {

      "command": "npx",

      "args": [

        "-y",

        "@amap/amap-maps-mcp-server"

      ],

      "env": {

        "AMAP_MAPS_API_KEY": "api_key"

      }

    }

  }

}

uvx:UV运行Python包提供的命令。它是uv tool run的简写

UV是由Astral开发的新一代Python包和项目管理工具。使用Rust编写,速度比pip快10-100倍!它是一体化工具:整合包管理(替代pip)、虚拟环境管理(替代venv)、依赖锁定(替代pip-tools)、Python版本管理(替代pyenv)、脚本运行(替代pipx)等功能。


快速安装

UV的安装非常简单,有多种方式可供选择:

方法1:独立安装脚本



macOS/Linux:


curl -LsSf https://astral.sh/uv/install.sh | sh



Windows:


powershell -c "irm https://astral.sh/uv/install.ps1 | iex"



方法2:使用pip安装



pip install uv


方法

3:Homebrew安装(macOS) 



brew install uv


 安装完成后,你可以通过在命令行输入uv --version来验证是否安装成功。


1.3、uv基本用法

1.3.1、创建项目

使用UV创建一个新项目


uv init uv_demo


1.3.2、创建虚拟环境

我是在conda创建的虚拟环境中安装了uv,你可以继续使用uv创建应用的虚拟环境。


cd uv_demo

uv venv


1.3.3、安装依赖包

uv安装依赖包非常简单且迅速:


uv add numpy pandas


1.3.4、运行Python脚本

 使用UV运行Python脚本:


uv run main.py


1.3.5、依赖锁定

生成锁文件,确保项目依赖版本的一致性:


uv lock


 这会创建一个uv.lock文件,详细记录所有依赖的精确版本和来源。


1.4、高级功能


1.4.1、Python版本管理

UV可以管理多个Python版本:



# 安装特定Python版本


uv python install 3.10 3.11 3.12



# 创建特定Python版本的虚拟环境


uv venv --python 3.11




1.4.2、工具管理


像pipx一样,UV可以运行和安装Python工具



# 在临时环境中运行工具


uvx pycowsay 'Hello UV!'



# 安装工具


uv tool install ruff




1.4.3、单文件脚本支持


UV支持带有内联依赖元数据的单文件脚本:



# /// [uv]


# dependencies = ["requests"]


# ///



import requests


print(requests.get("https://astral.sh").status_code)


 

然后直接运行:



uv run example.py


 

UV会自动处理依赖并在隔离环境中运行脚本




1.4.4、pip兼容接口


UV提供了pip兼容的接口,可直接替代pip命令:



# 编译依赖


uv pip compile requirements.in --output-file requirements.txt



# 安装锁定依赖


uv pip sync requirements.txt


UV命令速查

1.png


2、npx


npx是npm包管理器自5.2.0版本起内置的工具,全称为“Node Package Execute”,核心功能是临时执行Node.js模块命令。它简化了命令行工具的调用流程,无需预先全局或本地安装依赖包即可直接运行特定命令,尤其适合一次性或实验性操作。



npm的核心操作是包的安装与管理(install、uninstall等),而npx专注于“按需执行”。npm负责持久化依赖管理,npx负责临时或一次性操作的轻量化执行。



主要优势包括:



临时安装可执行依赖包:无需全局安装,避免环境污染


自动执行依赖包命令:安装完成后自动运行


自动加载 node_modules 中的依赖:无需手动指定 $PATH


可执行特定版本的命令:便于测试不同版本

支持执行 

GitHub 代码仓库:扩展了使用场景


2.1、npx基本用法


2.1.1、执行本地依赖包命令


若项目中已安装某个包(如knex),可直接运行其命令:



npx knex migrate:latest



无需全局安装knex,也无需手动配置package.json的scripts


2.1.2、临时安装并运行包


运行未安装的包(执行后自动删除):



npx create-react-app my-app  # 临时安装 create-react-app 并执行




2.1.3、指定版本运行


运行特定版本的包:



npx eslint@7.0.0 --version  # 使用 7.0.0 版本的 ESLint




2.1.4、执行远程代码

 

直接运行GitHub仓库中的代码:



npx https://gist.github.com/user/test  # 执行远程脚本




2.1.5、交互式命令模式


 进入包的交互式环境(如node REPL):



npx node@14  # 临时使用 Node.js 14 版本


 


2.2、npx使用示例


传统方式:先全局安装脚手架工具,再使用



# 安装


npm install fast-create-app -g


# 使用


fast-create-app create-app test



传统方式的缺点:



全局污染:全局安装的包会影响整个系统环境


版本冲突:不同项目可能需要同一工具的不同版本


权限问题:全局安装通常需要管理员权限


更新困难:全局包不会随项目依赖自动更新


存储占用:长期积累大量不再使用的全局包



npx 方式:一步到位,无需全局安装



npx fast-create-app create-app test



npx 的优势:

按需临时安装,用完即删

自动使用最新版本的包

可同时使用不同版本的工具

不需要额外的管理员权限


npx执行优先级机制


当执行命令时,npx遵循三级查找逻辑



1、本地项目依赖:优先在当前项目的node_modules/.bin目录中查找目标命令,适配项目级工具调用(如项目内配置的ESLint、Jest等)。



2、全局安装包:若本地未找到,检查用户全局安装的npm包(通过npm install -g安装的模块)。



3、临时下载执行:若前两步均未找到,npx会自动从npm仓库下载目标包到临时目录,执行完成后立即清理,避免磁盘空间浪费。



MCP协议详细讲解

Model Context Protocol(MCP)是由 Anthropic 推出的一种开源协议,旨在建立 AI 模型与开发环境之间的统一上下文交互标准。以下是对其的详细讲解:

1.png

背景与起源

在 AI 领域,大语言模型的应用常常面临数据孤岛和工具集成复杂的问题,不同的数据源和工具都有自己独特的 API 和集成方式,导致开发者需要为每个工具单独编写集成代码,开发和维护成本高,工具复用性低。为解决这些问题,Anthropic 于 2024 年 11 月 25 日开源发布了 MCP

核心概念

  • MCP Hosts :如 Claude Desktop、Cursor、 Cline、trae、Cherry Studio、IDE、AI 应用等,是运行 MCP 的主应用程序,负责发起连接并管理多个客户端实例,与用户进行交互并接收用户的问题或指令,再通过 MCP Clients 向 MCP Servers 发送请求以获取所需的数据或执行相应的操作
  • MCP Clients :由 Host 创建,与特定的 MCP Server 建立一对一的连接,负责协议通信和能力协商,充当 MCP Host 和 MCP Server 之间的“连接器”或“总机”,将 Host 的请求转发给 Server,并将 Server 的响应返回给 Host
  • MCP Servers :轻量级程序,通过标准化的模型上下文协议暴露特定功能,如文件读取、API 调用、数据库查询等,为 MCP Host 提供实际的数据和功能支持,每个 Server 提供一个特定的工具或能力

工作原理

  • 通信机制 :MCP 采用客户端 - 服务器架构,基于 JSON-RPC 2.0 消息格式,支持请求、响应和通知三种消息类型,确保通信的标准化和一致性。它主要支持两种通信方式,一种是标准输入输出(Stdio),适用于在同一台机器上运行的客户端和服务器之间的通信,客户端启动服务器程序作为子进程,消息通讯通过 stdin/stdout 进行;另一种是服务器发送事件(SSE),利用 HTTP 协议实现跨网络的实时数据传输,适用于需要访问远程资源的场景
  • 工作流程 :首先,Host 初始化 Client,Client 尝试与 Server 建立连接,并询问 Server 有哪些能力,Server 回应并返回所有支持的功能,从而建立 1:1 的连接。当用户与 LLM 交互提出问题或指令时,LLM 会告诉 Client 需要调用哪些 Tools,Client 收到 Host 的请求后,将请求信息发送给对应的 Server,Server 接收到信息后开始处理,处理完成后返回结果给 Client,Client 再将信息返回给 Host,Host 根据这些信息生成最终的回复返回给用户

主要功能与特性

  • 统一接口 :提供标准化的 API 接口,简化 AI 与各类上下文信息的交互,使得开发者无需为不同的数据源或工具编写复杂的适配代码,降低了开发难度和成本
  • 无缝集成 :能够轻松集成到现有开发工作流程中,无需对现有的系统和工具进行大规模的改造,即可实现 AI 模型与各种数据源和工具的快速连接和集成,提高了开发效率
  • 多源数据支持 :支持从多种来源获取上下文信息,包括代码仓库、文档、文件系统、数据库、远程 API 等,丰富了 AI 模型可以利用的数据资源,为模型的训练和推理提供了更全面、准确的上下文信息
  • 智能上下文管理 :优化上下文信息的传递,根据 AI 模型的需求和任务场景,自动筛选、组织和更新上下文信息,提高 AI 模型理解和生成的质量,使模型能够更准确地理解和处理复杂的任务
  • 扩展性设计 :具有灵活的架构,允许添加新的数据源和功能,开发者可以根据实际需求自由扩展 MCP 的功能,不断增加新的 MCP Servers 来提供新的工具和能力,以满足不断变化的业务需求

应用场景

  • 智能开发环境 :将 AI 模型与开发工具集成,如代码编辑器、IDE 等,使 AI 能够实时理解代码上下文,为开发者提供智能代码补全、代码生成、代码解释等功能,提高开发效率和代码质量
  • 智能办公助手 :连接办公软件和在线服务,如日历、邮件、文档管理系统等,帮助用户自动完成日常办公任务,如安排会议、发送邮件、生成报告等,提升办公自动化水平
  • 智能数据分析 :将 AI 模型与数据分析工具和数据源集成,如数据库、数据仓库、BI 工具等,使 AI 能够协助分析师进行数据查询、数据分析、数据可视化等工作,为决策提供更有力的支持
  • 智能客服系统 :集成企业内部的客户信息管理系统、订单管理系统等,使 AI 客服能够快速准确地获取客户相关的信息,为客户提供更精准、高效的咨询服务,提高客户满意度


JSON-RPC 2.0 的请求和响应示例

请求示例

{

  "jsonrpc": "2.0",

  "method": "add",

  "params": [2, 3],

  "id": 1

}

响应示例

{

  "jsonrpc": "2.0",

  "result": 5,

  "id": 1

}

错误响应示例

{

  "jsonrpc": "2.0",

  "error": {

    "code": -32601,

    "message": "Method not found"

  },

  "id": 1

}


批量请求示例

[

  {

    "jsonrpc": "2.0",

    "method": "add",

    "params": [2, 3],

    "id": 1

  },

  {

    "jsonrpc": "2.0",

    "method": "subtract",

    "params": [5, 2],

    "id": 2

  }

]

批量响应示例

[

  {

    "jsonrpc": "2.0",

    "result": 5,

    "id": 1

  },

  {

    "jsonrpc": "2.0",

    "result": 3,

    "id": 2

  }

]

这些示例展示了 JSON-RPC 2.0 请求和响应的基本格式,包括请求、响应以及错误处理等场景。



AI 模型调用 MCP 服务的过程

准备工作

  • 搭建 MCP 服务器 :开发者需先搭建 MCP 服务器,可使用 Anthropic 提供的开源框架如 FastMCP 等。定义好服务器的基本配置,如名称、版本等,并通过装饰器注册工具函数,每个工具函数对应一个具体的功能,如查询天气、发送邮件等
  • 集成 MCP 客户端 :在 AI 模型所在的系统或应用中集成 MCP 客户端,如在 Python 项目中安装相应的客户端库等

调用过程

  1. 用户发起请求 :用户通过与 AI 模型交互的方式,如在聊天界面输入问题或指令,表达其想要实现的需求
  2. AI 模型解析意图 :MCP 客户端将用户请求发送给 AI 模型,AI 模型对用户输入的自然语言进行理解和解析,确定用户的需求,并选择与之匹配的 MCP 函数及相应的参数
  3. 发送调用请求 :MCP 客户端根据 AI 模型返回的函数调用信息,向 MCP 服务器发送请求。请求中包含请求 ID、函数名称及参数等,格式通常为 JSON
  4. 执行服务并返回结果 :MCP 服务器接收到请求后,执行对应的工具函数,在本地或通过调用其他外部服务完成具体的任务处理,然后将执行结果按照规定的格式返回给 MCP 客户端。
  5. 结果整合与反馈 :MCP 客户端将 MCP 服务器返回的结果整合到对话上下文中,再次发送给 AI 模型。AI 模型根据整合后的上下文生成自然语言的回复,由 MCP 客户端将最终结果呈现给用户

通信机制

  • STDIO 方式 :适用于本地服务。MCP 客户端启动 MCP 服务器程序作为子进程,通过 stdin 和 stdout 进行消息传递,消息格式遵循 JSON-RPC 2.0
  • SSE 方式 :用于远程服务。MCP 客户端通过 Server-Sent Events 与 MCP 服务器进行通信,服务器定义特定接口用于推送和接收数据,消息格式同样基于 JSON-RPC 2.0

动态上下文管理

MCP 协议具有动态上下文管理机制,通过上下文窗口存储用户偏好、会话记录和环境数据等。在每次交互过程中,上下文会不断扩展和更新,同时对非关键信息进行压缩,以保证对话的连贯性和减少资源消耗

安全与认证机制

  • API 密钥验证 :MCP 服务通常会要求进行 API 密钥验证,只有拥有正确 API 密钥的客户端才能访问服务。
  • HTTPS 加密 :采用 HTTPS 协议对数据传输进行加密,确保数据在网络传输过程中的安全性。
  • 请求限制 :设置请求频率限制和配额限制等,防止服务被滥用,保护服务的稳定性和可靠性



AI 模型调用 MCP 服务的代码示例

基于 Python 的简单 MCP 服务端

Python

pip install mcp

/*

from mcp.server.fastmcp import FastMCP

import tools


mcp=FastMCP("host info mcp")

mcp.add_tool(tools.get_host_info)


def main()->none:

   print("hello from ai-mcp!")

   mcp.run("stdio")#还有sse

   mcp.run(transport="sse", port=9000)

   


if __name__=="__main__":

   main()


tools.py内容

def get_hosts_info()->str:

...



*/


from mcp import MCP, tool


mcp = MCP()


@mcp.register_tool

class WeatherTool:

    @tool(name="get_weather", description="获取指定城市的天气信息")

    def get_weather(self, city: str):

        # 这里可以添加获取天气信息的逻辑,比如调用天气 API 等

        return f"The weather in {city} is sunny."


    @tool(name="get_weather_forecast", description="获取指定城市未来几天的天气预报")

    def get_weather_forecast(self, city: str, days: int):

        # 添加获取天气预报的逻辑

        return f"The weather forecast for {city} in the next {days} days."


if __name__ == "__main__":

    mcp.start()

基于 Java 的 MCP 服务端

java

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.io.ClassPathResource;

import org.springframework.core.io.Resource;

import org.springframework.util.StringUtils;

import org.springframework.web.reactive.function.server.RouterFunctions;

import org.springframework.web.reactive.function.server.ServerResponse;

import reactor.core.publisher.Mono;


import java.util.Collections;

import java.util.Map;


@Configuration

public class MCPConfig {


    @Bean

    public RouterFunctions.Route mcpRoute() {

        return RouterFunctions.route()

                .POST("/mcp/weather", this::getWeather)

                .build();

    }


    private Mono<ServerResponse> getWeather(ServerRequest request) {

        Map<String, String> queryParams = request.queryParams();

        String city = queryParams.get("city");

        if (StringUtils.hasText(city)) {

            String weatherInfo = "The weather in " + city + " is sunny.";

            return ServerResponse.ok().bodyValue(Collections.singletonMap("weather", weatherInfo));

        } else {

            return ServerResponse.badRequest().bodyValue(Collections.singletonMap("error", "City parameter is required"));

        }

    }

}

AI 模型调用 MCP 服务的代码示例

基于 Python 的 OpenAI 模型调用 MCP 服务

Python

import openai

import requests

from mcp import MCPClient


# 初始化 MCP 客户端

mcp_client = MCPClient()

mcp_client.connect("http://localhost:8080/mcp")  # 替换为 MCP 服务的实际地址


# 调用 MCP 服务中的工具

def call_mcp_tool(tool_name, **kwargs):

    return mcp_client.call_tool(tool_name, **kwargs)


# 使用 OpenAI 模型

openai.api_key = "your_openai_api_key"  # 替换为你的 OpenAI API 密钥


def get_ai_response(user_query):

    # 构建消息列表

    messages = [

        {"role": "system", "content": "You are a helpful assistant."},

        {"role": "user", "content": user_query}

    ]


    # 调用 OpenAI API

    response = openai.ChatCompletion.create(

        model="gpt-4-turbo-preview",

        messages=messages,

        tools=mcp_client.list_tools(),  # 提供可用的 MCP 工具

        tool_choice="auto"

    )


    # 处理模型返回的结果

    ai_response = ""

    for choice in response.choices:

        message = choice.message

        if message.content:

            ai_response += message.content + "\n"

        if message.tool_calls:

            for tool_call in message.tool_calls:

                tool_name = tool_call.function.name

                tool_args = tool_call.function.arguments

                # 调用 MCP 工具

                tool_result = call_mcp_tool(tool_name, **tool_args)

                ai_response += f"Calling tool {tool_name} with args {tool_args}\n"

                ai_response += tool_result + "\n"

                # 将工具结果添加到消息中,继续与模型对话

                messages.append({"role": "assistant", "content": "", "tool_calls": [tool_call]})

                messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": tool_result})

                # 获取下一个模型响应

                next_response = openai.ChatCompletion.create(

                    model="gpt-4-turbo-preview",

                    messages=messages,

                    tools=mcp_client.list_tools(),

                    tool_choice="auto"

                )

                if next_response.choices[0].message.content:

                    ai_response += next_response.choices[0].message.content + "\n"

    return ai_response


# 示例 usage

user_input = "What's the weather like in Beijing?"

print(get_ai_response(user_input))

基于 Java 的 Spring AI 模型调用 MCP 服务

java

import org.springframework.ai.chat.client.ChatClient;

import org.springframework.ai.chat.client.ChatClientBuilder;

import org.springframework.ai.mcp.client.McpClient;

import org.springframework.ai.mcp.client.McpClientBuilder;

import org.springframework.ai.mcp.client.McpFunctionCallback;

import org.springframework.ai.tool.ToolCallbackProvider;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;


import java.util.List;


@Configuration

public class AIConfig {


    @Bean

    public McpClient mcpClient() {

        // 配置 MCP 服务器参数

        var stdioParams = ServerParameters.builder("java")

                .args("-Dspring.ai.mcp.server.stdio=true",

                        "-Dspring.main.web-application-type=none",

                        "-Dlogging.pattern.console=",

                        "-jar",

                        "target/mcp-server-0.0.1-SNAPSHOT.jar")

                .build();

        // 创建 MCP 客户端

        return McpClient.sync(new StdioClientTransport(stdioParams));

    }


    @Bean

    public ToolCallbackProvider mcpTools(McpClient mcpClient) {

        // 获取 MCP 服务器中的工具列表并转换为 Function Callback

        return mcpClient.listTools(null)

                .tools()

                .stream()

                .map(tool -> new McpFunctionCallback(mcpClient, tool))

                .toList();

    }


    @Bean

    public ChatClient chatClient(ChatClientBuilder chatClientBuilder, ToolCallbackProvider mcpTools) {

        // 初始化聊天客户端并设置默认工具

        return chatClientBuilder.defaultFunctions(mcpTools).build();

    }

}


// 使用示例

public class AIService {

    private final ChatClient chatClient;


    public AIService(ChatClient chatClient) {

        this.chatClient = chatClient;

    }


    public String generateResponse(String userQuery) {

        return chatClient

                .prompt(userQuery)

                .call()

                .content();

    }

}


使用 ASP.NET Core 来创建一个 Web API 服务,并模拟天气查询功能

C# MCP 服务端代码示例

csharp

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.AspNetCore.Mvc;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Hosting;


namespace MCPService

{

    public class Startup

    {

        public void ConfigureServices(IServiceCollection services)

        {

            services.AddControllers();

        }


        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

        {

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }


            app.UseRouting();


            app.UseEndpoints(endpoints =>

            {

                endpoints.MapControllers();

            });

        }

    }

    /*

这段代码定义了一个名为WeatherController的控制器类。这个类继承自ControllerBase

,并使用了[ApiController]和[Route("mcp")]特性,表明这是用于处理HTTP请求的API控制器,并指定了其基础路由为/mcp。

在控制器类中,定义了一个名为GetWeather的方法,该方法使用了[HttpGet("weather")]特性。这表明这是一个处理HTTP GET请求的方法,其对应的路由是mcp/weather。这个方法接受一个名为city的参数,通过[FromQuery]特性从查询字符串中获取。

当客户端向/mcp/weather发起一个带有查询参数(如city=Paris)的GET请求时,GetWeather方法会处理这个请求,并返回一个IActionResult类型的对象,即一个包含响应内容和状态码的对象。在实际应用中,这个方法可能会根据提供的城市名称来获取和返回相应的天气信息。

*/

    [ApiController]

    [Route("mcp")]

    public class WeatherController : ControllerBase

    {

        [HttpGet("weather")]

        public IActionResult GetWeather([FromQuery] string city)

        {

            if (string.IsNullOrEmpty(city))

            {

                return BadRequest("City parameter is required");

            }


            // 模拟天气查询逻辑

            var weatherInfo = $"The weather in {city} is sunny.";


            return Ok(new { weather = weatherInfo });

        }


        [HttpGet("weather-forecast")]

        public IActionResult GetWeatherForecast([FromQuery] string city, [FromQuery] int days)

        {

            if (string.IsNullOrEmpty(city))

            {

                return BadRequest("City parameter is required");

            }


            // 模拟天气预报逻辑

            var weatherForecast = $"The weather forecast for {city} in the next {days} days.";


            return Ok(new { forecast = weatherForecast });

        }

   

[HttpPost("weather")]

    public IActionResult PostWeather([FromBody] WeatherRequest weatherRequest)

    {

        // 处理POST请求的逻辑

        return Ok($"Received weather data for {weatherRequest.City}: {weatherRequest.Temperature}°C");

    }


// 新增的可以GET和POST调用的方法

    [HttpGet("data")]

    [HttpPost("data")]

    public IActionResult GetAndPostData([FromQuery] string name, [FromBody] string postData = null)

    {

        if (HttpContext.Request.Method == HttpMethods.Get)

        {

            return Ok($"Received GET request with name: {name}");

        }

        else if (HttpContext.Request.Method == HttpMethods.Post)

 {

                   return Ok($"Received POST request with name: {name} and post data: {postData}");

        }


        return BadRequest("Invalid request method");

    }



}


public class WeatherRequest

{

    public string City { get; set; }

    public double Temperature { get; set; }

}



    public class Program

    {

        public static void Main(string[] args)

        {

            var host = CreateHostBuilder(args).Build();

            host.Run();

        }


        public static IHostBuilder CreateHostBuilder(string[] args) =>

            Host.CreateDefaultBuilder(args)

                .ConfigureWebHostDefaults(webBuilder =>

                {

                    webBuilder.UseStartup<Startup>();

                });

    }

}

说明

项目结构:

Startup 类配置了服务和中间件。

WeatherController 是一个 ASP.NET Core 控制器,提供了两个端点 /mcp/weather 和 /mcp/weather-forecast。

功能:

/mcp/weather 接受一个 city 参数,返回该城市的天气信息。

/mcp/weather-forecast 接受 city 和 days 参数,返回该城市未来几天的天气预报。

运行服务:

创建一个 ASP.NET Core 项目并复制上述代码。

使用 dotnet run 命令启动服务,服务默认运行在 https://localhost:5001 和 http://localhost:5000。

测试服务:

使用工具如 Postman 或 curl 测试 API:

获取天气信息:GET http://localhost:5000/mcp/weather?city=Beijing

获取天气预报:GET http://localhost:5000/mcp/weather-forecast?city=Beijing&days=3


C# 用OpenAI模型调用

public class WeatherRequestFunction : IRequestFunction

{

    public string Name => "weather";


    public async Task<IDictionary<string, object>> InvokeAsync(IDictionary<string, object> parameters)

    {

        using var httpClient = new HttpClient();

        var city = parameters["city"].ToString();

        var response = await httpClient.GetAsync($"http://localhost:5000/mcp/weather?city={city}");

        response.EnsureSuccessStatusCode();

        var content = await response.Content.ReadAsStringAsync();

        return new Dictionary<string, object> { { "result", content } };

    }


    public string Serialize(IRequestFunction function)

    {

        return $"Calling tool {function.Name} with parameters {function}";

    }


    public Task SerializeAsync(IRequestFunction function)

    {

        // 实现序列化逻辑

        return Task.CompletedTask;

    }

}

代码说明

OpenAI 客户端:创建 OpenAI 客户端实例,并配置 API 密钥和日志记录器。

MCP 工具:定义一个 WeatherRequestFunction 类实现 IRequestFunction 接口,用于调用 MCP 服务中的天气查询工具。

ChatClient:创建 ChatClient 实例,传入 OpenAI 客户端和日志记录器。

聊天历史:初始化聊天历史记录。

交互式聊天:在循环中读取用户输入,将其添加到聊天历史中,并调用 OpenAI API 获取响应。打印助手的响应并将其添加到聊天历史中。

其他信息

确保你的 MCP 服务正在运行,并且可以通过 http://localhost:5000/mcp/weather 访问。

替换成您的实际 OpenAI API 密钥。

如果您没有 MCP 服务,可以参考前面的示例代码实现一个简单的 MCP 服务。



C# 编写 Agent 调用 ollama 及 MCP 的方法

调用 ollama

安装 Ollama SDK :可以使用如下命令安装 Ollama 的 C# SDK,“dotnet add package Ollama --version 1.9.0”。

简单对话 :设置模型名称和 ollama 的 API 地址,利用 OllamaApiClient 进行对话生成,示例代码如下:

**```csharp

string modelName = "qwen2:7b";

using var ollama = new OllamaApiClient(baseUri: new Uri("http://127.0.0.1:11434/api"));

Console.WriteLine("开始对话!!!");

string userInput = "";

do

{

Console.WriteLine("User:");

userInput = Console.ReadLine()!;

var enumerable = ollama.Completions.GenerateCompletionAsync(modelName, userInput);

Console.WriteLine("Agent:");

await foreach (var response in enumerable)

{

Console.Write($"{response.Response}");

}

Console.WriteLine();

} while (!string.Equals(userInput, "exit", StringComparison.OrdinalIgnoreCase));

Console.WriteLine("对话结束!!!");



**[^2^]


  * **多轮对话** :使用 Chat 对象进行分角色的多轮对话,通过 List 消息存储之前的对话记录,以便模型捕获上下文,代码示例:

**```csharp

string modelName = "glm4:9b";

using var ollama = new OllamaApiClient(baseUri: new Uri("http://127.0.0.1:11434/api"));

Console.WriteLine("开始对话!!!");

string userInput = "";

List messages = [];

do

{

    messages = messages.TakeLast(5).ToList();

    Console.WriteLine("User:");

    userInput = Console.ReadLine()!;

    messages.Add(new Message(MessageRole.User, userInput));

    var enumerable = ollama.Chat.GenerateChatCompletionAsync(modelName, messages, stream: true);

    Console.WriteLine("Agent:");

    StringBuilder builder = new();

    await foreach (var response in enumerable)

    {

        string content = response.Message.Content;

        builder.AppendLine(content);

        Console.Write(content);

    }

    messages.Add(new Message(MessageRole.Assistant, builder.ToString()));

    Console.WriteLine();

} while (!string.Equals(userInput, "exit", StringComparison.OrdinalIgnoreCase));

Console.WriteLine("对话结束!!!");



```**[^2^]


  * **Function call** :若要使用 function call 功能,需设置 autoCallTools 为 true,并给 Ollama 注册相应的工具类,代码如下:

**```csharp

string modelName = "llama3.1:8b";

using var ollama = new OllamaApiClient(baseUri: new Uri("http://127.0.0.1:11434/api"));

var chat = ollama.Chat(

    model: modelName,

    systemMessage: "You are a helpful assistant.",

    autoCallTools: true);

var mathService = new MathService();

chat.AddToolService(mathService.AsTools(), mathService.AsCalls());

while (true)

{

    try

    {

        Console.WriteLine("User>");

        var newMessage = Console.ReadLine();

        var msg = await chat.SendAsync(newMessage);

        Console.WriteLine("Agent> " + msg.Content);

    }

    finally

    {

        Console.WriteLine(chat.PrintMessages());

    }

}

```**[^2^]


### 调用 MCP

目前未查到有成熟的 C# 调用 MCP 的官方 SDK 或常用库,但可以尝试以下思路:

  * **通过 HTTP 请求调用** :如果 MCP 提供了 HTTP API 接口,可以使用 C# 中的 HttpClient 类来发送 HTTP 请求进行调用。基本步骤如下:

    1. 创建 HttpClient 对象,并设置相关请求头等信息。

    2. 构造请求内容,根据 MCP API 的要求,将请求参数进行序列化。

    3. 发送 POST 或 GET 等请求到 MCP 的 API 地址。

    4. 处理返回的响应,对响应内容进行反序列化等操作,获取所需数据。


例如,假设 MCP 的 API 地址为<http://localhost:8000/mcp/api>,需要发送一个获取数据的请求,代码可能如下:

**```csharp

using (var client = new HttpClient())

{

    client.BaseAddress = new Uri("http://localhost:8000/");

    var response = await client.GetAsync("mcp/api?param1=value1");

    if (response.IsSuccessStatusCode)

    {

        var result = await response.Content.ReadAsStringAsync();

        // 处理结果

    }

    else

    {

        // 处理错误

    }

}

```**

  * **参考 Python 实现进行移植** :上述提到的 Python 调用 MCP 的代码示例中,展示了如何创建 MCP Server、获取工具列表以及创建 Agent 等过程。可以参考其逻辑和交互方式,在 C# 中进行相应的实现。例如,对于 MCP Server 的连接,可以考虑在 C# 中使用类似的网络通信方式;对于工具的调用,可以解析 MCP 返回的工具信息,并根据用户输入的问题,选择合适的工具进行调用等[^4^]。


MathService代码:

using System;

using System.Collections.Generic;

using System.Linq;


// 定义工具接口

public interface IToolsService

{

    public string Name { get; }

    public List<ToolDefinition> DefineTools();

}


// 定义工具函数

public class MathService : IToolsService

{

    public string Name => "math";

    

    // 定义工具

    public List<ToolDefinition> DefineTools()

    {

        return new List<ToolDefinition>

        {

            new ToolDefinition("add", "Add two numbers", "a: number, b: number", Add),

            new ToolDefinition("subtract", "Subtract two numbers", "a: number, b: number", Subtract),

            new ToolDefinition("multiply", "Multiply two numbers", "a: number, b: number", Multiply),

            new ToolDefinition("divide", "Divide two numbers", "a: number, b: number", Divide)

        };

    }


    // 加法

    public double Add(double a, double b)

    {

        return a + b;

    }


    // 减法

    public double Subtract(double a, double b)

    {

        return a - b;

    }


    // 乘法

    public double Multiply(double a, double b)

    {

        return a * b;

    }


    // 除法

    public double Divide(double a, double b)

    {

        if (b == 0)

        {

            throw new DivideByZeroException("Division by zero is not allowed.");

        }

        return a / b;

    }

}


ToolDefinition类通常不是.NET标准库或框架的一部分,也不是Ollama或其他主流库的内置类。因此,您需要自己定义它,或者参考您所使用的特定库或框架的实现

using System;


public class ToolDefinition

{

    // 工具名称

    public string Name { get; set; }

    // 工具描述

    public string Description { get; set; }

    // 工具参数列表

    public string Parameters { get; set; }

    // 工具处理函数的委托类型

    public Func<object[], object> Function { get; set; }


    public ToolDefinition(string name, string description, string parameters, Func<object[], object> function)

    {

        Name = name;

        Description = description;

        Parameters = parameters;

        Function = function;

    }

}



Chrome MCP Server

点击进入源码页

Chrome MCP Server 是一个基于chrome插件的 模型上下文协议 (MCP) 服务器,它将您的 Chrome 浏览器功能暴露给 Claude 等 AI 助手,实现复杂的浏览器自动化、内容分析和语义搜索等。与传统的浏览器自动化工具(如playwright)不同,Chrome MCP server直接使用您日常使用的chrome浏览器,基于现有的用户习惯和配置、登录态,让各种大模型或者各种chatbot都可以接管你的浏览器,真正成为你的如常助手


环境要求

Node.js >= 18.19.0 和 (npm 或 pnpm)

Chrome/Chromium 浏览器

安装pnpm :npm install -g pnpm

安装步骤

1.从github上下载最新的chrome扩展

下载地址:https://github.com/hangwin/mcp-chrome/releases


2.全局安装mcp-chrome-bridge

npm


npm install -g mcp-chrome-bridge

pnpm


# 方法1:全局启用脚本(推荐)

pnpm config set enable-pre-post-scripts true

pnpm install -g mcp-chrome-bridge


# 方法2:如果 postinstall 没有运行,手动注册

pnpm install -g mcp-chrome-bridge

mcp-chrome-bridge register

注意:pnpm v7+ 默认禁用 postinstall 脚本以提高安全性。enable-pre-post-scripts 设置控制是否运行 pre/post 安装脚本。如果自动注册失败,请使用上述手动注册命令。


3.加载 Chrome 扩展


打开 Chrome 并访问 chrome://extensions/

启用"开发者模式"

点击"加载已解压的扩展程序",选择 your/dowloaded/extension/folder

点击插件图标打开插件,点击连接即可看到mcp的配置


在支持MCP协议的客户端中使用

使用streamable http的方式连接(👍🏻推荐)

将以下配置添加到客户端的 MCP 配置中以cherryStudio为例:


推荐用streamable http的连接方式


{

  "mcpServers": {

    "chrome-mcp-server": {

      "type": "streamableHttp",

      "url": "http://127.0.0.1:12306/mcp"

    }

  }

}

使用stdio的方式连接(备选)

假设你的客户端仅支持stdio的连接方式,那么请使用下面的方法:


1.先查看你刚刚安装的npm包的安装位置

# npm 查看方式

npm list -g mcp-chrome-bridge

# pnpm 查看方式

pnpm list -g mcp-chrome-bridge

假设上面的命令输出的路径是:/Users/xxx/Library/pnpm/global/5 那么你的最终路径就是:/Users/xxx/Library/pnpm/global/5/node_modules/mcp-chrome-bridge/dist/mcp/mcp-server-stdio.js


2.把下面的配置替换成你刚刚得到的最终路径

{

  "mcpServers": {

    "chrome-mcp-stdio": {

      "command": "npx",

      "args": [

        "node",

        "/Users/xxx/Library/pnpm/global/5/node_modules/mcp-chrome-bridge/dist/mcp/mcp-server-stdio.js"

      ]

    }

  }

}


mcp2mqtt动动嘴就可以控制智能家居

点击进入开源地址

本项目通过将 MCP 协议转换为 MQTT 协议,我们能够利用强大的大型语言模型(LLMs),就能轻松操控您的智能家居、机器人或其他硬件设备。



excel-mcp-server使用 AI 代理创建、读取和修改 Excel 工作簿

点击查看源码

模型上下文协议 (MCP) 服务器,无需安装 Microsoft Excel 即可作 Excel 文件。使用 AI 代理创建、读取和修改 Excel 工作簿。

Excel 作 :创建、读取、更新工作簿和工作表

数据作 :公式、格式、图表、数据透视表和 Excel 表格

数据验证 :内置范围、公式和数据完整性验证

格式: 字体样式、颜色、边框、对齐方式和条件格式

表格作 :使用自定义样式创建和管理 Excel 表格

图表创建 :生成各种图表类型(折线图、条形图、饼图、散点图等)

数据透视表 :创建用于数据分析的动态数据透视表

工作表管理 :轻松复制、重命名、删除工作表

三重传输支持 :stdio、SSE(已弃用)和可流式传输的 HTTP

远程和本地 :既可以在本地工作,也可以作为远程服务工作



Trae+Chrome MCP Server 让AI接管你的浏览器

点击查看原文

一、安装与配置

环境准备

Node.js ≥ 18.19.0 + npm

Chrome/Chromium 浏览器

快速部署和使用

1、安装Chrome扩展插件

        从 GitHub Releases 下载最新扩展包,在 chrome://extensions 中启用开发者模式并加载解压的文件夹。


2、安装桥接工具

npm install -g mcp-chrome-bridge

AI写代码

    若自动注册失败,需手动执行 mcp-chrome-bridge register。


3、打开Chrome浏览器,点击扩展程序进入配置页

1.png


4、点击连接

1.png


5、打开Trae客户端,进入MCP管理页

1.png


6、添加MCP服务

{

  "mcpServers": {

    "chrome-mcp-server": {

      "type": "streamableHttp",

      "url": "http://127.0.0.1:12306/mcp"

    }

  }

}

AI写代码

7、MCP服务需要添加到智能体才可以在Trae内使用,进入智能体管理页面

1.png


8、配置智能体,勾选刚刚配置的MCP服务

1.png


9、在Trae的对话界面选择智能体就可以对话,让浏览器帮你干活啦

1.png


二、应用场景

内容创作

        AI 自动总结网页内容 → 调用 Excalidraw 绘制思维导图。


竞品监控

        定时截图竞品网站首页,对比分析布局更新。


工作流优化

        自动填写表单、批量关闭冗余标签页、整理书签。


开发调试

        网络请求拦截与 API 结构分析。


Windows MCP.Net基于 .NET 的 Windows 桌面自动化 MCP (Model Context Protocol) 服务器

点击进入源码页

一个基于 .NET 的 Windows 桌面自动化 MCP (Model Context Protocol) 服务器,为 AI 助手提供与 Windows 桌面环境交互的能力。

重要提示: 本项目需要 .NET 10 才能运行,请先确保你的本地安装了 .NET 10。如果尚未安装,请访问 .NET 10 下载页面 进行下载和安装。


1. MCP 客户端配置

在您的 MCP 客户端配置中添加以下配置:


使用全局安装的工具(推荐)

{

    "mcpServers": {

     "Windows-MCP.Net": {

      "type": "stdio",

      "command": "dnx",

      "args": ["Windows-MCP.Net@", "--yes"],

      "env": {}

    }

    }

}

使用项目源码直接运行(开发模式)

方式一:工作区配置

在项目根目录创建 .vscode/mcp.json 文件:


{

  "mcpServers": {

    "Windows-MCP.Net-Dev": {

      "type": "stdio",

      "command": "dotnet",

      "args": ["run", "--project", "src/Windows-MCP.Net.csproj"],

      "cwd": "${workspaceFolder}",

      "env": {}

    }

  }

}

方式二:用户配置

通过VS Code命令面板运行 MCP: Open User Configuration,添加:


{

  "mcpServers": {

    "Windows-MCP.Net-Local": {

      "type": "stdio",

      "command": "dotnet",

      "args": ["run", "--project", "src/Windows-MCP.Net.csproj"],

      "env": {}

    }

  }

}

注意: 使用项目源码方式便于开发调试,修改代码后无需重新安装即可生效。VS Code 1.102+ 版本支持MCP服务器的自动发现和管理。


2. 安装和运行

方式一:全局安装(推荐)

dotnet tool install --global WindowsMCP.Net

方式二:从源码运行

# 克隆仓库

git clone https://github.com/AIDotNet/Windows-MCP.Net.git

cd Windows-MCP.Net

# 构建项目

dotnet build

# 运行项目

dotnet run --project src/Windows-MCP.Net.csproj

3. 开始使用

配置完成后,重启您的MCP客户端,即可开始使用Windows桌面自动化功能!



Windows-MCP用于 Windows 计算机的轻量级 MCP 服务器

点击查看源码

"mcpServers": {

    "windows-mcp": {

      "command": "uv",

      "args": [

        "--directory",

        "<path to the windows-mcp directory>",

        "run",

        "main.py"

      ]

    }

  }



详细介绍NPX或UVX配置MCP服务

要使用 npx 或 uvx 配置和运行 MCP(Model Context Protocol)服务,需结合具体的 MCP 服务实现工具(通常是 Node.js 或 Python 生态的包)。以下是详细步骤和说明:

一、背景知识

npx:Node.js 生态的包执行工具,可直接运行 npm 仓库中的包(无需全局安装),适用于 Node.js 编写的 MCP 服务。

uvx:Rust 编写的快速 Python 包执行工具(类似 npx,属于 uv 包管理器的一部分),适用于 Python 编写的 MCP 服务。

MCP 服务:需遵循 MCP 协议(如可流式 HTTP 传输),提供标准化的客户端 - 服务器通信能力(如模型上下文管理、消息流式传输等)。

二、使用 npx 配置 Node.js 版 MCP 服务

若 MCP 服务基于 Node.js 实现(如 @mcp/server 等包),步骤如下:

1. 安装 Node.js 和 npm

确保环境中已安装 Node.js(含 npm),推荐版本 16+。

验证:node -v 和 npm -v 可正常输出版本号。

2. 直接运行 MCP 服务包

使用 npx 临时执行 MCP 服务包,无需提前安装。基本命令格式:


bash

npx [mcp-package-name] [配置参数]

3. 常见配置参数(以假设的 @mcp/server 为例)

MCP 服务通常支持通过命令行参数或环境变量配置核心功能,例如:


bash

# 启动 MCP 服务,指定端口、端点路径和允许的 Origin

npx @mcp/server \

  --port 8080 \                 # 服务端口(默认可能为 65432)

  --endpoint /mcp \             # MCP 端点路径(符合协议要求的单一端点)

  --allowed-origins "http://localhost:3000" \  # 允许的客户端 Origin(防 DNS 重绑定)

  --log-level info \            # 日志级别

  --session-timeout 3600        # 会话超时时间(秒)

4. 环境变量配置

部分参数可通过环境变量设置(优先级可能高于命令行):


bash

# 示例:通过环境变量配置

export MCP_PORT=8080

export MCP_ALLOWED_ORIGINS="http://localhost:3000,https://example.com"

npx @mcp/server  # 自动读取环境变量

5. 验证服务是否启动

服务启动后,可通过 curl 测试端点是否可用:


bash

curl http://localhost:8080/mcp -I  # 检查是否返回 200 或 405(允许 POST/GET)

三、使用 uvx 配置 Python 版 MCP 服务

若 MCP 服务基于 Python 实现(如 mcp-server 等包),步骤如下:

1. 安装 uv 包管理器

uvx 是 uv 的子命令,需先安装 uv:

bash

# 安装 uv(适用于 Linux/macOS,Windows 需调整)

curl -LsSf https://astral.sh/uv/install.sh | sh


验证:uv --version 和 uvx --version 可正常输出。

2. 直接运行 MCP 服务包

使用 uvx 执行 Python 版 MCP 服务,命令格式:


bash

uvx [mcp-package-name] [配置参数]

3. 常见配置参数(以假设的 mcp-server 为例)

Python 版 MCP 服务的配置参数与 Node.js 版类似,例如:


bash

# 启动 MCP 服务,配置核心参数

uvx mcp-server \

  --host 127.0.0.1 \            # 绑定本地地址(符合安全要求,避免暴露公网)

  --port 8080 \

  --endpoint /mcp \

  --cors-allowed-origins "http://localhost:3000" \  # CORS 配置(对应 Origin 验证)

  --enable-sse true             # 启用 SSE 流式传输(符合可流式 HTTP 要求)

4. 配置文件方式

复杂配置可通过 JSON 或 YAML 文件指定,例如:


bash

# 使用配置文件启动

uvx mcp-server --config ./mcp-config.json


mcp-config.json 示例:


json

{

  "port": 8080,

  "endpoint": "/mcp",

  "allowed_origins": ["http://localhost:3000"],

  "session": {

    "timeout": 3600,

    "auto_create": true

  }

}

5. 验证服务

同 Node.js 版,通过 curl 测试:


bash

curl http://localhost:8080/mcp -X POST \

  -H "Content-Type: application/json" \

  -d '{"jsonrpc": "2.0", "method": "initialize", "id": 1}'


四、核心配置项说明(符合 MCP 协议要求)

无论使用 npx 还是 uvx,MCP 服务的配置需满足协议规范:


端点路径:必须提供单一 HTTP 端点(如 /mcp),支持 POST(客户端发消息)和 GET(SSE 流)。

安全验证:

必须验证客户端的 Origin 头(通过 allowed-origins 配置)。

本地运行时绑定 127.0.0.1(而非 0.0.0.0),避免未授权访问。

会话管理:支持通过 Mcp-Session-Id 头管理会话,需配置会话超时时间。

流式传输:启用 SSE(text/event-stream)支持服务器向客户端流式发送消息。

五、总结

npx 适用于 Node.js 生态的 MCP 服务,直接运行 npm 包并通过命令行 / 环境变量配置。

uvx 适用于 Python 生态的 MCP 服务,依赖 uv 工具,支持配置文件和参数化启动。

核心是确保配置符合 MCP 协议(如端点、安全验证、流式传输),具体参数需参考所用 MCP 服务包的文档。


npx 的核心作用是 无需全局安装包,直接执行对应 MCP 工具的可执行文件。

例子 1:通用 TCP 控制型 MCP 服务(基于 mcp-server)

场景

搭建简单的 MCP 服务,实现「客户端 → MCP 服务 → 目标服务器」的 TCP 连接转发,并支持连接数限制、日志输出等基础控制。

完整 npx 命令

npx mcp-server@latest \

  --protocol tcp \

  --listen-port 8080 \

  --listen-host 0.0.0.0 \

  --target-host 192.168.1.100 \

  --target-port 9090 \

  --log-level info \

  --max-connections 50 \

  --timeout 30000


mcp-server@latest 包名 + 版本 如 @1.2.0(固定版) 指定要执行的 MCP 服务包,@latest 表示使用最新版本,生产环境建议固定版本(如 @1.2.0)。


例子 2:本地自定义 MCP 服务(基于项目依赖 mcp-cli)

场景

本地 Node.js 项目中已将 mcp-cli 作为开发依赖(npm install mcp-cli --save-dev),通过 npx 直接执行本地依赖的 MCP 工具,加载自定义配置文件启动服务(适合企业内部定制化 MCP 服务,如设备管理、数据采集)。

完整 npx 命令

bash

npx mcp-cli start \

  --config ./config/mcp-service.yaml \

  --env production \

  --port 8888 \

  --watch \

  --debug \

  --log-rotate 7


mcp-cli start包名 + 命令无默认值mcp-cli 是本地项目依赖的 MCP 管理工具,start 是其内置命令(表示 “启动 MCP 服务”)。



CherryStudio的MCP配置

点击查看官方配置MCP文档

手动配置一个STADIO MCP

一个STATIO MCP配置例子,它的源码地址

1.jpg


它的uvx的json

{

  "mcpServers": {

    "fetch": {

      "command": "uvx",

      "args": ["mcp-server-fetch"]

    }

  }

}


多参数配置,一行一个参数

1.jpg


自动安装MCP

直接给指令:

帮我安装一个 filesystem mcp server



AI辅助生成MCP例子

####【豆包】

你知道AI模型调用MCP吗??

。。。

写一个MCP的完整例子并给出模型调用这个MCP例子

。。。


Python实现
mcp_weather_server.py

import json

import socket

import threading

from typing import Dict, Any


class MCPWeatherServer:

    """MCP天气服务服务器实现"""

    

    def __init__(self, host: str = 'localhost', port: int = 8000):

        self.host = host

        self.port = port

        self.server_socket = None

        self.running = False

        

        # 模拟天气数据库

        self.weather_database = {

            "北京": {"temperature": 25, "condition": "晴朗", "wind": "微风"},

            "上海": {"temperature": 28, "condition": "多云", "wind": "东风3级"},

            "广州": {"temperature": 30, "condition": "小雨", "wind": "南风2级"},

            "深圳": {"temperature": 29, "condition": "阴天", "wind": "东南风1级"},

            "成都": {"temperature": 23, "condition": "晴转多云", "wind": "西北风2级"}

        }

    

    def start(self):

        """启动MCP服务器"""

        self.running = True

        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.server_socket.bind((self.host, self.port))

        self.server_socket.listen(5)

        print(f"MCP天气服务已启动,监听 {self.host}:{self.port}")

        

        try:

            while self.running:

                client_socket, client_address = self.server_socket.accept()

                print(f"接收到来自 {client_address} 的连接")

                client_handler = threading.Thread(

                    target=self.handle_client,

                    args=(client_socket,)

                )

                client_handler.start()

        except KeyboardInterrupt:

            print("服务器正在关闭...")

        finally:

            self.stop()

    

    def stop(self):

        """停止MCP服务器"""

        self.running = False

        if self.server_socket:

            self.server_socket.close()

        print("MCP天气服务已关闭")

    

    def handle_client(self, client_socket: socket.socket):

        """处理客户端请求"""

        try:

            # 接收请求数据

            data = client_socket.recv(1024).decode('utf-8')

            if not data:

                return

                

            print(f"收到请求: {data}")

            

            # 解析MCP请求

            request = json.loads(data)

            

            # 处理请求

            response = self.process_request(request)

            

            # 发送响应

            client_socket.sendall(json.dumps(response).encode('utf-8'))

            print(f"发送响应: {response}")

            

        except Exception as e:

            error_response = {

                "jsonrpc": "2.0",

                "error": {

                    "code": -1,

                    "message": f"处理请求时出错: {str(e)}"

                },

                "id": request.get("id") if 'request' in locals() else None

            }

            client_socket.sendall(json.dumps(error_response).encode('utf-8'))

        finally:

            client_socket.close()

    

    def process_request(self, request: Dict[str, Any]) -> Dict[str, Any]:

        """处理MCP请求"""

        # 验证请求格式

        if "jsonrpc" not in request or request["jsonrpc"] != "2.0":

            return {

                "jsonrpc": "2.0",

                "error": {"code": -32600, "message": "无效的请求"},

                "id": request.get("id")

            }

            

        if "method" not in request:

            return {

                "jsonrpc": "2.0",

                "error": {"code": -32601, "message": "方法不存在"},

                "id": request.get("id")

            }

        

        # 处理天气查询方法

        if request["method"] == "get_weather":

            params = request.get("params", {})

            city = params.get("city")

            

            if not city:

                return {

                    "jsonrpc": "2.0",

                    "error": {"code": -32602, "message": "缺少城市参数"},

                    "id": request.get("id")

                }

            

            # 查询天气数据

            weather_data = self.weather_database.get(city)

            if weather_data:

                return {

                    "jsonrpc": "2.0",

                    "result": {

                        "city": city,

                        "weather": weather_data,

                        "source": "MCP Weather Service"

                    },

                    "id": request.get("id")

                }

            else:

                return {

                    "jsonrpc": "2.0",

                    "error": {"code": 404, "message": f"未找到城市 {city} 的天气数据"},

                    "id": request.get("id")

                }

        

        # 处理服务描述方法

        elif request["method"] == "describe":

            return {

                "jsonrpc": "2.0",

                "result": {

                    "name": "WeatherService",

                    "description": "提供城市天气查询服务",

                    "methods": {

                        "get_weather": {

                            "description": "获取指定城市的天气信息",

                            "parameters": {

                                "city": {

                                    "type": "string",

                                    "description": "城市名称"

                                }

                            },

                            "returns": {

                                "type": "object",

                                "description": "包含温度、天气状况和风力的天气信息"

                            }

                        }

                    }

                },

                "id": request.get("id")

            }

        

        # 未知方法

        else:

            return {

                "jsonrpc": "2.0",

                "error": {"code": -32601, "message": f"方法 {request['method']} 不存在"},

                "id": request.get("id")

            }


if __name__ == "__main__":

    # 创建并启动MCP服务器

    server = MCPWeatherServer(host='localhost', port=8000)

    server.start()


mcp_client.py

import json

import socket

from typing import Dict, Any, Optional


class MCPClient:

    """MCP客户端,用于与MCP服务器通信"""

    

    def __init__(self, host: str = 'localhost', port: int = 8000):

        self.host = host

        self.port = port

        self.request_id = 0

    

    def _get_next_id(self) -> int:

        """获取下一个请求ID"""

        self.request_id += 1

        return self.request_id

    

    def send_request(self, method: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:

        """发送MCP请求到服务器"""

        # 创建请求

        request = {

            "jsonrpc": "2.0",

            "method": method,

            "id": self._get_next_id()

        }

        

        if params is not None:

            request["params"] = params

        

        # 建立连接并发送请求

        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:

            s.connect((self.host, self.port))

            s.sendall(json.dumps(request).encode('utf-8'))

            

            # 接收响应

            response_data = s.recv(1024).decode('utf-8')

            if not response_data:

                return {"error": "未收到响应"}

                

            return json.loads(response_data)

    

    def describe_service(self) -> Dict[str, Any]:

        """获取服务描述信息"""

        return self.send_request("describe")

    

    def get_weather(self, city: str) -> Dict[str, Any]:

        """查询指定城市的天气"""

        return self.send_request("get_weather", {"city": city})


# 模型调用MCP服务的示例

def model_use_mcp_service():

    """模拟AI模型使用MCP服务的过程"""

    print("=== AI模型开始运行 ===")

    

    # 1. 创建MCP客户端

    print("创建MCP客户端,准备连接天气服务...")

    client = MCPClient(host='localhost', port=8000)

    

    # 2. 先查询服务描述,了解可用功能

    print("\n查询MCP服务描述...")

    description = client.describe_service()

    print(f"服务描述: {json.dumps(description, ensure_ascii=False, indent=2)}")

    

    # 3. 根据服务描述,调用天气查询功能

    target_city = "北京"

    print(f"\n调用MCP服务查询 {target_city} 的天气...")

    weather_result = client.get_weather(target_city)

    

    # 4. 处理返回结果

    print(f"天气查询结果: {json.dumps(weather_result, ensure_ascii=False, indent=2)}")

    

    # 5. 根据结果生成回答

    if "result" in weather_result:

        weather_data = weather_result["result"]["weather"]

        response = (f"{target_city}当前的天气状况为:{weather_data['condition']},"

                   f"气温{weather_data['temperature']}°C,{weather_data['wind']}。")

    else:

        response = f"抱歉,无法获取{target_city}的天气信息:{weather_result.get('error', {}).get('message', '未知错误')}"

    

    print(f"\n=== AI模型生成回答 ===")

    print(response)


if __name__ == "__main__":

    # 模拟模型调用MCP服务

    model_use_mcp_service()


C#实现

Models.cs  

using System;

using System.Collections.Generic;

using System.Text.Json.Serialization;


namespace McpCommon

{

    /// <summary>

    /// MCP请求模型

    /// </summary>

    public class McpRequest

    {

        [JsonPropertyName("jsonrpc")]

        public string JsonRpc { get; set; } = "2.0";

        

        [JsonPropertyName("method")]

        public string Method { get; set; }

        

        [JsonPropertyName("params")]

        public Dictionary<string, object> Parameters { get; set; }

        

        [JsonPropertyName("id")]

        public int Id { get; set; }

    }

    

    /// <summary>

    /// MCP响应模型

    /// </summary>

    public class McpResponse

    {

        [JsonPropertyName("jsonrpc")]

        public string JsonRpc { get; set; } = "2.0";

        

        [JsonPropertyName("result")]

        public object Result { get; set; }

        

        [JsonPropertyName("error")]

        public McpError Error { get; set; }

        

        [JsonPropertyName("id")]

        public int Id { get; set; }

    }

    

    /// <summary>

    /// MCP错误模型

    /// </summary>

    public class McpError

    {

        [JsonPropertyName("code")]

        public int Code { get; set; }

        

        [JsonPropertyName("message")]

        public string Message { get; set; }

    }

    

    /// <summary>

    /// 天气数据模型

    /// </summary>

    public class WeatherData

    {

        public string City { get; set; }

        public string Condition { get; set; }

        public int Temperature { get; set; }

        public string Wind { get; set; }

        public DateTime UpdateTime { get; set; }

    }

    

    /// <summary>

    /// 服务描述模型

    /// </summary>

    public class ServiceDescription

    {

        public string Name { get; set; }

        public string Description { get; set; }

        public string Version { get; set; }

        public List<ServiceMethod> Methods { get; set; } = new List<ServiceMethod>();

    }

    

    /// <summary>

    /// 服务方法描述

    /// </summary>

    public class ServiceMethod

    {

        public string Name { get; set; }

        public string Description { get; set; }

        public List<MethodParameter> Parameters { get; set; } = new List<MethodParameter>();

    }

    

    /// <summary>

    /// 方法参数描述

    /// </summary>

    public class MethodParameter

    {

        public string Name { get; set; }

        public string Type { get; set; }

        public string Description { get; set; }

        public bool Required { get; set; }

    }

}

    

MCPServer.cs

using System;

using System.Collections.Generic;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Text.Json;

using System.Threading;

using McpCommon;


namespace McpServer

{

    class Program

    {

        private static TcpListener _server;

        private static bool _isRunning;

        private static readonly Dictionary<string, WeatherData> _mockWeatherData = new Dictionary<string, WeatherData>

        {

            { "北京", new WeatherData { City = "北京", Condition = "晴朗", Temperature = 25, Wind = "微风", UpdateTime = DateTime.Now } },

            { "上海", new WeatherData { City = "上海", Condition = "多云", Temperature = 28, Wind = "东风3级", UpdateTime = DateTime.Now } },

            { "广州", new WeatherData { City = "广州", Condition = "小雨", Temperature = 30, Wind = "南风2级", UpdateTime = DateTime.Now } },

            { "深圳", new WeatherData { City = "深圳", Condition = "阴天", Temperature = 29, Wind = "东北风1级", UpdateTime = DateTime.Now } }

        };


        static void Main(string[] args)

        {

            StartServer();

            

            Console.WriteLine("MCP天气服务已启动,按任意键停止...");

            Console.ReadKey();

            

            StopServer();

        }


        private static void StartServer()

        {

            int port = 8000;

            _server = new TcpListener(IPAddress.Any, port);

            _server.Start();

            _isRunning = true;

            

            Console.WriteLine($"MCP服务器已启动,监听端口 {port}...");

            

            // 启动一个线程处理客户端连接

            new Thread(ListenForClients) { IsBackground = true }.Start();

        }


        private static void StopServer()

        {

            _isRunning = false;

            _server.Stop();

            Console.WriteLine("MCP服务器已停止");

        }


        private static void ListenForClients()

        {

            while (_isRunning)

            {

                try

                {

                    // 等待客户端连接

                    TcpClient client = _server.AcceptTcpClient();

                    Console.WriteLine("新客户端连接");

                    

                    // 为每个客户端创建一个线程处理

                    new Thread(HandleClient) { IsBackground = true }.Start(client);

                }

                catch (SocketException ex)

                {

                    if (_isRunning)

                    {

                        Console.WriteLine($"Socket错误: {ex.Message}");

                    }

                }

                catch (Exception ex)

                {

                    Console.WriteLine($"错误: {ex.Message}");

                }

            }

        }


        private static void HandleClient(object obj)

        {

            using (TcpClient client = (TcpClient)obj)

            using (NetworkStream stream = client.GetStream())

            {

                byte[] buffer = new byte[1024];

                int bytesRead;

                

                try

                {

                    // 读取客户端发送的数据

                    while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)

                    {

                        string requestString = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                        Console.WriteLine($"收到请求: {requestString}");

                        

                        // 解析请求

                        McpRequest request = JsonSerializer.Deserialize<McpRequest>(requestString);

                        McpResponse response = ProcessRequest(request);

                        

                        // 发送响应

                        string responseString = JsonSerializer.Serialize(response);

                        byte[] responseBytes = Encoding.UTF8.GetBytes(responseString);

                        stream.Write(responseBytes, 0, responseBytes.Length);

                        

                        Console.WriteLine($"发送响应: {responseString}");

                    }

                }

                catch (Exception ex)

                {

                    Console.WriteLine($"处理客户端时出错: {ex.Message}");

                }

                

                Console.WriteLine("客户端连接已关闭");

            }

        }


        private static McpResponse ProcessRequest(McpRequest request)

        {

            var response = new McpResponse { Id = request.Id };

            

            try

            {

                switch (request.Method)

                {

                    case "describe":

                        response.Result = GetServiceDescription();

                        break;

                        

                    case "get_weather":

                        if (request.Parameters != null && request.Parameters.ContainsKey("city"))

                        {

                            string city = request.Parameters["city"].ToString();

                            response.Result = new { weather = GetWeatherData(city) };

                        }

                        else

                        {

                            response.Error = new McpError { Code = -1, Message = "缺少参数: city" };

                        }

                        break;

                        

                    default:

                        response.Error = new McpError { Code = -2, Message = $"未知方法: {request.Method}" };

                        break;

                }

            }

            catch (Exception ex)

            {

                response.Error = new McpError { Code = -999, Message = ex.Message };

            }

            

            return response;

        }


        private static ServiceDescription GetServiceDescription()

        {

            return new ServiceDescription

            {

                Name = "WeatherService",

                Description = "提供城市天气查询服务",

                Version = "1.0.0",

                Methods = new List<ServiceMethod>

                {

                    new ServiceMethod

                    {

                        Name = "describe",

                        Description = "获取服务描述信息",

                        Parameters = new List<MethodParameter>()

                    },

                    new ServiceMethod

                    {

                        Name = "get_weather",

                        Description = "查询指定城市的天气信息",

                        Parameters = new List<MethodParameter>

                        {

                            new MethodParameter

                            {

                                Name = "city",

                                Type = "string",

                                Description = "城市名称",

                                Required = true

                            }

                        }

                    }

                }

            };

        }


        private static WeatherData GetWeatherData(string city)

        {

            if (_mockWeatherData.TryGetValue(city, out var weatherData))

            {

                // 更新时间为当前时间

                weatherData.UpdateTime = DateTime.Now;

                return weatherData;

            }

            

            // 如果没有该城市的数据,返回一个默认值

            return new WeatherData

            {

                City = city,

                Condition = "未知",

                Temperature = 0,

                Wind = "未知",

                UpdateTime = DateTime.Now

            };

        }

    }

}

    

MCPClient.cs

MCP服务相关技术收集MCP

MCP协议详细讲解

AI 模型调用 MCP 服务的过程

AI 模型调用 MCP 服务的代码示例

C# 编写 Agent 调用 ollama 及 MCP 的方法

Trae+Chrome MCP Server 让AI接管你的浏览器

MCP典型服务

Chrome MCP Server

mcp2mqtt动动嘴就可以控制智能家居

excel-mcp-server使用 AI 代理创建、读取和修改 Excel 工作簿

Windows MCP.Net基于 .NET 的 Windows 桌面自动化 MCP (Model Context Protocol) 服务器

Windows-MCP用于 Windows 计算机的轻量级 MCP 服务器

AI辅助生成MCP例子



MCP协议详细讲解

Model Context Protocol(MCP)是由 Anthropic 推出的一种开源协议,旨在建立 AI 模型与开发环境之间的统一上下文交互标准。以下是对其的详细讲解:

1.png

背景与起源

在 AI 领域,大语言模型的应用常常面临数据孤岛和工具集成复杂的问题,不同的数据源和工具都有自己独特的 API 和集成方式,导致开发者需要为每个工具单独编写集成代码,开发和维护成本高,工具复用性低。为解决这些问题,Anthropic 于 2024 年 11 月 25 日开源发布了 MCP

核心概念

  • MCP Hosts :如 Claude Desktop、Cursor、 Cline、trae、Cherry Studio、IDE、AI 应用等,是运行 MCP 的主应用程序,负责发起连接并管理多个客户端实例,与用户进行交互并接收用户的问题或指令,再通过 MCP Clients 向 MCP Servers 发送请求以获取所需的数据或执行相应的操作
  • MCP Clients :由 Host 创建,与特定的 MCP Server 建立一对一的连接,负责协议通信和能力协商,充当 MCP Host 和 MCP Server 之间的“连接器”或“总机”,将 Host 的请求转发给 Server,并将 Server 的响应返回给 Host
  • MCP Servers :轻量级程序,通过标准化的模型上下文协议暴露特定功能,如文件读取、API 调用、数据库查询等,为 MCP Host 提供实际的数据和功能支持,每个 Server 提供一个特定的工具或能力

工作原理

  • 通信机制 :MCP 采用客户端 - 服务器架构,基于 JSON-RPC 2.0 消息格式,支持请求、响应和通知三种消息类型,确保通信的标准化和一致性。它主要支持两种通信方式,一种是标准输入输出(Stdio),适用于在同一台机器上运行的客户端和服务器之间的通信,客户端启动服务器程序作为子进程,消息通讯通过 stdin/stdout 进行;另一种是服务器发送事件(SSE),利用 HTTP 协议实现跨网络的实时数据传输,适用于需要访问远程资源的场景
  • 工作流程 :首先,Host 初始化 Client,Client 尝试与 Server 建立连接,并询问 Server 有哪些能力,Server 回应并返回所有支持的功能,从而建立 1:1 的连接。当用户与 LLM 交互提出问题或指令时,LLM 会告诉 Client 需要调用哪些 Tools,Client 收到 Host 的请求后,将请求信息发送给对应的 Server,Server 接收到信息后开始处理,处理完成后返回结果给 Client,Client 再将信息返回给 Host,Host 根据这些信息生成最终的回复返回给用户

主要功能与特性

  • 统一接口 :提供标准化的 API 接口,简化 AI 与各类上下文信息的交互,使得开发者无需为不同的数据源或工具编写复杂的适配代码,降低了开发难度和成本
  • 无缝集成 :能够轻松集成到现有开发工作流程中,无需对现有的系统和工具进行大规模的改造,即可实现 AI 模型与各种数据源和工具的快速连接和集成,提高了开发效率
  • 多源数据支持 :支持从多种来源获取上下文信息,包括代码仓库、文档、文件系统、数据库、远程 API 等,丰富了 AI 模型可以利用的数据资源,为模型的训练和推理提供了更全面、准确的上下文信息
  • 智能上下文管理 :优化上下文信息的传递,根据 AI 模型的需求和任务场景,自动筛选、组织和更新上下文信息,提高 AI 模型理解和生成的质量,使模型能够更准确地理解和处理复杂的任务
  • 扩展性设计 :具有灵活的架构,允许添加新的数据源和功能,开发者可以根据实际需求自由扩展 MCP 的功能,不断增加新的 MCP Servers 来提供新的工具和能力,以满足不断变化的业务需求

应用场景

  • 智能开发环境 :将 AI 模型与开发工具集成,如代码编辑器、IDE 等,使 AI 能够实时理解代码上下文,为开发者提供智能代码补全、代码生成、代码解释等功能,提高开发效率和代码质量
  • 智能办公助手 :连接办公软件和在线服务,如日历、邮件、文档管理系统等,帮助用户自动完成日常办公任务,如安排会议、发送邮件、生成报告等,提升办公自动化水平
  • 智能数据分析 :将 AI 模型与数据分析工具和数据源集成,如数据库、数据仓库、BI 工具等,使 AI 能够协助分析师进行数据查询、数据分析、数据可视化等工作,为决策提供更有力的支持
  • 智能客服系统 :集成企业内部的客户信息管理系统、订单管理系统等,使 AI 客服能够快速准确地获取客户相关的信息,为客户提供更精准、高效的咨询服务,提高客户满意度


JSON-RPC 2.0 的请求和响应示例

请求示例

{

  "jsonrpc": "2.0",

  "method": "add",

  "params": [2, 3],

  "id": 1

}

响应示例

{

  "jsonrpc": "2.0",

  "result": 5,

  "id": 1

}

错误响应示例

{

  "jsonrpc": "2.0",

  "error": {

    "code": -32601,

    "message": "Method not found"

  },

  "id": 1

}


批量请求示例

[

  {

    "jsonrpc": "2.0",

    "method": "add",

    "params": [2, 3],

    "id": 1

  },

  {

    "jsonrpc": "2.0",

    "method": "subtract",

    "params": [5, 2],

    "id": 2

  }

]

批量响应示例

[

  {

    "jsonrpc": "2.0",

    "result": 5,

    "id": 1

  },

  {

    "jsonrpc": "2.0",

    "result": 3,

    "id": 2

  }

]

这些示例展示了 JSON-RPC 2.0 请求和响应的基本格式,包括请求、响应以及错误处理等场景。



AI 模型调用 MCP 服务的过程


准备工作

  • 搭建 MCP 服务器 :开发者需先搭建 MCP 服务器,可使用 Anthropic 提供的开源框架如 FastMCP 等。定义好服务器的基本配置,如名称、版本等,并通过装饰器注册工具函数,每个工具函数对应一个具体的功能,如查询天气、发送邮件等
  • 集成 MCP 客户端 :在 AI 模型所在的系统或应用中集成 MCP 客户端,如在 Python 项目中安装相应的客户端库等

调用过程

  1. 用户发起请求 :用户通过与 AI 模型交互的方式,如在聊天界面输入问题或指令,表达其想要实现的需求
  2. AI 模型解析意图 :MCP 客户端将用户请求发送给 AI 模型,AI 模型对用户输入的自然语言进行理解和解析,确定用户的需求,并选择与之匹配的 MCP 函数及相应的参数
  3. 发送调用请求 :MCP 客户端根据 AI 模型返回的函数调用信息,向 MCP 服务器发送请求。请求中包含请求 ID、函数名称及参数等,格式通常为 JSON
  4. 执行服务并返回结果 :MCP 服务器接收到请求后,执行对应的工具函数,在本地或通过调用其他外部服务完成具体的任务处理,然后将执行结果按照规定的格式返回给 MCP 客户端。
  5. 结果整合与反馈 :MCP 客户端将 MCP 服务器返回的结果整合到对话上下文中,再次发送给 AI 模型。AI 模型根据整合后的上下文生成自然语言的回复,由 MCP 客户端将最终结果呈现给用户

通信机制

  • STDIO 方式 :适用于本地服务。MCP 客户端启动 MCP 服务器程序作为子进程,通过 stdin 和 stdout 进行消息传递,消息格式遵循 JSON-RPC 2.0
  • SSE 方式 :用于远程服务。MCP 客户端通过 Server-Sent Events 与 MCP 服务器进行通信,服务器定义特定接口用于推送和接收数据,消息格式同样基于 JSON-RPC 2.0

动态上下文管理

MCP 协议具有动态上下文管理机制,通过上下文窗口存储用户偏好、会话记录和环境数据等。在每次交互过程中,上下文会不断扩展和更新,同时对非关键信息进行压缩,以保证对话的连贯性和减少资源消耗

安全与认证机制

  • API 密钥验证 :MCP 服务通常会要求进行 API 密钥验证,只有拥有正确 API 密钥的客户端才能访问服务。
  • HTTPS 加密 :采用 HTTPS 协议对数据传输进行加密,确保数据在网络传输过程中的安全性。
  • 请求限制 :设置请求频率限制和配额限制等,防止服务被滥用,保护服务的稳定性和可靠性



AI 模型调用 MCP 服务的代码示例


基于 Python 的简单 MCP 服务端

Python

pip install mcp

/*


from mcp.server.fastmcp import FastMCP

import tools


mcp=FastMCP("host info mcp")

mcp.add_tool(tools.get_host_info)


def main()->none:

   print("hello from ai-mcp!")

   mcp.run("stdio")#还有sse

   mcp.run(transport="sse", port=9000)

   


if __name__=="__main__":

   main()


tools.py内容

def get_hosts_info()->str:

...



*/


from mcp import MCP, tool


mcp = MCP()


@mcp.register_tool

class WeatherTool:

    @tool(name="get_weather", description="获取指定城市的天气信息")

    def get_weather(self, city: str):

        # 这里可以添加获取天气信息的逻辑,比如调用天气 API 等

        return f"The weather in {city} is sunny."


    @tool(name="get_weather_forecast", description="获取指定城市未来几天的天气预报")

    def get_weather_forecast(self, city: str, days: int):

        # 添加获取天气预报的逻辑

        return f"The weather forecast for {city} in the next {days} days."


if __name__ == "__main__":

    mcp.start()

基于 Java 的 MCP 服务端

java

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.io.ClassPathResource;

import org.springframework.core.io.Resource;

import org.springframework.util.StringUtils;

import org.springframework.web.reactive.function.server.RouterFunctions;

import org.springframework.web.reactive.function.server.ServerResponse;

import reactor.core.publisher.Mono;


import java.util.Collections;

import java.util.Map;


@Configuration

public class MCPConfig {


    @Bean

    public RouterFunctions.Route mcpRoute() {

        return RouterFunctions.route()

                .POST("/mcp/weather", this::getWeather)

                .build();

    }


    private Mono<ServerResponse> getWeather(ServerRequest request) {

        Map<String, String> queryParams = request.queryParams();

        String city = queryParams.get("city");

        if (StringUtils.hasText(city)) {

            String weatherInfo = "The weather in " + city + " is sunny.";

            return ServerResponse.ok().bodyValue(Collections.singletonMap("weather", weatherInfo));

        } else {

            return ServerResponse.badRequest().bodyValue(Collections.singletonMap("error", "City parameter is required"));

        }

    }

}

AI 模型调用 MCP 服务的代码示例

基于 Python 的 OpenAI 模型调用 MCP 服务

Python

import openai

import requests

from mcp import MCPClient


# 初始化 MCP 客户端

mcp_client = MCPClient()

mcp_client.connect("http://localhost:8080/mcp")  # 替换为 MCP 服务的实际地址


# 调用 MCP 服务中的工具

def call_mcp_tool(tool_name, **kwargs):

    return mcp_client.call_tool(tool_name, **kwargs)


# 使用 OpenAI 模型

openai.api_key = "your_openai_api_key"  # 替换为你的 OpenAI API 密钥


def get_ai_response(user_query):

    # 构建消息列表

    messages = [

        {"role": "system", "content": "You are a helpful assistant."},

        {"role": "user", "content": user_query}

    ]


    # 调用 OpenAI API

    response = openai.ChatCompletion.create(

        model="gpt-4-turbo-preview",

        messages=messages,

        tools=mcp_client.list_tools(),  # 提供可用的 MCP 工具

        tool_choice="auto"

    )


    # 处理模型返回的结果

    ai_response = ""

    for choice in response.choices:

        message = choice.message

        if message.content:

            ai_response += message.content + "\n"

        if message.tool_calls:

            for tool_call in message.tool_calls:

                tool_name = tool_call.function.name

                tool_args = tool_call.function.arguments

                # 调用 MCP 工具

                tool_result = call_mcp_tool(tool_name, **tool_args)

                ai_response += f"Calling tool {tool_name} with args {tool_args}\n"

                ai_response += tool_result + "\n"

                # 将工具结果添加到消息中,继续与模型对话

                messages.append({"role": "assistant", "content": "", "tool_calls": [tool_call]})

                messages.append({"role": "tool", "tool_call_id": tool_call.id, "content": tool_result})

                # 获取下一个模型响应

                next_response = openai.ChatCompletion.create(

                    model="gpt-4-turbo-preview",

                    messages=messages,

                    tools=mcp_client.list_tools(),

                    tool_choice="auto"

                )

                if next_response.choices[0].message.content:

                    ai_response += next_response.choices[0].message.content + "\n"

    return ai_response


# 示例 usage

user_input = "What's the weather like in Beijing?"

print(get_ai_response(user_input))

基于 Java 的 Spring AI 模型调用 MCP 服务

java

import org.springframework.ai.chat.client.ChatClient;

import org.springframework.ai.chat.client.ChatClientBuilder;

import org.springframework.ai.mcp.client.McpClient;

import org.springframework.ai.mcp.client.McpClientBuilder;

import org.springframework.ai.mcp.client.McpFunctionCallback;

import org.springframework.ai.tool.ToolCallbackProvider;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;


import java.util.List;


@Configuration

public class AIConfig {


    @Bean

    public McpClient mcpClient() {

        // 配置 MCP 服务器参数

        var stdioParams = ServerParameters.builder("java")

                .args("-Dspring.ai.mcp.server.stdio=true",

                        "-Dspring.main.web-application-type=none",

                        "-Dlogging.pattern.console=",

                        "-jar",

                        "target/mcp-server-0.0.1-SNAPSHOT.jar")

                .build();

        // 创建 MCP 客户端

        return McpClient.sync(new StdioClientTransport(stdioParams));

    }


    @Bean

    public ToolCallbackProvider mcpTools(McpClient mcpClient) {

        // 获取 MCP 服务器中的工具列表并转换为 Function Callback

        return mcpClient.listTools(null)

                .tools()

                .stream()

                .map(tool -> new McpFunctionCallback(mcpClient, tool))

                .toList();

    }


    @Bean

    public ChatClient chatClient(ChatClientBuilder chatClientBuilder, ToolCallbackProvider mcpTools) {

        // 初始化聊天客户端并设置默认工具

        return chatClientBuilder.defaultFunctions(mcpTools).build();

    }

}


// 使用示例

public class AIService {

    private final ChatClient chatClient;


    public AIService(ChatClient chatClient) {

        this.chatClient = chatClient;

    }


    public String generateResponse(String userQuery) {

        return chatClient

                .prompt(userQuery)

                .call()

                .content();

    }

}


使用 ASP.NET Core 来创建一个 Web API 服务,并模拟天气查询功能

C# MCP 服务端代码示例

csharp

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.AspNetCore.Mvc;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Hosting;


namespace MCPService

{

    public class Startup

    {

        public void ConfigureServices(IServiceCollection services)

        {

            services.AddControllers();

        }


        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

        {

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }


            app.UseRouting();


            app.UseEndpoints(endpoints =>

            {

                endpoints.MapControllers();

            });

        }

    }

    /*

这段代码定义了一个名为WeatherController的控制器类。这个类继承自ControllerBase

,并使用了[ApiController]和[Route("mcp")]特性,表明这是用于处理HTTP请求的API控制器,并指定了其基础路由为/mcp。

在控制器类中,定义了一个名为GetWeather的方法,该方法使用了[HttpGet("weather")]特性。这表明这是一个处理HTTP GET请求的方法,其对应的路由是mcp/weather。这个方法接受一个名为city的参数,通过[FromQuery]特性从查询字符串中获取。

当客户端向/mcp/weather发起一个带有查询参数(如city=Paris)的GET请求时,GetWeather方法会处理这个请求,并返回一个IActionResult类型的对象,即一个包含响应内容和状态码的对象。在实际应用中,这个方法可能会根据提供的城市名称来获取和返回相应的天气信息。

*/

    [ApiController]

    [Route("mcp")]

    public class WeatherController : ControllerBase

    {

        [HttpGet("weather")]

        public IActionResult GetWeather([FromQuery] string city)

        {

            if (string.IsNullOrEmpty(city))

            {

                return BadRequest("City parameter is required");

            }


            // 模拟天气查询逻辑

            var weatherInfo = $"The weather in {city} is sunny.";


            return Ok(new { weather = weatherInfo });

        }


        [HttpGet("weather-forecast")]

        public IActionResult GetWeatherForecast([FromQuery] string city, [FromQuery] int days)

        {

            if (string.IsNullOrEmpty(city))

            {

                return BadRequest("City parameter is required");

            }


            // 模拟天气预报逻辑

            var weatherForecast = $"The weather forecast for {city} in the next {days} days.";


            return Ok(new { forecast = weatherForecast });

        }

   

[HttpPost("weather")]

    public IActionResult PostWeather([FromBody] WeatherRequest weatherRequest)

    {

        // 处理POST请求的逻辑

        return Ok($"Received weather data for {weatherRequest.City}: {weatherRequest.Temperature}°C");

    }



// 新增的可以GET和POST调用的方法

    [HttpGet("data")]

    [HttpPost("data")]

    public IActionResult GetAndPostData([FromQuery] string name, [FromBody] string postData = null)

    {

        if (HttpContext.Request.Method == HttpMethods.Get)

        {

            return Ok($"Received GET request with name: {name}");

        }

        else if (HttpContext.Request.Method == HttpMethods.Post)

 {

                   return Ok($"Received POST request with name: {name} and post data: {postData}");

        }


        return BadRequest("Invalid request method");

    }



}


public class WeatherRequest

{

    public string City { get; set; }

    public double Temperature { get; set; }

}



    public class Program

    {

        public static void Main(string[] args)

        {

            var host = CreateHostBuilder(args).Build();

            host.Run();

        }


        public static IHostBuilder CreateHostBuilder(string[] args) =>

            Host.CreateDefaultBuilder(args)

                .ConfigureWebHostDefaults(webBuilder =>

                {

                    webBuilder.UseStartup<Startup>();

                });

    }

}

说明

项目结构:

Startup 类配置了服务和中间件。

WeatherController 是一个 ASP.NET Core 控制器,提供了两个端点 /mcp/weather 和 /mcp/weather-forecast。

功能:

/mcp/weather 接受一个 city 参数,返回该城市的天气信息。

/mcp/weather-forecast 接受 city 和 days 参数,返回该城市未来几天的天气预报。

运行服务:

创建一个 ASP.NET Core 项目并复制上述代码。

使用 dotnet run 命令启动服务,服务默认运行在 https://localhost:5001 和 http://localhost:5000。

测试服务:

使用工具如 Postman 或 curl 测试 API:

获取天气信息:GET http://localhost:5000/mcp/weather?city=Beijing

获取天气预报:GET http://localhost:5000/mcp/weather-forecast?city=Beijing&days=3


C# 用OpenAI模型调用

public class WeatherRequestFunction : IRequestFunction

{

    public string Name => "weather";


    public async Task<IDictionary<string, object>> InvokeAsync(IDictionary<string, object> parameters)

    {

        using var httpClient = new HttpClient();

        var city = parameters["city"].ToString();

        var response = await httpClient.GetAsync($"http://localhost:5000/mcp/weather?city={city}");

        response.EnsureSuccessStatusCode();

        var content = await response.Content.ReadAsStringAsync();

        return new Dictionary<string, object> { { "result", content } };

    }


    public string Serialize(IRequestFunction function)

    {

        return $"Calling tool {function.Name} with parameters {function}";

    }


    public Task SerializeAsync(IRequestFunction function)

    {

        // 实现序列化逻辑

        return Task.CompletedTask;

    }

}

代码说明

OpenAI 客户端:创建 OpenAI 客户端实例,并配置 API 密钥和日志记录器。

MCP 工具:定义一个 WeatherRequestFunction 类实现 IRequestFunction 接口,用于调用 MCP 服务中的天气查询工具。

ChatClient:创建 ChatClient 实例,传入 OpenAI 客户端和日志记录器。

聊天历史:初始化聊天历史记录。

交互式聊天:在循环中读取用户输入,将其添加到聊天历史中,并调用 OpenAI API 获取响应。打印助手的响应并将其添加到聊天历史中。

其他信息

确保你的 MCP 服务正在运行,并且可以通过 http://localhost:5000/mcp/weather 访问。

替换成您的实际 OpenAI API 密钥。

如果您没有 MCP 服务,可以参考前面的示例代码实现一个简单的 MCP 服务。



C# 编写 Agent 调用 ollama 及 MCP 的方法


调用 ollama

安装 Ollama SDK :可以使用如下命令安装 Ollama 的 C# SDK,“dotnet add package Ollama --version 1.9.0”。

简单对话 :设置模型名称和 ollama 的 API 地址,利用 OllamaApiClient 进行对话生成,示例代码如下:

**```csharp

string modelName = "qwen2:7b";

using var ollama = new OllamaApiClient(baseUri: new Uri("http://127.0.0.1:11434/api"));

Console.WriteLine("开始对话!!!");

string userInput = "";

do

{

Console.WriteLine("User:");

userInput = Console.ReadLine()!;

var enumerable = ollama.Completions.GenerateCompletionAsync(modelName, userInput);

Console.WriteLine("Agent:");

await foreach (var response in enumerable)

{

Console.Write($"{response.Response}");

}

Console.WriteLine();

} while (!string.Equals(userInput, "exit", StringComparison.OrdinalIgnoreCase));

Console.WriteLine("对话结束!!!");



**[^2^]


  * **多轮对话** :使用 Chat 对象进行分角色的多轮对话,通过 List 消息存储之前的对话记录,以便模型捕获上下文,代码示例:

**```csharp

string modelName = "glm4:9b";

using var ollama = new OllamaApiClient(baseUri: new Uri("http://127.0.0.1:11434/api"));

Console.WriteLine("开始对话!!!");

string userInput = "";

List messages = [];

do

{

    messages = messages.TakeLast(5).ToList();

    Console.WriteLine("User:");

    userInput = Console.ReadLine()!;

    messages.Add(new Message(MessageRole.User, userInput));

    var enumerable = ollama.Chat.GenerateChatCompletionAsync(modelName, messages, stream: true);

    Console.WriteLine("Agent:");

    StringBuilder builder = new();

    await foreach (var response in enumerable)

    {

        string content = response.Message.Content;

        builder.AppendLine(content);

        Console.Write(content);

    }

    messages.Add(new Message(MessageRole.Assistant, builder.ToString()));

    Console.WriteLine();

} while (!string.Equals(userInput, "exit", StringComparison.OrdinalIgnoreCase));

Console.WriteLine("对话结束!!!");



```**[^2^]


  * **Function call** :若要使用 function call 功能,需设置 autoCallTools 为 true,并给 Ollama 注册相应的工具类,代码如下:

**```csharp

string modelName = "llama3.1:8b";

using var ollama = new OllamaApiClient(baseUri: new Uri("http://127.0.0.1:11434/api"));

var chat = ollama.Chat(

    model: modelName,

    systemMessage: "You are a helpful assistant.",

    autoCallTools: true);

var mathService = new MathService();

chat.AddToolService(mathService.AsTools(), mathService.AsCalls());

while (true)

{

    try

    {

        Console.WriteLine("User>");

        var newMessage = Console.ReadLine();

        var msg = await chat.SendAsync(newMessage);

        Console.WriteLine("Agent> " + msg.Content);

    }

    finally

    {

        Console.WriteLine(chat.PrintMessages());

    }

}

```**[^2^]


### 调用 MCP

目前未查到有成熟的 C# 调用 MCP 的官方 SDK 或常用库,但可以尝试以下思路:

  * **通过 HTTP 请求调用** :如果 MCP 提供了 HTTP API 接口,可以使用 C# 中的 HttpClient 类来发送 HTTP 请求进行调用。基本步骤如下:

    1. 创建 HttpClient 对象,并设置相关请求头等信息。

    2. 构造请求内容,根据 MCP API 的要求,将请求参数进行序列化。

    3. 发送 POST 或 GET 等请求到 MCP 的 API 地址。

    4. 处理返回的响应,对响应内容进行反序列化等操作,获取所需数据。


例如,假设 MCP 的 API 地址为<http://localhost:8000/mcp/api>,需要发送一个获取数据的请求,代码可能如下:

**```csharp

using (var client = new HttpClient())

{

    client.BaseAddress = new Uri("http://localhost:8000/");

    var response = await client.GetAsync("mcp/api?param1=value1");

    if (response.IsSuccessStatusCode)

    {

        var result = await response.Content.ReadAsStringAsync();

        // 处理结果

    }

    else

    {

        // 处理错误

    }

}

```**

  * **参考 Python 实现进行移植** :上述提到的 Python 调用 MCP 的代码示例中,展示了如何创建 MCP Server、获取工具列表以及创建 Agent 等过程。可以参考其逻辑和交互方式,在 C# 中进行相应的实现。例如,对于 MCP Server 的连接,可以考虑在 C# 中使用类似的网络通信方式;对于工具的调用,可以解析 MCP 返回的工具信息,并根据用户输入的问题,选择合适的工具进行调用等[^4^]。


MathService代码:

using System;

using System.Collections.Generic;

using System.Linq;


// 定义工具接口

public interface IToolsService

{

    public string Name { get; }

    public List<ToolDefinition> DefineTools();

}


// 定义工具函数

public class MathService : IToolsService

{

    public string Name => "math";

    

    // 定义工具

    public List<ToolDefinition> DefineTools()

    {

        return new List<ToolDefinition>

        {

            new ToolDefinition("add", "Add two numbers", "a: number, b: number", Add),

            new ToolDefinition("subtract", "Subtract two numbers", "a: number, b: number", Subtract),

            new ToolDefinition("multiply", "Multiply two numbers", "a: number, b: number", Multiply),

            new ToolDefinition("divide", "Divide two numbers", "a: number, b: number", Divide)

        };

    }


    // 加法

    public double Add(double a, double b)

    {

        return a + b;

    }


    // 减法

    public double Subtract(double a, double b)

    {

        return a - b;

    }


    // 乘法

    public double Multiply(double a, double b)

    {

        return a * b;

    }


    // 除法

    public double Divide(double a, double b)

    {

        if (b == 0)

        {

            throw new DivideByZeroException("Division by zero is not allowed.");

        }

        return a / b;

    }

}



ToolDefinition类通常不是.NET标准库或框架的一部分,也不是Ollama或其他主流库的内置类。因此,您需要自己定义它,或者参考您所使用的特定库或框架的实现

using System;


public class ToolDefinition

{

    // 工具名称

    public string Name { get; set; }

    // 工具描述

    public string Description { get; set; }

    // 工具参数列表

    public string Parameters { get; set; }

    // 工具处理函数的委托类型

    public Func<object[], object> Function { get; set; }


    public ToolDefinition(string name, string description, string parameters, Func<object[], object> function)

    {

        Name = name;

        Description = description;

        Parameters = parameters;

        Function = function;

    }

}



Chrome MCP Server

点击进入源码页

Chrome MCP Server 是一个基于chrome插件的 模型上下文协议 (MCP) 服务器,它将您的 Chrome 浏览器功能暴露给 Claude 等 AI 助手,实现复杂的浏览器自动化、内容分析和语义搜索等。与传统的浏览器自动化工具(如playwright)不同,Chrome MCP server直接使用您日常使用的chrome浏览器,基于现有的用户习惯和配置、登录态,让各种大模型或者各种chatbot都可以接管你的浏览器,真正成为你的如常助手


环境要求

Node.js >= 18.19.0 和 (npm 或 pnpm)

Chrome/Chromium 浏览器

安装pnpm :npm install -g pnpm

安装步骤

1.从github上下载最新的chrome扩展

下载地址:https://github.com/hangwin/mcp-chrome/releases


2.全局安装mcp-chrome-bridge

npm


npm install -g mcp-chrome-bridge

pnpm


# 方法1:全局启用脚本(推荐)

pnpm config set enable-pre-post-scripts true

pnpm install -g mcp-chrome-bridge


# 方法2:如果 postinstall 没有运行,手动注册

pnpm install -g mcp-chrome-bridge

mcp-chrome-bridge register

注意:pnpm v7+ 默认禁用 postinstall 脚本以提高安全性。enable-pre-post-scripts 设置控制是否运行 pre/post 安装脚本。如果自动注册失败,请使用上述手动注册命令。


3.加载 Chrome 扩展


打开 Chrome 并访问 chrome://extensions/

启用"开发者模式"

点击"加载已解压的扩展程序",选择 your/dowloaded/extension/folder

点击插件图标打开插件,点击连接即可看到mcp的配置


在支持MCP协议的客户端中使用

使用streamable http的方式连接(👍🏻推荐)

将以下配置添加到客户端的 MCP 配置中以cherryStudio为例:


推荐用streamable http的连接方式


{

  "mcpServers": {

    "chrome-mcp-server": {

      "type": "streamableHttp",

      "url": "http://127.0.0.1:12306/mcp"

    }

  }

}

使用stdio的方式连接(备选)

假设你的客户端仅支持stdio的连接方式,那么请使用下面的方法:


1.先查看你刚刚安装的npm包的安装位置

# npm 查看方式

npm list -g mcp-chrome-bridge

# pnpm 查看方式

pnpm list -g mcp-chrome-bridge

假设上面的命令输出的路径是:/Users/xxx/Library/pnpm/global/5 那么你的最终路径就是:/Users/xxx/Library/pnpm/global/5/node_modules/mcp-chrome-bridge/dist/mcp/mcp-server-stdio.js


2.把下面的配置替换成你刚刚得到的最终路径

{

  "mcpServers": {

    "chrome-mcp-stdio": {

      "command": "npx",

      "args": [

        "node",

        "/Users/xxx/Library/pnpm/global/5/node_modules/mcp-chrome-bridge/dist/mcp/mcp-server-stdio.js"

      ]

    }

  }

}


mcp2mqtt动动嘴就可以控制智能家居

点击进入开源地址

本项目通过将 MCP 协议转换为 MQTT 协议,我们能够利用强大的大型语言模型(LLMs),就能轻松操控您的智能家居、机器人或其他硬件设备。



excel-mcp-server使用 AI 代理创建、读取和修改 Excel 工作簿

点击查看源码

模型上下文协议 (MCP) 服务器,无需安装 Microsoft Excel 即可作 Excel 文件。使用 AI 代理创建、读取和修改 Excel 工作簿。

Excel 作 :创建、读取、更新工作簿和工作表

数据作 :公式、格式、图表、数据透视表和 Excel 表格

数据验证 :内置范围、公式和数据完整性验证

格式: 字体样式、颜色、边框、对齐方式和条件格式

表格作 :使用自定义样式创建和管理 Excel 表格

图表创建 :生成各种图表类型(折线图、条形图、饼图、散点图等)

数据透视表 :创建用于数据分析的动态数据透视表

工作表管理 :轻松复制、重命名、删除工作表

三重传输支持 :stdio、SSE(已弃用)和可流式传输的 HTTP

远程和本地 :既可以在本地工作,也可以作为远程服务工作



Trae+Chrome MCP Server 让AI接管你的浏览器

点击查看原文


一、安装与配置

环境准备

Node.js ≥ 18.19.0 + npm

Chrome/Chromium 浏览器

快速部署和使用

1、安装Chrome扩展插件

        从 GitHub Releases 下载最新扩展包,在 chrome://extensions 中启用开发者模式并加载解压的文件夹。


2、安装桥接工具

npm install -g mcp-chrome-bridge

AI写代码

    若自动注册失败,需手动执行 mcp-chrome-bridge register。


3、打开Chrome浏览器,点击扩展程序进入配置页

1.png


4、点击连接

1.png


5、打开Trae客户端,进入MCP管理页

1.png


6、添加MCP服务

{

  "mcpServers": {

    "chrome-mcp-server": {

      "type": "streamableHttp",

      "url": "http://127.0.0.1:12306/mcp"

    }

  }

}

AI写代码

7、MCP服务需要添加到智能体才可以在Trae内使用,进入智能体管理页面

1.png


8、配置智能体,勾选刚刚配置的MCP服务

1.png


9、在Trae的对话界面选择智能体就可以对话,让浏览器帮你干活啦

1.png


二、应用场景

内容创作

        AI 自动总结网页内容 → 调用 Excalidraw 绘制思维导图。


竞品监控

        定时截图竞品网站首页,对比分析布局更新。


工作流优化

        自动填写表单、批量关闭冗余标签页、整理书签。


开发调试

        网络请求拦截与 API 结构分析。


Windows MCP.Net基于 .NET 的 Windows 桌面自动化 MCP (Model Context Protocol) 服务器

点击进入源码页


一个基于 .NET 的 Windows 桌面自动化 MCP (Model Context Protocol) 服务器,为 AI 助手提供与 Windows 桌面环境交互的能力。

重要提示: 本项目需要 .NET 10 才能运行,请先确保你的本地安装了 .NET 10。如果尚未安装,请访问 .NET 10 下载页面 进行下载和安装。


1. MCP 客户端配置

在您的 MCP 客户端配置中添加以下配置:


使用全局安装的工具(推荐)

{

    "mcpServers": {

     "Windows-MCP.Net": {

      "type": "stdio",

      "command": "dnx",

      "args": ["Windows-MCP.Net@", "--yes"],

      "env": {}

    }

    }

}

使用项目源码直接运行(开发模式)

方式一:工作区配置

在项目根目录创建 .vscode/mcp.json 文件:


{

  "mcpServers": {

    "Windows-MCP.Net-Dev": {

      "type": "stdio",

      "command": "dotnet",

      "args": ["run", "--project", "src/Windows-MCP.Net.csproj"],

      "cwd": "${workspaceFolder}",

      "env": {}

    }

  }

}

方式二:用户配置

通过VS Code命令面板运行 MCP: Open User Configuration,添加:


{

  "mcpServers": {

    "Windows-MCP.Net-Local": {

      "type": "stdio",

      "command": "dotnet",

      "args": ["run", "--project", "src/Windows-MCP.Net.csproj"],

      "env": {}

    }

  }

}

注意: 使用项目源码方式便于开发调试,修改代码后无需重新安装即可生效。VS Code 1.102+ 版本支持MCP服务器的自动发现和管理。


2. 安装和运行

方式一:全局安装(推荐)

dotnet tool install --global WindowsMCP.Net

方式二:从源码运行

# 克隆仓库

git clone https://github.com/AIDotNet/Windows-MCP.Net.git

cd Windows-MCP.Net

# 构建项目

dotnet build

# 运行项目

dotnet run --project src/Windows-MCP.Net.csproj

3. 开始使用

配置完成后,重启您的MCP客户端,即可开始使用Windows桌面自动化功能!



Windows-MCP用于 Windows 计算机的轻量级 MCP 服务器

点击查看源码


"mcpServers": {

    "windows-mcp": {

      "command": "uv",

      "args": [

        "--directory",

        "<path to the windows-mcp directory>",

        "run",

        "main.py"

      ]

    }

  }



详细介绍NPX或UVX配置MCP服务


要使用 npx 或 uvx 配置和运行 MCP(Model Context Protocol)服务,需结合具体的 MCP 服务实现工具(通常是 Node.js 或 Python 生态的包)。以下是详细步骤和说明:

一、背景知识

npx:Node.js 生态的包执行工具,可直接运行 npm 仓库中的包(无需全局安装),适用于 Node.js 编写的 MCP 服务。

uvx:Rust 编写的快速 Python 包执行工具(类似 npx,属于 uv 包管理器的一部分),适用于 Python 编写的 MCP 服务。

MCP 服务:需遵循 MCP 协议(如可流式 HTTP 传输),提供标准化的客户端 - 服务器通信能力(如模型上下文管理、消息流式传输等)。

二、使用 npx 配置 Node.js 版 MCP 服务

若 MCP 服务基于 Node.js 实现(如 @mcp/server 等包),步骤如下:

1. 安装 Node.js 和 npm

确保环境中已安装 Node.js(含 npm),推荐版本 16+。

验证:node -v 和 npm -v 可正常输出版本号。

2. 直接运行 MCP 服务包

使用 npx 临时执行 MCP 服务包,无需提前安装。基本命令格式:


bash

npx [mcp-package-name] [配置参数]

3. 常见配置参数(以假设的 @mcp/server 为例)

MCP 服务通常支持通过命令行参数或环境变量配置核心功能,例如:


bash

# 启动 MCP 服务,指定端口、端点路径和允许的 Origin

npx @mcp/server \

  --port 8080 \                 # 服务端口(默认可能为 65432)

  --endpoint /mcp \             # MCP 端点路径(符合协议要求的单一端点)

  --allowed-origins "http://localhost:3000" \  # 允许的客户端 Origin(防 DNS 重绑定)

  --log-level info \            # 日志级别

  --session-timeout 3600        # 会话超时时间(秒)

4. 环境变量配置

部分参数可通过环境变量设置(优先级可能高于命令行):


bash

# 示例:通过环境变量配置

export MCP_PORT=8080

export MCP_ALLOWED_ORIGINS="http://localhost:3000,https://example.com"

npx @mcp/server  # 自动读取环境变量

5. 验证服务是否启动

服务启动后,可通过 curl 测试端点是否可用:


bash

curl http://localhost:8080/mcp -I  # 检查是否返回 200 或 405(允许 POST/GET)

三、使用 uvx 配置 Python 版 MCP 服务

若 MCP 服务基于 Python 实现(如 mcp-server 等包),步骤如下:

1. 安装 uv 包管理器

uvx 是 uv 的子命令,需先安装 uv:

bash

# 安装 uv(适用于 Linux/macOS,Windows 需调整)

curl -LsSf https://astral.sh/uv/install.sh | sh


验证:uv --version 和 uvx --version 可正常输出。

2. 直接运行 MCP 服务包

使用 uvx 执行 Python 版 MCP 服务,命令格式:


bash

uvx [mcp-package-name] [配置参数]

3. 常见配置参数(以假设的 mcp-server 为例)

Python 版 MCP 服务的配置参数与 Node.js 版类似,例如:


bash

# 启动 MCP 服务,配置核心参数

uvx mcp-server \

  --host 127.0.0.1 \            # 绑定本地地址(符合安全要求,避免暴露公网)

  --port 8080 \

  --endpoint /mcp \

  --cors-allowed-origins "http://localhost:3000" \  # CORS 配置(对应 Origin 验证)

  --enable-sse true             # 启用 SSE 流式传输(符合可流式 HTTP 要求)

4. 配置文件方式

复杂配置可通过 JSON 或 YAML 文件指定,例如:


bash

# 使用配置文件启动

uvx mcp-server --config ./mcp-config.json


mcp-config.json 示例:


json

{

  "port": 8080,

  "endpoint": "/mcp",

  "allowed_origins": ["http://localhost:3000"],

  "session": {

    "timeout": 3600,

    "auto_create": true

  }

}

5. 验证服务

同 Node.js 版,通过 curl 测试:


bash

curl http://localhost:8080/mcp -X POST \

  -H "Content-Type: application/json" \

  -d '{"jsonrpc": "2.0", "method": "initialize", "id": 1}'


四、核心配置项说明(符合 MCP 协议要求)

无论使用 npx 还是 uvx,MCP 服务的配置需满足协议规范:


端点路径:必须提供单一 HTTP 端点(如 /mcp),支持 POST(客户端发消息)和 GET(SSE 流)。

安全验证:

必须验证客户端的 Origin 头(通过 allowed-origins 配置)。

本地运行时绑定 127.0.0.1(而非 0.0.0.0),避免未授权访问。

会话管理:支持通过 Mcp-Session-Id 头管理会话,需配置会话超时时间。

流式传输:启用 SSE(text/event-stream)支持服务器向客户端流式发送消息。

五、总结

npx 适用于 Node.js 生态的 MCP 服务,直接运行 npm 包并通过命令行 / 环境变量配置。

uvx 适用于 Python 生态的 MCP 服务,依赖 uv 工具,支持配置文件和参数化启动。

核心是确保配置符合 MCP 协议(如端点、安全验证、流式传输),具体参数需参考所用 MCP 服务包的文档。


npx 的核心作用是 无需全局安装包,直接执行对应 MCP 工具的可执行文件。

例子 1:通用 TCP 控制型 MCP 服务(基于 mcp-server)

场景

搭建简单的 MCP 服务,实现「客户端 → MCP 服务 → 目标服务器」的 TCP 连接转发,并支持连接数限制、日志输出等基础控制。

完整 npx 命令

npx mcp-server@latest \

  --protocol tcp \

  --listen-port 8080 \

  --listen-host 0.0.0.0 \

  --target-host 192.168.1.100 \

  --target-port 9090 \

  --log-level info \

  --max-connections 50 \

  --timeout 30000


mcp-server@latest 包名 + 版本 如 @1.2.0(固定版) 指定要执行的 MCP 服务包,@latest 表示使用最新版本,生产环境建议固定版本(如 @1.2.0)。


例子 2:本地自定义 MCP 服务(基于项目依赖 mcp-cli)

场景

本地 Node.js 项目中已将 mcp-cli 作为开发依赖(npm install mcp-cli --save-dev),通过 npx 直接执行本地依赖的 MCP 工具,加载自定义配置文件启动服务(适合企业内部定制化 MCP 服务,如设备管理、数据采集)。

完整 npx 命令

bash

npx mcp-cli start \

  --config ./config/mcp-service.yaml \

  --env production \

  --port 8888 \

  --watch \

  --debug \

  --log-rotate 7


mcp-cli start包名 + 命令无默认值mcp-cli 是本地项目依赖的 MCP 管理工具,start 是其内置命令(表示 “启动 MCP 服务”)。



CherryStudio的MCP配置

点击查看官方配置MCP文档

手动配置一个STADIO MCP

一个STATIO MCP配置例子,它的源码地址

1.jpg


它的uvx的json

{

  "mcpServers": {

    "fetch": {

      "command": "uvx",

      "args": ["mcp-server-fetch"]

    }

  }

}


多参数配置,一行一个参数

1.jpg


自动安装MCP

直接给指令:

帮我安装一个 filesystem mcp server



AI辅助生成MCP例子

####【豆包】


你知道AI模型调用MCP吗??

。。。

写一个MCP的完整例子并给出模型调用这个MCP例子

。。。


Python实现
mcp_weather_server.py

import json

import socket

import threading

from typing import Dict, Any


class MCPWeatherServer:

    """MCP天气服务服务器实现"""

    

    def __init__(self, host: str = 'localhost', port: int = 8000):

        self.host = host

        self.port = port

        self.server_socket = None

        self.running = False

        

        # 模拟天气数据库

        self.weather_database = {

            "北京": {"temperature": 25, "condition": "晴朗", "wind": "微风"},

            "上海": {"temperature": 28, "condition": "多云", "wind": "东风3级"},

            "广州": {"temperature": 30, "condition": "小雨", "wind": "南风2级"},

            "深圳": {"temperature": 29, "condition": "阴天", "wind": "东南风1级"},

            "成都": {"temperature": 23, "condition": "晴转多云", "wind": "西北风2级"}

        }

    

    def start(self):

        """启动MCP服务器"""

        self.running = True

        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.server_socket.bind((self.host, self.port))

        self.server_socket.listen(5)

        print(f"MCP天气服务已启动,监听 {self.host}:{self.port}")

        

        try:

            while self.running:

                client_socket, client_address = self.server_socket.accept()

                print(f"接收到来自 {client_address} 的连接")

                client_handler = threading.Thread(

                    target=self.handle_client,

                    args=(client_socket,)

                )

                client_handler.start()

        except KeyboardInterrupt:

            print("服务器正在关闭...")

        finally:

            self.stop()

    

    def stop(self):

        """停止MCP服务器"""

        self.running = False

        if self.server_socket:

            self.server_socket.close()

        print("MCP天气服务已关闭")

    

    def handle_client(self, client_socket: socket.socket):

        """处理客户端请求"""

        try:

            # 接收请求数据

            data = client_socket.recv(1024).decode('utf-8')

            if not data:

                return

                

            print(f"收到请求: {data}")

            

            # 解析MCP请求

            request = json.loads(data)

            

            # 处理请求

            response = self.process_request(request)

            

            # 发送响应

            client_socket.sendall(json.dumps(response).encode('utf-8'))

            print(f"发送响应: {response}")

            

        except Exception as e:

            error_response = {

                "jsonrpc": "2.0",

                "error": {

                    "code": -1,

                    "message": f"处理请求时出错: {str(e)}"

                },

                "id": request.get("id") if 'request' in locals() else None

            }

            client_socket.sendall(json.dumps(error_response).encode('utf-8'))

        finally:

            client_socket.close()

    

    def process_request(self, request: Dict[str, Any]) -> Dict[str, Any]:

        """处理MCP请求"""

        # 验证请求格式

        if "jsonrpc" not in request or request["jsonrpc"] != "2.0":

            return {

                "jsonrpc": "2.0",

                "error": {"code": -32600, "message": "无效的请求"},

                "id": request.get("id")

            }

            

        if "method" not in request:

            return {

                "jsonrpc": "2.0",

                "error": {"code": -32601, "message": "方法不存在"},

                "id": request.get("id")

            }

        

        # 处理天气查询方法

        if request["method"] == "get_weather":

            params = request.get("params", {})

            city = params.get("city")

            

            if not city:

                return {

                    "jsonrpc": "2.0",

                    "error": {"code": -32602, "message": "缺少城市参数"},

                    "id": request.get("id")

                }

            

            # 查询天气数据

            weather_data = self.weather_database.get(city)

            if weather_data:

                return {

                    "jsonrpc": "2.0",

                    "result": {

                        "city": city,

                        "weather": weather_data,

                        "source": "MCP Weather Service"

                    },

                    "id": request.get("id")

                }

            else:

                return {

                    "jsonrpc": "2.0",

                    "error": {"code": 404, "message": f"未找到城市 {city} 的天气数据"},

                    "id": request.get("id")

                }

        

        # 处理服务描述方法

        elif request["method"] == "describe":

            return {

                "jsonrpc": "2.0",

                "result": {

                    "name": "WeatherService",

                    "description": "提供城市天气查询服务",

                    "methods": {

                        "get_weather": {

                            "description": "获取指定城市的天气信息",

                            "parameters": {

                                "city": {

                                    "type": "string",

                                    "description": "城市名称"

                                }

                            },

                            "returns": {

                                "type": "object",

                                "description": "包含温度、天气状况和风力的天气信息"

                            }

                        }

                    }

                },

                "id": request.get("id")

            }

        

        # 未知方法

        else:

            return {

                "jsonrpc": "2.0",

                "error": {"code": -32601, "message": f"方法 {request['method']} 不存在"},

                "id": request.get("id")

            }


if __name__ == "__main__":

    # 创建并启动MCP服务器

    server = MCPWeatherServer(host='localhost', port=8000)

    server.start()


mcp_client.py

import json

import socket

from typing import Dict, Any, Optional


class MCPClient:

    """MCP客户端,用于与MCP服务器通信"""

    

    def __init__(self, host: str = 'localhost', port: int = 8000):

        self.host = host

        self.port = port

        self.request_id = 0

    

    def _get_next_id(self) -> int:

        """获取下一个请求ID"""

        self.request_id += 1

        return self.request_id

    

    def send_request(self, method: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:

        """发送MCP请求到服务器"""

        # 创建请求

        request = {

            "jsonrpc": "2.0",

            "method": method,

            "id": self._get_next_id()

        }

        

        if params is not None:

            request["params"] = params

        

        # 建立连接并发送请求

        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:

            s.connect((self.host, self.port))

            s.sendall(json.dumps(request).encode('utf-8'))

            

            # 接收响应

            response_data = s.recv(1024).decode('utf-8')

            if not response_data:

                return {"error": "未收到响应"}

                

            return json.loads(response_data)

    

    def describe_service(self) -> Dict[str, Any]:

        """获取服务描述信息"""

        return self.send_request("describe")

    

    def get_weather(self, city: str) -> Dict[str, Any]:

        """查询指定城市的天气"""

        return self.send_request("get_weather", {"city": city})


# 模型调用MCP服务的示例

def model_use_mcp_service():

    """模拟AI模型使用MCP服务的过程"""

    print("=== AI模型开始运行 ===")

    

    # 1. 创建MCP客户端

    print("创建MCP客户端,准备连接天气服务...")

    client = MCPClient(host='localhost', port=8000)

    

    # 2. 先查询服务描述,了解可用功能

    print("\n查询MCP服务描述...")

    description = client.describe_service()

    print(f"服务描述: {json.dumps(description, ensure_ascii=False, indent=2)}")

    

    # 3. 根据服务描述,调用天气查询功能

    target_city = "北京"

    print(f"\n调用MCP服务查询 {target_city} 的天气...")

    weather_result = client.get_weather(target_city)

    

    # 4. 处理返回结果

    print(f"天气查询结果: {json.dumps(weather_result, ensure_ascii=False, indent=2)}")

    

    # 5. 根据结果生成回答

    if "result" in weather_result:

        weather_data = weather_result["result"]["weather"]

        response = (f"{target_city}当前的天气状况为:{weather_data['condition']},"

                   f"气温{weather_data['temperature']}°C,{weather_data['wind']}。")

    else:

        response = f"抱歉,无法获取{target_city}的天气信息:{weather_result.get('error', {}).get('message', '未知错误')}"

    

    print(f"\n=== AI模型生成回答 ===")

    print(response)


if __name__ == "__main__":

    # 模拟模型调用MCP服务

    model_use_mcp_service()


C#实现

Models.cs  

using System;

using System.Collections.Generic;

using System.Text.Json.Serialization;


namespace McpCommon

{

    /// <summary>

    /// MCP请求模型

    /// </summary>

    public class McpRequest

    {

        [JsonPropertyName("jsonrpc")]

        public string JsonRpc { get; set; } = "2.0";

        

        [JsonPropertyName("method")]

        public string Method { get; set; }

        

        [JsonPropertyName("params")]

        public Dictionary<string, object> Parameters { get; set; }

        

        [JsonPropertyName("id")]

        public int Id { get; set; }

    }

    

    /// <summary>

    /// MCP响应模型

    /// </summary>

    public class McpResponse

    {

        [JsonPropertyName("jsonrpc")]

        public string JsonRpc { get; set; } = "2.0";

        

        [JsonPropertyName("result")]

        public object Result { get; set; }

        

        [JsonPropertyName("error")]

        public McpError Error { get; set; }

        

        [JsonPropertyName("id")]

        public int Id { get; set; }

    }

    

    /// <summary>

    /// MCP错误模型

    /// </summary>

    public class McpError

    {

        [JsonPropertyName("code")]

        public int Code { get; set; }

        

        [JsonPropertyName("message")]

        public string Message { get; set; }

    }

    

    /// <summary>

    /// 天气数据模型

    /// </summary>

    public class WeatherData

    {

        public string City { get; set; }

        public string Condition { get; set; }

        public int Temperature { get; set; }

        public string Wind { get; set; }

        public DateTime UpdateTime { get; set; }

    }

    

    /// <summary>

    /// 服务描述模型

    /// </summary>

    public class ServiceDescription

    {

        public string Name { get; set; }

        public string Description { get; set; }

        public string Version { get; set; }

        public List<ServiceMethod> Methods { get; set; } = new List<ServiceMethod>();

    }

    

    /// <summary>

    /// 服务方法描述

    /// </summary>

    public class ServiceMethod

    {

        public string Name { get; set; }

        public string Description { get; set; }

        public List<MethodParameter> Parameters { get; set; } = new List<MethodParameter>();

    }

    

    /// <summary>

    /// 方法参数描述

    /// </summary>

    public class MethodParameter

    {

        public string Name { get; set; }

        public string Type { get; set; }

        public string Description { get; set; }

        public bool Required { get; set; }

    }

}

    

MCPServer.cs

using System;

using System.Collections.Generic;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Text.Json;

using System.Threading;

using McpCommon;


namespace McpServer

{

    class Program

    {

        private static TcpListener _server;

        private static bool _isRunning;

        private static readonly Dictionary<string, WeatherData> _mockWeatherData = new Dictionary<string, WeatherData>

        {

            { "北京", new WeatherData { City = "北京", Condition = "晴朗", Temperature = 25, Wind = "微风", UpdateTime = DateTime.Now } },

            { "上海", new WeatherData { City = "上海", Condition = "多云", Temperature = 28, Wind = "东风3级", UpdateTime = DateTime.Now } },

            { "广州", new WeatherData { City = "广州", Condition = "小雨", Temperature = 30, Wind = "南风2级", UpdateTime = DateTime.Now } },

            { "深圳", new WeatherData { City = "深圳", Condition = "阴天", Temperature = 29, Wind = "东北风1级", UpdateTime = DateTime.Now } }

        };


        static void Main(string[] args)

        {

            StartServer();

            

            Console.WriteLine("MCP天气服务已启动,按任意键停止...");

            Console.ReadKey();

            

            StopServer();

        }


        private static void StartServer()

        {

            int port = 8000;

            _server = new TcpListener(IPAddress.Any, port);

            _server.Start();

            _isRunning = true;

            

            Console.WriteLine($"MCP服务器已启动,监听端口 {port}...");

            

            // 启动一个线程处理客户端连接

            new Thread(ListenForClients) { IsBackground = true }.Start();

        }


        private static void StopServer()

        {

            _isRunning = false;

            _server.Stop();

            Console.WriteLine("MCP服务器已停止");

        }


        private static void ListenForClients()

        {

            while (_isRunning)

            {

                try

                {

                    // 等待客户端连接

                    TcpClient client = _server.AcceptTcpClient();

                    Console.WriteLine("新客户端连接");

                    

                    // 为每个客户端创建一个线程处理

                    new Thread(HandleClient) { IsBackground = true }.Start(client);

                }

                catch (SocketException ex)

                {

                    if (_isRunning)

                    {

                        Console.WriteLine($"Socket错误: {ex.Message}");

                    }

                }

                catch (Exception ex)

                {

                    Console.WriteLine($"错误: {ex.Message}");

                }

            }

        }


        private static void HandleClient(object obj)

        {

            using (TcpClient client = (TcpClient)obj)

            using (NetworkStream stream = client.GetStream())

            {

                byte[] buffer = new byte[1024];

                int bytesRead;

                

                try

                {

                    // 读取客户端发送的数据

                    while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)

                    {

                        string requestString = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                        Console.WriteLine($"收到请求: {requestString}");

                        

                        // 解析请求

                        McpRequest request = JsonSerializer.Deserialize<McpRequest>(requestString);

                        McpResponse response = ProcessRequest(request);

                        

                        // 发送响应

                        string responseString = JsonSerializer.Serialize(response);

                        byte[] responseBytes = Encoding.UTF8.GetBytes(responseString);

                        stream.Write(responseBytes, 0, responseBytes.Length);

                        

                        Console.WriteLine($"发送响应: {responseString}");

                    }

                }

                catch (Exception ex)

                {

                    Console.WriteLine($"处理客户端时出错: {ex.Message}");

                }

                

                Console.WriteLine("客户端连接已关闭");

            }

        }


        private static McpResponse ProcessRequest(McpRequest request)

        {

            var response = new McpResponse { Id = request.Id };

            

            try

            {

                switch (request.Method)

                {

                    case "describe":

                        response.Result = GetServiceDescription();

                        break;

                        

                    case "get_weather":

                        if (request.Parameters != null && request.Parameters.ContainsKey("city"))

                        {

                            string city = request.Parameters["city"].ToString();

                            response.Result = new { weather = GetWeatherData(city) };

                        }

                        else

                        {

                            response.Error = new McpError { Code = -1, Message = "缺少参数: city" };

                        }

                        break;

                        

                    default:

                        response.Error = new McpError { Code = -2, Message = $"未知方法: {request.Method}" };

                        break;

                }

            }

            catch (Exception ex)

            {

                response.Error = new McpError { Code = -999, Message = ex.Message };

            }

            

            return response;

        }


        private static ServiceDescription GetServiceDescription()

        {

            return new ServiceDescription

            {

                Name = "WeatherService",

                Description = "提供城市天气查询服务",

                Version = "1.0.0",

                Methods = new List<ServiceMethod>

                {

                    new ServiceMethod

                    {

                        Name = "describe",

                        Description = "获取服务描述信息",

                        Parameters = new List<MethodParameter>()

                    },

                    new ServiceMethod

                    {

                        Name = "get_weather",

                        Description = "查询指定城市的天气信息",

                        Parameters = new List<MethodParameter>

                        {

                            new MethodParameter

                            {

                                Name = "city",

                                Type = "string",

                                Description = "城市名称",

                                Required = true

                            }

                        }

                    }

                }

            };

        }


        private static WeatherData GetWeatherData(string city)

        {

            if (_mockWeatherData.TryGetValue(city, out var weatherData))

            {

                // 更新时间为当前时间

                weatherData.UpdateTime = DateTime.Now;

                return weatherData;

            }

            

            // 如果没有该城市的数据,返回一个默认值

            return new WeatherData

            {

                City = city,

                Condition = "未知",

                Temperature = 0,

                Wind = "未知",

                UpdateTime = DateTime.Now

            };

        }

    }

}

    

MCPClient.cs

using System;

using System.Collections.Generic;

using System.Net.Sockets;

using System.Text;

using System.Text.Json;

using McpCommon;


namespace McpClient

{

    class McpClient

    {

        private readonly string _host;

        private readonly int _port;

        private int _requestId;


        public McpClient(string host = "localhost", int port = 8000)

        {

            _host = host;

            _port = port;

            _requestId = 0;

        }


        private int GetNextRequestId()

        {

            return ++_requestId;

        }


        public McpResponse SendRequest(string method, Dictionary<string, object> parameters = null)

        {

            var request = new McpRequest

            {

                Method = method,

                Parameters = parameters,

                Id = GetNextRequestId()

            };


            try

            {

                using (var client = new TcpClient(_host, _port))

                using (var stream = client.GetStream())

                {

                    // 发送请求

                    string requestString = JsonSerializer.Serialize(request);

                    byte[] requestBytes = Encoding.UTF8.GetBytes(requestString);

                    stream.Write(requestBytes, 0, requestBytes.Length);

                    

                    // 接收响应

                    byte[] buffer = new byte[1024];

                    int bytesRead = stream.Read(buffer, 0, buffer.Length);

                    string responseString = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                    

                    return JsonSerializer.Deserialize<McpResponse>(responseString);

                }

            }

            catch (Exception ex)

            {

                return new McpResponse

                {

                    Id = request.Id,

                    Error = new McpError { Code = -999, Message = $"通信错误: {ex.Message}" }

                };

            }

        }


        public ServiceDescription DescribeService()

        {

            var response = SendRequest("describe");

            if (response.Error != null)

            {

                throw new Exception($"获取服务描述失败: {response.Error.Message}");

            }

            

            return JsonSerializer.Deserialize<ServiceDescription>(JsonSerializer.Serialize(response.Result));

        }


        public WeatherData GetWeather(string city)

        {

            var parameters = new Dictionary<string, object>

            {

                { "city", city }

            };

            

            var response = SendRequest("get_weather", parameters);

            if (response.Error != null)

            {

                throw new Exception($"获取天气失败: {response.Error.Message}");

            }

            

            // 解析嵌套的结果

            var resultDict = JsonSerializer.Deserialize<Dictionary<string, object>>(JsonSerializer.Serialize(response.Result));

            return JsonSerializer.Deserialize<WeatherData>(JsonSerializer.Serialize(resultDict["weather"]));

        }

    }


    class Program

    {

        static void Main(string[] args)

        {

            try

            {

                ModelUseMcpService();

            }

            catch (Exception ex)

            {

                Console.WriteLine($"发生错误: {ex.Message}");

            }

            

            Console.WriteLine("按任意键退出...");

            Console.ReadKey();

        }


        static void ModelUseMcpService()

        {

            Console.WriteLine("=== AI模型开始运行 ===");

            

            // 1. 创建MCP客户端

            Console.WriteLine("创建MCP客户端,准备连接天气服务...");

            var client = new McpClient("localhost", 8000);

            

            // 2. 查询服务描述,了解可用功能

            Console.WriteLine("\n查询MCP服务描述...");

            var description = client.DescribeService();

            Console.WriteLine("服务描述:");

            Console.WriteLine($"名称: {description.Name} v{description.Version}");

            Console.WriteLine($"描述: {description.Description}");

            Console.WriteLine("可用方法:");

            foreach (var method in description.Methods)

            {

                Console.WriteLine($"- {method.Name}: {method.Description}");

                foreach (var param in method.Parameters)

                {

                    Console.WriteLine($"  * {param.Name} ({param.Type}): {param.Description} {(param.Required ? "(必填)" : "")}");

                }

            }

            

            // 3. 调用天气查询功能

            string targetCity = "北京";

            Console.WriteLine($"\n调用MCP服务查询 {targetCity} 的天气...");

            var weatherData = client.GetWeather(targetCity);

            

            // 4. 处理返回结果

            Console.WriteLine("天气查询结果:");

            Console.WriteLine($"城市: {weatherData.City}");

            Console.WriteLine($"天气状况: {weatherData.Condition}");

            Console.WriteLine($"气温: {weatherData.Temperature}°C");

            Console.WriteLine($"风向风力: {weatherData.Wind}");

            Console.WriteLine($"更新时间: {weatherData.UpdateTime:yyyy-MM-dd HH:mm:ss}");

            

            // 5. 根据结果生成回答

            string response = $"{targetCity}当前的天气状况为:{weatherData.Condition},气温{weatherData.Temperature}°C,{weatherData.Wind}。";

            

            Console.WriteLine("\n=== AI模型生成回答 ===");

            Console.WriteLine(response);

        }

    }

}

    


Python编写MCP一般使用FastMCP,支持发布为studio sse streamable_http

FastMCP介绍

FastMCP官方文档

该excel-mcp-server例子的源码地址:https://github.com/haris-musa/excel-mcp-server

源码:

excel-mcp-server-main.zip


import typer

from .server import run_sse, run_stdio, run_streamable_http

app = typer.Typer(help="Excel MCP Server")


@app.command()

def sse():

    """Start Excel MCP Server in SSE mode"""

    try:

        run_sse()

    except KeyboardInterrupt:

        print("\nShutting down server...")

    except Exception as e:

        print(f"\nError: {e}")

        import traceback

        traceback.print_exc()

    finally:

        print("Service stopped.")


if __name__ == "__main__":

    app() 


这段 Python 代码是一个使用 Typer 库创建的命令行应用程序,用于启动 Excel MCP Server 的 SSE 模式服务。下面是详细讲解:

导入依赖

import typer

from .server import run_sse, run_stdio, run_streamable_http


导入了typer库,这是一个用于构建命令行界面的工具

从当前包的server模块导入了三个函数,分别对应不同的服务运行模式

创建 Typer 应用实例

app = typer.Typer(help="Excel MCP Server")


创建了一个 Typer 应用实例,help参数设置了应用的描述信息 "Excel MCP Server"

这个app对象将用于定义各种命令

定义 SSE 模式命令

@app.command()

def sse():

    """Start Excel MCP Server in SSE mode"""

    # 函数实现...



使用@app.command()装饰器定义了一个名为sse的命令

函数文档字符串描述了该命令的功能:"以 SSE 模式启动 Excel MCP 服务器"

SSE 指的是 Server-Sent Events,是一种服务器向客户端推送实时数据的技术

命令实现逻辑

try:

    run_sse()  # 尝试运行SSE模式服务

except KeyboardInterrupt:

    print("\nShutting down server...")  # 处理用户中断(如Ctrl+C)

except Exception as e:

    print(f"\nError: {e}")  # 捕获并显示其他错误

    import traceback

    traceback.print_exc()  # 打印详细的错误堆栈信息

finally:

    print("Service stopped.")  # 无论是否发生异常,最终都显示服务已停止



MCP实现部分

mcp = FastMCP(

    "excel-mcp",

    host=os.environ.get("FASTMCP_HOST", "0.0.0.0"),

    port=int(os.environ.get("FASTMCP_PORT", "8017")),

    instructions="Excel MCP Server for manipulating Excel files"

)

@mcp.tool()

def format_range(

    filepath: str,

    sheet_name: str,

    start_cell: str,

    end_cell: Optional[str] = None,

    bold: bool = False,

    italic: bool = False,

    underline: bool = False,

    font_size: Optional[int] = None,

    font_color: Optional[str] = None,

    bg_color: Optional[str] = None,

    border_style: Optional[str] = None,

    border_color: Optional[str] = None,

    number_format: Optional[str] = None,

    alignment: Optional[str] = None,

    wrap_text: bool = False,

    merge_cells: bool = False,

    protection: Optional[Dict[str, Any]] = None,

    conditional_format: Optional[Dict[str, Any]] = None

) -> str:

    """Apply formatting to a range of cells."""

    try:

        full_path = get_excel_path(filepath)

        from excel_mcp.formatting import format_range as format_range_func

        

        # Convert None values to appropriate defaults for the underlying function

        format_range_func(

            filepath=full_path,

            sheet_name=sheet_name,

            start_cell=start_cell,

            end_cell=end_cell,  # This can be None

            bold=bold,

            italic=italic,

            underline=underline,

            font_size=font_size,  # This can be None

            font_color=font_color,  # This can be None

            bg_color=bg_color,  # This can be None

            border_style=border_style,  # This can be None

            border_color=border_color,  # This can be None

            number_format=number_format,  # This can be None

            alignment=alignment,  # This can be None

            wrap_text=wrap_text,

            merge_cells=merge_cells,

            protection=protection,  # This can be None

            conditional_format=conditional_format  # This can be None

        )

        return "Range formatted successfully"

    except (ValidationError, FormattingError) as e:

        return f"Error: {str(e)}"

    except Exception as e:

        logger.error(f"Error formatting range: {e}")

        raise


1. 装饰器与函数定义

python

运行

@mcp.tool()

def format_range(...):

    """Apply formatting to a range of cells."""

    # 函数实现

@mcp.tool():这是一个自定义装饰器,推测其作用是将该函数注册为 MCP(可能是某种管理控制协议)工具集中的一个可用工具

函数名format_range清晰表明其功能:对单元格范围应用格式化

文档字符串说明了函数的核心功能:"对单元格范围应用格式化"

2. 参数解析

函数定义了多个参数,涵盖了 Excel 单元格格式化的各种常见需求:

基础定位参数(必填):

filepath: str:Excel 文件路径

sheet_name: str:工作表名称

start_cell: str:起始单元格(如 "A1")

范围扩展参数(可选):

end_cell: Optional[str] = None:结束单元格,None 表示仅格式化单个单元格

字体格式参数:

bold: bool = False:是否加粗

italic: bool = False:是否斜体

underline: bool = False:是否下划线

font_size: Optional[int] = None:字体大小

font_color: Optional[str] = None:字体颜色

单元格样式参数:

bg_color: Optional[str] = None:背景颜色

border_style: Optional[str] = None:边框样式

border_color: Optional[str] = None:边框颜色

number_format: Optional[str] = None:数字格式(如日期、货币等)

alignment: Optional[str] = None:对齐方式

wrap_text: bool = False:是否自动换行

merge_cells: bool = False:是否合并单元格

高级功能参数:

protection: Optional[Dict[str, Any]] = None:单元格保护设置

conditional_format: Optional[Dict[str, Any]] = None:条件格式设置

所有可选参数都使用了Optional类型注解并设置了默认值None,表示这些参数是可选的。

3. 函数逻辑解析

python

运行

try:

    # 获取完整的Excel文件路径

    full_path = get_excel_path(filepath)

    # 导入实际执行格式化的函数

    from excel_mcp.formatting import format_range as format_range_func

    

    # 调用实际的格式化函数,传递所有参数

    format_range_func(...)

    return "Range formatted successfully"

except (ValidationError, FormattingError) as e:

    return f"Error: {str(e)}"

except Exception as e:

    logger.error(f"Error formatting range: {e}")

    raise

函数执行流程:

首先通过get_excel_path(filepath)获取 Excel 文件的完整路径

导入实际执行格式化操作的核心函数format_range_func

调用核心函数并传递所有参数

成功时返回 "Range formatted successfully"

4. 异常处理机制

捕获ValidationError和FormattingError(特定领域异常):

这两种异常可能是格式化过程中常见的验证错误和格式错误

捕获后返回友好的错误信息

捕获通用Exception:

记录错误日志(logger.error)

重新抛出异常(raise),让上层调用者处理未预料到的错误

5. 设计特点

职责分离:该函数主要作为接口层,实际格式化逻辑在format_range_func中实现

参数透明传递:将接收的所有参数原封不动地传递给核心函数

清晰的错误处理:区分已知异常和未知异常,分别处理

灵活性:通过大量可选参数支持各种格式化需求,用户可根据需要指定

6. 使用场景推测

这个函数很可能用于 Excel 文件的自动化处理工具中,允许用户通过代码或命令行:

批量设置单元格格式

标准化 Excel 文件的样式

实现复杂的条件格式设置

集成到工作流中自动格式化报表

通过这种设计,用户可以灵活地指定需要的格式化选项,而不必关心底层 Excel 文件操作的细节。

































Top