# mcp-demo
**Repository Path**: zidafone/mcp-demo
## Basic Information
- **Project Name**: mcp-demo
- **Description**: 使用AI技术的网站
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2025-04-03
- **Last Updated**: 2025-04-10
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# MCP 官方 Java SDK 示例
MCP(Model Context Protocol)是一个强大的协议,用于模型与上下文的交互。本文将通过一个完整的 Java 示例来展示如何使用 MCP 官方 SDK 构建客户端和服务器应用程序。
## 项目概述
我们的示例项目包含以下主要代码文件:
1. `MyServer.java` - MCP 服务器实现
2. `MyClient.java` - MCP 客户端实现
3. `pom.xml` - Maven 项目配置
4. `logback.xml` - 日志配置
## 环境配置
项目的 Maven 依赖非常简单:
```xml
io.modelcontextprotocol.sdk
mcp
0.8.1
ch.qos.logback
logback-classic
1.4.11
```
项目使用 Java 17,并配置了必要的插件以确保 UTF-8 编码支持和依赖打包。
## MCP 服务器实现
`MyServer.java` 展示了如何创建一个基本的 MCP 服务器,提供工具、资源和提示功能。
### 服务器初始化
```java
// 设置系统默认编码为UTF-8,确保正确处理中文字符
System.setProperty("file.encoding", "UTF-8");
// 创建基于标准输入输出的传输提供者,用于服务器通信
StdioServerTransportProvider transportProvider = new StdioServerTransportProvider(new ObjectMapper());
// 创建并配置MCP同步服务器
McpSyncServer syncServer = McpServer.sync(transportProvider)
.serverInfo("my-server", "1.0.0") // 设置服务器标识和版本
.capabilities(ServerCapabilities.builder()
.resources(true, true) // 启用资源读写功能
.tools(true) // 启用工具功能
.prompts(true) // 启用提示功能
.logging() // 启用日志功能
.build())
.build();
```
### 添加计算器工具
服务器实现了一个简单的计算器工具,支持加减乘除四种基本运算:
```java
private static void addCalculatorTool(McpSyncServer syncServer) throws JsonProcessingException {
// 创建工具的JSON Schema定义
String schema = createSchema();
// 创建工具规范,包含工具定义和处理逻辑
McpServerFeatures.SyncToolSpecification syncToolSpecification = new McpServerFeatures.SyncToolSpecification(
new Tool("calculator", "Basic calculator", schema),
(exchange, arguments) -> {
List result = new ArrayList<>();
try {
// 从参数中提取操作类型和操作数
String operation = (String) arguments.get("operation");
double a = ((Number) arguments.get("a")).doubleValue();
double b = ((Number) arguments.get("b")).doubleValue();
// 根据操作类型执行相应的计算
double calculationResult = 0;
switch (operation) {
case "add":
calculationResult = a + b;
break;
// ... 其他操作 ...
}
result.add(new TextContent("计算结果: " + calculationResult));
} catch (Exception e) {
// 处理计算过程中的异常
result.add(new TextContent("计算错误: " + e.getMessage()));
return new CallToolResult(result, true);
}
return new CallToolResult(result, false);
});
syncServer.addTool(syncToolSpecification);
}
```
### 添加资源和提示
服务器还提供了资源访问和提示生成功能:
```java
private static void addExampleResource(McpSyncServer syncServer) {
// 创建资源规范,包含资源定义和访问处理逻辑
McpServerFeatures.SyncResourceSpecification syncResourceSpecification = new McpServerFeatures.SyncResourceSpecification(
// 定义资源的基本信息:URI、名称、描述和内容类型
new Resource("custom://resource", "示例资源", "这是一个示例资源", "text/plain", null),
(exchange, request) -> {
// 处理资源读取请求
List contents = new ArrayList<>();
String content = "这是资源内容示例";
contents.add(new TextResourceContents("custom://resource/content", "text/plain", content));
return new ReadResourceResult(contents);
});
syncServer.addResource(syncResourceSpecification);
}
```
```java
private static void addGreetingPrompt(McpSyncServer syncServer) {
// 创建提示规范,包含提示定义和处理逻辑
McpServerFeatures.SyncPromptSpecification syncPromptSpecification = new McpServerFeatures.SyncPromptSpecification(
// 定义提示的基本信息和参数
new Prompt("greeting", "生成问候语", new ArrayList<>(Arrays.asList(
new PromptArgument("name", "用户名称", true)))),
(exchange, request) -> {
// 处理提示请求
List messages = new ArrayList<>();
// 处理用户名称,确保正确处理UTF-8编码
String name;
try {
name = new String(((String) request.arguments().get("name")).getBytes("UTF-8"), StandardCharsets.UTF_8);
} catch (UnsupportedEncodingException e) {
name = (String) request.arguments().get("name");
}
if (name == null || name.isEmpty()) {
name = "访客";
}
// 创建对话消息序列
// ...
return new GetPromptResult("为用户" + name + "生成的问候语", messages);
});
syncServer.addPrompt(syncPromptSpecification);
}
```
## MCP 客户端实现
`MyClient.java` 展示了如何创建 MCP 客户端并与服务器交互。
### 客户端初始化
```java
private static McpSyncClient initializeClient() {
// 创建客户端传输层
ServerParameters params = ServerParameters.builder("java")
.args("-Dfile.encoding=UTF-8", "-jar", "C:\\_Data\\git-project\\website-ai\\target\\ai-demo-0.0.1-SNAPSHOT.jar")
.build();
// ... 其他参数配置 ...
McpClientTransport transport = new StdioClientTransport(params);
// 创建同步客户端
McpSyncClient client = io.modelcontextprotocol.client.McpClient.sync(transport)
.requestTimeout(Duration.ofSeconds(1000))
.capabilities(ClientCapabilities.builder()
.roots(true) // 启用根目录支持
.sampling() // 启用采样支持
.build())
.sampling(request -> {
// 简单的采样处理器实现
System.out.println("收到采样请求: " + request);
return CreateMessageResult.builder()
.role(Role.ASSISTANT)
.message("这是一个示例响应")
.build();
})
.build();
// 初始化连接
System.out.println("正在初始化MCP客户端...");
client.initialize();
System.out.println("MCP客户端初始化完成");
return client;
}
```
### 与服务器交互
客户端实现了多种与服务器交互的方法:
#### 列出和调用工具
```java
private static void listTools(McpSyncClient client) {
System.out.println("\n获取可用工具列表:");
ListToolsResult tools = client.listTools();
tools.tools().forEach(tool -> {
System.out.println("工具名称: " + tool.name());
System.out.println("工具描述: " + tool.description());
System.out.println("工具Schema: " + tool.inputSchema());
System.out.println("-------------------");
});
}
private static void callCalculatorTool(McpSyncClient client) {
System.out.println("\n调用计算器工具:");
CallToolResult calcResult = client.callTool(
new CallToolRequest("calculator",
Map.of("operation", "add", "a", 2, "b", 3))
);
System.out.println("计算结果: ");
calcResult.content().forEach(content -> {
if (content instanceof TextContent) {
System.out.println(((TextContent) content).text());
}
});
}
```
#### 访问资源
```java
private static void listResources(McpSyncClient client) {
System.out.println("\n获取可用资源列表:");
ListResourcesResult resources = client.listResources();
resources.resources().forEach(resource -> {
System.out.println("资源URI: " + resource.uri());
System.out.println("资源名称: " + resource.name());
System.out.println("资源描述: " + resource.description());
System.out.println("资源类型: " + resource.mimeType());
System.out.println("-------------------");
});
}
private static void readResource(McpSyncClient client) {
ListResourcesResult resources = client.listResources();
if (!resources.resources().isEmpty()) {
Resource firstResource = resources.resources().get(0);
System.out.println("\n读取资源: " + firstResource.uri());
ReadResourceResult resourceResult = client.readResource(
new ReadResourceRequest(firstResource.uri())
);
System.out.println("资源内容: ");
resourceResult.contents().forEach(content -> {
if (content instanceof TextResourceContents) {
System.out.println(((TextResourceContents) content).text());
}
});
}
}
```
#### 使用提示
```java
private static void listPrompts(McpSyncClient client) {
System.out.println("\n获取可用提示列表:");
ListPromptsResult prompts = client.listPrompts();
prompts.prompts().forEach(prompt -> {
System.out.println("提示名称: " + prompt.name());
System.out.println("提示描述: " + prompt.description());
System.out.println("提示参数: ");
prompt.arguments().forEach(arg -> {
System.out.println(" - " + arg.name() + (arg.required() ? " (必需)" : " (可选)") + ": " + arg.description());
});
System.out.println("-------------------");
});
}
private static void useGreetingPrompt(McpSyncClient client) {
if (client.listPrompts().prompts().stream().anyMatch(prompt -> prompt.name().equals("greeting"))) {
System.out.println("\n使用问候提示:");
GetPromptResult promptResult = client.getPrompt(
new GetPromptRequest("greeting", Map.of("name", "张三"))
);
System.out.println("提示结果: " + promptResult.description());
System.out.println("消息: ");
promptResult.messages().forEach(message -> {
System.out.println("角色: " + message.role());
if (message.content() instanceof TextContent) {
System.out.println("内容: " + ((TextContent) message.content()).text());
}
System.out.println("-------------------");
});
}
}
```
#### 根目录管理
```java
private static void addRootDirectory(McpSyncClient client) {
System.out.println("\n添加根目录:");
client.addRoot(new Root("file:///tmp", "临时目录"));
System.out.println("根目录已添加");
// 通知服务器根目录列表已更改
client.rootsListChangedNotification();
System.out.println("已通知服务器根目录列表变更");
}
```
## 运行项目
要运行此示例项目,首先需要编译并打包:
```bash
mvn clean package
```
然后可以分别启动服务器和客户端:
```bash
# 启动服务器
java -jar target/ai-demo-0.0.1-SNAPSHOT.jar
# 在另一个终端启动客户端
java -cp target/ai-demo-0.0.1-SNAPSHOT.jar com.qidafang.demo.mcp.MyClient
```
## 总结
通过这个示例,我们展示了如何使用 MCP Java SDK 构建功能完整的客户端和服务器应用程序。MCP 协议提供了丰富的功能,包括:
1. 工具调用 - 允许客户端调用服务器提供的工具
2. 资源访问 - 提供对服务器资源的读取
3. 提示生成 - 支持参数化的提示模板
4. 根目录管理 - 允许客户端管理文件系统访问
这个示例可以作为开发更复杂 MCP 应用的起点,您可以根据自己的需求扩展功能。
希望这个示例能帮助您更好地理解和使用 MCP Java SDK!