@aws/agentcore 0.3.0-preview.2.1 → 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 (60) hide show
  1. package/dist/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap +415 -58
  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 +7 -1
  9. package/dist/assets/python/googleadk/base/main.py +10 -1
  10. package/dist/assets/python/googleadk/base/mcp_client/client.py +54 -3
  11. package/dist/assets/python/googleadk/base/pyproject.toml +2 -0
  12. package/dist/assets/python/langchain_langgraph/base/main.py +11 -1
  13. package/dist/assets/python/langchain_langgraph/base/mcp_client/client.py +52 -3
  14. package/dist/assets/python/langchain_langgraph/base/pyproject.toml +2 -1
  15. package/dist/assets/python/openaiagents/base/main.py +43 -3
  16. package/dist/assets/python/openaiagents/base/mcp_client/client.py +54 -3
  17. package/dist/assets/python/openaiagents/base/pyproject.toml +2 -0
  18. package/dist/assets/python/strands/base/README.md +1 -1
  19. package/dist/assets/python/strands/base/main.py +16 -3
  20. package/dist/assets/python/strands/base/mcp_client/client.py +56 -4
  21. package/dist/assets/python/strands/base/pyproject.toml +2 -0
  22. package/dist/cli/index.mjs +290 -286
  23. package/dist/lib/packaging/build-args.d.ts +6 -0
  24. package/dist/lib/packaging/build-args.d.ts.map +1 -0
  25. package/dist/lib/packaging/build-args.js +18 -0
  26. package/dist/lib/packaging/build-args.js.map +1 -0
  27. package/dist/lib/packaging/container.d.ts.map +1 -1
  28. package/dist/lib/packaging/container.js +2 -1
  29. package/dist/lib/packaging/container.js.map +1 -1
  30. package/dist/lib/schemas/io/cli-config.d.ts +10 -0
  31. package/dist/lib/schemas/io/cli-config.d.ts.map +1 -0
  32. package/dist/lib/schemas/io/cli-config.js +27 -0
  33. package/dist/lib/schemas/io/cli-config.js.map +1 -0
  34. package/dist/lib/schemas/io/index.d.ts +1 -0
  35. package/dist/lib/schemas/io/index.d.ts.map +1 -1
  36. package/dist/lib/schemas/io/index.js +3 -1
  37. package/dist/lib/schemas/io/index.js.map +1 -1
  38. package/dist/lib/utils/subprocess.d.ts.map +1 -1
  39. package/dist/lib/utils/subprocess.js +32 -10
  40. package/dist/lib/utils/subprocess.js.map +1 -1
  41. package/dist/schema/constants.d.ts.map +1 -1
  42. package/dist/schema/constants.js +0 -1
  43. package/dist/schema/constants.js.map +1 -1
  44. package/dist/schema/schemas/agentcore-project.d.ts +48 -5
  45. package/dist/schema/schemas/agentcore-project.d.ts.map +1 -1
  46. package/dist/schema/schemas/agentcore-project.js +19 -4
  47. package/dist/schema/schemas/agentcore-project.js.map +1 -1
  48. package/dist/schema/schemas/aws-targets.js +1 -1
  49. package/dist/schema/schemas/aws-targets.js.map +1 -1
  50. package/dist/schema/schemas/deployed-state.d.ts +32 -0
  51. package/dist/schema/schemas/deployed-state.d.ts.map +1 -1
  52. package/dist/schema/schemas/deployed-state.js +11 -1
  53. package/dist/schema/schemas/deployed-state.js.map +1 -1
  54. package/dist/schema/schemas/mcp-defs.d.ts +1 -1
  55. package/dist/schema/schemas/mcp-defs.js +1 -1
  56. package/dist/schema/schemas/mcp.d.ts +146 -6
  57. package/dist/schema/schemas/mcp.d.ts.map +1 -1
  58. package/dist/schema/schemas/mcp.js +49 -4
  59. package/dist/schema/schemas/mcp.js.map +1 -1
  60. package/package.json +12 -6
@@ -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": ".",
@@ -1561,7 +1635,11 @@ from google.adk.sessions import InMemorySessionService
1561
1635
  from google.genai import types
1562
1636
  from bedrock_agentcore.runtime import BedrockAgentCoreApp
1563
1637
  from model.load import load_model
