From e123495d5044d48422825882919fa4eb8c496c47 Mon Sep 17 00:00:00 2001 From: wutongyuonce <147830929+wutongyuonce@users.noreply.github.com> Date: Wed, 9 Sep 2026 12:49:29 +0800 Subject: [PATCH] fix(mcp): advertise Apache identity in OAuth DCR Point client_uri at the Apache product homepage and set software_id to the running clientName so TUI is no longer registered as desktop. Refs #5072 Generated-by: Pi --- packages/mcp/src/__tests__/oauth.test.ts | 28 ++++++++++++++++++++++++ packages/mcp/src/oauth.ts | 7 ++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/packages/mcp/src/__tests__/oauth.test.ts b/packages/mcp/src/__tests__/oauth.test.ts index c25b265b65..7f05710b76 100644 --- a/packages/mcp/src/__tests__/oauth.test.ts +++ b/packages/mcp/src/__tests__/oauth.test.ts @@ -80,6 +80,12 @@ describe('McpClientManager OAuth E2E', () => { assert.ok(authorizationUrl.searchParams.get('code_challenge')); // Dynamic registration ran before the redirect. assert.ok(fixture.registrations.length >= 1); + const registration = fixture.registrations[0]; + assert.ok(registration && typeof registration === 'object'); + const body = registration as Record; + assert.equal(body.client_uri, 'https://maka.apache.org/en/'); + assert.equal(body.software_id, 'maka'); + assert.equal(body.client_name, 'maka'); // Consent disclosure material: the resolved issuer, the scope the round // requests, and the round's state travel back to the caller so a UI can // show what is being granted before a browser opens. @@ -1064,6 +1070,28 @@ describe('McpClientManager OAuth E2E', () => { assert.equal(status.state, 'connected'); }); + test('OAuth client metadata identifies the Apache project and the running client', () => { + for (const clientName of ['maka', 'maka-tui', 'maka-desktop'] as const) { + const provider = new McpOAuthProvider({ + serverId: 'remote', + serverUrl: 'https://mcp.example/mcp', + storage: createMemoryMcpOAuthStorage(), + clientName, + clientVersion: '0.2.0', + }); + assert.equal(provider.clientMetadata.client_uri, 'https://maka.apache.org/en/'); + assert.equal(provider.clientMetadata.software_id, clientName); + assert.equal(provider.clientMetadata.client_name, clientName); + assert.equal(provider.clientMetadata.software_version, '0.2.0'); + assert.deepEqual(provider.clientMetadata.redirect_uris, []); + assert.deepEqual(provider.clientMetadata.grant_types, [ + 'authorization_code', + 'refresh_token', + ]); + assert.doesNotMatch(JSON.stringify(provider.clientMetadata), /maka-agent\/maka-agent/u); + } + }); + test('a discovery that moves to another authorization server drops the registered client', async () => { const storage = createMemoryMcpOAuthStorage(); await storage.set('remote', { diff --git a/packages/mcp/src/oauth.ts b/packages/mcp/src/oauth.ts index 9ca8834d82..00151756b8 100644 --- a/packages/mcp/src/oauth.ts +++ b/packages/mcp/src/oauth.ts @@ -160,6 +160,9 @@ export interface McpOAuthProviderOptions { * token request. */ const BACKGROUND_REDIRECT_URL = 'http://127.0.0.1/maka-mcp-oauth-noninteractive'; +/** Product homepage sent in OAuth dynamic client registration. */ +const MCP_OAUTH_CLIENT_URI = 'https://maka.apache.org/en/'; + export class McpOAuthProvider implements OAuthClientProvider { /** Present only when an interactive state was supplied — the SDK treats * a defined method as "client uses state". */ @@ -177,8 +180,8 @@ export class McpOAuthProvider implements OAuthClientProvider { get clientMetadata(): OAuthClientMetadata { return { client_name: this.options.clientName, - client_uri: 'https://github.com/maka-agent/maka-agent', - software_id: 'maka-desktop', + client_uri: MCP_OAUTH_CLIENT_URI, + software_id: this.options.clientName, software_version: this.options.clientVersion, redirect_uris: this.options.interactive ? [this.options.interactive.redirectUrl] : [], grant_types: ['authorization_code', 'refresh_token'],