【使用MCP协议连接本地和远程数据——以Claude的Windows客户端为例】

本博客内容主要是如何在Windows系统上为Claude客户端(无需开通会员)配置模型上下文协议(Model Context Protocol, MCP)服务器。

为什么选择 MCP?

MCP 可帮助您在 LLM 之上构建代理和复杂的工作流程。LLM 经常需要与数据和工具集成,而 MCP 提供:

  • 越来越多的预构建集成,您的 LLM 可以直接插入
  • 在 LLM 提供商和供应商之间切换的灵活性
  • 在基础架构中保护数据的最佳实践

MCP协议

MCP是什么?这里我们先不做定义,先提出一个问题,如果我问Claude获取当前北京时间,它会怎么回复?

这里可以看到claude明确表示没有获取实时时间的功能,但是通过MCP协议,就可以打破“数据孤岛”问题,让 AI 在访问外部资源时不再受限,效果如下:

只需要地区或者时区就能获取实时时间,非常的有趣 

环境准备

1.安装 Claude Desktop App

2.安装Node.js(v18.x或更高版本)

3.安装Python 3.10或更高版本(直接下载指定版本python或者使用Conda创建指定版本环境均可)

安装步骤

1. 安装包管理器

这里我们安装 uv(Python 包管理器和虚拟环境工具),SQLite(轻量级的关系型数据库管理系统),Git (版本控制系统)

以管理员身份打开PowerShell并运行以下两条命令:

winget install --id=astral-sh.uv -e
winget install git.git sqlite.sqlite

上述安装也可以使用npm安装:

# 用于基于Python的服务器
npm install -g uv

2. 安装MCP服务器

基于Node.js的服务器:
# 全局安装服务器
npm install -g @modelcontextprotocol/server-memory
npm install -g @modelcontextprotocol/server-everything
npm install -g @modelcontextprotocol/server-brave-search
# ...安装其他你需要的服务器
基于Python的服务器:
# 使用uvx
uvx mcp-server-sqlite

3. 创建Claude配置文件

  1. 进入目录:%AppData%\Claude\
  2. 创建并使用记事本或者json工具编辑claude_desktop_config.json
  3. 你可以打开运行Win+R,然后直接输入%APPDATA%/Claude/claude_desktop_config.json
  4. 使用以下配置结构:
{
  "globalShortcut": "Ctrl+Space",
  "mcpServers": {
    "sqlite": {
      "command": "uvx",
      "args": ["mcp-server-sqlite", "--db-path", "C:\\Users\\你的用户名\\test.db"]
    },
    "memory": {
      "command": "node",
      "args": ["C:\\Users\\你的用户名\\AppData\\Roaming\\npm\\node_modules\\@modelcontextprotocol\\server-memory\\dist\\index.js"],
      "env": {
        "DEBUG": "*"
      }
    },
    "everything": {
      "command": "node",
      "args": ["C:\\Users\\你的用户名\\AppData\\Roaming\\npm\\node_modules\\@modelcontextprotocol\\server-everything\\dist\\index.js"],
      "env": {
        "DEBUG": "*"
      }
    },
    "brave-search": {
      "command": "node",
      "args": ["C:\\Users\\你的用户名\\AppData\\Roaming\\npm\\node_modules\\@modelcontextprotocol\\server-brave-search\\dist\\index.js"],
      "env": {
        "BRAVE_API_KEY": "你的API密钥",
        "DEBUG": "*"
      }
    }
  }
}

重要提示:

  • 你的用户名替换为你的Windows用户名
  • 你的API密钥替换为需要API密钥的服务的实际密钥
  • Windows路径中使用双反斜杠(\)
  • 路径要指向npm模块目录中的dist/index.js文件

特定服务器设置

SQLite服务器

  • 仅需要上述基本设置
  • 可以自定义--db-path参数指向你偏好的位置

Memory服务器

  • 无需额外设置
  • 默认启用调试日志

Everything服务器

  • 无需额外设置
  • 默认启用调试日志

