fix: fall back to project credential for user-scoped tools without per-user credential#2904
fix: fall back to project credential for user-scoped tools without per-user credential#2904amikofalvy wants to merge 1 commit intomainfrom
Conversation
…r-user credential After #2899 correctly resolved userId for playground requests, user-scoped tools now enter the user-credential lookup path. If no per-user credential exists, the code previously gave up. This adds an explicit fallback to the project-level credentialReferenceId, restoring the pre-existing behavior where tools configured with a shared project credential continued to work. Made-with: Cursor
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
1 Skipped Deployment
|
|
TL;DR — When a user-scoped MCP tool has no per-user credential, the code now falls back to the project-level Key changes
Summary | 1 file | 1 commit | base:
|
There was a problem hiding this comment.
Clean, well-scoped fix. The fallback logic is correct and the soft error handling (warn instead of throw) for the user-scoped case is the right call — a missing project credential for a user-scoped tool should degrade gracefully. The storeReference flows correctly into downstream Composio pinning. LGTM.
Claude Opus | 𝕏
There was a problem hiding this comment.
PR Review Summary
(3) Total Issues | Risk: Medium
🟠⚠️ Major (2) 🟠⚠️
🟠 1) AgentMcpManager.ts:99-103 Inconsistent error handling for missing credential reference
Issue: When a user-scoped tool falls back to a project credential but the credentialReferenceId lookup fails, the code logs a warning and continues with storeReference = undefined. This allows the MCP connection to proceed without credentials.
Why: The project-scoped branch (line 113) throws an error for the identical scenario. This creates unpredictable failure modes: user-scoped tools fail silently with cryptic 401/403 errors at runtime, while project-scoped tools fail fast with clear configuration errors. Engineers debugging "why is my playground tool unauthorized?" will waste time tracing through MCP connection logs when the root cause is a missing credential reference.
Fix: See inline comment — throw an error matching the project-scoped branch behavior.
Refs:
Inline Comments:
- 🟠 Major:
AgentMcpManager.ts:99-103Inconsistent error handling — logs warning instead of throwing error
🟠 2) AgentMcpManager.test.ts Missing test coverage for user-scoped credential fallback
Issue: The new credential fallback logic (lines 88-104) has zero automated test coverage. The existing test suite covers project-scoped credentials, Composio integration, and header forwarding, but no tests exist for user-scoped credential resolution.
Why: This is critical authentication logic that determines whether playground tools work. If this code path breaks in future refactoring, there's no automated detection. The manual test plan in the PR description confirms manual testing, but the logic is complex enough (user credential → project credential fallback → no credential) that unit tests would catch regressions that manual testing might miss.
Fix: Add test cases covering:
- User-scoped tool uses per-user credential when available
- User-scoped tool falls back to project credential when no per-user credential exists ← the new code path
- User-scoped tool with no credentials at all (warning path)
Refs:
🟡 Minor (1) 🟡
🟡 1) scope Missing changeset for bug fix
Issue: The changeset-bot flagged this PR has no changeset. Per AGENTS.md, bug fixes to published packages require a changeset.
Why: This is a bug fix to agents-api that restores expected behavior for playground users. Without a changeset, the fix won't be documented in release notes.
Fix: Run pnpm bump patch --pkg agents-api "Fix fallback to project credential for user-scoped tools without per-user credential"
Refs:
💭 Consider (2) 💭
💭 1) AgentMcpManager.ts:88-104 Code duplication with project-credential branch
Issue: The fallback credential lookup (lines 88-104) duplicates the exact same pattern from the project-scoped branch (lines 111-117): lookup credential by ID, check if exists, build storeReference object.
Why: Any future changes to credential resolution must be made in two places. Consider extracting to a helper or restructuring control flow so both paths share the lookup.
Fix: Optional refactor — extract credential lookup or restructure so user-scoped fallback falls through to the shared project-credential branch.
💭 2) AgentMcpManager.ts:88 IAM policy consideration: user-scoped tool using project credential
Issue: When a tool is marked credentialScope: 'user', the intent is typically per-user credential isolation. The fallback allows any authenticated project member to use shared project credentials even when the tool was configured for per-user access.
Why: This is likely intentional (graceful degradation when users haven't connected their account), and the info log at lines 95-98 provides an audit trail. Worth documenting this behavior explicitly if it's the intended policy.
Fix: No code change needed if this is intentional — consider adding a code comment explaining the policy rationale.
🚫 REQUEST CHANGES
Summary: The fix correctly restores the fallback behavior, but the error handling inconsistency (warning vs. throwing) creates a silent failure path that will confuse users and complicate debugging. The missing test coverage for a critical auth path is also concerning — this exact scenario (user-scoped credential resolution) caused the regression that this PR fixes. Adding tests would prevent future regressions.
Blocking: Fix the error handling inconsistency (Major #1). The changeset can be added before merge.
Discarded (2)
| Location | Issue | Reason Discarded |
|---|---|---|
AgentMcpManager.ts:106-109 |
Inadequate error message lacks actionable guidance | Pre-existing issue not introduced by this PR — the warning message existed before |
system |
Integration test for playground flow | Nice-to-have but unit tests are sufficient to catch regressions in credential resolution logic |
Reviewers (5)
| Reviewer | Returned | Main Findings | Consider | While You're Here | Inline Comments | Pending Recs | Discarded |
|---|---|---|---|---|---|---|---|
pr-review-errors |
3 | 1 | 0 | 0 | 1 | 0 | 1 |
pr-review-tests |
2 | 1 | 0 | 0 | 0 | 0 | 1 |
pr-review-precision |
2 | 0 | 1 | 0 | 0 | 0 | 1 |
pr-review-security-iam |
1 | 0 | 1 | 0 | 0 | 0 | 0 |
pr-review-standards |
1 | 0 | 0 | 0 | 0 | 0 | 1 |
| Total | 9 | 2 | 2 | 0 | 1 | 0 | 4 |
| } else { | ||
| logger.warn( | ||
| { toolId: tool.id, userId, credentialReferenceId }, | ||
| 'User-scoped tool has no user or project credential' | ||
| ); |
There was a problem hiding this comment.
🟠 MAJOR Inconsistent error handling when credential reference not found
Issue: When credentialReferenceId exists but the lookup fails (line 90 returns undefined), this fallback branch logs a warning (lines 100-103) and continues with storeReference = undefined. However, the project-scoped branch below (line 113) throws an error for the identical scenario.
Why: This inconsistency creates unpredictable failure modes:
- User-scoped tool with missing project credential → soft fail (warning logged, MCP connection proceeds without auth, tool fails later with cryptic 401/403)
- Project-scoped tool with missing credential → hard fail (immediate error with clear message)
Users debugging "why is my playground tool returning 401?" will have to trace through MCP connection logs and remote service errors to discover the root cause is a missing credential reference.
Fix: Match the project-scoped behavior — throw an error when the credential reference is configured but not found:
| } else { | |
| logger.warn( | |
| { toolId: tool.id, userId, credentialReferenceId }, | |
| 'User-scoped tool has no user or project credential' | |
| ); | |
| } else { | |
| throw new Error( | |
| `User-scoped tool ${tool.id} has no user credential for userId ${userId} and project credential reference not found: ${credentialReferenceId}` | |
| ); |
Refs:
Summary
Follow-up to #2899. After that PR correctly resolved
userIdfor playground requests, user-scoped tools now properly enter the user-credential lookup branch inAgentMcpManager. However, if no per-user credential exists for the current user, the code gave up without checking if a project-levelcredentialReferenceIdwas available as a fallback.Before #2899,
userIdwasundefinedfor playground requests, so theisUserScoped && userIdcondition was false and the code fell through to theelse if (credentialReferenceId)branch — accidentally using the project credential. #2899 fixed the userId but removed this accidental fallback.This PR adds an explicit fallback: when a user-scoped tool has no per-user credential, check for a project-level
credentialReferenceIdbefore giving up.Test plan
credentialReferenceIdbut no per-user credential — verify it falls back to the project credentialelse ifbranch)Made with Cursor