mcp-groovy文件系统服务器v0.8.75
Spring Boot/Groovy MCP服务器提供文件系统、开发人员工具链和服务器生命周期操作 通过STDIO(主)和Streamable HTTP(HTTP伴随模式)连接到Claude Desktop和Claude Code。
______________________________________________________________________
架构--FS↔ 上下文服务器调用模式
了解FS和上下文服务器如何交互对于在出现问题时进行正确诊断至关重要。
运输路径
Claude Desktop (DT)
│
├─ stdio ──► FS stdio JVM (McpController) ← Claude tool calls arrive here
│ │
│ ├─ file_read / file_write / execute / server_lifecycle
│ │
│ ├─ FilesystemTelemetryService ← records tool_call_telemetry
│ │ └─ JDBC ──► best_practices.db ← shared SQLite, also owned by context-server
│ │
│ └─ ContextServerClient ← async HTTP to context HTTP companion
│ ├─ persistStructureAsync() ← fire-and-forget, non-blocking
│ ├─ upsertFileRegistryAsync() ← fire-and-forget, non-blocking
│ └─ resolveSessionId() ─► readActiveSessionId()
│ └─ JDBC ──► active_session table (best_practices.db)
│
└─ stdio ──► context-server stdio JVM (context_lifecycle, context_read, context_write)
│
└─ HTTP companion on :8082 ← separate process, separate JVM
└─ JDBC ──► best_practices.db ← same DB, different connection
mcp-agentic-workflow stdio JVM
└─ flow nodes use mcp.tool_call ──► HTTP :8081 (FS) ← NOT the same as FS stdio
└─► HTTP :8082 (ctx)诊断的关键规则
1. context_lifecycle 是一个上下文服务器工具,而不是FS。 当克劳德来电时 context_lifecycle start,它直接进入上下文服务器stdio JVM。 McpController 在FS中从未见过它。因此,接线 setActiveSessionId() 在FS McpController 在生命周期开始时,响应不起作用——呼叫永远不会到达那里。
2.会话ID解析——单点真值: active_session 桌子。 FilesystemTelemetryService.readActiveSessionId() 内容如下:
SELECT session_id FROM active_session ORDER BY id DESC LIMIT 1这首先被称为懒惰 recordToolCall() 并缓存在 trackedSessionId 为了会议。 这 active_session 表有列 (id, session_id, updated_at) --没有 status 列。 永远不要使用HTTP /current-session endpoint——它返回HTTP伴侣自己的会话范围, 不是DT stdio用户会话。
3.FS stdio和FS HTTP伴侣是完全独立的JVM。 file_read 来自克劳德→ FS stdio(单线程请求/响应)。 mcp.tool_call serverPort=8081 来自AW流节点→ FS HTTP伴侣。 他们共享 best_practices.db 通过JDBC,但具有单独的内存状态。
4.热路径(McpController→ 响应)必须具有零阻塞I/O。 McpController.handleToolsCall() 在stdio请求线程上运行。此处有任何阻塞I/O (JDBC打开,HTTP调用)将保持线程并导致MCP超时(-32001)。仅使用 volatile字段读取和异步提交到此路径上。从以下位置读取会话ID trackedSessionId volatile字段——在热路径上从未解决。
5. execute action=cmd --切勿使用 2>&1 与Gradle。 Windows同步管道缓冲区死锁:进程写入合并管道、管道填充、进程 阻塞等待消费者,消费者等待进程退出。Gradle写了严重的错误。 该工具在 stderr 自动响应字段。 对的: gradlew.bat compileGroovy --no-daemon 错误: gradlew.bat compileGroovy --no-daemon 2>&1
6.stdio上的Unicode——从v0.8.40开始强制执行UTF-8。 StdioMcpServer 用途 InputStreamReader(System.in, StandardCharsets.UTF_8). McpGroovyFileSystemServerApplication.main() 套 System.setOut(new PrintStream(System.out, true, "UTF-8")). 在v0.8.40之前,Windows JVM默认字符集(Cp1252)已损坏 → (U+2192), — (U+2014)和 工具参数中的其他非Latin-1字符,导致 file_write action=replace 默默地失败 和 oldText not found 即使文本在视觉上完全相同。
______________________________________________________________________
MCP工具(5个参数化工具)
| 工具 | 说明 |
|---|---|
file_read | 读取文件/目录:Read、head、tail、range、grep、multi_grep、multi、structure、get_method、info、校验和、diff、list(listing_hash+knownHash短路) |
file_write | 写入/修改文件:写入、追加、替换、修补、multi_replace、server_transform、chunk_Write |
file_search | 跨目录搜索文件内容(正则表达式)或文件名 |
file_lifecycle | 文件/目录创建、删除、复制、移动、重命名、触摸 |
server_lifecycle | 管理HTTP伴随服务器进程:start_ager、确保、停止、状态、重新加载 |
execute | 运行脚本:cmd、powershell、python、groovy、bash |
______________________________________________________________________
最新动态
v0.8.75--争用条件修复:在FileReadService和FileWriteService init()中使用回退重试(2026-04-30)
根本原因: @PostConstruct init() CS HTTP伴侣之前发生火灾(:8082)准备好了。 ServerLifecycleService.autoStartHttpCompanions() 分叉后返回-- :8082 尚未听 FileReadService / FileWriteService 呼叫 getHelpSection().第一次尝试得到 ConnectException,回落到 DEFAULT_DESC,会话在其整个生命周期内都在硬编码字符串上运行。
修复: 两者 FileReadService.init() 和 FileWriteService.init() 现在使用回退重试:在回退到之前,以0ms/300ms/700ms的速度重试3次 DEFAULT_DESC_*。涵盖了典型的200-500ms伴随启动窗口。 Thread.sleep 上 @PostConstruct 仅线程——对热路径没有影响。
两者 file_read 和 file_write 工具描述现在已从CS加载 help_sections 在启动时,不需要重建来更新它们。
FileWriteService.@PostConstruct init()电话ContextServerClient.getHelpSection('tool_desc_file_write')(紧凑型)和getHelpSection('tool_desc_file_write_verbose')在FS启动时。回退到DEFAULT_DESC_COMPACT/DEFAULT_DESC_VERBOSE如果CS不可达,则使用静态常数。getToolDefinitions()现在使用toolDescriptionCompact/toolDescriptionVerbose字段,而不是硬编码的内联字符串。help_sections在CS中播种的行:tool_desc_file_write(紧凑型,496个字符)和tool_desc_file_write_verbose(完整,1110个字符)。ContextServerClient.getHelpSection()已经在v0.8.70中实现了——重用不变。- 更新
file_write无构建的描述:context_write scope=help type=section action=update section_key=tool_desc_file_write content=然后重新启动DT。 - 想法#109(
Add DB-driven tool description loading to FileWriteService)标记delivered在v0.8.74版本中。delivered_inCS思想表中更新了进化轨迹。 FileReadService(v0.8.70)+FileWriteService(v0.8.74)现在都是DB驱动的。FileSearchService/ExecuteService保持硬编码(优先级较低——描述很少改变)。
根本原因已解决:缺失 expectedHash 允许静默双写和跨组文件哈希溢出。
FileReplaceService.doReplace,doMultiReplace和FilePatchService.doPatch:expectedHash现在是a 硬性要求缺失=立即toolError(是:记录警告并继续)。消除了整个类别的静默双写和漂移错误。FileWriteService.promoteTopLevelParamsbug修复:当两者都expectedHash和oldText/newText是顶级的(不嵌套在options),thecase 'replace'街区正在重建merged从空options,删除已晋升的expectedHash.通过播种固定merged ?: options.- CT-EH-1a/b/c: 拒绝
replace/multi_replace/patch当expectedHash缺席--文件未更改。 - CT-EH-2: 陈腐的
expectedHash→ 漂移警卫开火,文件不变。 - CT-EH-3: 正确
expectedHash→ 成功(防止过度阻塞)。 - CT-57/CT-61 更新:旧合同是“警告并继续”;新合同是“错误拒绝”。
- CT-63 已更新:虚拟
expectedHash提供了so file not found错误触发(不是哈希保护)。 FileWriteService.getToolDefinitions()更新了简洁而详细的描述:expectedHash现在被描述为强制性。- 计算机科学
tool_descriptions插入的行file_write强制性语言;help_sections tool_desc_file_read最后一行已更正。 - 全套:153次测试,0次失败。
v0.8.72--CT-RW-1..5:取代结构安全(2026-04-30)
- CT-RW-1:
replace上.groovy/.java不平衡支架newText现在是a 硬错误 (文件未修改)--与patch/multi_replace。以前只是一个警告。 - CT-RW-3:
DESTRUCTIVE_REPLACE警卫现在接受force=true合法大删除的逃生舱。警卫仍处于活动状态force. - CT-RW-4:
DESTRUCTIVE_REPLACE错误消息现在包括'pass options.force=true'提示。 - CT-RW-5: 替换为
oldTextnot found返回明显的not found错误(预先存在的行为,现在经过合约测试)。 - 全套:143次测试,0次失败。
v0.8.71--贴片式三角防护;更换防护顺序修复(2026-04-30)
- CT-80/CT-81:
FilePatchService.doPatch现在检查每次替换的括号增量.groovy/.java,与支架三角架(CT-14)相同。收市时渔获量下降)方法调用GString(例如。prepareStatement("""..""")). - CT-2/CT-19/CT-73/CT-76: 固定警卫秩序
FileReplaceService.doReplace—oldText之前检查过newText,因此空选项调用surface'oldText required'不'newText missing'.
v0.8.78--FIX-KH-UTO硬化:提示抑制+扩展测试覆盖范围(2026-05-01)
ReadResponseHelper.autoKhHintsSuppressed 添加了标志(mcp.filesystem.auto-kh-hints-suppressed.enabled,默认值 true).当自动查找处于活动状态并且CS可访问时, _knownhash_hint 由于服务器现在自动处理下一次读取,因此每次读取内容时消除了约40个噪声标记。当禁用自动查找或无法访问CS时,将恢复提示。
扩展测试覆盖范围: FileHashAutoLookupSpec CT-KH-AUTO-9..13(来自CS的格式错误的哈希→ 完整内容,持续CS空值→ 失败打开、检测到相同长度的内容更改、抑制/恢复提示)。 SqliteRangeCacheStoreSpec CT-RCS-19/20(阳性范围不可见的哨兵行 check()/checkWithTimestamp() 呼叫)。 HttpMcpControllerFileHashSpec CT-HMC-14..20(端点验证合同)。
v0.8.77-FIX-KH-AUTO:用于整个文件读取的服务器端自动knownHash(2026-05-01)
knownHash 尽管有提示、CLAUDE.md检查表和 _knownhash_hint 注射。根本原因:所有机制都要求调用者在N个工具调用中记住并重新传递一个瞬态哈希值——这在设计上是不可靠的。
修复:通过CS进行服务器端自动查找 /fileHashCache 终点。每次内容返回后 doRead(),FS异步存储 (sessionId, normalizedPath, hash) 在CS(ContextServerClient.storeFileHashAsync).在每一个后续的 doRead() 没有 options.knownHash,FS同步查找缓存的哈希(lookupFileHash,300毫秒超时)并返回 {unchanged:true, _auto_kh:true} 如果磁盘上的文件没有更改。呼叫者在不跟踪任何东西的情况下获得代币节省。
范围约束(选项A): 自动查找仅适用于整个文件 doRead(). doRange, doHead, doTail, doGetMethod 被排除在外--返回 unchanged:true 对于调用者没有看到的范围,这是一个正确性错误。范围/方法读取继续使用显式 knownHash +现有的范围读取缓存。
新类/方法: ContextServerClient.storeFileHashAsync(), lookupFileHash(). ReadResponseHelper.checkKnownHash(autoLookup=true) 超载。 storeAndHintKnownHash(autoStore=true) 替换 injectKnownHashHint().特征标志: mcp.filesystem.auto-kh-lookup.enabled=true.
CS侧: SqliteRangeCacheStore.storeFileHash() / lookupFileHash() 使用 session_read_cache 与哨兵 start_line=-1, end_line=-1. HttpMcpController.handleFileHashCache() 瘦代理端点。测试范围:CT-RCS-10..18、CT-KH-AUTO-1..8。
v0.8.70--通过ContextServerClient描述数据库驱动的工具(2026-04-29)
FileReadService.getToolDefinitions() 现在由DB驱动 ContextServerClient.getHelpSection(). @PostConstruct init() 负载 tool_desc_file_read 来自CS的行 help_sections 在启动时。回退到 DEFAULT_DESC 如果CS不可达,则为静态常数。
v0.8.69--FIX-6A:在BLOCKED_UNRANGED_INDEXED_READ中的已知哈希(2026-04-29)
BLOCKED_UNRANGED_INDEXED_READ 错误现在包括 known_hash 当CS有路径的注册表项时,每个被阻止文件的字段。FS通过以下方式呼叫CS ContextServerClient.getKnownHashForPath(normalizedPath) — context_read scope=ontology action=file-hash。允许呼叫者通过 knownHash 立即,无需单独阅读。
v0.8.68--CT-77..CT-79:补丁 expectedRemovedText 内容保护(2026-04-26)
doPatch 验证每个替换条目的可选项 expectedRemovedText 反对 lines[start..end].不匹配= CONTENT_MISMATCH toolError,文件未被修改。防止过时的行号错误悄无声息地损坏文件。字段是可选的。
v0.8.67-CT-DR-1..CT-DR-4:破坏性更换比例防护装置(2026-04-22)
doReplace 拒绝时 oldText.length > 500 与 newText.length &1)
- 构建 —
gradlew.bat packageMcpbThin installMcpbLocal - 流动 --
flow_management start mode=flow templateName=mcp-deploy version=3.6
使用参数: serverName, projectDir, newVersion, jarPrefix (jarPrefix=mcp-groovy-filesystem-server 对于此服务器)
- 人门 --关闭DT,重新打开DT
- 验证 --新会话自动检测
deploy-state.json,确认jar,删除状态文件
mcp-http-servers.json 现在已自动更新 通过 copyToJarsDir (v0.8.48)--部署后不需要手动补丁。
在步骤4未完成之前,切勿重新启动DT。 流程更新 mcp-http-servers.json, cc-config, server_versions,并写道 deploy-state.json。跳过它需要手动 每次修补这些文件。
______________________________________________________________________
server_transform--文件类型规则(v0.8.20+)
| 转换 | 文件类型 | 关键选项 |
|---|---|---|
replace_method | .groovy, .java 只有 | options.method, options.newBody |
add_method | .groovy, .java 只有 | options.method, options.newBody |
add_import | .groovy, .java 只有 | options.import |
replace_section | .md, .yml, .yaml, .toml | options.heading, options.newContent |
insert_before_match | 任何文件类型 | options.match (子字符串), options.content, options.occurrence (1/-1/N) |
insert_after_heading | .md, .yml, .yaml, .toml | options.heading, options.content |
append_section | .md, .yml, .yaml, .toml | options.heading, options.content |
replace_between | 任何文件类型 | options.startAnchor, options.endAnchor, options.newContent |
所有转换都需要 options.expectedHash。对于任意文本交换:使用 file_write action=multi_replace.
______________________________________________________________________
mcp-http-servers.json——服务器配置
位于 C:/Users/willw/claude-sync/mcp-http-servers.json.
| 字段 | 描述 | |
|---|---|---|
name | 服务器标识符 | |
jar | Jar文件名(in jarsDir) — 即使对于MCPB服务器,每次部署都必须更新 | |
port | HTTP端口 | |
startupPolicy | eager | lazy |
mcpb | true =作为MCPB扩展部署(DT从Claude Extensions目录读取) | |
dtOwned | true =DT管理stdio生命周期 | |
autoHttpCompanion | true =在FS stdio启动时以HTTP子级身份启动 | |
jvmArgs | 额外的JVM参数 |
这 jar 字段驱动HTTP伴侣启动,即使是 mcpb:true 服务器。错误版本=配套 从错误的罐子开始。始终由更新 mcp-deploy:3.6 update-http-servers 节点(运行预构建)。
______________________________________________________________________
构建
# Compile check (no artifact)
cd C:/Users/willw/IdeaProjects/mcp-groovy-filesystem-server
gradlew.bat compileGroovy --no-daemon # NO 2>&1 -- pipe deadlock on Windows
# Full build + install
gradlew.bat packageMcpbThin installMcpbLocal安装到:
%APPDATA%/Claude/Claude Extensions/local.mcpb.will-woodman.mcp-groovy-filesystem-server/
manifest.json
server/mcp-groovy-filesystem-server-.jar还将jar复制到 claude-sync/jars/ 通过 copyToJarsDir 任务(用于HTTP伴随模式)。
______________________________________________________________________
版本历史记录
| 版本 | 亮点 | ||
|---|---|---|---|
| 0.8.75 | 竞赛条件修复:在中使用回退(0ms/300ms/700ms)重试 FileReadService.init() 和 FileWriteService.init().防止 @PostConstruct 在CS HTTP伴侣准备就绪之前触发,这导致了静默回退 DEFAULT_DESC 整个会议。 | ||
| 0.8.74 | DB驱动 file_write 工具描述(想法#109已完成)。 @PostConstruct init() 负载 tool_desc_file_write + tool_desc_file_write_verbose 来自CS help_sections.回落到 DEFAULT_DESC_* 如果CS不可达。通过以下方式更新描述而无需重建 context_write scope=help两者都有 file_read (0.8.70)和 file_write (0.8.74)现在由DB驱动。 | ||
| 0.8.73 | CT-EH-1-- expectedHash 必须的 replace | patch | multi_replace (缺席时出现硬错误)。 promoteTopLevelParams bug已修复--顶级 expectedHash+oldText 现在两个土地 options.5项新的CT-EH合同测试。计算机科学 tool_descriptions + help_sections 更新。153次测试,0次失败。 |
| 0.8.72 | CT-RW-1..5--替换结构安全:不平衡支撑=硬误差; DESTRUCTIVE_REPLACE force=true 舱口;警卫命令固定;未找到合同测试。 | ||
| 0.8.71 | CT-80/CT-81——贴片式三角防护 .groovy/.javaCT-2/CT-19/CT-73/CT-76-- doReplace 警卫命令修复(oldText 之前 newText). | ||
| 0.8.70 | FileReadService 通过CS驱动的工具描述数据库 help_sections (tool_desc_file_read 行)。如果CS不可访问,则返回默认编译状态。 | ||
| 0.8.69 | FIX-6A-- BLOCKED_UNRANGED_INDEXED_READ 错误包括 known_hash 从CS文件注册表中。 FS→CS通过 getKnownHashForPath(). | ||
| 0.8.68 | CT-77…CT-79-- doPatch expectedRemovedText 内容保护。不匹配= CONTENT_MISMATCH toolError,文件未被修改。 | ||
| 0.8.67 | CT-DR-1…CT-DR-4-- DESTRUCTIVE_REPLACE 比率保护:拒绝 oldText>500 + newText&1 与Gradle。 | ||
| 0.8.39 | McpController 会话ID通过 trackedSessionId 不稳定的领域。 ContextServerClient.activeSessionId 包范围。 | ||
| 0.8.38 | readActiveSessionId() SQL修复程序-- active_session 没有 status 列。查询: ORDER BY id DESC LIMIT 1. | ||
| 0.8.37 | 单点控制: FilesystemTelemetryService.readActiveSessionId() JDBC——替换损坏的HTTP /current-session.修复了以下49K行 session='unknown'. session_working_files 现在填充。 | ||
| 0.8.36 | mcp-http-servers-runtime.json v2格式。 killHttpCompanions Gradle任务。 | ||
| 0.8.35 | FileReplaceService 三通Unicode标准化(NFC→NFKC→方框图)。 | ||
| 0.8.34 | MCPB包装: generateMcpbManifest, packageMcpbThin, installMcpbLocal, copyToJarsDir. | ||
| 0.8.33 | replace_section headingStyle=text --任意锚匹配。 | ||
| 0.8.32 | GCU沉降1.1.0→ 1.1.1. | ||
| 0.8.31 | startServer() 通过 -Dspring.profiles.active=http HTTP配套ProcessBuilder。 | ||
| 0.8.29 | 关键:自伴生成修复——stdio不再在端口8081冲突时崩溃。 | ||
| 0.8.28 | grepPattern stdout上限修复。 | ||
| 0.8.27 | execute options.grepPattern --stdout上的Java正则表达式。 | ||
| 0.8.26 | server_transform 文件类型保护修复; add_import 参数已更正。 | ||
| 0.8.21 | file_read action=list 列表哈希+ knownHash; multi_grep 行动。 | ||
| 0.8.18 | 已启用编码 file_read action=list. | ||
| 0.8.17 | stopOneServer 杀人后 waitForPortFree + killByPort netstat回退。 | ||
| 0.8.10 | autoStartHttpCompanions --stdio启动时HTTP伴随自动启动。 | ||
| 0.8.6 | StdioMcpServer 1MB缓冲区(8KB)。 | ||
| 0.8.5 | 可流式HTTP传输(HttpMcpController). |
