@aws/agentcore 0.3.0-preview.2.0 → 0.3.0-preview.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap +486 -133
  2. package/dist/assets/cdk/README.md +19 -7
  3. package/dist/assets/cdk/bin/cdk.ts +37 -2
  4. package/dist/assets/cdk/lib/cdk-stack.ts +25 -2
  5. package/dist/assets/cdk/package.json +1 -1
  6. package/dist/assets/cdk/test/cdk.test.ts +18 -14
  7. package/dist/assets/cdk/tsconfig.json +4 -4
  8. package/dist/assets/container/python/Dockerfile +19 -9
  9. package/dist/assets/container/python/dockerignore.template +7 -0
  10. package/dist/assets/python/autogen/base/README.md +9 -11
  11. package/dist/assets/python/autogen/base/mcp_client/__init__.py +1 -1
  12. package/dist/assets/python/autogen/base/model/__init__.py +1 -1
  13. package/dist/assets/python/crewai/base/README.md +9 -11
  14. package/dist/assets/python/crewai/base/model/__init__.py +1 -1
  15. package/dist/assets/python/googleadk/base/README.md +9 -9
  16. package/dist/assets/python/googleadk/base/main.py +10 -1
  17. package/dist/assets/python/googleadk/base/mcp_client/__init__.py +1 -1
  18. package/dist/assets/python/googleadk/base/mcp_client/client.py +54 -3
  19. package/dist/assets/python/googleadk/base/model/__init__.py +1 -1
  20. package/dist/assets/python/googleadk/base/pyproject.toml +2 -0
  21. package/dist/assets/python/langchain_langgraph/base/README.md +9 -11
  22. package/dist/assets/python/langchain_langgraph/base/main.py +11 -1
  23. package/dist/assets/python/langchain_langgraph/base/mcp_client/__init__.py +1 -1
  24. package/dist/assets/python/langchain_langgraph/base/mcp_client/client.py +52 -3
  25. package/dist/assets/python/langchain_langgraph/base/model/__init__.py +1 -1
  26. package/dist/assets/python/langchain_langgraph/base/pyproject.toml +2 -1
  27. package/dist/assets/python/openaiagents/base/README.md +9 -9
  28. package/dist/assets/python/openaiagents/base/main.py +43 -3
  29. package/dist/assets/python/openaiagents/base/mcp_client/__init__.py +1 -1
  30. package/dist/assets/python/openaiagents/base/mcp_client/client.py +54 -3
  31. package/dist/assets/python/openaiagents/base/model/__init__.py +1 -1
  32. package/dist/assets/python/openaiagents/base/pyproject.toml +2 -0
  33. package/dist/assets/python/strands/base/README.md +10 -12
  34. package/dist/assets/python/strands/base/main.py +16 -3
  35. package/dist/assets/python/strands/base/mcp_client/__init__.py +1 -1
  36. package/dist/assets/python/strands/base/mcp_client/client.py +56 -4
  37. package/dist/assets/python/strands/base/model/__init__.py +1 -1
  38. package/dist/assets/python/strands/base/pyproject.toml +4 -1
  39. package/dist/assets/python/strands/capabilities/memory/__init__.py +1 -0
  40. package/dist/cli/index.mjs +290 -286
  41. package/dist/lib/packaging/build-args.d.ts +6 -0
  42. package/dist/lib/packaging/build-args.d.ts.map +1 -0
  43. package/dist/lib/packaging/build-args.js +18 -0
  44. package/dist/lib/packaging/build-args.js.map +1 -0
  45. package/dist/lib/packaging/container.d.ts.map +1 -1
  46. package/dist/lib/packaging/container.js +2 -1
  47. package/dist/lib/packaging/container.js.map +1 -1
  48. package/dist/lib/schemas/io/cli-config.d.ts +10 -0
  49. package/dist/lib/schemas/io/cli-config.d.ts.map +1 -0
  50. package/dist/lib/schemas/io/cli-config.js +27 -0
  51. package/dist/lib/schemas/io/cli-config.js.map +1 -0
  52. package/dist/lib/schemas/io/index.d.ts +1 -0
  53. package/dist/lib/schemas/io/index.d.ts.map +1 -1
  54. package/dist/lib/schemas/io/index.js +3 -1
  55. package/dist/lib/schemas/io/index.js.map +1 -1
  56. package/dist/lib/utils/subprocess.d.ts.map +1 -1
  57. package/dist/lib/utils/subprocess.js +32 -10
  58. package/dist/lib/utils/subprocess.js.map +1 -1
  59. package/dist/schema/constants.d.ts.map +1 -1
  60. package/dist/schema/constants.js +0 -1
  61. package/dist/schema/constants.js.map +1 -1
  62. package/dist/schema/schemas/agentcore-project.d.ts +48 -5
  63. package/dist/schema/schemas/agentcore-project.d.ts.map +1 -1
  64. package/dist/schema/schemas/agentcore-project.js +19 -4
  65. package/dist/schema/schemas/agentcore-project.js.map +1 -1
  66. package/dist/schema/schemas/aws-targets.js +1 -1
  67. package/dist/schema/schemas/aws-targets.js.map +1 -1
  68. package/dist/schema/schemas/deployed-state.d.ts +32 -0
  69. package/dist/schema/schemas/deployed-state.d.ts.map +1 -1
  70. package/dist/schema/schemas/deployed-state.js +11 -1
  71. package/dist/schema/schemas/deployed-state.js.map +1 -1
  72. package/dist/schema/schemas/mcp-defs.d.ts +1 -1
  73. package/dist/schema/schemas/mcp-defs.js +1 -1
  74. package/dist/schema/schemas/mcp.d.ts +146 -6
  75. package/dist/schema/schemas/mcp.d.ts.map +1 -1
  76. package/dist/schema/schemas/mcp.js +49 -4
  77. package/dist/schema/schemas/mcp.js.map +1 -1
  78. package/package.json +8 -8
@@ -13,20 +13,32 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/.prettierrc should ma
13
13
  `;
14
14
 
15
15
  exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/README.md should match snapshot 1`] = `
16
- "# Welcome to your CDK TypeScript project
16
+ "# AgentCore CDK Project
17
17
 
18
- This is a blank project for CDK development with TypeScript.
18
+ This CDK project is managed by the AgentCore CLI. It deploys your agent infrastructure into AWS using the \`@aws/agentcore-cdk\` L3 constructs.
19
19
 
20
- The \`cdk.json\` file tells the CDK Toolkit how to execute your app.
20
+ ## Structure
21
+
22
+ - \`bin/cdk.ts\` — Entry point. Reads project configuration from \`agentcore/\` and creates a stack per deployment target.
23
+ - \`lib/cdk-stack.ts\` — Defines \`AgentCoreStack\`, which wraps the \`AgentCoreApplication\` L3 construct.
24
+ - \`test/cdk.test.ts\` — Unit tests for stack synthesis.
21
25
 
22
26
  ## Useful commands
23
27
 
24
- - \`npm run build\` compile typescript to js
25
- - \`npm run watch\` watch for changes and compile
26
- - \`npm run test\` perform the jest unit tests
28
+ - \`npm run build\` compile TypeScript to JavaScript
29
+ - \`npm run test\` run unit tests
30
+ - \`npx cdk synth\` emit the synthesized CloudFormation template
27
31
  - \`npx cdk deploy\` deploy this stack to your default AWS account/region
28
32
  - \`npx cdk diff\` compare deployed stack with current state
29
- - \`npx cdk synth\` emits the synthesized CloudFormation template
33
+
34
+ ## Usage
35
+
36
+ You typically don't need to interact with this directory directly. The AgentCore CLI handles synthesis and deployment:
37
+
38
+ \`\`\`bash
39
+ agentcore deploy # synthesizes and deploys via CDK
40
+ agentcore status # checks deployment status
41
+ \`\`\`
30
42
  "
31
43
  `;