Brave搜索服务器

  1. Brave Search API | Brave 获取API密钥
  2. 如上所示将其添加到配置的env部分

验证和故障排除

验证安装

# 列出已安装的包
npm list -g --depth=0

# 测试各个服务器
npx @modelcontextprotocol/server-memory
npx @modelcontextprotocol/server-brave-search
uvx mcp-server-sqlite

常见问题

  1. “无法连接到MCP服务器”

    • 确认配置中的路径与你的系统匹配
    • 确保所有包都已全局安装(使用-g标志)
    • 检查指定路径中是否存在dist/index.js
  2. 服务器未在Claude中显示

    • 重启Claude Desktop
    • 验证配置文件的JSON语法
    • 检查文件路径是否正确
  • 始终使用全局安装(npm install -g
  • 在配置中使用dist/index.js的完整路径
  • 保留DEBUG环境变量以便故障排除
  • 更改配置后杀掉进程重启Claude Desktop

成功开启后,Claude会有下图的新的icon:

本次实践使用的claude_desktop_config.json内容如下(获取实时时间):

{
  "mcpServers": {
    "time": {
      "command": "uvx",
      "args": [
        "mcp-server-time",
        "--local-timezone=Asia/Shanghai"
      ]
    }
  }
}

常用的MCP服务器工具

MCP服务器功能
GitHub代码仓库管理、Git操作、API集成
Filesystem访问本地文件系统,读取/写入文件
SQLite与SQLite数据库的交互
Brave Search网络搜索、获取实时信息
Google Maps位置服务、路线规划、地点详情
Puppeteer浏览器自动化和爬虫程序

参考博客:

MCP协议详解:如何使用Claude连接本地和远程数据,轻松管理一切! 

如何在windows电脑上开启Claude MCP Server - Blog - Playground

 如何设置 Github MCP 服务器以与 Windows 和 Mac 上的 Claude Desktop 一起使用

<工具 Claude Desktop> 配置 MCP server 连接本地 SQLite, 本机文件夹(目录) 网络驱动器 Windows 11 系统-CSDN博客MCP开源地址:modelcontextprotocol/servers: Model Context Protocol Servers 

MCP文档地址:Introduction - Model Context Protocol

<think>我们正在开发基于JDK8的MCP协议客户端与服务端,并实现智能体交互模块。根据引用[2]的描述,MCP协议(可能是Model CallingProtocol)用于大模型与外部工具的无缝集成。我们的目标是用纯Java(JDK8)实现。步骤分解:1.理解MCP协议:从引用[2]可知,MCP协议包含服务端定义工具,客户端连接服务端并调用工具,然后通过大模型处理工具结果并生成自然语言响应。2.设计客户端服务端:我们需要实现一个服务端,用于注册工具(即一些功能函数),并等待客户端的调用请求;客户端则负责连接服务端,发送请求并接收结果。3.智能体交互模块:智能体可以理解为能够调用工具并根据结果生成响应的模块。在客户端,我们可以设计一个智能体,它根据用户输入决定调用哪个工具,然后将工具返回的结果交给大模型(如DeepSeek)生成自然语言响应。由于引用中并没有提供MCP协议的具体细节,我们将基于常见的RPC模式设计一个简化的MCP协议。简化MCP协议设计:-服务端:监听某个端口,接收客户端请求。请求包含要调用的工具名参数。服务端根据工具名调用注册的工具,执行并返回结果。-客户端:能够向服务端发送调用请求,并接收结果。-智能体交互:客户端有一个智能体模块,它接收用户输入,解析出意图(如通过规则或简单的NLP),然后调用相应的工具,得到结果后,可以调用大模型生成自然语言响应(这里我们假设大模型是远程服务,客户端通过API调用)。实现步骤:一、服务端实现1.定义工具接口:所有工具必须实现该接口。2.工具注册中心:服务端维护一个工具注册表(Map),将工具名映射到工具实。3.网络通信:使用Java的ServerSocketSocket实现TCP通信,接收客户端请求(请求格式可设计为JSON,包含方法名参数列表),执行工具,返回结果(JSON格式)。二、客户端实现1.网络通信:能够向服务端发送请求并接收响应。2.工具代理:客户端可以生成工具的动态代理,这样调用本地方法就会转换为网络请求(类似于RPC)。3.智能体模块:智能体接收用户输入,根据输入决定调用哪个工具,然后调用工具代理,得到结果后,再调用大模型API生成自然语言响应。三、智能体交互模块1.意图解析:将用户输入映射到工具调用(这里我们可以先设计一个简单的映射规则)。2.工具调用:通过客户端代理调用远程工具。3.大模型集成:调用大模型API(如DeepSeek)生成自然语言响应。代码结构:服务端:- Tool接口:只有一个方法 `Objectexecute(Map<String,Object>params)`- ToolRegistry:注册工具,提供根据名称获取工具的方法。-Server:启动服务,监听端口,处理请求。客户端:- MCPClient:能够发送请求到服务端并接收响应。- ToolProxy:动态代理生成工具代理对象。- Agent:智能体,包含一个工具代理的集合,根据用户输入选择工具,调用工具,然后调用大模型API。由于大模型API是远程的,我们需要一个HTTP客户端来调用(使用JDK自带的HttpURLConnection或第三方库如Apache HttpClient)。但注意,我们要求使用JDK8,所以不能使用太新的库。考虑到时间,我们实现一个简化版本:服务端代码示:首先,定义工具接口: ```javapublic interfaceTool {Objectexecute(Map<String,Object>parameters);} ```然后,实现一个具体的工具,如计算两个数之:```javapublicclass AddTool implementsTool {@OverridepublicObject execute(Map<String, Object> parameters) {doublea =Double.parseDouble(parameters.get("a").toString());double b= Double.parseDouble(parameters.get("b").toString());returna +b;}} ```工具注册中心: ```javaimport java.util.HashMap; importjava.util.Map;public classToolRegistry{private finalMap<String, Tool> toolMap =new HashMap<>();public voidregister(StringtoolName, Tooltool){toolMap.put(toolName, tool);}public ToolgetTool(String toolName){return toolMap.get(toolName);} }```服务端主程序(使用ServerSocket): ```javaimport java.io.*;import java.net.ServerSocket; importjava.net.Socket; importjava.util.HashMap; importjava.util.Map;public classServer {privatestatic finalint PORT=8888;private finalToolRegistrytoolRegistry= newToolRegistry();public Server() {//注册工具toolRegistry.register("add", newAddTool());//可以注册更多工具}public voidstart()throws IOException{ServerSocketserverSocket= newServerSocket(PORT);System.out.println("Server startedon port" +PORT);while(true) {SocketclientSocket =serverSocket.accept();new Thread(() ->handleClient(clientSocket)).start();}}private voidhandleClient(SocketclientSocket) {try(ObjectInputStream in= newObjectInputStream(clientSocket.getInputStream());ObjectOutputStreamout =new ObjectOutputStream(clientSocket.getOutputStream())){//读取客户端请求,这里我们假设请求是一个Map对象Map<String,Object>request =(Map<String,Object>)in.readObject();StringtoolName= (String)request.get("tool");Map<String, Object> parameters= (Map<String, Object>) request.get("parameters");Tooltool =toolRegistry.getTool(toolName);if(tool== null) {Map<String,Object>response =new HashMap<>();response.put("error", "Tool notfound:" +toolName);out.writeObject(response);} else{Object result= tool.execute(parameters);Map<String,Object>response =new HashMap<>();response.put("result", result);out.writeObject(response);}} catch(IOException| ClassNotFoundException e) {e.printStackTrace();}finally {try{clientSocket.close();}catch (IOException e) {e.printStackTrace();}}}publicstatic voidmain(String[] args) throwsIOException {newServer().start();}} ```客户端代码:首先,实现一个发送请求的客户端类: ```javaimport java.io.*;import java.net.Socket;import java.util.Map; publicclass MCPClient{private finalString host;private finalint port;public MCPClient(String host, intport){this.host =host;this.port= port;}public ObjectcallTool(String toolName,Map<String, Object> parameters) throwsIOException,ClassNotFoundException{try (Socket socket= newSocket(host,port);ObjectOutputStream out= newObjectOutputStream(socket.getOutputStream());ObjectInputStreamin =new ObjectInputStream(socket.getInputStream())){Map<String, Object> request= Map.of("tool",toolName, "parameters",parameters);out.writeObject(request);Map<String,Object>response =(Map<String,Object>)in.readObject();if(response.containsKey("error")){throw newRuntimeException(response.get("error").toString());}returnresponse.get("result");}} }```然后,我们可以创建一个工具的动态代理,这样客户端可以像调用本地方法一样调用远程工具。但是为了简化,我们直接使用MCPClient调用。智能体模块:假设我们有一个智能体,它能够根据用户输入决定调用哪个工具。这里我们做一个简单的规则匹配:如,用户输入:“计算3加5”,我们识别出“计算”“加”,然后提取数字,调用add工具。但是,为了演示,我们简化:智能体固定调用add工具,并提取两个数字。然后,智能体将工具返回的结果(一个数字)发送给大模型API,生成自然语言响应。大模型API调用(模拟):由于实际调用大模型需要APIkey网络请求,我们这里模拟一个假的调用。智能体代码: ```javaimport java.util.HashMap; importjava.util.Map;public classAgent {privatefinal MCPClientmcpClient;publicAgent(MCPClientmcpClient) {this.mcpClient =mcpClient;}//模拟调用大模型APIprivateString callModel(String prompt) {//这里应该使用HTTP客户端调用大模型API,返回生成的文本//为了简化,我们返回一个固定字符串return"大模型生成的响应:" +prompt;}publicString interact(String userInput){//简单规则:如果用户输入包含"加"或"add",则调用add工具if (userInput.contains("加")|| userInput.contains("add")) {//提取数字(简单处理,实际应用需要更复杂的NLP)String[] numbers= userInput.replaceAll("[^0-9]+"," ").trim().split(" ");if(numbers.length <2) {return"请提供两个数字";}try{double a= Double.parseDouble(numbers[0]);double b= Double.parseDouble(numbers[1]);Map<String,Object>params =new HashMap<>();params.put("a", a);params.put("b", b);//调用工具Object result= mcpClient.callTool("add", params);//将结果转换为自然语言描述String prompt= "用户要求计算"+ a+ "加"+ b+ ",结果是" +result;returncallModel(prompt);} catch(Exceptione){return "出错:" +e.getMessage();}}return "我不知道你在说什么";}} ```客户端主程序:```javaimportjava.io.IOException;public classClientApp{public staticvoid main(String[]args){MCPClientclient =new MCPClient("localhost",8888);Agent agent= newAgent(client);String userInput ="计算3加5";Stringresponse =agent.interact(userInput);System.out.println(response);}} ```注意:以上代码仅为示,实际应用中需要更健壮的错误处理、更复杂的协议(如使用JSON overHTTP)以及更智能的意图解析。总结:1.服务端:启动后注册工具,监听端口,处理客户端请求。2.客户端:通过MCPClient发送请求到服务端。3.智能体:解析用户输入,调用工具,然后调用大模型生成响应。根据引用[3],未来可以扩展支持更多数据库类型、流式查询等,但当前我们实现了基本框架。相关问题:1. MCP协议的具体细节是什么?如何设计更高效的通信协议?2.如何扩展工具注册中心以支持动态加载工具?3.如何提高智能体的意图识别能力?4.如何集成真实的大模型API(如DeepSeek)?5.如何保证服务端在高并发情况下的性能?注意:以上代码使用了Java序列化进行对象传输,实际中可能更倾向于使用JSON等文本协议,以便跨语言。如果需要,我们可以修改为JSON格式。修改为JSON通信:服务端客户端可以使用JSON来序列化反序列化请求响应。我们可以使用Jackson或Gson,但为了不依赖第三方库,我们使用JDK自带的JSON库(但JDK8没有内置,所以这里我们使用字符串拼接简单实现,或者使用org.json,但需要引入)。为了简化,我们使用字符串拼接解析。由于时间关系,我们只提供修改思路:请求格式:{"tool":"add","parameters":{"a":3, "b":5}}响应格式:{"result":8}或{"error":"message"}在服务端,用BufferedReader读取字符串,然后解析JSON(可以使用第三方库,如Jackson,这里为了简化,我们假设使用第三方库,但实际开发中建议使用)。考虑到项目要求,我们这里不展开。以上实现基于JDK8,没有使用任何外部库(除了大模型调用可能需要HTTP客户端,但JDK8可以使用HttpURLConnection)。注意:如果不想引入第三方JSON库,可以使用Java字符串操作手动拼接解析简单JSON,但对于复杂对象,建议使用库。由于问题要求使用JDK8,我们可以使用内置的javax.json(但需要单独引入,因为JDK8不包含)或者使用其他方式。因此,我们之前的实现使用Java序列化虽然不跨语言,但简单。如果需要跨语言,则必须使用文本协议(如JSON)HTTP协议。我们可以将服务端改为HTTP服务器,使用HttpServer(JDK内置):```javaimport com.sun.net.httpserver.HttpExchange;import com.sun.net.httpserver.HttpHandler;import com.sun.net.httpserver.HttpServer;import java.io.IOException; importjava.io.InputStream;import java.io.OutputStream;import java.net.InetSocketAddress;import java.util.concurrent.Executors;//需要处理HTTPPOST请求,请求体为JSONpublic classHttpServerExample{//省略ToolRegistry等,类似之前的注册publicstatic voidmain(String[] args) throwsIOException {HttpServer server= HttpServer.create(new InetSocketAddress(8000),0);server.createContext("/tool", newToolHandler());server.setExecutor(Executors.newCachedThreadPool());server.start();System.out.println("HTTP Serverstarted onport8000");}static classToolHandlerimplements HttpHandler {@Overridepublicvoid handle(HttpExchangeexchange)throws IOException{if ("POST".equals(exchange.getRequestMethod())) {InputStreamis =exchange.getRequestBody();//读取请求体(JSON字符串)//解析JSON,调用工具,返回结果//这里省略具体实现String response= "{\"result\":8}";//示响应exchange.sendResponseHeaders(200, response.length());OutputStream os= exchange.getResponseBody();os.write(response.getBytes());os.close();} else{exchange.sendResponseHeaders(405, -1);//方法不允许}}} }```但考虑到时间,我们不再详细展开HTTP版本。我们回到问题:使用JDK8实现MCP协议客户端服务端,并开发智能体交互模块。我们已经用Java序列化方式实现了一个简化版本。如果实际项目中需要更健壮的实现,建议:1.使用成熟的RPC框架(如gRPC)来实现协议。2.使用SpringBoot快速构建HTTP服务端(但题目要求JDK8,且不指定框架,所以我们用最基础的Java实现)。以上代码仅供参考,实际生产环境需要更多考虑(如安全性、性能、错误处理等)。</think>基于JDK 8实现MCP协议客户端/服务端及智能体交互模块,以下是分步实现方案: ### 一、系统架构设计 ```mermaid graph LR A[客户端] -->|MCP协议| B[服务端] B --> C[工具执行引擎] C --> D[MySQL/外部工具] B --> E[大模型接口] A --> F[智能体交互模块] ``` ### 二、核心模块实现 #### 1. MCP协议基础框架 **协议格式**: ```java public class MCPMessage { private String messageId; private MessageType type; // REQUEST/RESPONSE/ERROR private String toolName; private Map<String, Object> parameters; private Object result; // getters/setters } ``` #### 2. 服务端实现 **工具注册中心**: ```java public class ToolRegistry { private static Map<String, Tool> tools = new ConcurrentHashMap<>(); public static void registerTool(String name, Tool tool) { tools.put(name, tool); } public static Object executeTool(String name, Map<String, Object> params) { return tools.get(name).execute(params); } } public interface Tool { Object execute(Map<String, Object> parameters); } ``` **服务端监听**: ```java public class MCPServer { public static void start(int port) throws IOException { try (ServerSocket serverSocket = new ServerSocket(port)) { while (true) { Socket clientSocket = serverSocket.accept(); new Thread(() -> processRequest(clientSocket)).start(); } } } private static void processRequest(Socket socket) { try (ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream())) { MCPMessage request = (MCPMessage) in.readObject(); Object result = ToolRegistry.executeTool(request.getToolName(), request.getParameters()); MCPMessage response = new MCPMessage(); response.setResult(result); out.writeObject(response); } // 异常处理 } } ``` #### 3. 客户端实现 ```java public class MCPClient { private final String host; private final int port; public MCPClient(String host, int port) { this.host = host; this.port = port; } public Object callTool(String toolName, Map<String, Object> params) { try (Socket socket = new Socket(host, port); ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); ObjectInputStream in = new ObjectInputStream(socket.getInputStream())) { MCPMessage request = new MCPMessage(); request.setToolName(toolName); request.setParameters(params); out.writeObject(request); MCPMessage response = (MCPMessage) in.readObject(); return response.getResult(); } // 异常处理 } } ``` ### 三、智能体交互模块 ```java public class AgentInteraction { private final MCPClient mcpClient; private final LLMService llmService; // 大模型服务接口 public String processInput(String userInput) { // 1. 意图识别 String toolName = detectIntent(userInput); // 2. 参数提取 Map<String, Object> params = extractParams(userInput); // 3. 工具执行 Object toolResult = mcpClient.callTool(toolName, params); // 4. 生成自然语言响应 return llmService.generateResponse(userInput, toolResult); } private String detectIntent(String input) { // 基于规则/NLP的意图识别 if (input.contains("查询") && input.contains("订单")) return "OrderQueryTool"; // ... } } ``` ### 四、MySQL工具集成示 ```java public class MySQLQueryTool implements Tool { @Override public Object execute(Map<String, Object> params) { String sql = (String) params.get("sql"); try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS); Statement stmt = conn.createStatement()) { ResultSet rs = stmt.executeQuery(sql); List<Map<String, Object>> results = new ArrayList<>(); ResultSetMetaData metaData = rs.getMetaData(); while (rs.next()) { Map<String, Object> row = new HashMap<>(); for (int i = 1; i <= metaData.getColumnCount(); i++) { row.put(metaData.getColumnName(i), rs.getObject(i)); } results.add(row); } return results; } } } // 注册工具 ToolRegistry.registerTool("SQLQuery", new MySQLQueryTool()); ``` ### 五、部署与测试 1. **启动服务端**: ```java public class ServerMain { public static void main(String[] args) throws IOException { // 注册工具 ToolRegistry.registerTool("SQLQuery", new MySQLQueryTool()); ToolRegistry.registerTool("Calculator", new CalculatorTool()); MCPServer.start(8888); } } ``` 2. **客户端调用**: ```java public class ClientDemo { public static void main(String[] args) { MCPClient client = new MCPClient("localhost", 8888); AgentInteraction agent = new AgentInteraction(client, new DeepSeekService()); String response = agent.processInput("帮我查询订单12345的状态"); System.out.println(response); } } ``` ### 六、性能优化建议 1. **连接池管理**:使用Apache Commons Pool管理数据连接 2. **异步处理**:对耗时操作使用CompletableFuture ```java CompletableFuture.supplyAsync(() -> tool.execute(params)) .thenAccept(result -> sendResponse(socket, result)); ``` 3. **协议压缩**:对大数据使用GZIP压缩 4. **安全机制**:添加TLS加密JWT认证 > 提示:完整实现需处理异常、超时、重试等边界情况,建议使用Netty优化网络层[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值