Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -429,4 +429,34 @@ describe("useServerState hosted OAuth callback guards", () => {
);
});
});

it("falls back to interactive OAuth when hosted reconnect reports a missing refresh token", async () => {
mockReconnectServer.mockResolvedValueOnce({
success: false,
error: "Stored hosted OAuth credential is missing refresh_token",
});
mockEnsureAuthorizedForReconnect.mockResolvedValueOnce({
kind: "error",
error: "OAuth init failed",
});

const dispatch = vi.fn();
const { result } = renderHostedServerState(dispatch);

await act(async () => {
await result.current.handleReconnect("asana");
});

await waitFor(() => {
expect(mockEnsureAuthorizedForReconnect).toHaveBeenCalledWith(
expect.objectContaining({
name: "asana",
useOAuth: true,
}),
expect.objectContaining({
beforeRedirect: expect.any(Function),
}),
);
});
});
});
3 changes: 3 additions & 0 deletions mcpjam-inspector/client/src/hooks/use-server-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ function requiresFreshOAuthAuthorization(error: unknown): boolean {
const normalized = errorMessage.toLowerCase();
return (
normalized.includes("requires oauth authentication") ||
normalized.includes(
"stored hosted oauth credential is missing refresh_token",
) ||
Comment on lines +133 to +135
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.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP -C2 'missing\s+refresh[_ ]token' --iglob '!**/node_modules/**'

Repository: MCPJam/inspector

Length of output: 1587


🏁 Script executed:

#!/bin/bash
# Find backend code that might emit this error
find . -type f \( -name "*.py" -o -name "*.go" -o -name "*.rs" -o -name "*.ts" -o -name "*.tsx" \) | head -20 | xargs rg -l "missing refresh" --max-count 1

Repository: MCPJam/inspector

Length of output: 44


🏁 Script executed:

#!/bin/bash
# Check if there's an SDK or backend module
fd -t f -e ts -e tsx -e py -e go -e rs | grep -E "(sdk|backend|server)" | head -20

Repository: MCPJam/inspector

Length of output: 681


🏁 Script executed:

#!/bin/bash
# Search for where mockReconnectServer might be defined or what it represents
rg -n "mockReconnectServer\|reconnectServer" mcpjam-inspector/client/ -A 3 | head -30

Repository: MCPJam/inspector

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Check if error constants/enums are used elsewhere in the codebase
rg -n "const.*ERROR|const.*MESSAGE" mcpjam-inspector/client/src/ | head -20

Repository: MCPJam/inspector

Length of output: 2279


🏁 Script executed:

#!/bin/bash
# Check what error constants exist in use-hosted-oauth-gate.ts
cat mcpjam-inspector/client/src/hooks/hosted/use-hosted-oauth-gate.ts | head -100

Repository: MCPJam/inspector

Length of output: 3462


🏁 Script executed:

#!/bin/bash
# Search for the error message in SDK code
fd -t f \( -name "*.ts" -o -name "*.tsx" \) sdk/ | xargs rg -l "missing refresh" --max-count 5

Repository: MCPJam/inspector

Length of output: 446


🏁 Script executed:

#!/bin/bash
# Look at the full use-server-state.ts around the error checks to understand context
sed -n '125,145p' mcpjam-inspector/client/src/hooks/use-server-state.ts

Repository: MCPJam/inspector

Length of output: 724


🏁 Script executed:

#!/bin/bash
# Search for where the error is generated in SDK
rg "Stored hosted OAuth credential is missing refresh_token" --iglob '!**/node_modules/**'

Repository: MCPJam/inspector

Length of output: 215


🏁 Script executed:

#!/bin/bash
# Look at the test file to understand the source of the error
sed -n '430,450p' mcpjam-inspector/client/src/hooks/__tests__/use-server-state.hosted-oauth.test.tsx

Repository: MCPJam/inspector

Length of output: 663


🏁 Script executed:

#!/bin/bash
# Search for similar error message patterns in SDK to understand where they originate
rg "stored.*oauth.*credential|oauth.*credential" --iglob '!**/node_modules/**' -i

Repository: MCPJam/inspector

Length of output: 6357


🏁 Script executed:

#!/bin/bash
# Find the definition/setup of mockReconnectServer
rg "mockReconnectServer\s*=" mcpjam-inspector/client/src/hooks/__tests__/use-server-state.hosted-oauth.test.tsx -B 5 -A 5 | head -30

Repository: MCPJam/inspector

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Look for any backend or server implementation that might emit this error
find . -type f \( -name "*.py" -o -name "*.go" -o -name "*.rs" \) 2>/dev/null | head -10

Repository: MCPJam/inspector

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Search for error handling in the entire codebase related to reconnect
rg "refresh_token|reconnect" --iglob '!**/node_modules/**' | grep -i error | head -15

Repository: MCPJam/inspector

Length of output: 1980


🏁 Script executed:

#!/bin/bash
# Look for reconnectServer implementation/definition
rg "reconnectServer.*=" mcpjam-inspector/client/ -B 3 -A 3 | head -40

Repository: MCPJam/inspector

Length of output: 3616


🏁 Script executed:

#!/bin/bash
# Check if there's an API call or service that provides reconnectServer
rg "function.*reconnect|const.*reconnect" mcpjam-inspector/client/src/lib/ -i | head -20

Repository: MCPJam/inspector

Length of output: 174


🏁 Script executed:

#!/bin/bash
# Find where the error string originates by checking for API responses
sed -n '1,50p' mcpjam-inspector/client/src/test/mocks/mcp-api.ts

Repository: MCPJam/inspector

Length of output: 1573


🏁 Script executed:

#!/bin/bash
# Find the actual reconnectServer implementation
rg "export.*reconnectServer|const reconnectServer" mcpjam-inspector/client/src/state/ -A 10

Repository: MCPJam/inspector

Length of output: 820


🏁 Script executed:

#!/bin/bash
# Check mcp-api.ts file
cat mcpjam-inspector/client/src/state/mcp-api.ts | head -150

Repository: MCPJam/inspector

Length of output: 4209


🏁 Script executed:

#!/bin/bash
# Look for the server backend that returns the error
find . -type f -name "*.ts" | xargs rg -l "refresh_token.*missing|missing.*refresh" --max-count 5 | grep -v node_modules | grep -v test

Repository: MCPJam/inspector

Length of output: 116


🏁 Script executed:

#!/bin/bash
# Look at servers-api.ts to see how validateHostedServer is implemented
cat mcpjam-inspector/client/src/lib/apis/web/servers-api.ts | head -200

Repository: MCPJam/inspector

Length of output: 1398


🏁 Script executed:

#!/bin/bash
# Check the backend server code for the error message
find . -path ./node_modules -prune -o -type f \( -name "*.ts" -o -name "*.tsx" \) -print | xargs rg "Stored.*OAuth\|refresh_token.*credential" | head -20

Repository: MCPJam/inspector

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Look at the test to see exactly how the error is used
sed -n '428,460p' mcpjam-inspector/client/src/hooks/__tests__/use-server-state.hosted-oauth.test.tsx

Repository: MCPJam/inspector

Length of output: 961


🏁 Script executed:

#!/bin/bash
# Search for where the backend might be generating this error
find . -type f -name "*.ts" -o -name "*.tsx" | xargs rg -l "api.*servers.*validate|Stored.*OAuth" | grep -v node_modules | grep -v test

Repository: MCPJam/inspector

Length of output: 475


🏁 Script executed:

#!/bin/bash
# Check if there's a backend implementation in the server directory
ls -la mcpjam-inspector/server/

Repository: MCPJam/inspector

Length of output: 1141


🏁 Script executed:

#!/anbin/bash
# Look at the server code for validation
find mcpjam-inspector/server -name "*.ts" -type f | xargs rg -l "oauth\|credential" | head -10

Repository: MCPJam/inspector

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Look at server routes
ls -la mcpjam-inspector/server/routes/

Repository: MCPJam/inspector

Length of output: 387


🏁 Script executed:

#!/bin/bash
# Search for web routes specifically
find mcpjam-inspector/server/routes -type f -name "*.ts" | head -20

Repository: MCPJam/inspector

Length of output: 1294


🏁 Script executed:

#!/bin/bash
# Search for the specific error message in the entire server codebase
rg "Stored.*OAuth\|missing.*refresh" mcpjam-inspector/server/ --type ts

Repository: MCPJam/inspector

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Look for web routes validation
find mcpjam-inspector/server/routes/web -type f -name "*.ts" 2>/dev/null | head -20

Repository: MCPJam/inspector

Length of output: 1313


🏁 Script executed:

#!/an/bin/bash
# Search more broadly for the error message in all TypeScript files
rg "missing refresh" . --type ts --type tsx | grep -v node_modules | grep -v ".next"

Repository: MCPJam/inspector

Length of output: 88


🏁 Script executed:

#!/bin/bash
# Look at the services directory
find mcpjam-inspector/server/services -type f -name "*.ts" | head -20

Repository: MCPJam/inspector

Length of output: 1384


🏁 Script executed:

#!/bin/bash
# Search for where this specific error is generated or mocked
rg "Stored hosted OAuth credential" . --max-count 10

Repository: MCPJam/inspector

Length of output: 217


🏁 Script executed:

#!/bin/bash
# Look for web/servers routes specifically
cat mcpjam-inspector/server/routes/web/servers.ts 2>/dev/null | head -150

Repository: MCPJam/inspector

Length of output: 4242


🏁 Script executed:

#!/bin/bash
# Check if this is an external service call by looking for fetch/axios calls
rg "reconnect|validate.*server" mcpjam-inspector/server/routes/web/ --type ts -A 5 | head -40

Repository: MCPJam/inspector

Length of output: 2564


🏁 Script executed:

#!/bin/bash
# Check if there are other similar hardcoded error checks in the file
sed -n '125,160p' mcpjam-inspector/client/src/hooks/use-server-state.ts

Repository: MCPJam/inspector

Length of output: 987


🏁 Script executed:

#!/bin/bash
# Look at all the error checks to understand the pattern
sed -n '128,142p' mcpjam-inspector/client/src/hooks/use-server-state.ts

Repository: MCPJam/inspector

Length of output: 479


🏁 Script executed:

#!/bin/bash
# Verify whether there is a constant file or shared errors module
find mcpjam-inspector/client/src -name "*constant*" -o -name "*error*" -o -name "*message*" | grep -v test | head -20

Repository: MCPJam/inspector

Length of output: 980


🏁 Script executed:

#!/bin/bash
# Check OAuth constants
cat mcpjam-inspector/client/src/lib/oauth/constants.ts

Repository: MCPJam/inspector

Length of output: 1870


🏁 Script executed:

#!/bin/bash
# Check error guidance
cat mcpjam-inspector/client/src/lib/xaa/error-guidance.ts

Repository: MCPJam/inspector

Length of output: 13862


🏁 Script executed:

#!/bin/bash
# Look for where shouldRetriggerHostedReauth is called
rg "shouldRetriggerHostedReauth" mcpjam-inspector/client/ -B 5 -A 5

Repository: MCPJam/inspector

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Search for the function that contains the hardcoded string
rg "shouldRetriggerHostedReauth" . --max-count 10

Repository: MCPJam/inspector

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Look at context around where the error message is checked
sed -n '120,180p' mcpjam-inspector/client/src/hooks/use-server-state.ts

Repository: MCPJam/inspector

Length of output: 1657


🏁 Script executed:

#!/bin/bash
# Find where this function is defined
ast-grep --pattern 'function shouldRetriggerHostedReauth' mcpjam-inspector/client/src/

Repository: MCPJam/inspector

Length of output: 42


🏁 Script executed:

#!/bin/bash
# Find the function that contains this error check
rg -B 10 'stored hosted oauth credential is missing refresh_token' mcpjam-inspector/client/src/hooks/use-server-state.ts | head -30

Repository: MCPJam/inspector

Length of output: 331


🏁 Script executed:

#!/bin/bash
# Look at the test to understand expectations and confirm the string is stable
sed -n '428,465p' mcpjam-inspector/client/src/hooks/__tests__/use-server-state.hosted-oauth.test.tsx

Repository: MCPJam/inspector

Length of output: 971


🏁 Script executed:

#!/bin/bash
# Check if there are any other files that reference this exact error string
rg -r 'Stored hosted OAuth credential' . --max-count 10

Repository: MCPJam/inspector

Length of output: 50375


Extract the error string to a constant.

The predicate relies on matching "stored hosted oauth credential is missing refresh_token" after lowercasing. If the backend or external service that emits this error ever rewords it—adding punctuation, changing refresh_token to refresh token, or localizing—the reconnect flow will silently fail, leaving users with an error toast instead of an OAuth redirect. Creating a shared constant makes this coupling explicit and easier to maintain.

const MISSING_REFRESH_TOKEN_ERROR = 
  "stored hosted oauth credential is missing refresh_token";

Consider extracting all three error predicates in that function to constants for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@mcpjam-inspector/client/src/hooks/use-server-state.ts` around lines 133 -
135, The predicate currently matches the literal string "stored hosted oauth
credential is missing refresh_token" inline (normalized.includes(...)) which
couples the reconnect flow to a fragile error wording; extract that literal into
a shared constant (e.g. MISSING_REFRESH_TOKEN_ERROR) and replace the inline
normalized.includes(...) with a reference to that constant, and similarly
extract the other two error predicates used in the same function in
use-server-state.ts for consistency so all three checks use named constants
rather than hardcoded strings.

(normalized.includes("authentication failed") &&
normalized.includes("invalid_token"))
);
Expand Down
Loading