1638
+ {{#if hasGateway}}
1639
+ from mcp_client.client import get_all_gateway_mcp_toolsets
1640
+ {{else}}
1564
1641
  from mcp_client.client import get_streamable_http_mcp_client
1642
+ {{/if}}
1565
1643
 
1566
1644
  app = BedrockAgentCoreApp()
1567
1645
  log = app.logger
@@ -1579,7 +1657,12 @@ def add_numbers(a: int, b: int) -> int:
1579
1657
 
1580
1658
 
1581
1659
  # Get MCP Toolset
1582
- 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}}
1583
1666
 
1584
1667
  _credentials_loaded = False
1585
1668
 
@@ -1654,21 +1737,72 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/go
1654
1737
  `;
1655
1738
 
1656
1739
  exports[`Assets Directory Snapshots > Python framework assets > python/python/googleadk/base/mcp_client/client.py should match snapshot 1`] = `
1657
- "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
1658
1743
  from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
1659
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}}
1660
1795
  # ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
1661
1796
  EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
1662
1797
 
1663
1798
 
1664
1799
  def get_streamable_http_mcp_client() -> MCPToolset:
1665
- """
1666
- Returns an MCP Toolset compatible with Google ADK.
1667
- """
1800
+ """Returns an MCP Toolset compatible with Google ADK."""
1668
1801
  # to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
1669
1802
  return MCPToolset(
1670
1803
  connection_params=StreamableHTTPConnectionParams(url=EXAMPLE_MCP_ENDPOINT)
1671
1804
  )
1805
+ {{/if}}
1672
1806
  "
1673
1807
  `;
1674
1808
 
@@ -1739,6 +1873,8 @@ dependencies = [
1739
1873
  "google-adk >= 1.17.0",
1740
1874
  "bedrock-agentcore >= 1.0.3",
1741
1875
  "botocore[crt] >= 1.35.0",
1876
+ {{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
1877
+ {{/if}}{{/if}}
1742
1878
  ]
1743
1879
 
1744
1880
  [tool.hatch.build.targets.wheel]
@@ -1841,7 +1977,11 @@ from langgraph.prebuilt import create_react_agent
1841
1977
  from langchain.tools import tool
1842
1978
  from bedrock_agentcore.runtime import BedrockAgentCoreApp
1843
1979
  from model.load import load_model
1980
+ {{#if hasGateway}}
1981
+ from mcp_client.client import get_all_gateway_mcp_client
1982
+ {{else}}
1844
1983
  from mcp_client.client import get_streamable_http_mcp_client
1984
+ {{/if}}
1845
1985
 
1846
1986
  app = BedrockAgentCoreApp()
1847
1987
  log = app.logger
@@ -1871,10 +2011,16 @@ async def invoke(payload, context):
1871
2011
  log.info("Invoking Agent.....")
1872
2012
 
1873
2013
  # Get MCP Client
2014
+ {{#if hasGateway}}
2015
+ mcp_client = get_all_gateway_mcp_client()
2016
+ {{else}}
1874
2017
  mcp_client = get_streamable_http_mcp_client()
2018
+ {{/if}}
1875
2019
 
1876
2020
  # Load MCP Tools
1877
- mcp_tools = await mcp_client.get_tools()
2021
+ mcp_tools = []
2022
+ if mcp_client:
2023
+ mcp_tools = await mcp_client.get_tools()
1878
2024
 
1879
2025
  # Define the agent using create_react_agent
1880
2026
  graph = create_react_agent(get_or_create_model(), tools=mcp_tools + tools)
@@ -1900,16 +2046,64 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/la
1900
2046
  `;
1901
2047
 
1902
2048
  exports[`Assets Directory Snapshots > Python framework assets > python/python/langchain_langgraph/base/mcp_client/client.py should match snapshot 1`] = `
1903
- "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
1904
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}}
1905
2101
  # ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
1906
2102
  EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
1907
2103
 
1908
2104
 
1909
2105
  def get_streamable_http_mcp_client() -> MultiServerMCPClient:
1910
- """
1911
- Returns an MCP Client compatible with LangChain/LangGraph.
1912
- """
2106
+ """Returns an MCP Client compatible with LangChain/LangGraph."""
1913
2107
  # to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
1914
2108
  return MultiServerMCPClient(
1915
2109
  {
@@ -1919,6 +2113,7 @@ def get_streamable_http_mcp_client() -> MultiServerMCPClient:
1919
2113
  }
1920
2114
  }
1921
2115
  )
2116
+ {{/if}}
1922
2117
  "
1923
2118
  `;
1924
2119
 
