一个纯 Java 从零实现的 MCP (Model Context Protocol) Server。
- JSON-RPC 2.0 编解码器 — 基于字段检测的多态消息解码
- 传输层 — 可插拔的 Transport 接口 + Stdio 实现
- 生命周期状态机 —
AtomicReference<State>线程安全状态管理 - 注解驱动工具系统 —
@Tool+@ToolParam,反射自动注册
不依赖任何 MCP SDK。直接连接 Claude Desktop、Cursor 或任何 MCP 兼容客户端。
┌─────────────────────────────────────────────────────┐
│ MCP 客户端 │
│ (Claude Desktop / Cursor / 等) │
└──────────────────────┬──────────────────────────────┘
│ stdin / stdout (JSON-RPC 2.0)
┌──────────────────────▼──────────────────────────────┐
│ StdioTransport │
│ BufferedReader + daemon 线程 │
├─────────────────────────────────────────────────────┤
│ McpServerHandler │
│ AtomicReference<State> 状态机 │
│ UNINITIALIZED → INITIALIZING → OPERATIONAL │
├──────────┬──────────┬──────────────┬────────────────┤
│ 协议层 │ 工具系统 │ 资源系统 │ 异常体系 │
│ │ │ │ │
│ JsonRpc │ @Tool │ McpResource │ McpException │
│ Codec │ @ToolParam│ ResourceReg │ ├JsonRpcExc │
│ Request │ Registry │ SystemInfoR │ ├ToolException │
│ Response │ Invoker │ ProjectFileR │ └TransportExc │
│ Notif. │ Schema │ │ │
│ Error │ Generator│ │ │
├──────────┴──────────┴──────────────┴────────────────┤
│ 工具实现 │
│ ProjectTool │ ResumeTool │
│ (codeStats, dependencyAnalysis, │
│ complexityReport, engineeringCheck) │
└─────────────────────────────────────────────────────┘
客户端通过 stdin 发送 JSON-RPC 请求
→ StdioTransport 读取一行,通过 JsonRpcCodec 解码
→ McpServerHandler 根据 method 分发
→ "initialize" → InitializeHandler
→ "tools/list" → ToolRegistry.getTools()
→ "tools/call" → ToolInvoker → 反射调用 → @Tool 方法
→ "resources/list" → ResourceRegistry.listResources()
→ "resources/read" → ResourceRegistry.readResource(uri)
→ JsonRpcResponse 编码后写入 stdout
→ 客户端收到响应
| 工具 | 说明 |
|---|---|
analyzeProject |
全方位项目审计:目录树、代码统计、复杂度、依赖分析、工程化检查 → 九阶段面试导向报告 |
codeStats |
按语言统计代码量:文件数、总行数、代码行、注释行、空行 |
dependencyAnalysis |
从 pom.xml / build.gradle 中提取并分类项目依赖 |
complexityReport |
Java 代码复杂度指标:类/方法数量、平均密度、最大文件 |
engineeringCheck |
检查工程化基础设施:CI/CD、Docker、测试、日志、多环境配置 |
readPdf |
读取 PDF 文件内容并返回文本 |
analyzeResume |
读取 PDF 简历,按 2026 互联网大厂标准进行十阶段全面审计 |
| URI | MIME 类型 | 说明 |
|---|---|---|
mcp://system/info |
application/json | 运行时环境:Java 版本、操作系统、处理器数、内存使用 |
mcp://project/pom.xml |
application/xml | Maven 项目配置 |
mcp://project/README.md |
text/plain | 项目文档 |
- Java 17+(使用了模式匹配、文本块、switch 表达式)
- Maven 3.6+
git clone https://github.com/kunxing/java-mcp-server.git
cd java-mcp-server
mvn clean package构建产物为 fat JAR:target/java-mcp-server-1.0.0.jar。
编辑 claude_desktop_config.json:
{
"mcpServers": {
"java-tools": {
"command": "java",
"args": ["-jar", "/path/to/java-mcp-server-1.0.0.jar"]
}
}
}在项目根目录创建 .mcp.json:
{
"mcpServers": {
"java-mcp-server": {
"command": "java",
"args": ["-jar", "/path/to/java-mcp-server-1.0.0.jar"]
}
}
}重启后工具和资源会自动加载。
基于字段检测的多态消息解码:
method + id → JsonRpcRequest
仅有 method → JsonRpcNotification
result / error → JsonRpcResponse
不依赖外部 RPC 库,仅使用 Jackson 进行 JSON 序列化。
零样板代码定义工具:
public class MyTool {
@Tool(name = "greet", description = "返回问候语")
public String greet(@ToolParam(name = "name") String name) {
return "Hello, " + name + "!";
}
}框架自动处理:
- ToolRegistry — 通过反射扫描
@Tool注解,构建方法注册表 - ToolSchemaGenerator — 从
@ToolParam注解自动生成 JSON Schema - ToolInvoker — 按名称解析参数、类型转换、反射调用
AtomicReference<State>: UNINITIALIZED → INITIALIZING → OPERATIONAL
服务器在 MCP 握手(initialize + notifications/initialized)完成前,拒绝所有工具/资源请求。
McpException(基类,携带协议错误码)
├── JsonRpcException (-32700 解析错误, -32600 无效请求, 等)
├── ToolException (-32001 工具未找到, -32002 执行失败, 等)
└── TransportException (-32050 传输错误, -32051 传输关闭)
Transport 接口将 I/O 与协议逻辑解耦:
public interface Transport {
void start();
void send(JsonRpcMessage message);
void onMessage(Consumer<JsonRpcMessage> handler);
void close();
}StdioTransport 是默认实现。可替换为 SSE、WebSocket 或自定义传输。
src/main/java/mcp/
├── McpServer.java # 入口 — 组装所有组件
├── protocol/
│ ├── JsonRpcCodec.java # JSON-RPC 2.0 编解码
│ ├── JsonRpcMessage.java # 消息抽象基类
│ ├── JsonRpcRequest.java # 请求(id, method, params)
│ ├── JsonRpcResponse.java # 响应(result 或 error)
│ ├── JsonRpcNotification.java # 单向通知
│ ├── JsonRpcError.java # 错误对象(code, message, data)
│ ├── McpException.java # 基础异常(携带错误码)
│ └── JsonRpcException.java # 协议层错误
├── transport/
│ ├── Transport.java # 可插拔传输接口
│ ├── StdioTransport.java # stdin/stdout 实现
│ └── TransportException.java # 传输层错误
├── server/
│ ├── McpServerHandler.java # 消息分发器 + 状态机
│ ├── InitializeHandler.java # MCP 握手处理器
│ └── ServerConfig.java # 服务器名称、版本、协议版本
├── tool/
│ ├── Tool.java # @Tool 注解
│ ├── ToolParam.java # @ToolParam 注解
│ ├── ToolRegistry.java # 注解扫描器 + 工具注册表
│ ├── ToolInvoker.java # 基于反射的参数解析与调用
│ ├── ToolSchemaGenerator.java # 从注解生成 JSON Schema
│ └── ToolException.java # 工具执行错误
├── resource/
│ ├── McpResource.java # 资源接口
│ ├── ResourceRegistry.java # 资源管理 + 内容读取
│ └── resources/
│ ├── SystemInfoResource.java # mcp://system/info
│ └── ProjectFileResource.java # mcp://project/<file>
└── tools/
├── ProjectTool.java # 5 个项目分析工具
└── ResumeTool.java # 2 个 PDF/简历工具
| 类别 | 技术 |
|---|---|
| 语言 | Java 17(模式匹配、文本块、switch 表达式) |
| JSON | Jackson 2.17.0 |
| Apache PDFBox 3.0.1 | |
| 日志 | SLF4J 2.0.12 + Logback 1.5.3 |
| 测试 | JUnit 5.10.2 + Mockito 5.11.0(30 个测试) |
| 构建 | Maven 3.6+ + Shade 插件(fat JAR) |
mvn test30 个测试覆盖所有核心模块:
| 测试类 | 覆盖范围 |
|---|---|
JsonRpcCodecTest |
编码、解码、往返测试、异常处理(13 个测试) |
ToolSystemTest |
ToolRegistry、ToolSchemaGenerator、ToolInvoker(10 个测试) |
StdioTransportTest |
发送、接收、多消息、往返、关闭(7 个测试) |
- 创建类,方法上添加
@Tool和@ToolParam注解:
package mcp.tools;
import mcp.tool.Tool;
import mcp.tool.ToolParam;
public class MyTool {
@Tool(name = "myFunction", description = "做些有用的事")
public String myFunction(
@ToolParam(name = "input", description = "输入参数") String input) {
return "处理结果: " + input;
}
}- 在
McpServer.java中注册:
toolRegistry.register(new MyTool());框架会自动生成 JSON Schema 并处理调用。
实现 McpResource 接口并在 McpServer.java 中注册:
resourceRegistry.register(new MyCustomResource());MIT // test comment