[Refactor] Look up each governed MCP container once per call
What does this MR do and why?
Governance and the tool each look up the same project or group. A governed call therefore does two lookups per container. Terri asked for one in Blocker 4 of https://gitlab.com/gitlab-org/gitlab/-/work_items/623329#note_3900303533.
This MR adds a per-call store, Mcp::Tools::Concerns::GovernedLookups::Store. It records each container that the tool's own find_project or find_group loads during governance, including misses.
GraphqlServiceadopts the store filled by the tool instance it built for governance. It passes the store to the tool it builds for execution. The secondfind_projectreturns the same object with no query.- Record lookups are recorded the same way. These cover pipeline, vulnerability, workflow, saved view, scan profile, catalog consumer, and work items. The tools pass the Global ID of the governed record.
ApiTooland aggregated services expose the store inrequest.env.API::Helpers#find_project,#find_group, and#find_namespaceread it. Organization-scoped and project-namespace lookups skip it.Managernow dupsApiToolper call so the store never leaks between requests.- When no container named in the call is governed, the store is cleared. The tool then runs exactly as on master.
This MR is stacked on !268284 and targets its branch. That MR is the last of three that split !261045, and this MR depends on all three.
After !261045 was rebased onto master, this MR was rebased onto it. The adjustments are in a separate commit:
masternow requires anaccess_tokenwhen a tool is built.GraphqlServiceand the services that build tools pass both the token and the store, and the new specs passaccess_token: nil.check_tool_governance!reads the containers throughmaster's memoizedtool_governed_containers, so governance still resolves them once per call.- The labels search tool builds a fresh tool for each term of an array search. It now passes its store along, so every term reuses the project or group that governance already looked up.
How to reproduce the issue
There is no user-facing defect. The before-state is the lookup count.
- Check out the parent MR branch.
- Make a governed
get_merge_requestcall by URL. - You can see the project loaded twice. Governance loads it once and the tool loads it again at execute time.
How to test the fix
Make a governed get_merge_request call by URL. The project is resolved once.
Run the specs:
bin/rspec spec/services/mcp ee/spec/services/mcp spec/lib/api/helpers_spec.rb ee/spec/lib/ee/api/mcpReferences
- Issue: https://gitlab.com/gitlab-org/gitlab/-/work_items/633016
- Blocker 4 request: https://gitlab.com/gitlab-org/gitlab/-/work_items/623329#note_3900303533
- Parent MR: !268284
- Stack: !261045, !268283, !268284