fix(mcp): normalize filename in post tools + fix schema docs (fixes #117, #118, #119)#120
Merged
Merged
fix(mcp): normalize filename in post tools + fix schema docs (fixes #117, #118, #119)#120
Conversation
…#117, Gridea-Pro#119, Gridea-Pro#118) Three related bugs in the Gridea Pro MCP server's post tools: 1. delete_post returned success without deleting the file (Gridea-Pro#117): - post_repo.go:Delete blindly appended '.md' to the filename parameter - If the caller passed a name with '.md' (e.g. 'xxx.md'), the actual os.Remove target was 'xxx.md.md' (didn't exist), the os.IsNotExist error was silently suppressed, and the function returned nil. - Fix: normalize the filename at the MCP entry point. 2. update_post could silently target the wrong file (Gridea-Pro#119): - The repo layer's cache stores FileName without '.md' (trimmed on read) but writes the file as FileName + '.md'. - createPostHandler didn't normalize the fileName parameter, so a caller passing 'xxx.md' would write 'xxx.md.md' to disk while the cache kept 'xxx.md' — permanently desynced. - Subsequent get_post / update_post / delete_post with 'xxx.md' would match the desynced cache entry, not the real 'xxx.md' file. - Fix: normalize at the entry of all 4 post handlers. 3. Tool schema descriptions mismatched implementation (Gridea-Pro#118): - get_post example 'hello-world.md' misled callers into passing '.md' (which then triggered bugs Gridea-Pro#117 and Gridea-Pro#119). - create_post tags description 'Comma separated tags or JSON array string' suggested JSON-array support that the handler never had. - README example used 'gridea-pro --mcp' (which doesn't exist) and 'GRIDEA_SITE_DIR' (actual env var is SOURCE_DIR). - Fix: clarify all schema descriptions; correct README config example; add note about out-of-order MCP responses (a mark3labs/mcp-go stdio transport behavior, not a Gridea bug, but undocumented). Approach: added a normalizeFileName helper and called it at the entry of all 4 post handlers (create / get / update / delete). The helper strips any trailing '.md' so callers can pass either 'hello-world' or 'hello-world.md' interchangeably. The repo layer is unchanged — it already has the correct invariant (FileName without '.md', disk file as FileName + '.md'); the bug was at the MCP boundary. Added tool_post_test.go with 9 cases for normalizeFileName, including the legacy 'xxx.md.md' migration case (a caller that hit the bug before this fix). End-to-end verification: built binary with the patch, ran a Python script that: - Creates a post with fileName='t1', then calls delete_post with filename='t1.md' (the exact bug pattern) — file is now actually deleted (previously: lied). - Creates a post with fileName='t2', then calls update_post with filename='t2.md' (the exact bug pattern) — title updates on the correct file (previously: silent miss). Both pass.
This was referenced Jun 3, 2026
Tespera
added a commit
that referenced
this pull request
Jun 3, 2026
#120 在 MCP handler 层兜住了 .md 双扩展/缓存失同步,本次把规范化下沉到 repo 本身, 消除「FileName 必须裸名」这个全靠 caller 自觉的隐性约定: - 新增 normalizeFileName 助手(循环 strip 末尾 .md,含历史遗留的 .md.md) - save(FileName + DeleteFileName)、Delete、GetByFileName 入口统一归一 - parsePost 改用它(与 save 补 .md 对称) - Delete 的 os.Remove 吞 IsNotExist 改为:非 NotExist 才返回错误;文件已不在则记一条 warning(归一后属幂等删除,记录以防隐性不一致) - 新增 normalizeFileName 单测 对现有调用方(GUI/facade 传裸名、MCP 已被 #120 归一)无行为变化,纯加固。 关联 #122 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
修复内容
修复 3 个 Gridea Pro MCP server 的相关问题(对应 issue #117 / #118 / #119):
1.
delete_post真正删文件(#117)backend/internal/repository/post_repo.go:Delete之前对fileName盲拼.md。如果 caller 传"xxx.md",实际os.Remove目标是"xxx.md.md"(不存在),os.IsNotExist错误被显式吞掉,函数返回nil——MCP 报"Post deleted"但文件没动。2.
update_post改对文件(#119)repo 缓存存的
FileName不带.md(parsePost 强制 trim),但save写盘时拼成FileName + ".md"。createPostHandler没规范化fileName参数——caller 传"xxx.md"会写到xxx.md.md,缓存里却存"xxx.md",永久 desync。后续get_post/update_post/delete_post用"xxx.md"找的是脏数据,不是真正的xxx.md文件。3. Schema 描述与实现对齐(#118)
get_post例子从'hello-world.md'改成'hello-world'(去掉误导)create_post.tags描述从 "Comma separated tags or JSON array string" 改成 "Comma-separated tag names, e.g. 'tag1, tag2, tag3'"(删除实际不支持的 JSON array 描述)create_post.fileName注明 "WITHOUT the .md extension"update_post.filename/delete_post.filename同上README.md和README-en.md修正 MCP 配置示例:gridea-pro --mcp→gridea-pro-mcp.exe、GRIDEA_SITE_DIR→SOURCE_DIR,并新增"响应乱序"说明(mark3labs/mcp-go v0.43.2 stdio transport 默认并发)方案
在
tool_post.go加normalizeFileName(name)工具函数(循环剥掉所有尾部.md),在 4 个 post handler(create / get / update / delete)入口处调用。Repo 层完全不动——它本身的 invariant 是对的(缓存FileName不带.md、盘上FileName + ".md"),bug 在 MCP 边界处。normalizeFileName也兼容修复前的脏数据:传"xxx.md.md"也会归一化成"xxx",所以已经被 bug 影响的用户的posts.json索引也会被新调用正确指向。测试
backend/internal/mcp/tool_post_test.go(新文件):9 个 case 覆盖 normalizeFileName 行为,含xxx.md.md迁移场景。端到端验证(用本地 build 的
gridea-pro-mcp.exe跑 stdio):create_post fileName=t1→delete_post filename=t1.mdcreate_post fileName=t2→update_post filename=t2.md title="Updated"完整
go test ./backend/...全过。变更
兼容性
"xxx.md"是 bug;之后传"xxx.md"会被归一化成"xxx",与传"xxx"等价。.md的名字)完全无影响。xxx.md.md文件的用户:新的create_post行为会写新的xxx.md,与旧的xxx.md.md共存;缓存会自动用新文件的 key。要清理旧文件需要手动重命名或删xxx.md.md。关联