Skip to content

Commit 2ba04cf

Browse files
committed
fix(tools): compare stored tool names in tool name conflict checks
The tool conflict checks compared raw names. The set_custom_name_and_slug listener stores the slug of the custom name in DbTool.name, with the gateway prefix for a gateway tool. A name that differs from its own slug never matched its stored row. The checks accepted duplicates in one visibility scope. register_tool() also had no private-scope check. Compute the stored name the same way as the listener, with slugify() or build_gateway_tool_invocation_name(). Check it against public tools, team tools of the same team, and private tools of the same owner. _tool_name_scope() is the one definition of these scopes. - register_tool() uses LIMIT 1, so legacy duplicate rows raise ToolNameConflictError (HTTP 409) and not MultipleResultsFound (HTTP 400). - update_tool() checks the final stored name on a rename, a custom_name change, or a visibility change. One helper covers tools with and without a gateway. - _process_tool_chunk() matches each incoming tool by its position. It applies the conflict strategy to existing rows and to earlier tools of the same chunk. - _load_authorized_tool_conflicts() and _existing_tools_query() look up stored names. The import ownership check and the late-collision check therefore cover slug-equivalent names. PR #6534 fixes the federation gap of the issue. A database-level unique constraint per visibility scope needs a migration and a maintainer decision. This change does not include it. gRPC reflection sync does not use these checks. Refs #6189 Signed-off-by: Waleed Khalid <wak327@gmail.com>
1 parent a211ab7 commit 2ba04cf

5 files changed

Lines changed: 554 additions & 177 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
SELECT owner_email, name, COUNT(*) AS duplicate_count FROM tools WHERE visibility = 'private' GROUP BY owner_email, name HAVING COUNT(*) > 1 ORDER BY owner_email, name;
3535
```
3636

37+
- **Tool creation and update reject normalized tool-name collisions** ([#6189](https://github.com/IBM/mcp-context-forge/issues/6189)) - Tool registration, tool update, and configuration import now compare the stored tool name in the public, team, and private visibility scopes. The stored name is the slug of the tool name, with the gateway prefix for gateway tools. The slug uses `GATEWAY_TOOL_NAME_SEPARATOR` (default `-`). `POST /tools` and the Admin UI return HTTP 409 for names that differ only in case or separator characters, such as `My_Tool` and `my-tool`. An exact repeat of a name that differs from its own slug, such as `Get_Weather`, also returns HTTP 409. A rename or visibility change that collides on the stored name fails with the existing update conflict response: HTTP 400 from `PUT /tools/{id}` and HTTP 409 from the Admin UI edit form. Configuration import applies its conflict strategy to existing rows and to earlier tools of the same import batch. Clients that created such duplicates before must handle the conflict response. The SQL queries in the *Federated gateway tool-name collisions* entry find existing duplicate rows.
38+
3739
- **Modern MCP protocol negotiation is on by default** - `MCP_CLIENT_CONNECT_MODE` and `MCP_INBOUND_PROTOCOL_MODE` now default to `auto` instead of `legacy`. Outbound upstream connections probe `server/discover` and negotiate the 2026-07-28 revision, with transparent fallback to the legacy `initialize` handshake. Inbound clients may send `mcp-protocol-version: 2026-07-28` instead of receiving a 400. Set either variable to `legacy` to restore the previous behaviour.
3840
- **`mcp-servers/` directory removed** - The unsupported sample/test MCP servers, the Go/Python scaffolding templates, and the `mcp-url-to-markdown-tests` workflow leave the repository. The six Python servers now live in [IBM/contextforge-examples](https://github.com/IBM/contextforge-examples) under `mcp-servers/python/`; the scaffolding templates are deleted without migration. The performance compose generator and benchmark docs now use the published `ghcr.io/ibm/cfex-mcp-fast-time-server` and `ghcr.io/ibm/cfex-mcp-benchmark-server` images. The `/v1/mcp-servers` REST API is unchanged: it remains the product-language alias for the gateways API.
3941

0 commit comments

Comments
 (0)