32
44
 
@@ -36,6 +48,7 @@ import { AgentCoreStack } from '../lib/cdk-stack';
36
48
  import { ConfigIO, type AwsDeploymentTarget } from '@aws/agentcore-cdk';
37
49
  import { App, type Environment } from 'aws-cdk-lib';
38
50
  import * as path from 'path';
51
+ import * as fs from 'fs';
39
52
 
40
53
  function toEnvironment(target: AwsDeploymentTarget): Environment {
41
54
  return {
@@ -44,8 +57,12 @@ function toEnvironment(target: AwsDeploymentTarget): Environment {
44
57
  };
45
58
  }
46
59
 
60
+ function sanitize(name: string): string {
61
+ return name.replace(/_/g, '-');
62
+ }
63
+
47
64
  function toStackName(projectName: string, targetName: string): string {
48
- return \`AgentCore-\${projectName}-\${targetName}\`;
65
+ return \`AgentCore-\${sanitize(projectName)}-\${sanitize(targetName)}\`;
49
66
  }
50
67
 
51
68
  async function main() {
@@ -56,6 +73,22 @@ async function main() {
56
73
  const spec = await configIO.readProjectSpec();
57
74
  const targets = await configIO.readAWSDeploymentTargets();
58
75
 
76
+ // Read MCP configuration if it exists
77
+ let mcpSpec;
78
+ try {
79
+ mcpSpec = await configIO.readMcpSpec();
80
+ } catch {
81
+ // MCP config is optional
82
+ }
83
+
84
+ // Read deployed state for credential ARNs (populated by pre-deploy identity setup)
85
+ let deployedState: Record<string, unknown> | undefined;
86
+ try {
87
+ deployedState = JSON.parse(fs.readFileSync(path.join(configRoot, '.cli', 'deployed-state.json'), 'utf8'));
88
+ } catch {
89
+ // Deployed state may not exist on first deploy
90
+ }
91
+
59
92
  if (targets.length === 0) {
60
93
  throw new Error('No deployment targets configured. Please define targets in agentcore/aws-targets.json');
61
94
  }
@@ -66,8 +99,19 @@ async function main() {
66
99
  const env = toEnvironment(target);
67
100
  const stackName = toStackName(spec.name, target.name);
68
101
 
102
+ // Extract credentials from deployed state for this target
103
+ const targetState = (deployedState as Record<string, unknown>)?.targets as
104
+ | Record<string, Record<string, unknown>>
105
+ | undefined;
106
+ const targetResources = targetState?.[target.name]?.resources as Record<string, unknown> | undefined;
107
+ const credentials = targetResources?.credentials as
108
+ | Record<string, { credentialProviderArn: string; clientSecretArn?: string }>
109
+ | undefined;
110
+
69
111
  new AgentCoreStack(app, stackName, {
70
112
  spec,
113
+ mcpSpec,
114
+ credentials,
71
115
  env,
72
116
  description: \`AgentCore stack for \${spec.name} deployed to \${target.name} (\${target.region})\`,
73
117
  tags: {
@@ -80,7 +124,10 @@ async function main() {
80
124
  app.synth();
81
125
  }
82
126
 
83
- main();
127
+ main().catch((error: unknown) => {
128
+ console.error('AgentCore CDK synthesis failed:', error instanceof Error ? error.message : error);
129
+ process.exitCode = 1;
130
+ });
84
131
  "
85
132
  `;
86
133
 
@@ -203,7 +250,12 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/jest.config.js should
203
250
  `;
204
251
 
205
252
  exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/lib/cdk-stack.ts should match snapshot 1`] = `
206
- "import { AgentCoreApplication, type AgentCoreProjectSpec } from '@aws/agentcore-cdk';
253
+ "import {
254
+ AgentCoreApplication,
255
+ AgentCoreMcp,
256
+ type AgentCoreProjectSpec,
257
+ type AgentCoreMcpSpec,
258
+ } from '@aws/agentcore-cdk';
207
259
  import { CfnOutput, Stack, type StackProps } from 'aws-cdk-lib';
208
260
  import { Construct } from 'constructs';
209
261
 
@@ -212,6 +264,14 @@ export interface AgentCoreStackProps extends StackProps {
212
264
  * The AgentCore project specification containing agents, memories, and credentials.
213
265
  */
214
266
  spec: AgentCoreProjectSpec;
267
+ /**
268
+ * The MCP specification containing gateways and servers.
269
+ */
270
+ mcpSpec?: AgentCoreMcpSpec;
271
+ /**
272
+ * Credential provider ARNs from deployed state, keyed by credential name.
273
+ */
274
+ credentials?: Record<string, { credentialProviderArn: string; clientSecretArn?: string }>;
215
275
  }
216
276
 
217
277
  /**
@@ -227,13 +287,23 @@ export class AgentCoreStack extends Stack {
227
287
  constructor(scope: Construct, id: string, props: AgentCoreStackProps) {
228
288
  super(scope, id, props);
229
289
 
230
- const { spec } = props;
290
+ const { spec, mcpSpec, credentials } = props;
231
291
 
232
292
  // Create AgentCoreApplication with all agents
233
293
  this.application = new AgentCoreApplication(this, 'Application', {
234
294
  spec,
235
295
  });
236
296
 
297
+ // Create AgentCoreMcp if there are gateways configured
298
+ if (mcpSpec?.agentCoreGateways && mcpSpec.agentCoreGateways.length > 0) {
299
+ new AgentCoreMcp(this, 'Mcp', {
300
+ projectName: spec.name,
301
+ mcpSpec,
302
+ agentCoreApplication: this.application,
303
+ credentials,
304
+ });
305
+ }
306
+
237
307
  // Stack-level output
238
308
  new CfnOutput(this, 'StackNameOutput', {
239
309
  description: 'Name of the CloudFormation Stack',
@@ -281,7 +351,7 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/package.json should m
281
351
  },
282
352
  "dependencies": {
283
353
  "@aws/agentcore-cdk": "^0.1.0-alpha.1",
284
- "aws-cdk-lib": "2.234.1",
354
+ "aws-cdk-lib": "2.239.0",
285
355
  "constructs": "^10.0.0"
286
356
  }
287
357
  }
@@ -289,21 +359,25 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/package.json should m
289
359
  `;
290
360
 
291
361
  exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/test/cdk.test.ts should match snapshot 1`] = `
292
- "// import * as cdk from 'aws-cdk-lib/core';
293
- // import { Template } from 'aws-cdk-lib/assertions';
294
- // import * as Cdk from '../lib/cdk-stack';
295
-
296
- // example test. To run these tests, uncomment this file along with the
297
- // example resource in lib/cdk-stack.ts
298
- test('SQS Queue Created', () => {
299
- // const app = new cdk.App();
300
- // // WHEN
301
- // const stack = new Cdk.CdkStack(app, 'MyTestStack');
302
- // // THEN
303
- // const template = Template.fromStack(stack);
304
- // template.hasResourceProperties('AWS::SQS::Queue', {
305
- // VisibilityTimeout: 300
306
- // });
362
+ "import * as cdk from 'aws-cdk-lib';
363
+ import { Template } from 'aws-cdk-lib/assertions';
364
+ import { AgentCoreStack } from '../lib/cdk-stack';
365
+
366
+ test('AgentCoreStack synthesizes with empty spec', () => {
367
+ const app = new cdk.App();
368
+ const stack = new AgentCoreStack(app, 'TestStack', {
369
+ spec: {
370
+ name: 'testproject',
371
+ version: 1,
372
+ agents: [],
373
+ memories: [],
374
+ credentials: [],
375
+ },
376
+ });
377
+ const template = Template.fromStack(stack);
378
+ template.hasOutput('StackNameOutput', {
379
+ Description: 'Name of the CloudFormation Stack',
380
+ });
307
381
  });
308
382
  "
309
383
  `;
@@ -321,14 +395,14 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/tsconfig.json should
321
395
  "strictNullChecks": true,
322
396
  "noImplicitThis": true,
323
397
  "alwaysStrict": true,
324
- "noUnusedLocals": false,
325
- "noUnusedParameters": false,
398
+ "noUnusedLocals": true,
399
+ "noUnusedParameters": true,
326
400
  "noImplicitReturns": true,
327
- "noFallthroughCasesInSwitch": false,
401
+ "noFallthroughCasesInSwitch": true,
328
402
  "inlineSourceMap": true,
329
403
  "inlineSources": true,
330
404
  "experimentalDecorators": true,
331
- "strictPropertyInitialization": false,
405
+ "strictPropertyInitialization": true,
332
406
  "skipLibCheck": true,
333
407
  "typeRoots": ["./node_modules/@types"],
334
408
  "rootDir": ".",
@@ -792,25 +866,23 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/au
792
866
 
793
867
  # Layout
794
868
 
795
- There is one directory with generated application code, \`src/\` . At the root, there is a \`.gitignore\` file, a
796
- \`.agentcore\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
869
+ The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
870
+ \`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
797
871
  commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
798
872
 
799
- ## src/
873
+ ## Agent Root
800
874
 
801
- The main entrypoint to your app is defined in \`src/main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
875
+ The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
802
876
  file defines a Starlette ASGI app with the AutoGen framework running within.
803
877
 
804
- \`src/model/load.py\` instantiates your chosen model provider.
878
+ \`model/load.py\` instantiates your chosen model provider.
805
879
 
806
880
  ## Environment Variables
807
881
 
808
- | Variable | Required | Description |
809
- | ------------------------------ | --------------- | ---------------------------------------------------------------- |
810
- | \`AGENTCORE_IDENTITY_OPENAI\` | Yes (OpenAI) | OpenAI API key (local) or Identity provider name (deployed) |
811
- | \`AGENTCORE_IDENTITY_ANTHROPIC\` | Yes (Anthropic) | Anthropic API key (local) or Identity provider name (deployed) |
812
- | \`AGENTCORE_IDENTITY_GEMINI\` | Yes (Gemini) | Gemini API key (local) or Identity provider name (deployed) |
813
- | \`LOCAL_DEV\` | No | Set to \`1\` to use \`agentcore/.env\` instead of AgentCore Identity |
882
+ | Variable | Required | Description |
883
+ | --- | --- | --- |
884
+ {{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
885
+ {{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
814
886
 
815
887
  # Developing locally
816
888
 
@@ -934,7 +1006,7 @@ if __name__ == "__main__":
934
1006
  `;
935
1007
 
936
1008
  exports[`Assets Directory Snapshots > Python framework assets > python/python/autogen/base/mcp_client/__init__.py should match snapshot 1`] = `
937
- "
1009
+ "# Package marker
938
1010
  "
939
1011
  `;
940
1012
 
@@ -961,7 +1033,7 @@ async def get_streamable_http_mcp_tools() -> List[StreamableHttpMcpToolAdapter]:
961
1033
  `;
962
1034
 
963
1035
  exports[`Assets Directory Snapshots > Python framework assets > python/python/autogen/base/model/__init__.py should match snapshot 1`] = `
964
- "
1036
+ "# Package marker
965
1037
  "
966
1038
  `;
967
1039
 
@@ -1148,25 +1220,23 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/cr
1148
1220
 
1149
1221
  # Layout
1150
1222
 
1151
- There is one directory with generated application code, \`src/\` . At the root, there is a \`.gitignore\` file, a
1152
- \`.agentcore\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
1223
+ The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
1224
+ \`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
1153
1225
  commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
1154
1226
 
1155
- ## src/
1227
+ ## Agent Root
1156
1228
 
1157
- The main entrypoint to your app is defined in \`src/main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
1229
+ The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
1158
1230
  file defines a Starlette ASGI app with the CrewAI framework running within.
1159
1231
 
1160
- \`src/model/load.py\` instantiates your chosen model provider.
1232
+ \`model/load.py\` instantiates your chosen model provider.
1161
1233
 
1162
1234
  ## Environment Variables
1163
1235
 
1164
- | Variable | Required | Description |
1165
- | ------------------------------ | --------------- | ---------------------------------------------------------------- |
1166
- | \`AGENTCORE_IDENTITY_OPENAI\` | Yes (OpenAI) | OpenAI API key (local) or Identity provider name (deployed) |
1167
- | \`AGENTCORE_IDENTITY_ANTHROPIC\` | Yes (Anthropic) | Anthropic API key (local) or Identity provider name (deployed) |
1168
- | \`AGENTCORE_IDENTITY_GEMINI\` | Yes (Gemini) | Gemini API key (local) or Identity provider name (deployed) |
1169
- | \`LOCAL_DEV\` | No | Set to \`1\` to use \`agentcore/.env\` instead of AgentCore Identity |
1236
+ | Variable | Required | Description |
1237
+ | --- | --- | --- |
1238
+ {{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
1239
+ {{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
1170
1240
 
1171
1241
  # Developing locally
1172
1242
 
@@ -1293,7 +1363,7 @@ if __name__ == "__main__":
1293
1363
  `;
1294
1364
 
1295
1365
  exports[`Assets Directory Snapshots > Python framework assets > python/python/crewai/base/model/__init__.py should match snapshot 1`] = `
1296
- "
1366
+ "# Package marker
1297
1367
  "
1298
1368
  `;
1299
1369
 
@@ -1474,23 +1544,23 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/go
1474
1544
 
1475
1545
  # Layout
1476
1546
 
1477
- There is one directory with generated application code, \`src/\` . At the root, there is a \`.gitignore\` file, a
1478
- \`.agentcore\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
1547
+ The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
1548
+ \`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
1479
1549
  commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
1480
1550
 
1481
- ## src/
1551
+ ## Agent Root
1482
1552
 
1483
- The main entrypoint to your app is defined in \`src/main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
1553
+ The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
1484
1554
  file defines a Starlette ASGI app with the Google ADK framework running within.
1485
1555
 
1486
- \`src/model/load.py\` instantiates your chosen model provider (Gemini).
1556
+ \`model/load.py\` instantiates your chosen model provider (Gemini).
1487
1557
 
1488
1558
  ## Environment Variables
1489
1559
 
1490
- | Variable | Required | Description |
1491
- | --------------------------- | -------- | ---------------------------------------------------------------- |
1492
- | \`AGENTCORE_IDENTITY_GEMINI\` | Yes | Gemini API key (local) or Identity provider name (deployed) |
1493
- | \`LOCAL_DEV\` | No | Set to \`1\` to use \`agentcore/.env\` instead of AgentCore Identity |
1560
+ | Variable | Required | Description |
1561
+ | --- | --- | --- |
1562
+ {{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
1563
+ {{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
1494
1564
 
1495
1565
  # Developing locally
1496
1566
 
@@ -1565,7 +1635,11 @@ from google.adk.sessions import InMemorySessionService
1565
1635
  from google.genai import types
1566
1636
  from bedrock_agentcore.runtime import BedrockAgentCoreApp
1567
1637
  from model.load import load_model
1638
+ {{#if hasGateway}}
1639
+ from mcp_client.client import get_all_gateway_mcp_toolsets
1640
+ {{else}}
1568
1641
  from mcp_client.client import get_streamable_http_mcp_client
1642
+ {{/if}}
1569
1643
 
1570
1644
  app = BedrockAgentCoreApp()
1571
1645
  log = app.logger
@@ -1583,7 +1657,12 @@ def add_numbers(a: int, b: int) -> int:
1583
1657
 
1584
1658
 
1585
1659
  # Get MCP Toolset
1586
- mcp_toolset = [get_streamable_http_mcp_client()]
1660
+ {{#if hasGateway}}
1661
+ mcp_toolset = get_all_gateway_mcp_toolsets()
1662
+ {{else}}
1663
+ mcp_client = get_streamable_http_mcp_client()
1664
+ mcp_toolset = [mcp_client] if mcp_client else []
1665
+ {{/if}}
1587
1666
 
1588
1667
  _credentials_loaded = False
1589
1668
 
@@ -1653,31 +1732,82 @@ if __name__ == "__main__":
1653
1732
  `;
1654
1733
 
1655
1734
  exports[`Assets Directory Snapshots > Python framework assets > python/python/googleadk/base/mcp_client/__init__.py should match snapshot 1`] = `
1656
- "
1735
+ "# Package marker
1657
1736
  "
1658
1737
  `;
1659
1738
 
1660
1739
  exports[`Assets Directory Snapshots > Python framework assets > python/python/googleadk/base/mcp_client/client.py should match snapshot 1`] = `
1661
- "from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
1740
+ "import os
1741
+ import logging
1742
+ from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
1662
1743
  from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
1663
1744
 
1745
+ logger = logging.getLogger(__name__)
1746
+
1747
+ {{#if hasGateway}}
1748
+ {{#if (includes gatewayAuthTypes "AWS_IAM")}}
1749
+ import httpx
1750
+ from mcp_proxy_for_aws.sigv4_helper import SigV4HTTPXAuth, create_aws_session
1751
+ {{/if}}
1752
+ {{#if (includes gatewayAuthTypes "CUSTOM_JWT")}}
1753
+ from bedrock_agentcore.identity import requires_access_token
1754
+ {{/if}}
1755
+
1756
+ {{#each gatewayProviders}}
1757
+ {{#if (eq authType "CUSTOM_JWT")}}
1758
+ @requires_access_token(
1759
+ provider_name="{{credentialProviderName}}",
1760
+ scopes=[{{#if scopes}}"{{scopes}}"{{/if}}],
1761
+ auth_flow="M2M",
1762
+ )
1763
+ def _get_bearer_token_{{snakeCase name}}(*, access_token: str):
1764
+ """Obtain OAuth access token via AgentCore Identity for {{name}}."""
1765
+ return access_token
1766
+
1767
+ {{/if}}
1768
+ {{/each}}
1769
+
1770
+ def get_all_gateway_mcp_toolsets() -> list[MCPToolset]:
1771
+ """Returns MCP Toolsets for all configured gateways."""
1772
+ toolsets = []
1773
+ {{#each gatewayProviders}}
1774
+ url = os.environ.get("{{envVarName}}")
1775
+ if url:
1776
+ {{#if (eq authType "AWS_IAM")}}
1777
+ session = create_aws_session()
1778
+ auth = SigV4HTTPXAuth(session.get_credentials(), "bedrock-agentcore", session.region_name)
1779
+ toolsets.append(MCPToolset(connection_params=StreamableHTTPConnectionParams(
1780
+ url=url,
1781
+ httpx_client_factory=lambda **kwargs: httpx.AsyncClient(auth=auth, **kwargs)
1782
+ )))
1783
+ {{else if (eq authType "CUSTOM_JWT")}}
1784
+ token = _get_bearer_token_{{snakeCase name}}()
1785
+ headers = {"Authorization": f"Bearer {token}"} if token else None
1786
+ toolsets.append(MCPToolset(connection_params=StreamableHTTPConnectionParams(url=url, headers=headers)))
1787
+ {{else}}
1788
+ toolsets.append(MCPToolset(connection_params=StreamableHTTPConnectionParams(url=url)))
1789
+ {{/if}}
1790
+ else:
1791
+ logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
1792
+ {{/each}}
1793
+ return toolsets
1794
+ {{else}}
1664
1795
  # ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
1665
1796
  EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
1666
1797
 
1667
1798
 
1668
1799
  def get_streamable_http_mcp_client() -> MCPToolset:
1669
- """
1670
- Returns an MCP Toolset compatible with Google ADK.
1671
- """
1800
+ """Returns an MCP Toolset compatible with Google ADK."""
1672
1801
  # to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
1673
1802
  return MCPToolset(
1674
1803
  connection_params=StreamableHTTPConnectionParams(url=EXAMPLE_MCP_ENDPOINT)
1675
1804
  )
1805
+ {{/if}}
1676
1806
  "
1677
1807
  `;
1678
1808
 
1679
1809
  exports[`Assets Directory Snapshots > Python framework assets > python/python/googleadk/base/model/__init__.py should match snapshot 1`] = `
1680
- "
1810
+ "# Package marker
1681
1811
  "
1682
1812
  `;
1683
1813
 
@@ -1743,6 +1873,8 @@ dependencies = [
1743
1873
  "google-adk >= 1.17.0",
1744
1874
  "bedrock-agentcore >= 1.0.3",
1745
1875
  "botocore[crt] >= 1.35.0",
1876
+ {{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
1877
+ {{/if}}{{/if}}
1746
1878
  ]
1747
1879
 
1748
1880
  [tool.hatch.build.targets.wheel]
@@ -1755,25 +1887,23 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/la
1755
1887
 
1756
1888
  # Layout
1757
1889
 
1758
- There is one directory with generated application code, \`src/\` . At the root, there is a \`.gitignore\` file, a
1759
- \`.agentcore\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
1890
+ The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
1891
+ \`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
1760
1892
  commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
1761
1893
 
1762
- ## src/
1894
+ ## Agent Root
1763
1895
 
1764
- The main entrypoint to your app is defined in \`src/main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
1896
+ The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
1765
1897
  file defines a Starlette ASGI app with the LangChain/LangGraph framework running within.
1766
1898
 
1767
- \`src/model/load.py\` instantiates your chosen model provider.
1899
+ \`model/load.py\` instantiates your chosen model provider.
1768
1900
 
1769
1901
  ## Environment Variables
1770
1902
 
1771
- | Variable | Required | Description |
1772
- | ------------------------------ | --------------- | ---------------------------------------------------------------- |
1773
- | \`AGENTCORE_IDENTITY_OPENAI\` | Yes (OpenAI) | OpenAI API key (local) or Identity provider name (deployed) |
1774
- | \`AGENTCORE_IDENTITY_ANTHROPIC\` | Yes (Anthropic) | Anthropic API key (local) or Identity provider name (deployed) |
1775
- | \`AGENTCORE_IDENTITY_GEMINI\` | Yes (Gemini) | Gemini API key (local) or Identity provider name (deployed) |
1776
- | \`LOCAL_DEV\` | No | Set to \`1\` to use \`agentcore/.env\` instead of AgentCore Identity |
1903
+ | Variable | Required | Description |
1904
+ | --- | --- | --- |
1905
+ {{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
1906
+ {{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
1777
1907
 
1778
1908
  # Developing locally
1779
1909
 
@@ -1847,7 +1977,11 @@ from langgraph.prebuilt import create_react_agent
1847
1977
  from langchain.tools import tool
1848
1978
  from bedrock_agentcore.runtime import BedrockAgentCoreApp
1849
1979
  from model.load import load_model
1980
+ {{#if hasGateway}}
1981
+ from mcp_client.client import get_all_gateway_mcp_client
1982
+ {{else}}
1850
1983
  from mcp_client.client import get_streamable_http_mcp_client
1984
+ {{/if}}
1851
1985
 
1852
1986
  app = BedrockAgentCoreApp()
1853
1987
  log = app.logger
@@ -1877,10 +2011,16 @@ async def invoke(payload, context):
1877
2011
  log.info("Invoking Agent.....")
1878
2012
 
1879
2013
  # Get MCP Client
2014
+ {{#if hasGateway}}
2015
+ mcp_client = get_all_gateway_mcp_client()
2016
+ {{else}}
1880
2017
  mcp_client = get_streamable_http_mcp_client()
2018
+ {{/if}}
1881
2019
 
1882
2020
  # Load MCP Tools
1883
- mcp_tools = await mcp_client.get_tools()
2021
+ mcp_tools = []
2022
+ if mcp_client:
2023
+ mcp_tools = await mcp_client.get_tools()
1884
2024
 
1885
2025
  # Define the agent using create_react_agent
1886
2026
  graph = create_react_agent(get_or_create_model(), tools=mcp_tools + tools)
@@ -1901,21 +2041,69 @@ if __name__ == "__main__":
1901
2041
  `;
1902
2042
 
1903
2043
  exports[`Assets Directory Snapshots > Python framework assets > python/python/langchain_langgraph/base/mcp_client/__init__.py should match snapshot 1`] = `
1904
- "
2044
+ "# Package marker
1905
2045
  "
1906
2046
  `;
1907
2047
 
1908
2048
  exports[`Assets Directory Snapshots > Python framework assets > python/python/langchain_langgraph/base/mcp_client/client.py should match snapshot 1`] = `
1909
- "from langchain_mcp_adapters.client import MultiServerMCPClient
2049
+ "import os
2050
+ import logging
2051
+ from langchain_mcp_adapters.client import MultiServerMCPClient
2052
+
2053
+ logger = logging.getLogger(__name__)
2054
+
2055
+ {{#if hasGateway}}
2056
+ {{#if (includes gatewayAuthTypes "AWS_IAM")}}
2057
+ from mcp_proxy_for_aws.sigv4_helper import SigV4HTTPXAuth, create_aws_session
2058
+ {{/if}}
2059
+ {{#if (includes gatewayAuthTypes "CUSTOM_JWT")}}
2060
+ from bedrock_agentcore.identity import requires_access_token
2061
+ {{/if}}
2062
+
2063
+ {{#each gatewayProviders}}
2064
+ {{#if (eq authType "CUSTOM_JWT")}}
2065
+ @requires_access_token(
2066
+ provider_name="{{credentialProviderName}}",
2067
+ scopes=[{{#if scopes}}"{{scopes}}"{{/if}}],
2068
+ auth_flow="M2M",
2069
+ )
2070
+ def _get_bearer_token_{{snakeCase name}}(*, access_token: str):
2071
+ """Obtain OAuth access token via AgentCore Identity for {{name}}."""
2072
+ return access_token
1910
2073
 
2074
+ {{/if}}
2075
+ {{/each}}
2076
+
2077
+ def get_all_gateway_mcp_client() -> MultiServerMCPClient | None:
2078
+ """Returns an MCP Client connected to all configured gateways."""
2079
+ servers = {}
2080
+ {{#each gatewayProviders}}
2081
+ url = os.environ.get("{{envVarName}}")
2082
+ if url:
2083
+ {{#if (eq authType "AWS_IAM")}}
2084
+ session = create_aws_session()
2085
+ auth = SigV4HTTPXAuth(session.get_credentials(), "bedrock-agentcore", session.region_name)
2086
+ servers["{{name}}"] = {"transport": "streamable_http", "url": url, "auth": auth}
2087
+ {{else if (eq authType "CUSTOM_JWT")}}
2088
+ token = _get_bearer_token_{{snakeCase name}}()
2089
+ headers = {"Authorization": f"Bearer {token}"} if token else None
2090
+ servers["{{name}}"] = {"transport": "streamable_http", "url": url, "headers": headers}
2091
+ {{else}}
2092
+ servers["{{name}}"] = {"transport": "streamable_http", "url": url}
2093
+ {{/if}}
2094
+ else:
2095
+ logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
2096
+ {{/each}}
2097
+ if not servers:
2098
+ return None
2099
+ return MultiServerMCPClient(servers)
2100
+ {{else}}
1911
2101
  # ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
1912
2102
  EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
1913
2103
 
1914
2104
 
1915
2105
  def get_streamable_http_mcp_client() -> MultiServerMCPClient:
1916
- """
1917
- Returns an MCP Client compatible with LangChain/LangGraph.
1918
- """
2106
+ """Returns an MCP Client compatible with LangChain/LangGraph."""
1919
2107
  # to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
1920
2108
  return MultiServerMCPClient(
1921
2109
  {
@@ -1925,11 +2113,12 @@ def get_streamable_http_mcp_client() -> MultiServerMCPClient:
1925
2113
  }
1926
2114
  }
1927
2115
  )
2116
+ {{/if}}
1928
2117
  "
1929
2118
  `;
1930
2119
 
1931
2120
  exports[`Assets Directory Snapshots > Python framework assets > python/python/langchain_langgraph/base/model/__init__.py should match snapshot 1`] = `
1932
- "
2121
+ "# Package marker
1933
2122
  "
1934
2123
  `;
1935
2124
 
@@ -2078,7 +2267,6 @@ dependencies = [
2078
2267
  "mcp >= 1.19.0",
2079
2268
  "langchain-mcp-adapters >= 0.1.11",
2080
2269
  "langchain >= 1.0.3",
2081
- "tiktoken == 0.11.0",
2082
2270
  "bedrock-agentcore >= 1.0.3",
2083
2271
  "botocore[crt] >= 1.35.0",
2084
2272
  {{#if (eq modelProvider "Bedrock")}}
@@ -2093,6 +2281,8 @@ dependencies = [
2093
2281
  {{#if (eq modelProvider "Gemini")}}
2094
2282
  "langchain-google-genai >= 3.0.3",
2095
2283
  {{/if}}
2284
+ {{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
2285
+ {{/if}}{{/if}}
2096
2286
  ]
2097
2287
 
2098
2288
  [tool.hatch.build.targets.wheel]
@@ -2105,23 +2295,23 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/op
2105
2295
 
2106
2296
  # Layout
2107
2297
 
2108
- There is one directory with generated application code, \`src/\` . At the root, there is a \`.gitignore\` file, a
2109
- \`.agentcore\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
2298
+ The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
2299
+ \`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
2110
2300
  commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
2111
2301
 
2112
- ## src/
2302
+ ## Agent Root
2113
2303
 
2114
- The main entrypoint to your app is defined in \`src/main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
2304
+ The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
2115
2305
  file defines a Starlette ASGI app with the OpenAI Agents SDK framework running within.
2116
2306
 
2117
- \`src/model/load.py\` instantiates your chosen model provider (OpenAI).
2307
+ \`model/load.py\` instantiates your chosen model provider (OpenAI).
2118
2308
 
2119
2309
  ## Environment Variables
2120
2310
 
2121
- | Variable | Required | Description |
2122
- | --------------------------- | -------- | ---------------------------------------------------------------- |
2123
- | \`AGENTCORE_IDENTITY_OPENAI\` | Yes | OpenAI API key (local) or Identity provider name (deployed) |
2124
- | \`LOCAL_DEV\` | No | Set to \`1\` to use \`agentcore/.env\` instead of AgentCore Identity |
2311
+ | Variable | Required | Description |
2312
+ | --- | --- | --- |
2313
+ {{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
2314
+ {{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
2125
2315
 
2126
2316
  # Developing locally
2127
2317
 
@@ -2193,13 +2383,22 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/op
2193
2383
  from agents import Agent, Runner, function_tool
2194
2384
  from bedrock_agentcore.runtime import BedrockAgentCoreApp
2195
2385
  from model.load import load_model
2386
+ {{#if hasGateway}}
2387
+ from mcp_client.client import get_all_gateway_mcp_servers
2388
+ {{else}}
2196
2389
  from mcp_client.client import get_streamable_http_mcp_client
2390
+ {{/if}}
2197
2391
 
2198
2392
  app = BedrockAgentCoreApp()
2199
2393
  log = app.logger
2200
2394
 
2201
2395
  # Get MCP Server
2396
+ {{#if hasGateway}}
2397
+ mcp_servers = get_all_gateway_mcp_servers()
2398
+ {{else}}
2202
2399
  mcp_server = get_streamable_http_mcp_client()
2400
+ mcp_servers = [mcp_server] if mcp_server else []
2401
+ {{/if}}
2203
2402
 
2204
2403
  _credentials_loaded = False
2205
2404
 
@@ -2221,16 +2420,47 @@ def add_numbers(a: int, b: int) -> int:
2221
2420
  async def main(query):
2222
2421
  ensure_credentials_loaded()
2223
2422
  try:
2224
- async with mcp_server as server:
2225
- active_servers = [server] if server else []
2423
+ {{#if hasGateway}}
2424
+ if mcp_servers:
2425
+ agent = Agent(
2426
+ name="{{ name }}",
2427
+ model="gpt-4.1",
2428
+ mcp_servers=mcp_servers,
2429
+ tools=[add_numbers]
2430
+ )
2431
+ result = await Runner.run(agent, query)
2432
+ return result
2433
+ else:
2434
+ agent = Agent(
2435
+ name="{{ name }}",
2436
+ model="gpt-4.1",
2437
+ mcp_servers=[],
2438
+ tools=[add_numbers]
2439
+ )
2440
+ result = await Runner.run(agent, query)
2441
+ return result
2442
+ {{else}}
2443
+ if mcp_servers:
2444
+ async with mcp_servers[0] as server:
2445
+ active_servers = [server]
2446
+ agent = Agent(
2447
+ name="{{ name }}",
2448
+ model="gpt-4.1",
2449
+ mcp_servers=active_servers,
2450
+ tools=[add_numbers]
2451
+ )
2452
+ result = await Runner.run(agent, query)
2453
+ return result
2454
+ else:
2226
2455
  agent = Agent(
2227
2456
  name="{{ name }}",
2228
2457
  model="gpt-4.1",
2229
- mcp_servers=active_servers,
2458
+ mcp_servers=[],
2230
2459
  tools=[add_numbers]
2231
2460
  )
2232
2461
  result = await Runner.run(agent, query)
2233
2462
  return result
2463
+ {{/if}}
2234
2464
  except Exception as e:
2235
2465
  log.error(f"Error during agent execution: {e}", exc_info=True)
2236
2466
  raise e
@@ -2256,30 +2486,81 @@ if __name__ == "__main__":
2256
2486
  `;
2257
2487
 
2258
2488
  exports[`Assets Directory Snapshots > Python framework assets > python/python/openaiagents/base/mcp_client/__init__.py should match snapshot 1`] = `
2259
- "
2489
+ "# Package marker
2260
2490
  "
2261
2491
  `;
2262
2492
 
2263
2493
  exports[`Assets Directory Snapshots > Python framework assets > python/python/openaiagents/base/mcp_client/client.py should match snapshot 1`] = `
2264
- "from agents.mcp import MCPServerStreamableHttp
2494
+ "import os
2495
+ import logging
2496
+ from agents.mcp import MCPServerStreamableHttp
2497
+
2498
+ logger = logging.getLogger(__name__)
2499
+
2500
+ {{#if hasGateway}}
2501
+ {{#if (includes gatewayAuthTypes "AWS_IAM")}}
2502
+ import httpx
2503
+ from mcp_proxy_for_aws.sigv4_helper import SigV4HTTPXAuth, create_aws_session
2504
+ {{/if}}
2505
+ {{#if (includes gatewayAuthTypes "CUSTOM_JWT")}}
2506
+ from bedrock_agentcore.identity import requires_access_token
2507
+ {{/if}}
2508
+
2509
+ {{#each gatewayProviders}}
2510
+ {{#if (eq authType "CUSTOM_JWT")}}
2511
+ @requires_access_token(
2512
+ provider_name="{{credentialProviderName}}",
2513
+ scopes=[{{#if scopes}}"{{scopes}}"{{/if}}],
2514
+ auth_flow="M2M",
2515
+ )
2516
+ def _get_bearer_token_{{snakeCase name}}(*, access_token: str):
2517
+ """Obtain OAuth access token via AgentCore Identity for {{name}}."""
2518
+ return access_token
2265
2519
 
2520
+ {{/if}}
2521
+ {{/each}}
2522
+
2523
+ def get_all_gateway_mcp_servers() -> list[MCPServerStreamableHttp]:
2524
+ """Returns MCP servers for all configured gateways."""
2525
+ servers = []
2526
+ {{#each gatewayProviders}}
2527
+ url = os.environ.get("{{envVarName}}")
2528
+ if url:
2529
+ {{#if (eq authType "AWS_IAM")}}
2530
+ session = create_aws_session()
2531
+ auth = SigV4HTTPXAuth(session.get_credentials(), "bedrock-agentcore", session.region_name)
2532
+ servers.append(MCPServerStreamableHttp(
2533
+ name="{{name}}",
2534
+ params={"url": url, "httpx_client_factory": lambda **kwargs: httpx.AsyncClient(auth=auth, **kwargs)}
2535
+ ))
2536
+ {{else if (eq authType "CUSTOM_JWT")}}
2537
+ token = _get_bearer_token_{{snakeCase name}}()
2538
+ headers = {"Authorization": f"Bearer {token}"} if token else {}
2539
+ servers.append(MCPServerStreamableHttp(name="{{name}}", params={"url": url, "headers": headers}))
2540
+ {{else}}
2541
+ servers.append(MCPServerStreamableHttp(name="{{name}}", params={"url": url}))
2542
+ {{/if}}
2543
+ else:
2544
+ logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
2545
+ {{/each}}
2546
+ return servers
2547
+ {{else}}
2266
2548
  # ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
2267
2549
  EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
2268
2550
 
2269
2551
 
2270
2552
  def get_streamable_http_mcp_client() -> MCPServerStreamableHttp:
2271
- """
2272
- Returns an MCP Client compatible with OpenAI Agents SDK.
2273
- """
2553
+ """Returns an MCP Client compatible with OpenAI Agents SDK."""
2274
2554
  # to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
2275
2555
  return MCPServerStreamableHttp(
2276
2556
  name="AgentCore Gateway MCP", params={"url": EXAMPLE_MCP_ENDPOINT}
2277
2557
  )
2558
+ {{/if}}
2278
2559
  "
2279
2560
  `;
2280
2561
 
2281
2562
  exports[`Assets Directory Snapshots > Python framework assets > python/python/openaiagents/base/model/__init__.py should match snapshot 1`] = `
2282
- "
2563
+ "# Package marker
2283
2564
  "
2284
2565
  `;
2285
2566
 
@@ -2340,6 +2621,8 @@ dependencies = [
2340
2621
  "openai-agents >= 0.4.2",
2341
2622
  "bedrock-agentcore >= 1.0.3",
2342
2623
  "botocore[crt] >= 1.35.0",
2624
+ {{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
2625
+ {{/if}}{{/if}}
2343
2626
  ]
2344
2627
 
2345
2628
  [tool.hatch.build.targets.wheel]
@@ -2348,29 +2631,27 @@ packages = ["."]
2348
2631
  `;
2349
2632
 
2350
2633
  exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/README.md should match snapshot 1`] = `
2351
- "This is a project generated by the agentcore create basic CLI tool!
2634
+ "This is a project generated by the AgentCore CLI!
2352
2635
 
2353
2636
  # Layout
2354
2637
 
2355
- There is one directory with generated application code, \`src/\` . At the root, there is a \`.gitignore\` file, a
2356
- \`.agentcore\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
2638
+ The generated application code lives at the agent root directory. At the root, there is a \`.gitignore\` file, an
2639
+ \`agentcore/\` folder which represents the configurations and state associated with this project. Other \`agentcore\`
2357
2640
  commands like \`deploy\`, \`dev\`, and \`invoke\` rely on the configuration stored here.
2358
2641
 
2359
- ## src/
2642
+ ## Agent Root
2360
2643
 
2361
- The main entrypoint to your app is defined in \`src/main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
2644
+ The main entrypoint to your app is defined in \`main.py\`. Using the AgentCore SDK \`@app.entrypoint\` decorator, this
2362
2645
  file defines a Starlette ASGI app with the chosen Agent framework SDK running within.
2363
2646
 
2364
- \`src/model/load.py\` instantiates your chosen model provider.
2647
+ \`model/load.py\` instantiates your chosen model provider.
2365
2648
 
2366
2649
  ## Environment Variables
2367
2650
 
2368
- | Variable | Required | Description |
2369
- | ------------------------------ | --------------- | ---------------------------------------------------------------- |
2370
- | \`AGENTCORE_IDENTITY_OPENAI\` | Yes (OpenAI) | OpenAI API key (local) or Identity provider name (deployed) |
2371
- | \`AGENTCORE_IDENTITY_ANTHROPIC\` | Yes (Anthropic) | Anthropic API key (local) or Identity provider name (deployed) |
2372
- | \`AGENTCORE_IDENTITY_GEMINI\` | Yes (Gemini) | Gemini API key (local) or Identity provider name (deployed) |
2373
- | \`LOCAL_DEV\` | No | Set to \`1\` to use \`agentcore/.env\` instead of AgentCore Identity |
2651
+ | Variable | Required | Description |
2652
+ | --- | --- | --- |
2653
+ {{#if hasIdentity}}| \`{{identityProviders.[0].envVarName}}\` | Yes | {{modelProvider}} API key (local) or Identity provider name (deployed) |
2654
+ {{/if}}| \`LOCAL_DEV\` | No | Set to \`1\` to use \`.env.local\` instead of AgentCore Identity |
2374
2655
 
2375
2656
  # Developing locally
2376
2657
 
@@ -2440,7 +2721,11 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/st
2440
2721
  "from strands import Agent, tool
2441
2722
  from bedrock_agentcore.runtime import BedrockAgentCoreApp
2442
2723
  from model.load import load_model
2724
+ {{#if hasGateway}}
2725
+ from mcp_client.client import get_all_gateway_mcp_clients
2726
+ {{else}}
2443
2727
  from mcp_client.client import get_streamable_http_mcp_client
2728
+ {{/if}}
2444
2729
  {{#if hasMemory}}
2445
2730
  from memory.session import get_memory_session_manager
2446
2731
  {{/if}}
@@ -2449,7 +2734,11 @@ app = BedrockAgentCoreApp()
2449
2734
  log = app.logger
2450
2735
 
2451
2736
  # Define a Streamable HTTP MCP Client
2452
- mcp_client = get_streamable_http_mcp_client()
2737
+ {{#if hasGateway}}
2738
+ mcp_clients = get_all_gateway_mcp_clients()
2739
+ {{else}}
2740
+ mcp_clients = [get_streamable_http_mcp_client()]
2741
+ {{/if}}
2453
2742
 
2454
2743
  # Define a collection of tools used by the model
2455
2744
  tools = []
@@ -2461,6 +2750,11 @@ def add_numbers(a: int, b: int) -> int:
2461
2750
  return a+b
2462
2751
  tools.append(add_numbers)
2463
2752
 
2753
+ # Add MCP client to tools if available
2754
+ for mcp_client in mcp_clients:
2755
+ if mcp_client:
2756
+ tools.append(mcp_client)
2757
+
2464
2758
 
2465
2759
  {{#if hasMemory}}
2466
2760
  def agent_factory():
@@ -2475,7 +2769,7 @@ def agent_factory():
2475
2769
  system_prompt="""
2476
2770
  You are a helpful assistant. Use tools when appropriate.
2477
2771
  """,
2478
- tools=tools+[mcp_client]
2772
+ tools=tools
2479
2773
  )
2480
2774
  return cache[key]
2481
2775
  return get_or_create_agent
@@ -2491,7 +2785,7 @@ def get_or_create_agent():
2491
2785
  system_prompt="""
2492
2786
  You are a helpful assistant. Use tools when appropriate.
2493
2787
  """,
2494
- tools=tools+[mcp_client]
2788
+ tools=tools
2495
2789
  )
2496
2790
  return _agent
2497
2791
  {{/if}}
@@ -2524,27 +2818,80 @@ if __name__ == "__main__":
2524
2818
  `;
2525
2819
 
2526
2820
  exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/mcp_client/__init__.py should match snapshot 1`] = `
2527
- "
2821
+ "# Package marker
2528
2822
  "
2529
2823
  `;
2530
2824
 
2531
2825
  exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/mcp_client/client.py should match snapshot 1`] = `
2532
- "from mcp.client.streamable_http import streamablehttp_client
2826
+ "import os
2827
+ import logging
2828
+ from mcp.client.streamable_http import streamablehttp_client
2533
2829
  from strands.tools.mcp.mcp_client import MCPClient
2534
2830
 
2831
+ logger = logging.getLogger(__name__)
2832
+
2833
+ {{#if hasGateway}}
2834
+ {{#if (includes gatewayAuthTypes "AWS_IAM")}}
2835
+ from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client
2836
+ {{/if}}
2837
+ {{#if (includes gatewayAuthTypes "CUSTOM_JWT")}}
2838
+ from bedrock_agentcore.identity import requires_access_token
2839
+ {{/if}}
2840
+
2841
+ {{#each gatewayProviders}}
2842
+ {{#if (eq authType "CUSTOM_JWT")}}
2843
+ @requires_access_token(
2844
+ provider_name="{{credentialProviderName}}",
2845
+ scopes=[{{#if scopes}}"{{scopes}}"{{/if}}],
2846
+ auth_flow="M2M",
2847
+ )
2848
+ def _get_bearer_token_{{snakeCase name}}(*, access_token: str):
2849
+ """Obtain OAuth access token via AgentCore Identity for {{name}}."""
2850
+ return access_token
2851
+
2852
+ {{/if}}
2853
+ {{/each}}
2854
+ {{#each gatewayProviders}}
2855
+ def get_{{snakeCase name}}_mcp_client() -> MCPClient | None:
2856
+ """Returns an MCP Client connected to the {{name}} gateway."""
2857
+ url = os.environ.get("{{envVarName}}")
2858
+ if not url:
2859
+ logger.warning("{{envVarName}} not set — {{name}} gateway tools unavailable")
2860
+ return None
2861
+ {{#if (eq authType "AWS_IAM")}}
2862
+ return MCPClient(lambda: aws_iam_streamablehttp_client(url, aws_service="bedrock-agentcore", aws_region=os.environ.get("AWS_REGION", os.environ.get("AWS_DEFAULT_REGION"))))
2863
+ {{else if (eq authType "CUSTOM_JWT")}}
2864
+ token = _get_bearer_token_{{snakeCase name}}()
2865
+ headers = {"Authorization": f"Bearer {token}"} if token else {}
2866
+ return MCPClient(lambda: streamablehttp_client(url, headers=headers))
2867
+ {{else}}
2868
+ return MCPClient(lambda: streamablehttp_client(url))
2869
+ {{/if}}
2870
+
2871
+ {{/each}}
2872
+ def get_all_gateway_mcp_clients() -> list[MCPClient]:
2873
+ """Returns MCP clients for all configured gateways."""
2874
+ clients = []
2875
+ {{#each gatewayProviders}}
2876
+ client = get_{{snakeCase name}}_mcp_client()
2877
+ if client:
2878
+ clients.append(client)
2879
+ {{/each}}
2880
+ return clients
2881
+ {{else}}
2535
2882
  # ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
2536
2883
  EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
2537
2884
 
2538
2885
  def get_streamable_http_mcp_client() -> MCPClient:
2539
- """
2540
- Returns an MCP Client compatible with Strands
2541
- """
2886
+ """Returns an MCP Client compatible with Strands"""
2542
2887
  # to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
2543
- return MCPClient(lambda: streamablehttp_client(EXAMPLE_MCP_ENDPOINT))"
2888
+ return MCPClient(lambda: streamablehttp_client(EXAMPLE_MCP_ENDPOINT))
2889
+ {{/if}}
2890
+ "
2544
2891
  `;
2545
2892
 
2546
2893
  exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/model/__init__.py should match snapshot 1`] = `
2547
- "
2894
+ "# Package marker
2548
2895
  "
2549
2896
  `;
2550
2897
 
@@ -2692,8 +3039,11 @@ dependencies = [
2692
3039
  "bedrock-agentcore >= 1.0.3",
2693
3040
  "botocore[crt] >= 1.35.0",
2694
3041
  {{#if (eq modelProvider "Gemini")}}"google-genai >= 1.0.0",
2695
- {{/if}}{{#if (eq modelProvider "OpenAI")}}"openai >= 1.0.0",
3042
+ {{/if}}"mcp >= 1.19.0",
3043
+ {{#if (eq modelProvider "OpenAI")}}"openai >= 1.0.0",
2696
3044
  {{/if}}"strands-agents >= 1.13.0",
3045
+ {{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
3046
+ {{/if}}{{/if}}
2697
3047
  ]
2698
3048
 
2699
3049
  [tool.hatch.build.targets.wheel]
@@ -2701,7 +3051,10 @@ packages = ["."]
2701
3051
  "
2702
3052
  `;
2703
3053
 
2704
- exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/capabilities/memory/__init__.py should match snapshot 1`] = `""`;
3054
+ exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/capabilities/memory/__init__.py should match snapshot 1`] = `
3055
+ "# Package marker
3056
+ "
3057
+ `;
2705
3058
 
2706
3059
  exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/capabilities/memory/session.py should match snapshot 1`] = `
2707
3060
  "import os