Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

fix(mcp): normalize filename in post tools + fix schema docs (fixes #117, #118, #119)#120

Merged
Tespera merged 1 commit into
Gridea-Pro:mainGridea-Pro/gridea-pro:mainfrom
gkd2323c:fix/mcp-tool-bugsgkd2323c/gridea-pro:fix/mcp-tool-bugsCopy head branch name to clipboard
Jun 3, 2026
Merged

fix(mcp): normalize filename in post tools + fix schema docs (fixes #117, #118, #119)#120
Tespera merged 1 commit into
Gridea-Pro:mainGridea-Pro/gridea-pro:mainfrom
gkd2323c:fix/mcp-tool-bugsgkd2323c/gridea-pro:fix/mcp-tool-bugsCopy head branch name to clipboard

Conversation

@gkd2323c

@gkd2323c gkd2323c commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

修复内容

修复 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.mdREADME-en.md 修正 MCP 配置示例:gridea-pro --mcpgridea-pro-mcp.exeGRIDEA_SITE_DIRSOURCE_DIR,并新增"响应乱序"说明(mark3labs/mcp-go v0.43.2 stdio transport 默认并发)

方案

tool_post.gonormalizeFileName(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):

Test Before After
create_post fileName=t1delete_post filename=t1.md 文件仍在 ✅ 文件删除
create_post fileName=t2update_post filename=t2.md title="Updated" 静默未命中 ✅ 正确更新

完整 go test ./backend/... 全过。

变更

README.md                                    | 11 ++++++++--
README-en.md                                 |  9 ++++++---
backend/internal/mcp/tool_post.go            | 35 +++++++++++++++++++++++++++--------
backend/internal/mcp/tool_post_test.go (new) | 51 +++++++++++
4 files changed, 76 insertions(+), 15 deletions(-)

兼容性

  • 行为变化:之前传 "xxx.md" 是 bug;之后传 "xxx.md" 会被归一化成 "xxx",与传 "xxx" 等价。
  • 对正常 caller(传不带 .md 的名字)完全无影响。
  • 对之前踩过 bug、磁盘上有 xxx.md.md 文件的用户:新的 create_post 行为会写新的 xxx.md,与旧的 xxx.md.md 共存;缓存会自动用新文件的 key。要清理旧文件需要手动重命名或删 xxx.md.md

关联

…#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.
@gkd2323c
gkd2323c requested review from Tespera and kev1nweng June 2, 2026 11:57
@Tespera
Tespera merged commit 679e7c1 into Gridea-Pro:main 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.