diff --git a/src/types.test.ts b/src/types.test.ts index cd8cc071..031f455b 100644 --- a/src/types.test.ts +++ b/src/types.test.ts @@ -5,7 +5,8 @@ import { ContentBlockSchema, PromptMessageSchema, CallToolResultSchema, - CompleteRequestSchema + CompleteRequestSchema, + RootSchema } from './types.js'; describe('Types', () => { @@ -311,4 +312,44 @@ describe('Types', () => { } }); }); + + describe('Root', () => { + test('should validate roots with file:// URIs', () => { + const root = { + uri: 'file:///users/test/project', + name: 'Test Root' + }; + + const result = RootSchema.safeParse(root); + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.uri).toBe('file:///users/test/project'); + expect(result.data.name).toBe('Test Root'); + } + }); + + test('should validate roots with non-file URI schemes', () => { + const root = { + uri: 'https://github.com/owner/repo', + name: 'GitHub Repo' + }; + + const result = RootSchema.safeParse(root); + expect(result.success).toBe(true); + if (result.success) { + expect(result.data.uri).toBe('https://github.com/owner/repo'); + expect(result.data.name).toBe('GitHub Repo'); + } + }); + + test('should reject invalid URIs', () => { + const invalidRoot = { + uri: '/home/modelcontextprotocol/project', + name: 'Invalid Root' + }; + + const result = RootSchema.safeParse(invalidRoot); + expect(result.success).toBe(false); + }); + }); }); diff --git a/src/types.ts b/src/types.ts index e6d3fe46..a4d6702c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1365,9 +1365,10 @@ export const CompleteResultSchema = ResultSchema.extend({ export const RootSchema = z .object({ /** - * The URI identifying the root. This *must* start with file:// for now. + * The URI identifying the root. Can be any valid URI scheme (e.g., file://, https://, s3://, git://). + * Servers should document which URI schemes they support and handle unsupported schemes gracefully. */ - uri: z.string().startsWith('file://'), + uri: z.string().url(), /** * An optional name for the root. */