Conversation
d9e97a1 to
0ef3f89
Compare
42e28fd to
0f7bf73
Compare
1cc8717 to
5850a18
Compare
b80501d to
0fa8ac1
Compare
marekdano
left a comment
There was a problem hiding this comment.
Summary:
This PR successfully implements the refresh tools feature and overflow menu, but has some implementation concerns that should be addressed before merging.
Issues to Address
Medium Priority:
- Fragile relationship loading check (mcpgateway/services/gateway_service.py:4160)
tools_rel = gateway.__dict__.get("tools")
gateway_dict["tool_count"] = len(tools_rel) if tools_rel is not None else 0- Using dict.get() is SQLAlchemy-internal and fragile
- If selectinload is removed elsewhere, tool counts silently become 0 with no error
- Fix: Use inspect(gateway).attrs["tools"].loaded_value (official SQLAlchemy API) or add a clear comment explaining why dict is used
- Test scoping inconsistency (tests/playwright/test_gateways.py:545)
activate_btn = first_row.locator('button:text-is("Activate")')
deactivate_btn = first_row.locator('button:has-text("Deactivate")')- After refactor, these buttons are inside dropdown but test still scopes to first_row
- Fix: Change to dropdown.locator() for consistency with other assertions in same test
Low Priority / Polish:
- Defensive check could be clearer (mcpgateway/static/admin.js:~146)
- typeof getSelectedGatewayIds === "function" check silently returns [] if function missing
- Consider logging warning if function doesn't exist
- UX improvement opportunity
- When all delta counts are 0, showing "0 added, 0 updated, 0 removed" is technically correct but could be friendlier
- Consider "No changes detected" message for better UX (can be follow-up)
- Keyboard navigation gap
- Overflow menu lacks Escape key to close and arrow key navigation
- Minor a11y gap (can be follow-up issue)
What's Good
✅ Smart label toggling based on tool_count
✅ Proper eager loading with selectinload(DbGateway.tools)
✅ Good error handling in JavaScript
✅ Comprehensive test updates
✅ Proper accessibility attributes (role, aria-expanded)
✅ Well-written CHANGELOG
✅ No security concerns
0fa8ac1 to
edd24e2
Compare
@marekdano Addressed. |
vishu-bh
left a comment
There was a problem hiding this comment.
Change introduces a browser-triggered mutation on a non-admin API route (POST /gateways/{gateway_id}/tools/refresh) while the existing CSRF protection is scoped to admin_router. The new UI path calls the route with cookie credentials from mcpgateway/static/admin.js (mcpgateway/static/admin.js#L20848), but the route itself lives in mcpgateway/main.py (mcpgateway/main.py#L6573) rather than under the admin router where enforce_admin_csrf is applied (mcpgateway/admin.py (mcpgateway/admin.py#L1570)).
Under the default SameSite=Lax cookie setting this is probably not a classic arbitrary cross-site POST issue, but it still bypasses the app’s explicit CSRF boundary and becomes relevant in same-site cross-origin deployments or when COOKIE_SAMESITE=none is used. Would it make sense to add a small cookie-auth CSRF check on this route, while still allowing bearer-token API callers, so the admin UI action stays aligned with the existing CSRF model?
e2ac8c9 to
c818a57
Compare
|
Also noticed a cosmetic behaviour for the action button in table. Screen.Recording.2026-03-24.at.14.41.37.mov |
c818a57 to
737b8ee
Compare
@vishu-bh Addressed. Screen.Recording.2026-03-24.at.15.03.34.mov |
737b8ee to
8f37574
Compare
8f37574 to
9475ebb
Compare
Closes #3765 Closes #3519 Adds a Fetch/Refresh Tools action to the gateways table for all gateway auth types, not just OAuth. The label reads "Fetch Tools" on first use (no tools registered yet) and switches to "Refresh Tools" once tools exist, using the existing POST /gateways/{id}/tools/refresh endpoint. On success, a toast shows the delta counts (added / updated / removed) and the table reloads via HTMX. A matching "Refresh from MCPs" button is added to the virtual server edit form so users can pull the latest tools from selected gateways without leaving the modal. To support the contextual label, tool_count is added to GatewayRead (serialised as toolCount) and DbGateway.tools is eagerly loaded in the gateways partial query to avoid N+1 queries. As a piggyback improvement, the stacked action buttons in the gateways table are replaced with an Alpine.js overflow menu (...), housing all actions including the new refresh button. Signed-off-by: Gabriel Costa <gabrielcg@proton.me>
Signed-off-by: Gabriel Costa <gabrielcg@proton.me>
9475ebb to
8f533f3
Compare


✨ Feature / Enhancement PR
🔗 Epic / Issue
Closes #3765
🚀 Summary (1-2 sentences)
Adds buttons for refreshing an MCP server's tools
🧪 Checks
make lintpassesmake testpasses📓 Notes (optional)
Piggybacks (partially) #3519, to prevent an overclutered actions section
flowchart TD A[Client] -->|POST /gateway/gateway_id/refresh/tools| B(MCPGateway) B -->|/tools/list| C[MCP] B -->|Response - HTMX| A