@@ -2072,7 +2267,6 @@ dependencies = [
2072
2267
  "mcp >= 1.19.0",
2073
2268
  "langchain-mcp-adapters >= 0.1.11",
2074
2269
  "langchain >= 1.0.3",
2075
- "tiktoken == 0.11.0",
2076
2270
  "bedrock-agentcore >= 1.0.3",
2077
2271
  "botocore[crt] >= 1.35.0",
2078
2272
  {{#if (eq modelProvider "Bedrock")}}
@@ -2087,6 +2281,8 @@ dependencies = [
2087
2281
  {{#if (eq modelProvider "Gemini")}}
2088
2282
  "langchain-google-genai >= 3.0.3",
2089
2283
  {{/if}}
2284
+ {{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
2285
+ {{/if}}{{/if}}
2090
2286
  ]
2091
2287
 
2092
2288
  [tool.hatch.build.targets.wheel]
@@ -2187,13 +2383,22 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/op
2187
2383
  from agents import Agent, Runner, function_tool
2188
2384
  from bedrock_agentcore.runtime import BedrockAgentCoreApp
2189
2385
  from model.load import load_model
2386
+ {{#if hasGateway}}
2387
+ from mcp_client.client import get_all_gateway_mcp_servers
2388
+ {{else}}
2190
2389
  from mcp_client.client import get_streamable_http_mcp_client
2390
+ {{/if}}
2191
2391
 
2192
2392
  app = BedrockAgentCoreApp()
2193
2393
  log = app.logger
2194
2394
 
2195
2395
  # Get MCP Server
2396
+ {{#if hasGateway}}
2397
+ mcp_servers = get_all_gateway_mcp_servers()
2398
+ {{else}}
2196
2399
  mcp_server = get_streamable_http_mcp_client()
2400
+ mcp_servers = [mcp_server] if mcp_server else []
2401
+ {{/if}}
2197
2402
 
2198
2403
  _credentials_loaded = False
2199
2404
 
@@ -2215,16 +2420,47 @@ def add_numbers(a: int, b: int) -> int:
2215
2420
  async def main(query):
2216
2421
  ensure_credentials_loaded()
2217
2422
  try:
2218
- async with mcp_server as server:
2219
- active_servers = [server] if server else []
2423
+ {{#if hasGateway}}
2424
+ if mcp_servers:
2220
2425
  agent = Agent(
2221
2426
  name="{{ name }}",
2222
2427
  model="gpt-4.1",
2223
- mcp_servers=active_servers,
2428
+ mcp_servers=mcp_servers,
2224
2429
  tools=[add_numbers]
2225
2430
  )
2226
2431
  result = await Runner.run(agent, query)
2227
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:
2455
+ agent = Agent(
2456
+ name="{{ name }}",
2457
+ model="gpt-4.1",
2458
+ mcp_servers=[],
2459
+ tools=[add_numbers]
2460
+ )
2461
+ result = await Runner.run(agent, query)
2462
+ return result
2463
+ {{/if}}
2228
2464
  except Exception as e:
2229
2465
  log.error(f"Error during agent execution: {e}", exc_info=True)
2230
2466
  raise e
@@ -2255,20 +2491,71 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/op
2255
2491
  `;
2256
2492
 
2257
2493
  exports[`Assets Directory Snapshots > Python framework assets > python/python/openaiagents/base/mcp_client/client.py should match snapshot 1`] = `
2258
- "from agents.mcp import MCPServerStreamableHttp
2494
+ "import os
2495
+ import logging
2496
+ from agents.mcp import MCPServerStreamableHttp
2259
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
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}}
2260
2548
  # ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
2261
2549
  EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
2262
2550
 
2263
2551
 
2264
2552
  def get_streamable_http_mcp_client() -> MCPServerStreamableHttp:
2265
- """
2266
- Returns an MCP Client compatible with OpenAI Agents SDK.
2267
- """
2553
+ """Returns an MCP Client compatible with OpenAI Agents SDK."""
2268
2554
  # to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
2269
2555
  return MCPServerStreamableHttp(
2270
2556
  name="AgentCore Gateway MCP", params={"url": EXAMPLE_MCP_ENDPOINT}
2271
2557
  )
2558
+ {{/if}}
2272
2559
  "
2273
2560
  `;
2274
2561
 
@@ -2334,6 +2621,8 @@ dependencies = [
2334
2621
  "openai-agents >= 0.4.2",
2335
2622
  "bedrock-agentcore >= 1.0.3",
2336
2623
  "botocore[crt] >= 1.35.0",
2624
+ {{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
2625
+ {{/if}}{{/if}}
2337
2626
  ]
2338
2627
 
2339
2628
  [tool.hatch.build.targets.wheel]
@@ -2342,7 +2631,7 @@ packages = ["."]
2342
2631
  `;
2343
2632
 
2344
2633
  exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/README.md should match snapshot 1`] = `
2345
- "This is a project generated by the agentcore create basic CLI tool!
2634
+ "This is a project generated by the AgentCore CLI!
2346
2635
 
2347
2636
  # Layout
2348
2637
 
@@ -2432,7 +2721,11 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/st
2432
2721
  "from strands import Agent, tool
2433
2722
  from bedrock_agentcore.runtime import BedrockAgentCoreApp
2434
2723
  from model.load import load_model
2724
+ {{#if hasGateway}}
2725
+ from mcp_client.client import get_all_gateway_mcp_clients
2726
+ {{else}}
2435
2727
  from mcp_client.client import get_streamable_http_mcp_client
2728
+ {{/if}}
2436
2729
  {{#if hasMemory}}
2437
2730
  from memory.session import get_memory_session_manager
2438
2731
  {{/if}}
@@ -2441,7 +2734,11 @@ app = BedrockAgentCoreApp()
2441
2734
  log = app.logger
2442
2735
 
2443
2736
  # Define a Streamable HTTP MCP Client
2444
- 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}}
2445
2742
 
2446
2743
  # Define a collection of tools used by the model
2447
2744
  tools = []
@@ -2453,6 +2750,11 @@ def add_numbers(a: int, b: int) -> int:
2453
2750
  return a+b
2454
2751
  tools.append(add_numbers)
2455
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
+
2456
2758
 
2457
2759
  {{#if hasMemory}}
2458
2760
  def agent_factory():
@@ -2467,7 +2769,7 @@ def agent_factory():
2467
2769
  system_prompt="""
2468
2770
  You are a helpful assistant. Use tools when appropriate.
2469
2771
  """,
2470
- tools=tools+[mcp_client]
2772
+ tools=tools
2471
2773
  )
2472
2774
  return cache[key]
2473
2775
  return get_or_create_agent
@@ -2483,7 +2785,7 @@ def get_or_create_agent():
2483
2785
  system_prompt="""
2484
2786
  You are a helpful assistant. Use tools when appropriate.
2485
2787
  """,
2486
- tools=tools+[mcp_client]
2788
+ tools=tools
2487
2789
  )
2488
2790
  return _agent
2489
2791
  {{/if}}
@@ -2521,18 +2823,71 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/st
2521
2823
  `;
2522
2824
 
2523
2825
  exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/mcp_client/client.py should match snapshot 1`] = `
2524
- "from mcp.client.streamable_http import streamablehttp_client
2826
+ "import os
2827
+ import logging
2828
+ from mcp.client.streamable_http import streamablehttp_client
2525
2829
  from strands.tools.mcp.mcp_client import MCPClient
2526
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}}
2527
2882
  # ExaAI provides information about code through web searches, crawling and code context searches through their platform. Requires no authentication
2528
2883
  EXAMPLE_MCP_ENDPOINT = "https://mcp.exa.ai/mcp"
2529
2884
 
2530
2885
  def get_streamable_http_mcp_client() -> MCPClient:
2531
- """
2532
- Returns an MCP Client compatible with Strands
2533
- """
2886
+ """Returns an MCP Client compatible with Strands"""
2534
2887
  # to use an MCP server that supports bearer authentication, add headers={"Authorization": f"Bearer {access_token}"}
2535
- return MCPClient(lambda: streamablehttp_client(EXAMPLE_MCP_ENDPOINT))"
2888
+ return MCPClient(lambda: streamablehttp_client(EXAMPLE_MCP_ENDPOINT))
2889
+ {{/if}}
2890
+ "
2536
2891
  `;
2537
2892
 
2538
2893
  exports[`Assets Directory Snapshots > Python framework assets > python/python/strands/base/model/__init__.py should match snapshot 1`] = `
@@ -2687,6 +3042,8 @@ dependencies = [
2687
3042
  {{/if}}"mcp >= 1.19.0",
2688
3043
  {{#if (eq modelProvider "OpenAI")}}"openai >= 1.0.0",
2689
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}}
2690
3047
  ]
2691
3048
 
2692
3049
  [tool.hatch.build.targets.wheel]