diff --git a/packages/core/src/agents/agentLoader.test.ts b/packages/core/src/agents/agentLoader.test.ts index ca2b2be78b..f80a1e8cb3 100644 --- a/packages/core/src/agents/agentLoader.test.ts +++ b/packages/core/src/agents/agentLoader.test.ts @@ -493,6 +493,42 @@ Body`); }); }); + it('should convert mcp_servers with auth block in local agent (google-credentials)', () => { + const markdown = { + kind: 'local' as const, + name: 'spanner-test-agent', + description: 'An agent to test Spanner MCP with auth', + mcp_servers: { + spanner: { + url: 'https://spanner.googleapis.com/mcp', + type: 'http' as const, + auth: { + type: 'google-credentials' as const, + scopes: ['https://www.googleapis.com/auth/cloud-platform'], + }, + timeout: 30000, + }, + }, + system_prompt: 'You are a Spanner test agent.', + }; + + const result = markdownToAgentDefinition( + markdown, + ) as LocalAgentDefinition; + expect(result.kind).toBe('local'); + expect(result.mcpServers).toBeDefined(); + expect(result.mcpServers!['spanner']).toMatchObject({ + url: 'https://spanner.googleapis.com/mcp', + type: 'http', + authProviderType: 'google_credentials', + oauth: { + enabled: true, + scopes: ['https://www.googleapis.com/auth/cloud-platform'], + }, + timeout: 30000, + }); + }); + it('should pass through unknown model names (e.g. auto)', () => { const markdown = { kind: 'local' as const, diff --git a/packages/core/src/agents/agentLoader.ts b/packages/core/src/agents/agentLoader.ts index d34d0e974e..4c5e771af9 100644 --- a/packages/core/src/agents/agentLoader.ts +++ b/packages/core/src/agents/agentLoader.ts @@ -17,7 +17,11 @@ import { DEFAULT_MAX_TIME_MINUTES, } from './types.js'; import type { A2AAuthConfig } from './auth-provider/types.js'; -import { MCPServerConfig } from '../config/config.js'; +import { + MCPServerConfig, + AuthProviderType, + type MCPOAuthConfig, +} from '../config/config.js'; import { isValidToolName } from '../tools/tool-names.js'; import { FRONTMATTER_REGEX } from '../skills/skillLoader.js'; import { getErrorMessage } from '../utils/errors.js'; @@ -62,6 +66,22 @@ const mcpServerSchema = z.object({ description: z.string().optional(), include_tools: z.array(z.string()).optional(), exclude_tools: z.array(z.string()).optional(), + auth: z + .union([ + z.object({ + type: z.literal('google-credentials'), + scopes: z.array(z.string()).optional(), + }), + z.object({ + type: z.literal('oauth'), + client_id: z.string().optional(), + client_secret: z.string().optional(), + scopes: z.array(z.string()).optional(), + authorization_url: z.string().url().optional(), + token_url: z.string().url().optional(), + }), + ]) + .optional(), }); const localAgentSchema = z @@ -74,9 +94,12 @@ const localAgentSchema = z .array( z .string() - .refine((val) => isValidToolName(val, { allowWildcards: true }), { - message: 'Invalid tool name', - }), + .refine( + (val: string) => isValidToolName(val, { allowWildcards: true }), + { + message: 'Invalid tool name', + }, + ), ) .optional(), mcp_servers: z.record(mcpServerSchema).optional(), @@ -191,7 +214,7 @@ const remoteAgentJsonSchema = baseRemoteAgentSchema .extend({ agent_card_url: z.undefined().optional(), agent_card_json: z.string().refine( - (val) => { + (val: string) => { try { JSON.parse(val); return true; @@ -511,6 +534,28 @@ export function markdownToAgentDefinition( const mcpServers: Record = {}; if (markdown.mcp_servers) { for (const [name, config] of Object.entries(markdown.mcp_servers)) { + let authProviderType: AuthProviderType | undefined = undefined; + let oauth: MCPOAuthConfig | undefined = undefined; + + if (config.auth) { + if (config.auth.type === 'google-credentials') { + authProviderType = AuthProviderType.GOOGLE_CREDENTIALS; + oauth = { + enabled: true, + scopes: config.auth.scopes, + }; + } else if (config.auth.type === 'oauth') { + oauth = { + enabled: true, + clientId: config.auth.client_id, + clientSecret: config.auth.client_secret, + scopes: config.auth.scopes, + authorizationUrl: config.auth.authorization_url, + tokenUrl: config.auth.token_url, + }; + } + } + mcpServers[name] = new MCPServerConfig( config.command, config.args, @@ -526,6 +571,9 @@ export function markdownToAgentDefinition( config.description, config.include_tools, config.exclude_tools, + undefined, // extension + oauth, + authProviderType, ); } }