feat: support auth block in MCP servers config in agents (#24770)

This commit is contained in:
Tanmay Vartak
2026-04-13 12:41:40 -07:00
committed by GitHub
parent a4318f22ec
commit a172b328e2
2 changed files with 89 additions and 5 deletions

View File

@@ -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,

View File

@@ -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<string, MCPServerConfig> = {};
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,
);
}
}