关于 unsplash-mcp-server
尽管名称如此,README 实际上是通用 MCP 服务构建指南,并非 Unsplash 集成文档。内容涵盖协议架构、传输方式、服务端能力、实现与安全。
主要功能
- 01MCP 架构与消息生命周期
- 02Stdio 和 SSE 传输示例
- 03工具、资源与提示词
- 04TypeScript SDK 服务端教程
- 05安全与错误处理指南
适用场景
- 01了解 MCP 服务端与客户端职责
- 02比较 Stdio 和 SSE 示例
- 03构建基础 TypeScript MCP 服务
- 04检查传输与安全注意事项
MCP 相关
README 介绍 MCP 服务的设计与实现,包括服务如何向 MCP 客户端公开工具、资源和提示词。文档未说明 Unsplash 专属能力。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
unsplash-mcp-server
模型上下文协议(MCP)服务开发指南:为大模型构建强大的工具
目录
1. MCP 服务简介
什么是模型上下文协议(MCP)?
模型上下文协议(MCP)是一种标准化通信协议,用于促进大模型(LLM)应用(客户端)与外部服务(服务端)之间的交互。这些服务提供上下文信息、工具和资源。MCP 明确划分关注点,使大模型应用能够将数据检索、外部 API 访问和专门计算等任务委托给专门的服务处理。
服务在 MCP 生态系统中的作用
服务是 MCP 生态系统的支柱,充当大模型应用与外部世界之间的中介。服务可以提供各种功能,例如:
- 提供实时数据: 从数据库、API 或其他来源获取信息。
- 暴露专用工具: 提供图像处理、代码执行和数据分析等功能。
- 管理和共享提示词: 存储并提供预定义提示词或提示词模板。
- 连接外部系统: 与其他应用、服务或平台集成。
实现 MCP 服务的优势
实现 MCP 服务有许多优势:
- 可扩展性: 无需修改大模型应用的核心代码,即可轻松添加新功能。
- 模块化: 可将专用功能开发并维护为独立、可复用的组件。
- 互操作性: 让不同的大模型应用能够共享相同的上下文来源和工具。
- 可扩展性: 能够分配工作负载并高效处理复杂任务。
- 创新: 可以专注于利用大模型的能力开发独特功能和集成。
服务与客户端:理解两者的关系
在 MCP 架构中:
- 客户端通常是大模型应用(Claude Desktop、VS Code 或自定义应用),负责连接服务并请求服务。
- 服务是独立进程,负责处理客户端请求并提供响应,同时暴露工具、资源和提示词等功能。
一个客户端可以连接多个服务,一个服务也可以支持多个客户端。这种多对多关系支持灵活而强大的集成。
2. 核心服务架构
MCP 服务的核心组件
MCP 服务由多个协同工作的核心组件组成:
- 协议层: 这一层负责处理高级通信模式,例如消息帧、请求/响应关联和通知处理。它包含
Protocol、Client和Server等类。 - 传输层: 这一层负责管理客户端与服务之间的实际通信。MCP 支持多种传输机制,例如 Stdio 和 HTTP(服务器发送事件(SSE))。所有传输都使用 JSON-RPC 2.0 交换消息。
- 功能(Capabilities): 定义服务能够执行的操作。功能包括工具(可执行函数)、资源(数据源)和提示词(为大模型预定义的文本输入)。
协议的基本原则
MCP 基于客户端-服务端架构构建。大模型应用(主机)会发起连接。客户端在主机应用内与服务保持一对一连接。服务向客户端提供上下文、工具和提示词。
服务生命周期:连接、交互、终止
MCP 连接的生命周期包含三个主要阶段:
-
初始化:
- 客户端发送
initialize请求,其中包含协议版本和功能。 - 服务响应其协议版本和功能。
- 客户端发送
initialized通知以确认。 - 随后开始正常的消息交互。
- 客户端发送
-
消息交互: 初始化后,客户端与服务使用以下模式交换消息:
- 请求-响应: 一方发送请求,另一方发送响应。
- 通知: 一方发送消息(不需要响应)。
-
终止: 连接可以通过多种方式终止:
- 通过
close()方法正常关闭。 - 传输连接关闭。
- 发生错误时关闭。
- 通过
消息格式与传输
MCP 使用 JSON-RPC 2.0 作为消息格式。主要消息类型有三种:
- 请求(Requests): 需要响应的消息,包含
method和可选的params。
{
"jsonrpc": "2.0",
"id": "1",
"method": "method_name",
"params": { "key": "value" }
}
- 响应(Responses): 对请求的响应,包含
result(成功时)或error(失败时)。
{
"jsonrpc": "2.0",
"id": "1",
"result": { "key": "value" }
}
- 通知(Notifications): 不需要响应的单向消息。包含
method和可选的params。
{
"jsonrpc": "2.0",
"method": "method_name",
"params": { "key": "value" }
}
전송 방식
MCP는 여러 전송 메커니즘을 지원합니다. 기본적으로 두 가지 전송이 제공됩니다:
- 표준 입력/출력 (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);
- 서버-전송 이벤트(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 서버를 만드는 과정을 안내합니다.
개발 환경 설정
- Node.js와 npm 설치: Node.js(버전 18 이상)와 npm(Node Package Manager)을 시스템에 설치하십시오.
- 프로젝트 디렉토리 생성:
mkdir my-mcp-server
cd my-mcp-server
- Node.js 프로젝트 초기화:
npm init -y
- MCP TypeScript SDK 설치:
npm install @modelcontextprotocol/sdk
- TypeScript 및 기타 의존성 설치:
npm install typescript zod
tsconfig.json파일 생성:
{
"compilerOptions": {
"target": "ES2020",
"module": "NodeNext",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"outDir": "./build"
},
"include": ["src/**/*"]
}
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는 자동으로 클라이언트의 요청을 적절한 도구로 라우팅합니다.
이 서버를 실행하려면:
- TypeScript 코드 컴파일:
npx tsc
- 컴파일된 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!" } }
}
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。