模型上下文协议服务器

MCP服务器是连接大型语言模型(LLM)应用程序与外部服务的标准化通信协议,提供实时数据、特殊工具、提示管理等功能,支持多种传输机制和高级功能。

  • by Mineru98
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 mineru98/unsplash-mcp-server

使用说明

非闪存mcp服务器

模型上下文协议(MCP)服务器开发指南:为LLM构建强大的工具

目录

  1. MCP服务器简介
  2. 核心服务器体系结构
  3. 构建第一个MCP服务器
  4. 曝光功能
  5. 高级服务器功能
  6. 安全性和最佳实践
  7. 故障排除和资源
  8. 示例实施

1.MCP服务器简介

什么是模型上下文协议(MCP)?

模型上下文协议(MCP)是促进大型语言模型(LLM)应用程序(客户端)和外部服务(服务器)之间交互的标准通信协议。这些服务器提供上下文信息、工具和资源。MCP明确了关注点的分离,使LLM应用程序可以委派给专门负责数据检索、外部API访问和特殊计算等任务的服务器。

服务器在MCP生态系统中的作用

服务器是MCP生态系统的中枢,充当LLM应用程序和外部世界之间的中介。服务器可以提供多种功能:

  • 提供实时数据: 从数据库、API或其他来源获取信息。
  • 特殊工具曝光: 提供图像处理、代码执行和数据分析等功能。
  • 管理和共享提示: 保存并提供预定义的提示或提示模板。
  • 与外部系统的连接: 与其他应用程序、服务或平台集成。

实施MCP服务器的好处

实施MCP服务器有很多好处:

  • 可扩展性: 无需修改LLM应用程序的核心代码即可轻松添加新功能。
  • 模块化: 可以将特殊功能开发和维护为独立且可重复使用的组件。
  • 互操作性: 允许其他LLM应用程序共享相同的上下文源和工具。
  • 可扩展性: 分散工作负载,高效处理复杂任务。
  • 创新: 利用LLM的力量,您可以专注于开发独特的功能和集成。

服务器和客户端:了解关系

在MCP体系结构中:

  • 客户端通常是LLM应用程序(Claude Desktop、VS Code或定制应用程序),用于连接到服务器并请求服务。
  • 服务器是处理客户机请求并提供响应的独立流程,提供工具、资源和提示等功能。

一个客户端可以连接到多个服务器,一个服务器可以支持多个客户端。这种多对多关系允许灵活而强大的集成。

2.核心服务器体系结构

MCP服务器的核心组件

MCP服务器是一个由多个关键组件共同工作的系统:

  1. 协议层: 该层处理高级别的通信模式,包括消息帧、请求/响应连接和通知处理。 Protocol, Client, Server包括这样的类。
  2. 传输层: 此层管理客户端和服务器之间的实际通信。MCP支持多种传输机制,如Stdio和HTTP(Server-Sent Events(SSE))。所有传输都使用JSON-RPC 2.0进行消息交换。
  3. 功能(Capabilities): 定义服务器可以做的事情。功能包括工具(可执行函数)、资源(数据源)和提示(为LLM输入预定义文本)。

协议的基本原则

MCP基于客户机-服务器体系结构构建。LLM应用程序(主机)开始连接。客户端在主机应用程序中与服务器保持1:1的连接。服务器为客户端提供上下文、工具和提示。

服务器生命周期:连接、交换、终止

MCP连接的生命周期包括三个主要阶段:

  1. 初始化:

    • 客户机 initialize 发送请求,包括协议版本和功能。
    • 服务器将自己的协议版本和功能作为响应发送。
    • 客户机 initialized 发送通知进行确认。
    • 之后将开始正常的消息交换。
  2. 信息交换: 初始化后,客户端和服务器使用以下模式交换消息:

    • 请求-响应: 如果一方发送请求,另一方将发送响应。
    • 通知: 从一侧发送消息(无响应)。
  3. 结束: 连接可以通过多种方式终止:

    • close() 通过方法正常结束。
    • 传输连接结束。
    • 发生错误时结束。

消息格式和传输

MCP以消息格式使用JSON-RPC 2.0。主要消息类型有三种:

  1. 请求(Requests): 这是一条期待回复的消息。 method和选择性 params包括。
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "method_name",
  "params": { "key": "value" }
}
  1. 응답(回复): 作为对请求的响应。 result(成功时)或 error(失败时)。
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": { "key": "value" }
}
  1. 通知(Notifications): 不期望响应的单向消息。 method和选择性 params包括。
{
  "jsonrpc": "2.0",
  "method": "method_name",
  "params": { "key": "value" }
}

传输方式

MCP支持多种传输机制。默认情况下,有两种传输:

  1. 标准输入/输出(stdio): 此传输使用标准输入和输出,非常适合本地集成和命令行工具。

服务器示例:

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

const server = new McpServer({
  name: "example-server",
  version: "1.0.0"
}, { capabilities: {} });

const transport = new StdioServerTransport();
await server.connect(transport);

客户端示例:

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';

