今日已更新 319 条资讯 | 累计 31147 条内容
关于我们

My MCP Tool's Empty-Payload Guard Checks Whether You Passed a Field. It Never Checked Whether the Field Would Actually Change Anything.

Enjoy Kumawat 2026年08月13日 11:44 0 次阅读 来源:Dev.to

Back in early August I fixed a bug in update_article , one of the tools in this repo's DEV.to MCP server. The bug was straightforward: the tool built its PUT payload from three optional parameters, and if a caller passed none of them, it still fired a GET and a PUT with an empty {"article": {}} body against a live published post, then logged a no-op entry to the audit trail as if something had happened. The fix was a guard: raise before either network call if the built payload dict ends up empty. article = {} if title is not None : article [ " title " ] = title if body_markdown is not None : article [ " body_markdown " ] = body_markdown if published is not None : article [ " published " ] = published if not article : raise ValueError ( " update_article called with no fields to update " " (title/body_markdown/published all None) " ) before = _dev ( f " /articles/ { article_id } " ) result = _dev ( f " /articles/ { article_id } " , method = " PUT " , data = { " article " : article }) _log_article_update ( article_id , before , article . keys (), result ) I closed the ticket, ran a stubbed selftest, moved on. Going back into this function for something unrelated, I noticed the guard only ever asks one question: did the caller pass a field? It never asks the question that actually matters for a tool whose whole job is writing to a live post: would this field's value be different from what's already there? Walk through what happens if a caller — an agent that re-reads an article's current title before deciding whether to touch it, gets it slightly wrong, or just calls the tool defensively with the value it already has — passes title="Same Title It Already Has" , and that string is in fact identical to the article's current title. article isn't empty. It has one key. The guard passes clean. Both network calls fire: before = _dev ( f " /articles/ { article_id } " ) # GET, real call result = _dev ( f " /articles/ { article_id } " , method = " PUT " , data = { " article " :

本文内容来源于互联网,版权归原作者所有
查看原文