|
15 | 15 | import { Client, ClientCredentialsProvider, PrivateKeyJwtProvider, StreamableHTTPClientTransport } from '@modelcontextprotocol/client'; |
16 | 16 | import * as z from 'zod/v4'; |
17 | 17 |
|
| 18 | +import { ConformanceOAuthProvider } from './helpers/conformanceOAuthProvider.js'; |
18 | 19 | import { logger } from './helpers/logger.js'; |
19 | 20 | import { handle401, withOAuthRetry } from './helpers/withOAuthRetry.js'; |
20 | 21 |
|
@@ -42,6 +43,11 @@ const ClientConformanceContextSchema = z.discriminatedUnion('name', [ |
42 | 43 | name: z.literal('auth/client-credentials-basic'), |
43 | 44 | client_id: z.string(), |
44 | 45 | client_secret: z.string() |
| 46 | + }), |
| 47 | + z.object({ |
| 48 | + name: z.literal('auth/pre-registration'), |
| 49 | + client_id: z.string(), |
| 50 | + client_secret: z.string() |
45 | 51 | }) |
46 | 52 | ]); |
47 | 53 |
|
@@ -240,6 +246,43 @@ async function runClientCredentialsBasic(serverUrl: string): Promise<void> { |
240 | 246 |
|
241 | 247 | registerScenario('auth/client-credentials-basic', runClientCredentialsBasic); |
242 | 248 |
|
| 249 | +// ============================================================================ |
| 250 | +// Pre-registration scenario (no dynamic client registration) |
| 251 | +// ============================================================================ |
| 252 | + |
| 253 | +async function runPreRegistrationClient(serverUrl: string): Promise<void> { |
| 254 | + const ctx = parseContext(); |
| 255 | + if (ctx.name !== 'auth/pre-registration') { |
| 256 | + throw new Error(`Expected pre-registration context, got ${ctx.name}`); |
| 257 | + } |
| 258 | + |
| 259 | + // Create a provider pre-populated with registered credentials, |
| 260 | + // so the SDK skips dynamic client registration. |
| 261 | + const provider = new ConformanceOAuthProvider('http://localhost:3000/callback', { |
| 262 | + client_name: 'conformance-pre-registration', |
| 263 | + redirect_uris: ['http://localhost:3000/callback'] |
| 264 | + }); |
| 265 | + provider.saveClientInformation({ |
| 266 | + client_id: ctx.client_id, |
| 267 | + client_secret: ctx.client_secret, |
| 268 | + redirect_uris: ['http://localhost:3000/callback'] |
| 269 | + }); |
| 270 | + |
| 271 | + const oauthFetch = withOAuthRetry('conformance-pre-registration', new URL(serverUrl), handle401, undefined, provider)(fetch); |
| 272 | + |
| 273 | + const client = new Client({ name: 'conformance-pre-registration', version: '1.0.0' }, { capabilities: {} }); |
| 274 | + const transport = new StreamableHTTPClientTransport(new URL(serverUrl), { |
| 275 | + fetch: oauthFetch |
| 276 | + }); |
| 277 | + |
| 278 | + await client.connect(transport); |
| 279 | + await client.listTools(); |
| 280 | + await client.callTool({ name: 'test-tool', arguments: {} }); |
| 281 | + await transport.close(); |
| 282 | +} |
| 283 | + |
| 284 | +registerScenario('auth/pre-registration', runPreRegistrationClient); |
| 285 | + |
243 | 286 | // ============================================================================ |
244 | 287 | // Elicitation defaults scenario |
245 | 288 | // ============================================================================ |
|
0 commit comments