Skip to content

Commit 941178a

Browse files
committed
feat: mcp gateway schema types (auth, outbound auth, OAuth credentials)
1 parent bbfcdc4 commit 941178a

File tree

6 files changed

+101
-13
lines changed

6 files changed

+101
-13
lines changed

src/cli/operations/mcp/create-mcp.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export async function getExistingToolNames(): Promise<string[]> {
126126
// Gateway targets
127127
for (const gateway of mcpSpec.agentCoreGateways) {
128128
for (const target of gateway.targets) {
129-
for (const toolDef of target.toolDefinitions) {
129+
for (const toolDef of target.toolDefinitions ?? []) {
130130
toolNames.push(toolDef.name);
131131
}
132132
}
@@ -256,7 +256,7 @@ export async function createToolFromWizard(config: AddMcpToolConfig): Promise<Cr
256256
// Check for duplicate tool names
257257
for (const toolDef of toolDefs) {
258258
for (const existingTarget of gateway.targets) {
259-
if (existingTarget.toolDefinitions.some(t => t.name === toolDef.name)) {
259+
if ((existingTarget.toolDefinitions ?? []).some(t => t.name === toolDef.name)) {
260260
throw new Error(`Tool "${toolDef.name}" already exists in gateway "${gateway.name}".`);
261261
}
262262
}

src/cli/operations/remove/remove-mcp-tool.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export async function previewRemoveMcpTool(tool: RemovableMcpTool): Promise<Remo
109109
}
110110

111111
// Tool definitions in mcp-defs
112-
for (const toolDef of target.toolDefinitions) {
112+
for (const toolDef of target.toolDefinitions ?? []) {
113113
if (mcpDefs.tools[toolDef.name]) {
114114
summary.push(`Removing tool definition: ${toolDef.name}`);
115115
}
@@ -179,7 +179,7 @@ function computeRemovedToolMcpDefs(
179179
const gateway = mcpSpec.agentCoreGateways.find(g => g.name === tool.gatewayName);
180180
const target = gateway?.targets.find(t => t.name === tool.name);
181181
if (target) {
182-
for (const toolDef of target.toolDefinitions) {
182+
for (const toolDef of target.toolDefinitions ?? []) {
183183
toolNamesToRemove.push(toolDef.name);
184184
}
185185
}

src/cli/tui/screens/mcp/useAddGatewayWizard.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useCallback, useMemo, useState } from 'react';
55
/** Maps authorizer type to the next step after authorizer selection */
66
const AUTHORIZER_NEXT_STEP: Record<GatewayAuthorizerType, AddGatewayStep> = {
77
NONE: 'agents',
8+
AWS_IAM: 'agents',
89
CUSTOM_JWT: 'jwt-config',
910
};
1011

src/schema/schemas/__tests__/mcp.test.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ describe('AgentCoreGatewayTargetSchema', () => {
261261
name: 'myTarget',
262262
targetType: 'lambda',
263263
toolDefinitions: [validToolDef],
264+
compute: {
265+
host: 'Lambda',
266+
implementation: { language: 'Python', path: 'tools', handler: 'h' },
267+
pythonVersion: 'PYTHON_3_12',
268+
},
264269
});
265270
expect(result.success).toBe(true);
266271
});
@@ -270,6 +275,11 @@ describe('AgentCoreGatewayTargetSchema', () => {
270275
name: 'myTarget',
271276
targetType: 'lambda',
272277
toolDefinitions: [],
278+
compute: {
279+
host: 'Lambda',
280+
implementation: { language: 'Python', path: 'tools', handler: 'h' },
281+
pythonVersion: 'PYTHON_3_12',
282+
},
273283
});
274284
expect(result.success).toBe(false);
275285
});
@@ -303,6 +313,11 @@ describe('AgentCoreGatewaySchema', () => {
303313
name: 'target1',
304314
targetType: 'lambda',
305315
toolDefinitions: [validToolDef],
316+
compute: {
317+
host: 'Lambda',
318+
implementation: { language: 'Python', path: 'tools', handler: 'h' },
319+
pythonVersion: 'PYTHON_3_12',
320+
},
306321
},
307322
],
308323
};
@@ -387,7 +402,18 @@ describe('AgentCoreMcpSpecSchema', () => {
387402
agentCoreGateways: [
388403
{
389404
name: 'gw1',
390-
targets: [{ name: 't1', targetType: 'lambda', toolDefinitions: [validToolDef] }],
405+
targets: [
406+
{
407+
name: 't1',
408+
targetType: 'lambda',
409+
toolDefinitions: [validToolDef],
410+
compute: {
411+
host: 'Lambda',
412+
implementation: { language: 'Python', path: 'tools', handler: 'h' },
413+
pythonVersion: 'PYTHON_3_12',
414+
},
415+
},
416+
],
391417
},
392418
],
393419
});

src/schema/schemas/agentcore-project.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,6 @@ export type Memory = z.infer<typeof MemorySchema>;
7171
// Credential Schema
7272
// ============================================================================
7373

74-
export const CredentialTypeSchema = z.literal('ApiKeyCredentialProvider');
75-
export type CredentialType = z.infer<typeof CredentialTypeSchema>;
76-
7774
export const CredentialNameSchema = z
7875
.string()
7976
.min(3, 'Credential name must be at least 3 characters')
@@ -83,11 +80,33 @@ export const CredentialNameSchema = z
8380
'Must contain only alphanumeric characters, underscores, dots, and hyphens (3-255 chars)'
8481
);
8582

86-
export const CredentialSchema = z.object({
87-
type: CredentialTypeSchema,
83+
export const CredentialTypeSchema = z.enum(['ApiKeyCredentialProvider', 'OAuthCredentialProvider']);
84+
export type CredentialType = z.infer<typeof CredentialTypeSchema>;
85+
86+
export const ApiKeyCredentialSchema = z.object({
87+
type: z.literal('ApiKeyCredentialProvider'),
88+
name: CredentialNameSchema,
89+
});
90+
91+
export type ApiKeyCredential = z.infer<typeof ApiKeyCredentialSchema>;
92+
93+
export const OAuthCredentialSchema = z.object({
94+
type: z.literal('OAuthCredentialProvider'),
8895
name: CredentialNameSchema,
96+
/** OIDC discovery URL for the OAuth provider */
97+
discoveryUrl: z.string().url(),
98+
/** Scopes this credential provider supports */
99+
scopes: z.array(z.string()).default([]),
100+
/** Credential provider vendor type */
101+
vendor: z.string().default('CustomOauth2'),
102+
/** Whether this credential was auto-created by the CLI (e.g., for CUSTOM_JWT inbound auth) */
103+
managed: z.boolean().optional(),
89104
});
90105

106+
export type OAuthCredential = z.infer<typeof OAuthCredentialSchema>;
107+
108+
export const CredentialSchema = z.discriminatedUnion('type', [ApiKeyCredentialSchema, OAuthCredentialSchema]);
109+
91110
export type Credential = z.infer<typeof CredentialSchema>;
92111

93112
// ============================================================================

src/schema/schemas/mcp.ts

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export type GatewayTargetType = z.infer<typeof GatewayTargetTypeSchema>;
1515
// Gateway Authorization Schemas
1616
// ============================================================================
1717

18-
export const GatewayAuthorizerTypeSchema = z.enum(['NONE', 'CUSTOM_JWT']);
18+
export const GatewayAuthorizerTypeSchema = z.enum(['NONE', 'AWS_IAM', 'CUSTOM_JWT']);
1919
export type GatewayAuthorizerType = z.infer<typeof GatewayAuthorizerTypeSchema>;
2020

2121
/** OIDC well-known configuration endpoint suffix (per OpenID Connect Discovery 1.0 spec) */
@@ -44,6 +44,7 @@ export const CustomJwtAuthorizerConfigSchema = z.object({
4444
allowedAudience: z.array(z.string().min(1)),
4545
/** List of allowed client IDs */
4646
allowedClients: z.array(z.string().min(1)).min(1),
47+
allowedScopes: z.array(z.string().min(1)).optional(),
4748
});
4849

4950
export type CustomJwtAuthorizerConfig = z.infer<typeof CustomJwtAuthorizerConfigSchema>;
@@ -57,6 +58,19 @@ export const GatewayAuthorizerConfigSchema = z.object({
5758

5859
export type GatewayAuthorizerConfig = z.infer<typeof GatewayAuthorizerConfigSchema>;
5960

61+
export const OutboundAuthTypeSchema = z.enum(['OAUTH', 'API_KEY', 'NONE']);
62+
export type OutboundAuthType = z.infer<typeof OutboundAuthTypeSchema>;
63+
64+
export const OutboundAuthSchema = z
65+
.object({
66+
type: OutboundAuthTypeSchema.default('NONE'),
67+
credentialName: z.string().min(1).optional(),
68+
scopes: z.array(z.string()).optional(),
69+
})
70+
.strict();
71+
72+
export type OutboundAuth = z.infer<typeof OutboundAuthSchema>;
73+
6074
export const McpImplLanguageSchema = z.enum(['TypeScript', 'Python']);
6175
export type McpImplementationLanguage = z.infer<typeof McpImplLanguageSchema>;
6276

@@ -262,10 +276,38 @@ export const AgentCoreGatewayTargetSchema = z
262276
.object({
263277
name: z.string().min(1),
264278
targetType: GatewayTargetTypeSchema,
265-
toolDefinitions: z.array(ToolDefinitionSchema).min(1),
279+
/** Tool definitions. Required for Lambda targets. Optional for MCP Server (discovered via tools/list). */
280+
toolDefinitions: z.array(ToolDefinitionSchema).optional(),
281+
/** Compute configuration. Required for Lambda/Runtime scaffold targets. */
266282
compute: ToolComputeConfigSchema.optional(),
283+
/** MCP Server endpoint URL. Required for external MCP Server targets. */
284+
endpoint: z.string().url().optional(),
285+
/** Outbound auth configuration for the target. */
286+
outboundAuth: OutboundAuthSchema.optional(),
267287
})
268-
.strict();
288+
.strict()
289+
.refine(
290+
data => {
291+
// External MCP Server: needs endpoint, no compute
292+
if (data.targetType === 'mcpServer' && !data.compute && !data.endpoint) {
293+
return false;
294+
}
295+
// Lambda target: needs compute and tool definitions
296+
if (data.targetType === 'lambda') {
297+
if (!data.compute) return false;
298+
if (!data.toolDefinitions || data.toolDefinitions.length === 0) return false;
299+
}
300+
// Outbound auth with credential needs a credential name
301+
if (data.outboundAuth && data.outboundAuth.type !== 'NONE' && !data.outboundAuth.credentialName) {
302+
return false;
303+
}
304+
return true;
305+
},
306+
{
307+
message:
308+
'Invalid target configuration. MCP Server targets need an endpoint or compute. Lambda targets need compute and tool definitions. OAuth/API_KEY auth needs a credential name.',
309+
}
310+
);
269311

270312
export type AgentCoreGatewayTarget = z.infer<typeof AgentCoreGatewayTargetSchema>;
271313

0 commit comments

Comments
 (0)