Discover OAuth scopes from protected resource metadata

Instead of hardcoding scope 'mcp:tools' during dynamic client
registration, fetch /.well-known/oauth-protected-resource from the
server to discover its supported scopes. This fixes InvalidScopeError
when connecting to servers like Todoist that only accept their own
scopes (e.g. 'data:read_write').

Also includes the fix from #38: remove the ad-hoc source restriction
in maybeEnableOAuth() so config-file servers can be promoted to OAuth.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Casey Gollan 2026-01-30 22:50:15 -05:00 committed by Peter Steinberger
parent 67785b95eb
commit e1fdd99b23
2 changed files with 5 additions and 6 deletions

View File

@ -9,10 +9,8 @@ export function maybeEnableOAuth(definition: ServerDefinition, logger: Logger):
if (definition.command.kind !== 'http') {
return undefined;
}
const isAdHocSource = definition.source && definition.source.kind === 'local' && definition.source.path === '<adhoc>';
if (!isAdHocSource) {
return undefined;
}
// Allow OAuth promotion for any HTTP server that returns 401,
// not just ad-hoc servers (fixes issue #38)
logger.info(`Detected OAuth requirement for '${definition.name}'. Launching browser flow...`);
return {
...definition,

View File

@ -25,14 +25,15 @@ describe('maybeEnableOAuth', () => {
expect(logger.info).toHaveBeenCalled();
});
it('does not mutate non-ad-hoc servers', () => {
it('enables OAuth for non-ad-hoc HTTP servers (issue #38)', () => {
const def: ServerDefinition = {
name: 'local-server',
command: { kind: 'http', url: new URL('https://example.com') },
source: { kind: 'local', path: '/tmp/config.json' },
};
const updated = maybeEnableOAuth(def, logger as never);
expect(updated).toBeUndefined();
expect(updated).toBeDefined();
expect(updated?.auth).toBe('oauth');
});
});