docs: 全面更新文档 - README/需求文档/修改记录

README.md:
- 功能特性分 P0/P1/P2 三级展示
- 工具列表更新为 18 个(含 P0/P2 工具)
- 命令列表更新为 28 个(分基础/P0/P1/P2 四组)
- 新增 MCP 服务器配置和使用说明
- 新增插件系统使用说明(JAR 加载、目录结构)
- 新增 Vim 模式和 Hook 系统使用说明
- 架构图更新:含 mcp/、plugin/、core/ 新组件
- 核心流程图更新:含 Hook 和权限确认
- 对应关系表新增 MCP/Plugin/Hook/Task 映射

需求文档.md:
- 5.1 实现清单更新为 18 工具 + 28 命令
- 5.2 P0/P1/P2 标记为全部已实现
- 仅保留 P3 跳过项目

修改记录.md:
- 新增 P0/P1/P2 四条修改记录(倒序排列)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
liuzh
2026-04-01 23:04:01 +08:00
co-authored by Copilot
parent 79736cf16f
commit 1fc7a6a495
6 changed files with 411 additions and 112 deletions
+26 -21
View File
@@ -2,7 +2,6 @@ package com.claudecode.mcp;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -47,10 +46,10 @@ public class McpClient implements AutoCloseable {
private final Map<String, McpResource> resources = new ConcurrentHashMap<>();
/** 服务器能力信息 */
private JsonNode serverCapabilities;
private volatile JsonNode serverCapabilities;
/** 服务器信息 */
private JsonNode serverInfo;
private volatile JsonNode serverInfo;
/** 是否已完成初始化 */
private volatile boolean initialized = false;
@@ -165,15 +164,17 @@ public class McpClient implements AutoCloseable {
JsonNode response = transport.sendRequest(MAPPER.writeValueAsString(request));
JsonNode result = response.get("result");
if (result != null && result.has("tools")) {
ArrayNode toolsArray = (ArrayNode) result.get("tools");
for (JsonNode toolNode : toolsArray) {
String name = toolNode.get("name").asText();
String description = toolNode.has("description")
? toolNode.get("description").asText() : "";
JsonNode inputSchema = toolNode.get("inputSchema");
JsonNode toolsNode = result.get("tools");
if (toolsNode != null && toolsNode.isArray()) {
for (JsonNode toolNode : toolsNode) {
String name = toolNode.get("name").asText();
String description = toolNode.has("description")
? toolNode.get("description").asText() : "";
JsonNode inputSchema = toolNode.get("inputSchema");
tools.put(name, new McpTool(name, description, inputSchema));
log.debug("发现 MCP 工具: {} - {}", name, description);
tools.put(name, new McpTool(name, description, inputSchema));
log.debug("发现 MCP 工具: {} - {}", name, description);
}
}
}
} catch (McpException e) {
@@ -214,17 +215,19 @@ public class McpClient implements AutoCloseable {
JsonNode response = transport.sendRequest(MAPPER.writeValueAsString(request));
JsonNode result = response.get("result");
if (result != null && result.has("resources")) {
ArrayNode resourcesArray = (ArrayNode) result.get("resources");
for (JsonNode resNode : resourcesArray) {
String uri = resNode.get("uri").asText();
String name = resNode.has("name") ? resNode.get("name").asText() : uri;
String description = resNode.has("description")
? resNode.get("description").asText() : "";
String mimeType = resNode.has("mimeType")
? resNode.get("mimeType").asText() : "text/plain";
JsonNode resourcesNode = result.get("resources");
if (resourcesNode != null && resourcesNode.isArray()) {
for (JsonNode resNode : resourcesNode) {
String uri = resNode.get("uri").asText();
String name = resNode.has("name") ? resNode.get("name").asText() : uri;
String description = resNode.has("description")
? resNode.get("description").asText() : "";
String mimeType = resNode.has("mimeType")
? resNode.get("mimeType").asText() : "text/plain";
resources.put(uri, new McpResource(uri, name, description, mimeType));
log.debug("发现 MCP 资源: {} ({})", name, uri);
resources.put(uri, new McpResource(uri, name, description, mimeType));
log.debug("发现 MCP 资源: {} ({})", name, uri);
}
}
}
} catch (McpException e) {
@@ -409,6 +412,8 @@ public class McpClient implements AutoCloseable {
@Override
public void close() throws Exception {
initialized = false;
tools.clear();
resources.clear();
transport.close();
log.info("MCP 客户端 '{}' 已关闭", serverName);
}