Skip to content

Commit 98091e7

Browse files
feat(core): include OAuth schemas in specTypeSchema() map
specTypeSchema()/isSpecType() now also cover the OAuth/OpenID types from shared/auth.ts (OAuthTokens, OAuthMetadata, OAuthClientMetadata, etc.), addressing the standalone-validation use noted in #1680 for auth implementers.
1 parent 176d3b5 commit 98091e7

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

packages/core/src/types/specTypeSchema.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import type * as z from 'zod/v4';
22

3+
import * as authSchemas from '../shared/auth.js';
34
import type { StandardSchemaV1 } from '../util/standardSchema.js';
45
import * as schemas from './schemas.js';
56

6-
type SchemaModule = typeof schemas;
7+
type SchemaModule = typeof schemas & typeof authSchemas;
78

89
type StripSchemaSuffix<K> = K extends `${infer N}Schema` ? N : never;
910

@@ -17,8 +18,9 @@ type SchemaKey = {
1718
}[keyof SchemaModule];
1819

1920
/**
20-
* Union of every named type in the MCP spec schema (e.g. `'CallToolResult'`, `'ContentBlock'`,
21-
* `'Tool'`). Derived from the SDK's internal Zod schemas, so it stays in sync with the spec.
21+
* Union of every named type in the SDK's protocol and OAuth schemas (e.g. `'CallToolResult'`,
22+
* `'ContentBlock'`, `'Tool'`, `'OAuthTokens'`). Derived from the internal Zod schemas, so it stays
23+
* in sync with the spec.
2224
*/
2325
export type SpecTypeName = StripSchemaSuffix<SchemaKey>;
2426

@@ -32,9 +34,11 @@ export type SpecTypes = {
3234
};
3335

3436
const specTypeSchemas: Record<string, z.ZodTypeAny> = {};
35-
for (const [key, value] of Object.entries(schemas)) {
36-
if (key.endsWith('Schema') && value !== null && typeof value === 'object') {
37-
specTypeSchemas[key.slice(0, -'Schema'.length)] = value as z.ZodTypeAny;
37+
for (const source of [schemas, authSchemas]) {
38+
for (const [key, value] of Object.entries(source)) {
39+
if (key.endsWith('Schema') && value !== null && typeof value === 'object') {
40+
specTypeSchemas[key.slice(0, -'Schema'.length)] = value as z.ZodTypeAny;
41+
}
3842
}
3943
}
4044

packages/core/test/types/specTypeSchema.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, expect, expectTypeOf, it } from 'vitest';
22

3+
import type { OAuthMetadata, OAuthTokens } from '../../src/shared/auth.js';
34
import type { SpecTypeName, SpecTypes } from '../../src/types/specTypeSchema.js';
45
import { isSpecType, specTypeSchema } from '../../src/types/specTypeSchema.js';
56
import type { CallToolResult, ContentBlock, Implementation, JSONRPCRequest, Tool } from '../../src/types/types.js';
@@ -25,6 +26,13 @@ describe('specTypeSchema()', () => {
2526
const ok = specTypeSchema('JSONRPCRequest')['~standard'].validate({ jsonrpc: '2.0', id: 1, method: 'ping' });
2627
expect((ok as { issues?: unknown }).issues).toBeUndefined();
2728
});
29+
30+
it('covers OAuth types from shared/auth.ts', () => {
31+
const ok = specTypeSchema('OAuthTokens')['~standard'].validate({ access_token: 'x', token_type: 'Bearer' });
32+
expect((ok as { issues?: unknown }).issues).toBeUndefined();
33+
const bad = specTypeSchema('OAuthTokens')['~standard'].validate({ token_type: 'Bearer' });
34+
expect((bad as { issues?: readonly unknown[] }).issues?.length).toBeGreaterThan(0);
35+
});
2836
});
2937

3038
describe('isSpecType()', () => {
@@ -65,6 +73,8 @@ describe('SpecTypeName / SpecTypes (type-level)', () => {
6573
expectTypeOf<'Tool'>().toMatchTypeOf<SpecTypeName>();
6674
expectTypeOf<'Implementation'>().toMatchTypeOf<SpecTypeName>();
6775
expectTypeOf<'JSONRPCRequest'>().toMatchTypeOf<SpecTypeName>();
76+
expectTypeOf<'OAuthTokens'>().toMatchTypeOf<SpecTypeName>();
77+
expectTypeOf<'OAuthMetadata'>().toMatchTypeOf<SpecTypeName>();
6878
});
6979

7080
it('SpecTypes[K] matches the named export type', () => {
@@ -73,5 +83,7 @@ describe('SpecTypeName / SpecTypes (type-level)', () => {
7383
expectTypeOf<SpecTypes['Tool']>().toEqualTypeOf<Tool>();
7484
expectTypeOf<SpecTypes['Implementation']>().toEqualTypeOf<Implementation>();
7585
expectTypeOf<SpecTypes['JSONRPCRequest']>().toEqualTypeOf<JSONRPCRequest>();
86+
expectTypeOf<SpecTypes['OAuthTokens']>().toEqualTypeOf<OAuthTokens>();
87+
expectTypeOf<SpecTypes['OAuthMetadata']>().toEqualTypeOf<OAuthMetadata>();
7688
});
7789
});

0 commit comments

Comments
 (0)