@@ -1150,6 +1150,78 @@ async def test_check_tool_permission_for_key_team_allows_all_when_no_restriction
1150
1150
user_api_key_auth = user_auth ,
1151
1151
)
1152
1152
1153
+ @pytest .mark .asyncio
1154
+ async def test_allowed_tools_with_mixed_prefixed_and_unprefixed_names (self ):
1155
+ """
1156
+ Test that allowed_tools works with both unprefixed and prefixed tool names.
1157
+ This tests the scenario where allowed_tools = ["getpetbyid", "my_api_mcp-findpetsbystatus"]
1158
+ Both getpetbyid (unprefixed) and findpetsbystatus (called unprefixed but allowed via prefix) should work.
1159
+ """
1160
+ manager = MCPServerManager ()
1161
+
1162
+ # Create server with mixed prefixed/unprefixed allowed_tools
1163
+ server = MCPServer (
1164
+ server_id = "my_api_mcp" ,
1165
+ name = "my_api_mcp" ,
1166
+ transport = MCPTransport .stdio ,
1167
+ allowed_tools = ["getpetbyid" , "my_api_mcp-findpetsbystatus" ],
1168
+ disallowed_tools = None ,
1169
+ )
1170
+
1171
+ # Mock dependencies - set object_permission and object_permission_id to None
1172
+ # so permission checks return None (no restrictions)
1173
+ user_api_key_auth = MagicMock ()
1174
+ user_api_key_auth .object_permission = None
1175
+ user_api_key_auth .object_permission_id = None
1176
+ proxy_logging_obj = MagicMock ()
1177
+
1178
+ # Mock the async methods that pre_call_tool_check calls
1179
+ proxy_logging_obj ._create_mcp_request_object_from_kwargs = MagicMock (
1180
+ return_value = {}
1181
+ )
1182
+ proxy_logging_obj ._convert_mcp_to_llm_format = MagicMock (return_value = {})
1183
+ proxy_logging_obj .pre_call_hook = AsyncMock (return_value = {})
1184
+
1185
+ # Test 1: Call getpetbyid (unprefixed in allowed_tools) - should succeed
1186
+ await manager .pre_call_tool_check (
1187
+ name = "getpetbyid" ,
1188
+ arguments = {"petId" : "1" },
1189
+ server_name_from_prefix = "my_api_mcp" ,
1190
+ user_api_key_auth = user_api_key_auth ,
1191
+ proxy_logging_obj = proxy_logging_obj ,
1192
+ server = server ,
1193
+ )
1194
+
1195
+ # Test 2: Call findpetsbystatus (prefixed in allowed_tools as "my_api_mcp-findpetsbystatus") - should succeed
1196
+ await manager .pre_call_tool_check (
1197
+ name = "findpetsbystatus" ,
1198
+ arguments = {"status" : "available" },
1199
+ server_name_from_prefix = "my_api_mcp" ,
1200
+ user_api_key_auth = user_api_key_auth ,
1201
+ proxy_logging_obj = proxy_logging_obj ,
1202
+ server = server ,
1203
+ )
1204
+
1205
+ # Test 3: Call a tool that's not in allowed_tools - should fail
1206
+ with pytest .raises (HTTPException ) as exc_info :
1207
+ await manager .pre_call_tool_check (
1208
+ name = "deletepet" ,
1209
+ arguments = {"petId" : "1" },
1210
+ server_name_from_prefix = "my_api_mcp" ,
1211
+ user_api_key_auth = user_api_key_auth ,
1212
+ proxy_logging_obj = proxy_logging_obj ,
1213
+ server = server ,
1214
+ )
1215
+
1216
+ assert exc_info .value .status_code == 403
1217
+ assert (
1218
+ "Tool deletepet is not allowed for server my_api_mcp"
1219
+ in exc_info .value .detail ["error" ]
1220
+ )
1221
+ assert (
1222
+ "Contact proxy admin to allow this tool" in exc_info .value .detail ["error" ]
1223
+ )
1224
+
1153
1225
1154
1226
if __name__ == "__main__" :
1155
1227
pytest .main ([__file__ ])
0 commit comments