🐞 Bug Summary
12 admin /admin/*/partial, /admin/*/ids, and /admin/*/search endpoints in mcpgateway/admin.py build their queries by hand instead of going through BaseService/_apply_access_control(). Their team_id branch only adds globally-public rows owned by other teams when include_public=True — but nothing in the admin UI (admin.html, admin_ui/*.js) ever sets include_public=true. So filtering any resource table by team through the main admin UI (search, pagination, "select all", etc.) silently hides other teams' public rows, which contradicts the team_id semantics established by #4773/#6150/#6152 ("team_id narrows team-scoped rows, it does not suppress platform-public ones").
This is the inverse of the leak fixed in #6152 (under-inclusion instead of over-inclusion), and it's pre-existing — not introduced by #6152. Confirmed via review discussion on #6152: #6152 (comment)
Affected endpoints (mcpgateway/admin.py)
| Endpoint |
Line |
GET /admin/tools/partial |
8822 |
GET /admin/tools/ids |
9191 |
GET /admin/tools/search |
9293 |
GET /admin/prompts/partial |
9428 |
GET /admin/gateways/partial |
9666 |
GET /admin/gateways/ids |
9864 |
GET /admin/gateways/search |
9929 |
GET /admin/resources/partial |
10211 |
GET /admin/prompts/ids |
10451 |
GET /admin/resources/ids |
10549 |
GET /admin/resources/search |
10647 |
GET /admin/prompts/search |
10772 |
Each declares include_public: bool = False and, when team_id is set, only appends model_cls.visibility == "public" to the OR-conditions if include_public is true.
🧩 Affected Component
🔁 Steps to Reproduce
- As a platform admin (or any user in ≥2 teams), create a
public-visibility tool/resource/prompt/gateway owned by team A.
- In the Admin UI, select team B from the team filter on that resource's tab (drives
?team_id=B on the */partial endpoint).
- Team A's public item does not appear in the table, even though it should be visible platform-wide.
🤔 Expected Behavior
Filtering by team in the admin UI should follow the same team_id semantics as the service layer (fixed in #6152 for /admin/sections/* and the underlying services): team-scoped rows for the selected team, plus all globally-public rows regardless of owning team.
🧠 Environment Info
| Key |
Value |
| Version or commit |
main@47419b485 (post-#6152) |
| Runtime |
N/A — logic bug, reproducible on any version |
| Platform / OS |
N/A |
| Container |
N/A |
🧩 Additional Context
Likely fix: route these 12 endpoints through the same BaseService._team_scoped_conditions() helper introduced in #6152, or drop the include_public gate so team_id filtering always includes public rows from other teams, matching #4773's documented semantics. Out of scope for #6152 itself since these endpoints don't share code with BaseService._apply_access_control() — pulling them in would have expanded that PR's blast radius.
Related: #6152, #4773, #4732, #5496, #6150
🐞 Bug Summary
12 admin
/admin/*/partial,/admin/*/ids, and/admin/*/searchendpoints inmcpgateway/admin.pybuild their queries by hand instead of going throughBaseService/_apply_access_control(). Theirteam_idbranch only adds globally-public rows owned by other teams wheninclude_public=True— but nothing in the admin UI (admin.html,admin_ui/*.js) ever setsinclude_public=true. So filtering any resource table by team through the main admin UI (search, pagination, "select all", etc.) silently hides other teams' public rows, which contradicts theteam_idsemantics established by #4773/#6150/#6152 ("team_idnarrows team-scoped rows, it does not suppress platform-public ones").This is the inverse of the leak fixed in #6152 (under-inclusion instead of over-inclusion), and it's pre-existing — not introduced by #6152. Confirmed via review discussion on #6152: #6152 (comment)
Affected endpoints (
mcpgateway/admin.py)GET /admin/tools/partialGET /admin/tools/idsGET /admin/tools/searchGET /admin/prompts/partialGET /admin/gateways/partialGET /admin/gateways/idsGET /admin/gateways/searchGET /admin/resources/partialGET /admin/prompts/idsGET /admin/resources/idsGET /admin/resources/searchGET /admin/prompts/searchEach declares
include_public: bool = Falseand, whenteam_idis set, only appendsmodel_cls.visibility == "public"to the OR-conditions ifinclude_publicis true.🧩 Affected Component
mcpgateway- APImcpgateway- UI (admin panel)🔁 Steps to Reproduce
public-visibility tool/resource/prompt/gateway owned by team A.?team_id=Bon the*/partialendpoint).🤔 Expected Behavior
Filtering by team in the admin UI should follow the same
team_idsemantics as the service layer (fixed in #6152 for/admin/sections/*and the underlying services): team-scoped rows for the selected team, plus all globally-public rows regardless of owning team.🧠 Environment Info
main@47419b485(post-#6152)🧩 Additional Context
Likely fix: route these 12 endpoints through the same
BaseService._team_scoped_conditions()helper introduced in #6152, or drop theinclude_publicgate soteam_idfiltering always includes public rows from other teams, matching #4773's documented semantics. Out of scope for #6152 itself since these endpoints don't share code withBaseService._apply_access_control()— pulling them in would have expanded that PR's blast radius.Related: #6152, #4773, #4732, #5496, #6150