
前言:MCP 核心概念
什么是MCP协议,参考:MCP 协议
Resources
资源:客户端可读取的类文件数据(如 API 响应或文件内容)
资源是模型上下文协议(MCP)中的核心基本元素,允许服务器暴露数据和内容,这些数据和内容可以被客户端读取并用于LLM交互作为上下文。
工具:可由LLM调用的函数(需用户批准)
Prompts
提示词: 预先编写的模板,帮助用户完成特定任务
使用Spring AI 框架开发 Java MCP Server
1 初始化 Java Spring Boot 项目
使用IDEA创建:
-
打开 IntelliJ IDEA,点击 “File” -> “New Project”。
-
选择 Spring Initializr,填写 Group & Artifact 信息。
-
选择 Spring Boot 版本,添加 Spring Web
等依赖。
-
点击 Finish,等待 IDEA 自动构建项目。
-
运行 DemoApplication.java
(带 @SpringBootApplication
的主类)。
2 引入依赖
添加 Spring AI 依赖:
1
2
3
4
5
6
7
8
9
10
11
|
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
</dependencies>
|
3 编写MCP服务
AppleNotesService.java 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
package com.jiahongw.applenotesmcp.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jiahongw.applenotesmcp.utils.AppleScriptExecutor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;
@Service
public class AppleNotesService {
@Tool(description = "根据标题查询 Apple Notes")
public String queryNotes(@ToolParam(description = "标题") String title) {
// 使用Text Block构造AppleScript脚本,去除所有转义字符
String script = """
tell application "Notes"
set theNotes to every note whose name is "%s"
if (count of theNotes) > 0 then
return the body of item 1 of theNotes
else
return "未找到"
end if
end tell
""".formatted(title);
try {
String rawHtml = AppleScriptExecutor.execute(script);
// 1. 用 jsoup 解析
Document doc = Jsoup.parse(rawHtml);
// 2. 移除所有 base64 图像
Elements imgs = doc.select("img[src^=data:image]");
for (Element img : imgs) {
img.remove();
}
// 3. 返回文本内容
return doc.body().text();
} catch (Exception e) {
return "执行异常: " + e.getMessage();
}
}
@Tool(description = "查询指定目录下所有 Apple Notes,返回标题和内容")
public String queryNotesInFolder(@ToolParam(description = "目录名") String folderName) {
// AppleScript: 获取指定目录下所有笔记的标题和内容
String script = """
tell application "Notes"
set theFolder to first folder whose name is "%s"
set theNotes to notes of theFolder
set output to ""
repeat with n in theNotes
set noteTitle to the name of n
set noteBody to the body of n
set output to output & noteTitle & "|||SEP|||" & noteBody & "|||END|||"
end repeat
return output
end tell
""".formatted(folderName);
try {
String raw = AppleScriptExecutor.execute(script);
String[] noteBlocks = raw.split("\\|\\|\\|END\\|\\|\\|");
List<Map<String, String>> result = new ArrayList<>();
for (String block : noteBlocks) {
if (block.trim().isEmpty()) continue;
String[] parts = block.split("\\|\\|\\|SEP\\|\\|\\|", 2);
if (parts.length != 2) continue;
String title = parts[0];
String html = parts[1];
Document doc = Jsoup.parse(html);
Elements imgs = doc.select("img[src^=data:image]");
for (Element img : imgs) {
img.remove();
}
String content = doc.body().text();
Map<String, String> note = new HashMap<>();
note.put("title", title);
note.put("content", content);
result.add(note);
}
return new ObjectMapper().writeValueAsString(result);
} catch (Exception e) {
return "执行异常: " + e.getMessage();
}
}
}
|
4 打包配置
打包可执行文件:
这将在target目录下生成一个 xxx-0.0.1-SNAPSHOT.jar包文件
配置 MCP Server:
1
2
3
4
5
6
7
8
9
|
{
"apple-notes-spring-mcp": {
"command": "java",
"args": [
"-jar",
"-Dspring.ai.mcp.server.stdio=true",
"/Users/victor/Desktop/PARA.R/Areas/AI/MCP/MyMCP/apple-notes-spring-mcp/target/applenotesmcp-0.0.1-SNAPSHOT.jar"]
}
}
|
5 调试
执行下面指令打开 MCP Server 调试页面进行调试
1
|
npx @modelcontextprotocol/inspector
|

使用 Quarkus 框架开发 Java MCP Server
新建一个 Java 实现的访问 Apple Notes 的 MCP Server 。使用 quarkus 框架实现 。
1 新建 quarkus 项目
新建一个 apple-notes-mcp
项目:
1
|
quarkus create app apple-notes-mcp
|
测试编译调试:
1
2
|
cd apple-notes-mcp
./mvnw compile quarkus:dev
|
2 编写 MCP Server 代码逻辑
打开项目目录 ,在 pom.xml
文件添加 quarkus-mcp-server 依赖:
1
2
3
4
5
|
<dependency>
<groupId>io.quarkiverse.mcp</groupId>
<artifactId>quarkus-mcp-server-sse</artifactId>
<version>1.1.0</version>
</dependency>
|
核心代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
package org.acme;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import io.quarkiverse.mcp.server.Tool;
import io.quarkiverse.mcp.server.ToolArg;
public class AppleNotesService {
@Tool(description = "根据标题查询 Apple Notes")
public String queryNotes(
@ToolArg(description = "标题") String title) {
// 使用Text Block构造AppleScript脚本,去除所有转义字符
String script = """
tell application "Notes"
set theNotes to every note whose name is "%s"
if (count of theNotes) > 0 then
return the body of item 1 of theNotes
else
return "未找到"
end if
end tell
""".formatted(title);
try {
ProcessBuilder pb = new ProcessBuilder("osascript", "-e", script);
Process process = pb.start();
try (java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(process.getInputStream()))) {
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line).append("\n");
}
int exitCode = process.waitFor();
if (exitCode != 0) {
return "AppleScript 执行失败,退出码:" + exitCode;
}
// 处理 Apple Notes 返回内容,去除 base64 图像和 HTML 标签
String rawHtml = result.toString().trim();
// 1. 用 jsoup 解析
Document doc = Jsoup.parse(rawHtml);
// 2. 移除所有 base64 图像
Elements imgs = doc.select("img[src^=data:image]");
for (Element img : imgs) {
img.remove();
}
return doc.body().text();
}
} catch (Exception e) {
return "执行异常: " + e.getMessage();
}
}
}
|
3 编译调试
执行:
1
|
./mvnw compile quarkus:dev
|
打开: http://127.0.0.1:8080/q/dev/

找到 Tools 中的 方法进行调试:

执行测试:

4 打包运行配置
打包:
配置:
1
2
3
4
5
|
{
"apple-notes-mcp": {
"url": "http://127.0.0.1:8080/mcp/sse",
}
}
|
Reference: