diff --git a/README.md b/README.md index bd4789d7a..92f56786f 100644 --- a/README.md +++ b/README.md @@ -5,25 +5,27 @@ - [Overview](#overview) - [Installation](#installation) -- [Quickstart](#quick-start) -- [What is MCP?](#what-is-mcp) +- [Quick Start](#quick-start) - [Core Concepts](#core-concepts) - [Server](#server) - - [Resources](#resources) - [Tools](#tools) + - [Resources](#resources) - [Prompts](#prompts) - [Completions](#completions) + - [Display Names and Metadata](#display-names-and-metadata) - [Sampling](#sampling) - [Running Your Server](#running-your-server) - - [stdio](#stdio) - [Streamable HTTP](#streamable-http) + - [stdio](#stdio) - [Testing and Debugging](#testing-and-debugging) - [Examples](#examples) - [Echo Server](#echo-server) - [SQLite Explorer](#sqlite-explorer) - [Advanced Usage](#advanced-usage) - [Dynamic Servers](#dynamic-servers) + - [Improving Network Efficiency with Notification Debouncing](#improving-network-efficiency-with-notification-debouncing) - [Low-Level Server](#low-level-server) + - [Eliciting User Input](#eliciting-user-input) - [Writing MCP Clients](#writing-mcp-clients) - [Proxy Authorization Requests Upstream](#proxy-authorization-requests-upstream) - [Backwards Compatibility](#backwards-compatibility) diff --git a/package-lock.json b/package-lock.json index 4a2dc15d2..4c5deb6f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@modelcontextprotocol/sdk", - "version": "1.20.0", + "version": "1.20.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@modelcontextprotocol/sdk", - "version": "1.20.0", + "version": "1.20.1", "license": "MIT", "dependencies": { "ajv": "^6.12.6", diff --git a/package.json b/package.json index ad0db7075..1a5837a51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@modelcontextprotocol/sdk", - "version": "1.20.0", + "version": "1.20.1", "description": "Model Context Protocol implementation for TypeScript", "license": "MIT", "author": "Anthropic, PBC (https://anthropic.com)", diff --git a/src/client/auth.test.ts b/src/client/auth.test.ts index c38f19331..f2dadbb15 100644 --- a/src/client/auth.test.ts +++ b/src/client/auth.test.ts @@ -863,7 +863,8 @@ describe('OAuth Authorization', () => { const calls = mockFetch.mock.calls; const [, options] = calls[0]; expect(options.headers).toEqual({ - 'MCP-Protocol-Version': '2025-01-01' + 'MCP-Protocol-Version': '2025-01-01', + Accept: 'application/json' }); }); diff --git a/src/client/auth.ts b/src/client/auth.ts index 3c04f7cb5..1e90f34ba 100644 --- a/src/client/auth.ts +++ b/src/client/auth.ts @@ -738,7 +738,10 @@ export async function discoverAuthorizationServerMetadata( protocolVersion?: string; } = {} ): Promise { - const headers = { 'MCP-Protocol-Version': protocolVersion }; + const headers = { + 'MCP-Protocol-Version': protocolVersion, + Accept: 'application/json' + }; // Get the list of URLs to try const urlsToTry = buildDiscoveryUrls(authorizationServerUrl); diff --git a/src/shared/auth.test.ts b/src/shared/auth.test.ts index 41f9dc1a9..71877f341 100644 --- a/src/shared/auth.test.ts +++ b/src/shared/auth.test.ts @@ -1,5 +1,11 @@ import { describe, it, expect } from '@jest/globals'; -import { SafeUrlSchema, OAuthMetadataSchema, OpenIdProviderMetadataSchema, OAuthClientMetadataSchema } from './auth.js'; +import { + SafeUrlSchema, + OAuthMetadataSchema, + OpenIdProviderMetadataSchema, + OAuthClientMetadataSchema, + OptionalSafeUrlSchema +} from './auth.js'; describe('SafeUrlSchema', () => { it('accepts valid HTTPS URLs', () => { @@ -26,6 +32,12 @@ describe('SafeUrlSchema', () => { }); }); +describe('OptionalSafeUrlSchema', () => { + it('accepts empty string and transforms it to undefined', () => { + expect(OptionalSafeUrlSchema.parse('')).toBe(undefined); + }); +}); + describe('OAuthMetadataSchema', () => { it('validates complete OAuth metadata', () => { const metadata = { diff --git a/src/shared/auth.ts b/src/shared/auth.ts index 0e079646b..c5ddbda16 100644 --- a/src/shared/auth.ts +++ b/src/shared/auth.ts @@ -151,6 +151,11 @@ export const OAuthErrorResponseSchema = z.object({ error_uri: z.string().optional() }); +/** + * Optional version of SafeUrlSchema that allows empty string for retrocompatibility on tos_uri and logo_uri + */ +export const OptionalSafeUrlSchema = SafeUrlSchema.optional().or(z.literal('').transform(() => undefined)); + /** * RFC 7591 OAuth 2.0 Dynamic Client Registration metadata */ @@ -162,10 +167,10 @@ export const OAuthClientMetadataSchema = z response_types: z.array(z.string()).optional(), client_name: z.string().optional(), client_uri: SafeUrlSchema.optional(), - logo_uri: SafeUrlSchema.optional(), + logo_uri: OptionalSafeUrlSchema, scope: z.string().optional(), contacts: z.array(z.string()).optional(), - tos_uri: SafeUrlSchema.optional(), + tos_uri: OptionalSafeUrlSchema, policy_uri: z.string().optional(), jwks_uri: SafeUrlSchema.optional(), jwks: z.any().optional(),