Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit f0e1121

Browse files
committed
feat(McpOAuthClientProvider): adding callback to cancel callback server
1 parent dab4e2c commit f0e1121

2 files changed

Lines changed: 21 additions & 5 deletions

File tree

src/services/mcp/McpOAuthClientProvider.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export class McpOAuthClientProvider implements OAuthClientProvider {
7878
private _server: http.Server | null,
7979
private _port: number,
8080
private _authCodePromise: Promise<string> | null,
81+
private _cancelCallbackServer: (() => void) | null,
8182
private readonly _tokenEndpointAuthMethod: string,
8283
private readonly _grantTypes: string[],
8384
private readonly _scopes: string[],
@@ -122,9 +123,9 @@ export class McpOAuthClientProvider implements OAuthClientProvider {
122123
}
123124

124125
// Extract auth-method preferences.
125-
// Prefer "none" → first supported → "client_secret_post"
126+
// Only pick methods we actually implement: "none" or "client_secret_post".
126127
const authMethods: string[] = authServerMeta?.token_endpoint_auth_methods_supported ?? []
127-
const tokenEndpointAuthMethod = authMethods.includes("none") ? "none" : (authMethods[0] ?? "client_secret_post")
128+
const tokenEndpointAuthMethod = authMethods.includes("none") ? "none" : "client_secret_post"
128129
const grantTypes: string[] = authServerMeta?.grant_types_supported ?? ["authorization_code", "refresh_token"]
129130
const scopes: string[] = authServerMeta?.scopes_supported ?? []
130131

@@ -142,6 +143,7 @@ export class McpOAuthClientProvider implements OAuthClientProvider {
142143
null,
143144
0,
144145
null,
146+
null,
145147
tokenEndpointAuthMethod,
146148
grantTypes,
147149
scopes,
@@ -178,9 +180,10 @@ export class McpOAuthClientProvider implements OAuthClientProvider {
178180

179181
private async _doStartCallbackServer(): Promise<void> {
180182
this._closed = false
181-
const { server, port, result } = await startCallbackServer(this._port, this._state)
183+
const { server, port, result, cancel } = await startCallbackServer(this._port, this._state)
182184
this._server = server
183185
this._port = port
186+
this._cancelCallbackServer = cancel
184187
this._authCodePromise = result.then((r) => {
185188
if (r.error) throw new Error(`OAuth authorization failed: ${r.error}`)
186189
if (!r.code) throw new Error("No authorization code received in callback")
@@ -442,6 +445,12 @@ export class McpOAuthClientProvider implements OAuthClientProvider {
442445
code_verifier: codeVerifier,
443446
}
444447

448+
// RFC 8707: include resource indicator so servers that bind token requests
449+
// to a specific resource can validate the exchange.
450+
if (this._resourceIndicator) {
451+
params.resource = this._resourceIndicator
452+
}
453+
445454
// Include client_secret in the body when the auth method is client_secret_post.
446455
if (this._tokenEndpointAuthMethod === "client_secret_post" && this._clientInfo.client_secret) {
447456
params.client_secret = this._clientInfo.client_secret
@@ -489,6 +498,11 @@ export class McpOAuthClientProvider implements OAuthClientProvider {
489498
client_id: clientId,
490499
}
491500

501+
// RFC 8707: include resource indicator in refresh requests too.
502+
if (this._resourceIndicator) {
503+
params.resource = this._resourceIndicator
504+
}
505+
492506
if (this._tokenEndpointAuthMethod === "client_secret_post" && this._clientInfo?.client_secret) {
493507
params.client_secret = this._clientInfo.client_secret
494508
}
@@ -521,8 +535,9 @@ export class McpOAuthClientProvider implements OAuthClientProvider {
521535
}
522536
if (!this._closed && this._server) {
523537
this._closed = true
524-
await stopCallbackServer(this._server).catch(() => {})
538+
await stopCallbackServer(this._server, this._cancelCallbackServer ?? (() => {})).catch(() => {})
525539
this._server = null
540+
this._cancelCallbackServer = null
526541
this._authCodePromise = null
527542
}
528543
}

src/services/mcp/__tests__/McpOAuthClientProvider.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ function setupCallbackServerMock(code = "test-auth-code", state?: string) {
7575
server: mockServer,
7676
port: 12345,
7777
result: resultPromise,
78+
cancel: vi.fn(),
7879
})
7980
return { mockServer, resultPromise }
8081
}
@@ -675,7 +676,7 @@ describe("McpOAuthClientProvider", () => {
675676

676677
await provider.close()
677678

678-
expect(stopCallbackServer).toHaveBeenCalledWith(mockServer)
679+
expect(stopCallbackServer).toHaveBeenCalledWith(mockServer, expect.any(Function))
679680
})
680681

681682
it("should be idempotent", async () => {

0 commit comments

Comments
 (0)