ADR-0011: Allow gateways to add tools with the same server side name to the MCP Gateway without conflictΒΆ
- Status: Implemented
- Date: 2025-06-22
- Deciders: Core Engineering Team
- Implemented by: IBM/mcp-context-forge#116
ContextΒΆ
The current functionality only supports unique names for tools, making it hard for addition of tools from different gateways with similar common names.
This needs to be updated so that tool names are allowed with a combination of gateway name (slugified namespace) and tool name. This would allow servers to add their own versions of the tools.
The tool names would be stored along with their original name in the database so that the correct server side name is passed while invoking it.
DecisionΒΆ
We implemented this by making the following changes:
- Update IDs from integers to UUIDs:
- Modify the data type of
idinGateway,ToolandServerSQLAlchemy ORM classes from int to str - Use a default value of
uuid.uuid4().hexfor the IDs -
Modify
server_idandtool_idto String inserver_tool_associationtable -
Separate server side and gateway side names for tools:
- Add a new field called
original_namein Tool ORM class to store the MCP server side name used for invocation - Define a hybrid operator
nameto capture how the gateway exposes the tool. Set it asf"{slugify(self.gateway.name)}{settings.gateway_tool_name_separator}{self.original_name}" - Slugified
self.gateway.nameis used to remove spaces in new tool names - Hybrid operator is used so it can be used in Python and SQL code for filtering and querying
-
Add a new field called
gateway_slugwhich is defined as theslugof the Gateway linked viaself.gateway_id. This field is later used to extract the original name from name passed from APIs -
Addition of configurable environmental variable
GATEWAY_TOOL_NAME_SEPARATORto set how the tool name looks like: -
By default, this is set to
-in config.py -
Updates Python object schemas, function data types to match database ORM changes**
- Change data type of
gateway_id,tool_idandserver_idfrom int to str in API functions - When storing and updating tools, use
original_nameinDbToolobjects to store the original name coming from_initiate_gateway. - Remove check for only storing tools without matching original names
- Check if
gateway.urlexists instead ofgateway.nameexists before thowingGatewayNameConflictError. - Check for existing tools on
original_nameandgateway_idinstead of justname(as earlier) in update_gateway and toggle_gateway_status code. - Set
nameandgateway_slugjust before passing toToolReadseprately since these don't come from the database as these are properties and not columns. -
To obtain tool from database for invocation, handle the case that
namefrom the API is not stored as a column in the database, but is a property by making an appropriate comparison asDbTool.gateway_slug + settings.gateway_tool_name_separator + DbTool.original_name == name -
Handle tool changes from the gateway by adding and removing tools based on latest deactivate/activate or edit:
- Step 1: Add all tools not present in database based on
original_nametogateway.tools -
Step 2: Remove any tools not sent in the latest call to
_initialize_gatewayfromgateway.tools. -
Show row index in UI:
- Display the index of the row with
loop.indexin a new column calledS. No.in Gateways, Tools and Servers screens.
ConsequencesΒΆ
- Two gateways can have the tools with the same native name on the gateway. e.g.
gateway-1-get_system_timeandgateway-2-get_system_time. - If the tools on a gateway change, they will reflect after Deactivate/Activate cycle or after Edit Gateway action.
Alternatives ConsideredΒΆ
| Option | Why Not |
|---|---|
| Use qualified_name as display name and name as native MCP server name | Requires changes at more places since most clients display and call with the field name |