const client = new Client({
  name: "example-client",
  version: "1.0.0"
}, { capabilities: {} });

const transport = new StdioClientTransport({
  command: "./server", // 서버 실행 파일 경로
  args: ["--option", "value"] // 선택적 인수
});
await client.connect(transport);
  1. 服务器-传输事件(SSE): 此传输将HTTP POST请求用于客户端-服务器通信,并使用Server-Sent Events进行服务器-客户端流处理。

服务器示例:

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import express, { Response } from 'express';

const server = new McpServer({
  name: "example-server",
  version: "1.0.0"
}, { capabilities: {} });

const app = express();
app.use(express.json());

app.get("/sse", async (req, res) => {
  const transport = new SSEServerTransport("/messages", res as Response);
  await server.connect(transport);
  app.locals.transport = transport;
});

app.post("/messages", async (req, res) => {
  const transport = app.locals.transport;
  await transport.handlePostMessage(req, res);
});

app.listen(3000, () => {
  console.log('Server listening on port 3000');
});

客户端示例:

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';

const client = new Client({
  name: "example-client",
  version: "1.0.0"
}, { capabilities: {} });

const transport = new SSEClientTransport(
  new URL("http://localhost:3000/sse")
);
await client.connect(transport);

自定义传输

MCP支持自定义传输实施。自定义传输 Transport 必须实现接口。

interface Transport {
  start(): Promise<void>;
  send(message: JSONRPCMessage): Promise<void>;
  close(): Promise<void>;
  onclose?: () => void;
  onerror?: (error: Error) => void;
  onmessage?: (message: JSONRPCMessage) => void;
}

错误处理

传输实现必须处理连接错误、消息解析错误、协议错误、网络超时和资源清理。示例:

class ExampleTransport implements Transport {
  onclose?: () => void;
  onerror?: (error: Error) => void;
  onmessage?: (message: JSONRPCMessage) => void;

  async start() {
    try {
      // 연결 로직
    } catch (error) {
      this.onerror?.(new Error(`Failed to connect: ${error}`));
      throw error;
    }
  }

  async send(message: JSONRPCMessage) {
    try {
      // 전송 로직
    } catch (error) {
      this.onerror?.(new Error(`Failed to send message: ${error}`));
      throw error;
    }
  }
  
  async close(): Promise<void> {
    // 종료 로직
  }
}

3.构建第一个MCP服务器

本节介绍如何使用TypeScript SDK创建默认MCP服务器。

设置开发环境

  1. Node.js와 npm 설치: 在系统上安装Node.js(版本18或更高版本)和npm(Node Package Manager)。
  2. 创建项目目录:
mkdir my-mcp-server
cd my-mcp-server
  1. 初始化Node.js项目:
npm init -y
  1. 安装MCP TypeScript SDK:
npm install @modelcontextprotocol/sdk
  1. 安装TypeScript和其他依赖性:
npm install typescript zod
  1. tsconfig.json 创建文件:
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "NodeNext",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "outDir": "./build"
  },
  "include": ["src/**/*"]
}
  1. src 目录和 index.ts 创建文件:
mkdir src
touch src/index.ts

选择SDK

@modelcontextprotocol/sdk为使用TypeScript构建MCP服务器提供了方便的方法。通过处理协议详细信息,您可以集中精力实现服务器的功能。

实现服务器界面

我们将创建一个返回简单输入的服务器。 src/index.ts 在文件中创建以下内容:

#!/usr/bin/env node

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';

// MCP 서버 인스턴스 생성
const server = new McpServer({
  name: 'EchoServer',
  version: '1.0.0',
});

// 입력을 그대로 되돌려주는 도구 추가
server.tool(
  'echo',
  { message: z.string() }, // 입력 스키마 정의
  async ({ message }) => ({
    content: [{ type: 'text', text: `Echo: ${message}` }],
  })
);

// 전송 방식 생성 (이번 예시에서는 stdio 사용)
const transport = new StdioServerTransport();

// 서버와 전송 연결
await server.connect(transport);

连接和认证处理

在这个简单的示例中, StdioServerTransport使用自动处理连接。在更复杂的情况下,使用其他传输机制时可能需要实施自定义连接处理和身份验证。

处理客户端请求

server.tool() 方法定义服务器要处理的名为“echo”的工具。第二个参数是 { message: z.string() }路 zod 使用库定义工具的预期输入模式。第三个参数接受异步函数的输入并返回结果。 McpServer会自动将客户端的请求路由到相应的工具。

要运行此服务器,请:

  1. 编译TypeScript代码:
npx tsc
  1. 运行编译的JavaScript:
node build/index.js

package.json的 scripts 在部分中添加以下内容:

"scripts": {
  "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
  "start": "node build/index.js"
}

现在 npm run build哇 npm start可以运行。 ./build/index.js运行并输入JSON-RPC 2.0消息进行测试。

echo 工具有效的JSON-RPC 2.0消息示例:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": { "name": "echo", "arguments": { "message": "Hello, world!" } }
}