This commit is contained in:
janluedemann-esome 2026-04-05 02:21:10 +00:00 committed by GitHub
commit a2b63a1343
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 63 additions and 0 deletions

View file

@ -544,6 +544,10 @@ export class MCPConnectionFactory {
if (message.includes('authentication required') || message.includes('unauthorized')) {
return true;
}
// Check for missing authorization values (e.g., Amazon Ads MCP returns HTTP 400 with this)
if (message.includes('no authorization')) {
return true;
}
}
return false;

View file

@ -82,6 +82,10 @@ describe('MCPConnection Error Detection', () => {
if (message.includes('authentication required') || message.includes('unauthorized')) {
return true;
}
// Check for missing authorization values (e.g., Amazon Ads MCP returns HTTP 400 with this)
if (message.includes('no authorization')) {
return true;
}
}
return false;
@ -171,6 +175,24 @@ describe('MCPConnection Error Detection', () => {
};
expect(isOAuthError(error)).toBe(true);
});
it('should detect OAuth error for "no authorization" in message (HTTP 400)', () => {
const error = {
message:
'Either no authorization values are specified or it could not be derived from the request',
};
expect(isOAuthError(error)).toBe(true);
});
it('should detect OAuth error for "No authorization" with different casing', () => {
const error = { message: 'No Authorization header provided' };
expect(isOAuthError(error)).toBe(true);
});
it('should not detect OAuth error for unrelated 400 errors', () => {
const error = { code: 400, message: 'Bad request: missing required field' };
expect(isOAuthError(error)).toBe(false);
});
});
describe('error type differentiation', () => {

View file

@ -812,6 +812,39 @@ describe('MCPConnectionFactory', () => {
expect.stringContaining('OAuth required, stopping connection attempts'),
);
});
it('should identify "no authorization" errors as OAuth errors (HTTP 400)', async () => {
const basicOptions = {
serverName: 'test-server',
serverConfig: mockServerConfig,
};
const oauthOptions = {
useOAuth: true as const,
user: mockUser,
flowManager: mockFlowManager,
tokenMethods: {
findToken: jest.fn(),
createToken: jest.fn(),
updateToken: jest.fn(),
deleteTokens: jest.fn(),
},
};
const noAuthError = new Error(
'Either no authorization values are specified or it could not be derived from the request',
);
mockConnectionInstance.connect.mockRejectedValue(noAuthError);
mockConnectionInstance.isConnected.mockResolvedValue(false);
await expect(MCPConnectionFactory.create(basicOptions, oauthOptions)).rejects.toThrow(
'no authorization',
);
expect(mockLogger.info).toHaveBeenCalledWith(
expect.stringContaining('OAuth required, stopping connection attempts'),
);
});
});
describe('discoverTools static method', () => {

View file

@ -1264,6 +1264,10 @@ export class MCPConnection extends EventEmitter {
if (message.includes('authentication required') || message.includes('unauthorized')) {
return true;
}
// Check for missing authorization values (e.g., Amazon Ads MCP returns HTTP 400 with this)
if (message.includes('no authorization')) {
return true;
}
}
return false;