From 299dcce78faf414a4abb92cab1e12f5080999551 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Sat, 16 May 2026 21:04:29 +0000 Subject: [PATCH] repl: validate MCP tool names against Bedrock regex (closes #32) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anthropic-via-Bedrock enforces ^[a-zA-Z0-9_-]{1,128}$ on tool names. We already moved the alias separator from "." to "__" (commit f26cbd9), but a future MCP server could still register a tool whose name (or whose combination with the alias) contains characters outside that class — silently breaking calls to strict providers. connect_mcp now warns at startup for: - aliases containing "__" (would misparse on tool dispatch) - emitted alias__name strings that violate the regex or exceed 128 chars Behavior preserved: validation is informative-only. tools_schema() still emits the offending tool; local llama.cpp users accept lenient names and shouldn't be penalized for downstream strictness. Co-Authored-By: Claude Opus 4.7 (1M context) --- repl.lua | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/repl.lua b/repl.lua index b5f33f8..4041171 100644 --- a/repl.lua +++ b/repl.lua @@ -142,6 +142,22 @@ function M.run(config) if sess.version_warning then renderer.status("mcp " .. alias .. ": " .. sess.version_warning) end + -- Tool-name validation (issue #32): Anthropic via Bedrock enforces + -- ^[a-zA-Z0-9_-]{1,128}$. We use "__" as the alias separator, so the + -- emitted name is alias__tool. Warn at startup; emit anyway so local + -- llama.cpp users aren't penalized for lenient downstreams. + if alias:find("__", 1, true) then + renderer.status(("mcp %s: alias contains '__' (used as separator); " + .. "tool dispatch will misparse"):format(alias)) + end + for _, t in ipairs(sess:list_tools()) do + local full = alias .. "__" .. (t.name or "") + if #full > 128 or full:find("[^%w_-]") then + renderer.status(("mcp %s: tool name '%s' violates " + .. "^[a-zA-Z0-9_-]{1,128}$ (will fail with strict providers " + .. "e.g. anthropic via Bedrock)"):format(alias, full)) + end + end return true, #sess:list_tools() end