Skip to content

🧠 refactor: Memoize MCP Permission Checks Per Request - #13419

Merged
danny-avila merged 1 commit into
devfrom
danny-avila/memoize-mcp-permission-checks
May 30, 2026
Merged

danny-avila merged 1 commit into
devfrom
danny-avila/memoize-mcp-permission-checks

Conversation

@danny-avila

@danny-avila danny-avila commented May 30, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

I added request-scoped memoization for MCP server use permission checks so multi-agent requests and repeated MCP tool execution reuse the same role permission lookup.

  • Added checkAccessWithRequestCache to cache simple role permission checks by permission type, permissions, user ID, and role on the Express request.
  • Added a small MCP permission context interface so MCP tool construction receives canUseServers(user) instead of raw Express request state.
  • Routed MCP server use checks through the cached helper while preserving fail-closed behavior when the user or role is missing.
  • Passed the MCP permission context through load-time filtering, agent create/update/duplicate/revert filtering, and MCP tool construction so runtime calls reuse the same request cache.
  • Added unit coverage for cached access checks and repeated MCP tool invocations within one request.

Change Type

  • Bug fix (non-breaking change which fixes an issue)

Testing

  • cd packages/api && npx jest src/middleware/access.spec.ts --runInBand --coverage=false
  • npm run build:api
  • cd api && npx jest server/services/MCP.spec.js --runInBand --coverage=false
  • cd api && npx jest server/services/__tests__/ToolService.spec.js server/controllers/agents/filterAuthorizedTools.spec.js --runInBand --coverage=false
  • cd api && npx jest server/services/MCP.spec.js server/services/__tests__/ToolService.spec.js server/controllers/agents/filterAuthorizedTools.spec.js --runInBand --coverage=false
  • npx eslint packages/api/src/middleware/access.ts packages/api/src/middleware/access.spec.ts api/server/services/MCP.js api/server/services/MCP.spec.js api/app/clients/tools/util/handleTools.js api/server/services/ToolService.js api/server/controllers/agents/v1.js
  • npx eslint api/server/services/MCP.js api/server/services/MCP.spec.js api/app/clients/tools/util/handleTools.js api/server/services/ToolService.js api/server/services/__tests__/ToolService.spec.js api/server/controllers/agents/v1.js api/server/controllers/agents/filterAuthorizedTools.spec.js

Test Configuration:

  • Base branch: dev
  • Workspace: /Users/danny/.codex/worktrees/9dfc/LibreChat

Checklist

  • My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes

Copilot AI review requested due to automatic review settings May 30, 2026 20:55
@danny-avila danny-avila changed the title 🧠 fix: Memoize MCP Permission Checks Per Request 🧠 refactor: Memoize MCP Permission Checks Per Request May 30, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds request-scoped memoization for MCP server USE permission checks so multi-agent flows and repeated MCP tool invocations within a single request do not re-fetch the user's role. A new checkAccessWithRequestCache helper stores a Promise<boolean> keyed by permission type/permissions/user id/role on a non-enumerable property of the Express request, and userCanUseMCPServers is routed through it. The req object is now threaded through MCP load-time filtering, agent CRUD MCP filtering, and the MCP tool construction/invocation path.

Changes:

  • New checkAccessWithRequestCache helper in packages/api/src/middleware/access.ts with unit tests covering memoization, in-flight sharing, request isolation, and permission-key separation.
  • userCanUseMCPServers accepts and forwards req; threaded through createMCPTools/createMCPTool/createToolInstance and through agent CRUD (filterAuthorizedTools, update/duplicate/revert handlers) and loadTools/loadToolDefinitionsWrapper/loadAgentTools.
  • New MCP service test asserts a single getRoleByName call across two MCP tool invocations sharing the same request.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/api/src/middleware/access.ts Adds CheckAccessParams type and checkAccessWithRequestCache with a per-request promise cache.
packages/api/src/middleware/access.spec.ts New tests for memoization, in-flight sharing, request isolation, and per-permission cache keys.
api/server/services/MCP.js Switches userCanUseMCPServers to the cached helper and plumbs req through MCP tool construction/invocation.
api/server/services/MCP.spec.js Adds test verifying cached role lookup across two MCP tool invocations on one request.
api/server/services/ToolService.js Passes req into userCanUseMCPServers in both tool definition and tool loading paths.
api/server/controllers/agents/v1.js Threads req into filterAuthorizedTools and MCP permission checks across create/update/duplicate/revert.
api/app/clients/tools/util/handleTools.js Passes req into the MCP permission check and into MCP tool construction params.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@github-actions

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13419 index is now live on the MCP server.
Deploy run

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@danny-avila
danny-avila force-pushed the danny-avila/memoize-mcp-permission-checks branch from 9b28b87 to 333837f Compare May 30, 2026 21:21
@danny-avila

Copy link
Copy Markdown
Collaborator Author

@codex review

@danny-avila
danny-avila marked this pull request as ready for review May 30, 2026 21:23
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@github-actions

Copy link
Copy Markdown
Contributor

GitNexus: 🚀 deployed

The LibreChat-pr-13419 index is now live on the MCP server.
Deploy run

@danny-avila
danny-avila merged commit 479e9d5 into dev May 30, 2026
12 checks passed
@danny-avila
danny-avila deleted the danny-avila/memoize-mcp-permission-checks branch May 30, 2026 22:32
fuuuzzy pushed a commit to fuuuzzy/LibreChat that referenced this pull request Jun 1, 2026
ThomasVuNguyen pushed a commit to ThomasVuNguyen/LibreChat that referenced this pull request Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants