@aws/nx-plugin-mcp 1.0.0-rc.4 → 1.0.0-rc.41

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 (163) hide show
  1. package/bin/aws-nx-mcp.js +2240 -1030
  2. package/docs/get_started/building-with-ai.mdx +116 -0
  3. package/docs/get_started/concepts.mdx +52 -0
  4. package/docs/get_started/existing-project.mdx +176 -0
  5. package/docs/get_started/quick-start.mdx +266 -0
  6. package/docs/get_started/tutorials/contribute-generator.mdx +405 -0
  7. package/docs/get_started/tutorials/dungeon-game/1.mdx +1205 -0
  8. package/docs/get_started/tutorials/dungeon-game/2.mdx +237 -0
  9. package/docs/get_started/tutorials/dungeon-game/3.mdx +76 -0
  10. package/docs/get_started/tutorials/dungeon-game/4.mdx +162 -0
  11. package/docs/get_started/tutorials/dungeon-game/overview.mdx +144 -0
  12. package/docs/get_started/tutorials/dungeon-game/wrap-up.mdx +41 -0
  13. package/docs/get_started/tutorials/existing-project.mdx +4 -0
  14. package/docs/guides/agentcore-gateway.mdx +376 -0
  15. package/docs/guides/connection/agentcore-gateway-gateway.mdx +154 -0
  16. package/docs/guides/connection/agentcore-gateway-mcp.mdx +134 -0
  17. package/docs/guides/connection/py-agent-a2a.mdx +47 -15
  18. package/docs/guides/connection/py-agent-dynamodb.mdx +116 -0
  19. package/docs/guides/connection/py-agent-gateway.mdx +176 -0
  20. package/docs/guides/connection/py-agent-mcp.mdx +42 -13
  21. package/docs/guides/connection/py-agent-rdb.mdx +178 -0
  22. package/docs/guides/connection/py-fast-api-dynamodb.mdx +56 -0
  23. package/docs/guides/connection/py-fast-api-rdb.mdx +184 -0
  24. package/docs/guides/connection/py-mcp-server-dynamodb.mdx +116 -0
  25. package/docs/guides/connection/py-mcp-server-rdb.mdx +187 -0
  26. package/docs/guides/connection/react-agui.mdx +4 -4
  27. package/docs/guides/connection/react-fastapi.mdx +38 -2
  28. package/docs/guides/connection/react-py-agent.mdx +7 -13
  29. package/docs/guides/connection/react-smithy.mdx +3 -3
  30. package/docs/guides/connection/react-trpc.mdx +1 -1
  31. package/docs/guides/connection/react-ts-agent.mdx +8 -8
  32. package/docs/guides/connection/smithy-dynamodb.mdx +4 -4
  33. package/docs/guides/connection/smithy-rdb.mdx +5 -5
  34. package/docs/guides/connection/trpc-dynamodb.mdx +4 -4
  35. package/docs/guides/connection/trpc-rdb.mdx +5 -5
  36. package/docs/guides/connection/ts-agent-a2a.mdx +12 -9
  37. package/docs/guides/connection/ts-agent-dynamodb.mdx +3 -3
  38. package/docs/guides/connection/ts-agent-gateway.mdx +141 -0
  39. package/docs/guides/connection/ts-agent-mcp.mdx +11 -8
  40. package/docs/guides/connection/ts-agent-rdb.mdx +66 -21
  41. package/docs/guides/connection/ts-mcp-server-dynamodb.mdx +3 -3
  42. package/docs/guides/connection/ts-mcp-server-rdb.mdx +66 -16
  43. package/docs/guides/connection.mdx +104 -5
  44. package/docs/guides/docker-bundling.mdx +68 -8
  45. package/docs/guides/fastapi.mdx +244 -4
  46. package/docs/guides/license.mdx +264 -109
  47. package/docs/guides/local-development.mdx +87 -0
  48. package/docs/guides/nx-generator.mdx +7 -2
  49. package/docs/guides/py-agent.mdx +257 -49
  50. package/docs/guides/py-dynamodb.mdx +476 -0
  51. package/docs/guides/py-mcp-server.mdx +61 -2
  52. package/docs/guides/py-rdb.mdx +254 -0
  53. package/docs/guides/react-website-auth.mdx +58 -1
  54. package/docs/guides/react-website.mdx +130 -19
  55. package/docs/guides/security.mdx +75 -0
  56. package/docs/guides/terraform-project.mdx +1 -1
  57. package/docs/guides/trpc.mdx +45 -9
  58. package/docs/guides/ts-agent.mdx +149 -9
  59. package/docs/guides/ts-dynamodb.mdx +62 -239
  60. package/docs/guides/ts-mcp-server.mdx +66 -3
  61. package/docs/guides/ts-nx-plugin.mdx +1 -1
  62. package/docs/guides/ts-rdb.mdx +117 -470
  63. package/docs/guides/ts-smithy-api.mdx +183 -4
  64. package/docs/guides/typescript-infrastructure.mdx +9 -1
  65. package/docs/guides/typescript-project.mdx +5 -10
  66. package/docs/guides/workspace.mdx +2 -2
  67. package/docs/snippets/agent/architecture.mdx +1 -1
  68. package/docs/snippets/agent/bedrock-deployment.mdx +4 -0
  69. package/docs/snippets/agent/runtime-arn.mdx +21 -0
  70. package/docs/snippets/agent/securing-your-agent.mdx +39 -0
  71. package/docs/snippets/api/access-logging.mdx +33 -0
  72. package/docs/snippets/api/type-safe-api-integrations.mdx +31 -0
  73. package/docs/snippets/api/waf-configuration.mdx +1 -1
  74. package/docs/snippets/connection/dynamodb-local-development.mdx +2 -2
  75. package/docs/snippets/connection/py-dynamodb-local-development.mdx +7 -0
  76. package/docs/snippets/connection/py-lambda-rdb-ssl-requirements.mdx +7 -0
  77. package/docs/snippets/connection/rdb-api-infrastructure.mdx +50 -18
  78. package/docs/snippets/dynamodb/deploying-table.mdx +166 -0
  79. package/docs/snippets/dynamodb/gsi-config.mdx +38 -0
  80. package/docs/snippets/dynamodb/infrastructure.mdx +33 -0
  81. package/docs/snippets/dynamodb/local-dev-start.mdx +13 -0
  82. package/docs/snippets/dynamodb/local-dev-windows.mdx +15 -0
  83. package/docs/snippets/mcp/architecture.mdx +1 -1
  84. package/docs/snippets/mcp/bedrock-deployment.mdx +4 -0
  85. package/docs/snippets/mcp/config.mdx +3 -2
  86. package/docs/snippets/rdb/architecture.mdx +38 -0
  87. package/docs/snippets/rdb/cluster-instances.mdx +31 -0
  88. package/docs/snippets/rdb/deletion-protection.mdx +34 -0
  89. package/docs/snippets/rdb/deploying.mdx +187 -0
  90. package/docs/snippets/rdb/encryption-key-rotation.mdx +30 -0
  91. package/docs/snippets/rdb/engine-version.mdx +63 -0
  92. package/docs/snippets/rdb/infrastructure.mdx +35 -0
  93. package/docs/snippets/rdb/logging.mdx +32 -0
  94. package/docs/snippets/rdb/rds-proxy.mdx +50 -0
  95. package/docs/snippets/rdb/removal-policy.mdx +57 -0
  96. package/docs/snippets/rdb/serverless-capacity.mdx +32 -0
  97. package/docs/snippets/required-prerequisites.mdx +1 -1
  98. package/docs/snippets/trivy-image-scan.mdx +27 -0
  99. package/generators.json +101 -2
  100. package/package.json +1 -1
  101. package/src/agentcore-gateway/gateway-connection/schema.json +31 -0
  102. package/src/agentcore-gateway/mcp-connection/schema.json +31 -0
  103. package/src/agentcore-gateway/schema.json +70 -0
  104. package/src/connection/schema.json +5 -0
  105. package/src/infra/app/schema.json +5 -0
  106. package/src/init/schema.json +35 -0
  107. package/src/license/schema.json +11 -0
  108. package/src/preset/schema.json +11 -5
  109. package/src/py/agent/a2a-connection/schema.json +5 -0
  110. package/src/py/agent/gateway-connection/schema.json +31 -0
  111. package/src/py/agent/mcp-connection/schema.json +5 -0
  112. package/src/py/agent/react-connection/schema.json +5 -0
  113. package/src/py/agent/schema.json +6 -1
  114. package/src/py/api/schema.json +5 -0
  115. package/src/py/dynamodb/agent-connection/schema.json +27 -0
  116. package/src/py/dynamodb/fast-api-connection/schema.json +23 -0
  117. package/src/py/dynamodb/mcp-server-connection/schema.json +27 -0
  118. package/src/py/dynamodb/schema.json +75 -0
  119. package/src/py/fast-api/react/schema.json +5 -0
  120. package/src/py/fast-api/schema.json +5 -0
  121. package/src/py/lambda-function/schema.json +5 -0
  122. package/src/py/mcp-server/schema.json +5 -0
  123. package/src/py/project/schema.json +5 -0
  124. package/src/py/rdb/agent-connection/schema.json +27 -0
  125. package/src/py/rdb/fast-api-connection/schema.json +23 -0
  126. package/src/py/rdb/mcp-server-connection/schema.json +27 -0
  127. package/src/py/rdb/schema.json +77 -0
  128. package/src/smithy/project/schema.json +5 -0
  129. package/src/smithy/react-connection/schema.json +5 -0
  130. package/src/smithy/ts/api/schema.json +5 -0
  131. package/src/terraform/project/schema.json +5 -0
  132. package/src/trpc/backend/schema.json +5 -0
  133. package/src/trpc/react/schema.json +5 -0
  134. package/src/ts/agent/a2a-connection/schema.json +5 -0
  135. package/src/ts/agent/gateway-connection/schema.json +31 -0
  136. package/src/ts/agent/mcp-connection/schema.json +5 -0
  137. package/src/ts/agent/react-connection/schema.json +5 -0
  138. package/src/ts/agent/schema.json +5 -0
  139. package/src/ts/api/schema.json +5 -0
  140. package/src/ts/astro-docs/schema.json +3 -3
  141. package/src/ts/docs/schema.json +3 -3
  142. package/src/ts/dynamodb/agent-connection/schema.json +5 -0
  143. package/src/ts/dynamodb/mcp-server-connection/schema.json +5 -0
  144. package/src/ts/dynamodb/schema.json +25 -2
  145. package/src/ts/dynamodb/smithy-connection/schema.json +5 -0
  146. package/src/ts/dynamodb/trpc-connection/schema.json +5 -0
  147. package/src/ts/lambda-function/schema.json +5 -0
  148. package/src/ts/lib/schema.json +5 -0
  149. package/src/ts/mcp-server/schema.json +5 -0
  150. package/src/ts/nx-generator/schema.json +5 -0
  151. package/src/ts/nx-plugin/schema.json +5 -0
  152. package/src/ts/rdb/agent-connection/schema.json +5 -0
  153. package/src/ts/rdb/mcp-server-connection/schema.json +5 -0
  154. package/src/ts/rdb/schema.json +6 -1
  155. package/src/ts/rdb/smithy-connection/schema.json +5 -0
  156. package/src/ts/rdb/trpc-connection/schema.json +5 -0
  157. package/src/ts/react-website/app/schema.json +11 -6
  158. package/src/ts/react-website/cognito-auth/schema.json +5 -0
  159. package/src/ts/react-website/runtime-config/schema.json +5 -0
  160. package/src/ts/website/app/schema.json +11 -6
  161. package/src/ts/website/auth/schema.json +5 -0
  162. /package/docs/snippets/connection/{lambda-rdb-ssl-requirements.mdx → ts-lambda-rdb-ssl-requirements.mdx} +0 -0
  163. /package/docs/snippets/connection/{mcp-server-rdb-ssl-requirements.mdx → ts-mcp-server-rdb-ssl-requirements.mdx} +0 -0
@@ -7,7 +7,7 @@ when:
7
7
  - ts#agent
8
8
  - py#agent
9
9
  ---
10
- import { FileTree } from '@astrojs/starlight/components';
10
+ import { FileTree, Tabs, TabItem } from '@astrojs/starlight/components';
11
11
  import Link from '@components/link.astro';
12
12
  import RunGenerator from '@components/run-generator.astro';
13
13
  import GeneratorParameters from '@components/generator-parameters.astro';
@@ -22,7 +22,7 @@ The generator sets up all the necessary wiring so your agent can discover and in
22
22
 
23
23
  Before using this generator, ensure you have:
24
24
 
25
- 1. A Python project with a <Link path="guides/py-agent">Strands Agent</Link> component (any protocol)
25
+ 1. A Python project with a <Link path="guides/py-agent">Python Agent</Link> component (Strands or LangChain)
26
26
  2. A project with an Agent component generated with `--protocol=A2A` and `--auth=IAM` (either <Link path="guides/ts-agent">`ts#agent`</Link> or <Link path="guides/py-agent">`py#agent`</Link>)
27
27
  3. Both components created with `infra: agentcore`
28
28
 
@@ -48,30 +48,37 @@ The generator creates a shared `agent_connection` Python project at `packages/co
48
48
  - \<scope>\_agent\_connection
49
49
  - \_\_init\_\_.py Re-exports per-connection clients
50
50
  - core
51
- - agentcore\_a2a\_client.py Core AgentCore A2A client with SigV4 authentication
51
+ - agentcore\_endpoints.py Framework-agnostic ARN/URL resolution
52
+ - agentcore\_a2a\_client\_config.py Framework-agnostic A2A client config (signed `ClientConfig`)
53
+ - agentcore\_a2a\_client\_\<framework>.py A2A client wrapping the config for your agent's framework
54
+ - auth/ Framework-agnostic SigV4 / session-forwarding `httpx.Auth`
52
55
  - app
53
- - \<target\_agent\_name>\_client.py Per-connection client for each A2A agent
56
+ - \<target\_agent\_name>\_client\_\<framework>.py Per-connection A2A client for each A2A agent
54
57
 
55
58
  </FileTree>
56
59
 
60
+ The client suffix matches your agent's framework (`_strands` or `_langchain`). Both wrap the same framework-agnostic signed `ClientConfig`: the Strands client wraps a Strands `A2AAgent`, while the LangChain client drives the [a2a SDK](https://pypi.org/project/a2a-sdk/) directly.
61
+
57
62
  Additionally, the generator:
58
63
  - Transforms your agent's `agent.py` to register the remote A2A agent as a tool using `@tool`
59
64
  - Adds the `agent_connection` project as a workspace dependency of your agent project
60
- - Updates the agent's `serve-local` target to depend on the target agent's `serve-local` target
65
+ - Updates the agent's `dev` target to depend on the target agent's `dev` target
61
66
 
62
67
  ## Using the Connected A2A Agent
63
68
 
64
- The generator transforms your agent's `agent.py` to wrap the remote A2A agent as a tool:
69
+ The generator transforms your agent's `agent.py` to wrap the remote A2A agent as a tool. The remote agent is registered with a `@tool`-decorated delegate — the decorator's import and the agent constructor differ by framework:
65
70
 
66
- ```python title="packages/my-project/my_module/agent/agent.py" {4,9-15,21}
71
+ <Tabs syncKey="agent-framework">
72
+ <TabItem label="Strands" _filter={{ framework: 'strands' }}>
73
+ ```python title="packages/my-project/my_module/agent/agent.py" {4,8-13,15}
67
74
  from contextlib import contextmanager
68
75
  from strands import Agent, tool
69
76
 
70
- from my_scope_agent_connection import RemoteAgentClient
77
+ from my_scope_agent_connection import RemoteAgentClientStrands
71
78
 
72
79
  @contextmanager
73
- def get_agent(session_id: str):
74
- remote_agent = RemoteAgentClient.create(session_id=session_id)
80
+ def get_agent():
81
+ remote_agent = RemoteAgentClientStrands.create()
75
82
 
76
83
  @tool
77
84
  def ask_remote_agent(prompt: str) -> str:
@@ -83,10 +90,35 @@ def get_agent(session_id: str):
83
90
  tools=[ask_remote_agent],
84
91
  )
85
92
  ```
93
+ </TabItem>
94
+ <TabItem label="LangChain" _filter={{ framework: 'langchain' }}>
95
+ ```python title="packages/my-project/my_module/agent/agent.py" {4,7-12,14}
96
+ from langchain.agents import create_agent
97
+ from langchain_aws import ChatBedrockConverse
98
+ from langchain_core.tools import tool
99
+
100
+ from my_scope_agent_connection import RemoteAgentClientLangChain
101
+
102
+ def get_agent():
103
+ remote_agent = RemoteAgentClientLangChain.create()
104
+
105
+ @tool
106
+ def ask_remote_agent(prompt: str) -> str:
107
+ """Delegate a question to the remote RemoteAgent A2A agent and return its reply."""
108
+ return str(remote_agent(prompt))
109
+
110
+ return create_agent(
111
+ model=ChatBedrockConverse(model=MODEL_ID, region_name=REGION),
112
+ system_prompt="...",
113
+ tools=[ask_remote_agent],
114
+ )
115
+ ```
116
+ </TabItem>
117
+ </Tabs>
86
118
 
87
- The `session_id` parameter is plumbed through from the caller, ensuring consistency for [Bedrock AgentCore Observability](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability.html).
119
+ Both clients are directly callable, returning the remote agent's reply, and wrap an `httpx.AsyncClient` that signs requests with SigV4 when deployed to AWS and uses a plain `http://localhost:<port>/` endpoint when `LOCAL_DEV=true`. The Strands client wraps a Strands `A2AAgent`; the LangChain client drives the a2a SDK directly.
88
120
 
89
- Under the hood, `RemoteAgentClient.create(session_id=...)` returns a Strands `A2AAgent` configured with an `httpx.AsyncClient` that signs requests with SigV4 when deployed to AWS, and a plain `http://localhost:<port>/` endpoint when `SERVE_LOCAL=true`.
121
+ The AgentCore session ID is propagated to the remote agent automatically via the `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id` header, regardless of framework: the agent server binds the inbound request's session into an async context, and the connection client's signed `httpx.Auth` stamps it on every outbound call — ensuring consistency for [Bedrock AgentCore Observability](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability.html).
90
122
 
91
123
  ## Infrastructure
92
124
 
@@ -94,12 +126,12 @@ Under the hood, `RemoteAgentClient.create(session_id=...)` returns a Strands `A2
94
126
 
95
127
  ## Local Development
96
128
 
97
- The generator configures the host agent's `serve-local` target to:
129
+ The generator configures the host agent's `dev` target to:
98
130
  1. Start the connected A2A agent(s) automatically
99
- 2. Set `SERVE_LOCAL=true` so the generated client connects directly to `http://localhost:<port>/` instead of AgentCore
131
+ 2. Set `LOCAL_DEV=true` so the generated client connects directly to `http://localhost:<port>/` instead of AgentCore
100
132
 
101
133
  Run the agent locally with:
102
134
 
103
- <NxCommands commands={["<agent-name>-serve-local <project-name>"]} />
135
+ <NxCommands commands={["<agent-name>-dev <project-name>"]} />
104
136
 
105
137
  This will start both the host agent and all connected A2A agents, with the host agent calling the remote agents over plain HTTP on their assigned local ports.
@@ -0,0 +1,116 @@
1
+ ---
2
+ title: Python Agent to DynamoDB
3
+ description: Connect a Python Agent to a Python DynamoDB project
4
+ when:
5
+ sourceType: py#agent
6
+ targetType: py#dynamodb
7
+ ---
8
+ import Link from '@components/link.astro';
9
+ import RunGenerator from '@components/run-generator.astro';
10
+ import GeneratorParameters from '@components/generator-parameters.astro';
11
+ import Infrastructure from '@components/infrastructure.astro';
12
+ import Snippet from '@components/snippet.astro';
13
+
14
+ The `connection` generator wires a <Link path="guides/py-agent">Python Agent</Link> to a <Link path="guides/py-dynamodb">Python DynamoDB</Link> project, configuring local development so both start together automatically.
15
+
16
+ ## Prerequisites
17
+
18
+ Before using this generator, ensure you have:
19
+
20
+ 1. A <Link path="guides/py-agent">`py#agent`</Link> project
21
+ 2. A <Link path="guides/py-dynamodb">`py#dynamodb`</Link> project
22
+
23
+ ## Usage
24
+
25
+ ### Run the Generator
26
+
27
+ <RunGenerator generator="connection" />
28
+
29
+ Select your Agent project as the source and your DynamoDB project as the target. If the project contains multiple agent components, specify `sourceComponent` to disambiguate.
30
+
31
+ ### Options
32
+
33
+ <GeneratorParameters generator="connection" />
34
+
35
+ ## Generator Output
36
+
37
+ The generator updates the agent's `<agent-name>-dev` target in `project.json` to depend on the DynamoDB project's `dev` target, and adds the DynamoDB package as a workspace dependency. No source files are modified.
38
+
39
+ ## Using DynamoDB in Agents
40
+
41
+ Import entity classes from the DynamoDB package and use them inside your agent tools:
42
+
43
+ ```python title="packages/my_project/my_project/my_agent/agent.py"
44
+ from my_scope.my_table.entities.example import ExampleModel
45
+ from strands import tool
46
+
47
+ @tool
48
+ def list_examples() -> list:
49
+ """List all example items."""
50
+ return [item.attribute_values for item in ExampleModel.scan()]
51
+ ```
52
+
53
+ ## Infrastructure
54
+
55
+ To allow the agent's Lambda function to access the DynamoDB table, grant the necessary permissions in your infrastructure.
56
+
57
+ <Infrastructure>
58
+ <Fragment slot="cdk">
59
+
60
+ ```ts title="packages/infra/src/stacks/application-stack.ts"
61
+ import { MyTable } from ':my-scope/common-constructs';
62
+
63
+ const table = new MyTable(this, 'Table');
64
+ const myAgent = new MyAgent(this, 'MyAgent');
65
+
66
+ table.grantReadWriteData(myAgent);
67
+ ```
68
+
69
+ `grantReadWriteData` grants both the DynamoDB and KMS permissions to the agent's execution role.
70
+ </Fragment>
71
+ <Fragment slot="terraform">
72
+
73
+ ```hcl title="packages/infra/src/main.tf"
74
+ module "my_table" {
75
+ source = "../../common/terraform/src/app/dynamodb/my-table"
76
+ }
77
+
78
+ resource "aws_iam_role_policy" "dynamodb_access" {
79
+ role = module.my_agent.lambda_role_name
80
+
81
+ policy = jsonencode({
82
+ Version = "2012-10-17"
83
+ Statement = [
84
+ {
85
+ Effect = "Allow"
86
+ Action = [
87
+ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
88
+ "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
89
+ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
90
+ ]
91
+ Resource = [
92
+ module.my_table.table_arn,
93
+ "${module.my_table.table_arn}/index/*",
94
+ ]
95
+ },
96
+ {
97
+ Effect = "Allow"
98
+ Action = [
99
+ "kms:Encrypt",
100
+ "kms:Decrypt",
101
+ "kms:ReEncrypt*",
102
+ "kms:GenerateDataKey*",
103
+ "kms:DescribeKey"
104
+ ]
105
+ Resource = [module.my_table.kms_key_arn]
106
+ },
107
+ ]
108
+ })
109
+ }
110
+ ```
111
+ </Fragment>
112
+ </Infrastructure>
113
+
114
+ ## Local Development
115
+
116
+ <Snippet name="connection/py-dynamodb-local-development" />
@@ -0,0 +1,176 @@
1
+ ---
2
+ title: Python Agent to Gateway
3
+ description: Connect a Python Agent to an AgentCore Gateway
4
+ when:
5
+ sourceType: py#agent
6
+ targetType: agentcore-gateway
7
+ ---
8
+ import { FileTree, Tabs, TabItem } from '@astrojs/starlight/components';
9
+ import Link from '@components/link.astro';
10
+ import RunGenerator from '@components/run-generator.astro';
11
+ import GeneratorParameters from '@components/generator-parameters.astro';
12
+ import NxCommands from '@components/nx-commands.astro';
13
+ import Infrastructure from '@components/infrastructure.astro';
14
+
15
+ The `connection` generator can connect your <Link path="guides/py-agent">Python Agent</Link> to an <Link path="guides/agentcore-gateway">AgentCore Gateway</Link>.
16
+
17
+ The generator wires the agent so it authenticates to the Gateway with IAM SigV4 (via `httpx` request signing) when deployed, and connects to the local gateway started by the Gateway project when running locally.
18
+
19
+ ## Prerequisites
20
+
21
+ Before using this generator, ensure you have:
22
+
23
+ 1. A Python project with a <Link path="guides/py-agent">Agent</Link> component (`infra: agentcore`)
24
+ 2. A <Link path="guides/agentcore-gateway">`agentcore-gateway`</Link> project
25
+
26
+ ## Usage
27
+
28
+ ### Run the Generator
29
+
30
+ <RunGenerator generator="connection" />
31
+
32
+ Select the agent project as the source and the Gateway project as the target.
33
+
34
+ ### Options
35
+
36
+ <GeneratorParameters generator="connection" />
37
+
38
+ ## Generator Output
39
+
40
+ The generator emits shared core-gateway modules into your `agent_connection` Python project, plus a per-Gateway wrapper, and modifies your agent:
41
+
42
+ <FileTree>
43
+
44
+ - packages/common/agent\_connection
45
+ - \<scope>\_agent\_connection
46
+ - core/
47
+ - agentcore\_endpoints.py Framework-agnostic ARN/URL resolution
48
+ - agentcore\_gateway\_mcp\_transport.py Framework-agnostic Gateway MCP transport
49
+ - agentcore\_gateway\_mcp\_client\_\<framework>.py Gateway MCP client for your agent's framework
50
+ - auth/ Framework-agnostic SigV4 / session-forwarding `httpx.Auth`
51
+ - app/
52
+ - \<gateway\_snake>\_client\_\<framework>.py Per-Gateway client wrapper
53
+ - \_\_init\_\_.py Re-exports the Gateway client
54
+
55
+ </FileTree>
56
+
57
+ The client suffix matches your agent's framework (`_strands` or `_langchain`).
58
+
59
+ Additionally, the generator:
60
+
61
+ - Modifies your agent's `agent.py` to import the Gateway client and register its tools in `tools`
62
+ - Adds `agent_connection` as a workspace dependency of the agent
63
+ - Wires the agent's `<agent>-dev` target to depend on the Gateway's `dev` target
64
+
65
+ ## Using the connected Gateway
66
+
67
+ The generator transforms your agent's `agent.py` to use the Gateway client:
68
+
69
+ <Tabs syncKey="agent-framework">
70
+ <TabItem label="Strands" _filter={{ framework: 'strands' }}>
71
+ ```python title="packages/example/example/my_agent/agent.py" {4,8,9-13}
72
+ from contextlib import contextmanager
73
+ from strands import Agent
74
+
75
+ from my_scope_agent_connection import MyGatewayClientStrands
76
+
77
+ @contextmanager
78
+ def get_agent():
79
+ my_gateway = MyGatewayClientStrands.create()
80
+ with (
81
+ my_gateway,
82
+ ):
83
+ yield Agent(
84
+ system_prompt="...",
85
+ tools=[*my_gateway.list_tools_sync()],
86
+ )
87
+ ```
88
+
89
+ `MyGatewayClientStrands.create()` returns a single context-manageable `MCPClient` whose `list_tools_sync()` yields every tool available through the Gateway.
90
+ </TabItem>
91
+ <TabItem label="LangChain" _filter={{ framework: 'langchain' }}>
92
+ ```python title="packages/example/example/my_agent/agent.py" {4,8,12}
93
+ from langchain.agents import create_agent
94
+ from langchain_aws import ChatBedrockConverse
95
+
96
+ from my_scope_agent_connection import MyGatewayClientLangChain
97
+
98
+ def get_agent():
99
+ my_gateway = MyGatewayClientLangChain.create()
100
+ return create_agent(
101
+ model=ChatBedrockConverse(model=MODEL_ID, region_name=REGION),
102
+ system_prompt="...",
103
+ tools=[*my_gateway],
104
+ )
105
+ ```
106
+
107
+ `MyGatewayClientLangChain.create()` returns a list of tools loaded via [`langchain-mcp-adapters`](https://docs.langchain.com/oss/python/langchain/mcp). Each tool opens a fresh session per call, so no `with` block is needed.
108
+ </TabItem>
109
+ </Tabs>
110
+
111
+ In both cases the client behaves the same way per mode:
112
+
113
+ - **Deployed mode** (`LOCAL_DEV` unset): tools pointed at the Gateway's MCP endpoint, SigV4-signed.
114
+ - **Local mode** (`LOCAL_DEV=true`): plain-HTTP tools pointed at the local gateway started by the Gateway project's `dev` target.
115
+
116
+ The session ID is propagated to downstream MCP servers automatically via the `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id` header.
117
+
118
+ ## Infrastructure
119
+
120
+ After running the generator you must grant the agent permission to invoke the Gateway.
121
+
122
+ <Infrastructure>
123
+ <Fragment slot="cdk">
124
+ ```ts title="packages/infra/src/stacks/application-stack.ts" {5}
125
+ const gateway = new MyGateway(this, 'MyGateway');
126
+ const myAgent = new MyAgent(this, 'MyAgent');
127
+
128
+ // Grant the agent permissions to invoke the Gateway
129
+ gateway.grantInvokeAccess(myAgent);
130
+ ```
131
+
132
+ The Gateway URL is automatically registered in the `agentcore.gateways.<ClassName>` namespace of <Link path="guides/runtime-config">Runtime Configuration</Link> by the generated CDK construct, so the agent can discover it at runtime.
133
+ </Fragment>
134
+ <Fragment slot="terraform">
135
+ ```hcl title="packages/infra/src/main.tf" {6-13}
136
+ module "my_gateway" {
137
+ source = "../../common/terraform/src/app/gateways/my-gateway"
138
+ }
139
+
140
+ module "my_agent" {
141
+ source = "../../common/terraform/src/app/agents/my-agent"
142
+
143
+ # Grant the agent permission to invoke the Gateway
144
+ additional_iam_policy_statements = [{
145
+ Effect = "Allow"
146
+ Action = ["bedrock-agentcore:InvokeGateway"]
147
+ Resource = [module.my_gateway.gateway_arn]
148
+ }]
149
+ }
150
+ ```
151
+
152
+ The Gateway URL is automatically registered in the `agentcore.gateways.<ClassName>` namespace of <Link path="guides/runtime-config">Runtime Configuration</Link> by the generated Terraform module, so the agent can discover it at runtime.
153
+ </Fragment>
154
+ </Infrastructure>
155
+
156
+ ## Local Development
157
+
158
+ The generator configures the agent's `dev` target to:
159
+
160
+ 1. Start the connected Gateway's local gateway and every attached MCP server
161
+ 2. Set `LOCAL_DEV=true` so the generated client points at the local gateway instead of the deployed Gateway
162
+
163
+ Run the agent locally with:
164
+
165
+ <NxCommands commands={["<agent-name>-dev <project-name>"]} />
166
+
167
+ To run the agent locally **against the deployed Gateway** instead (for example, to exercise Cedar policies), use the agent's `serve` target. Without `LOCAL_DEV` set, the client resolves the deployed Gateway URL from runtime configuration and SigV4-signs requests with your local AWS credentials:
168
+
169
+ <NxCommands commands={["<agent-name>-serve <project-name>"]} />
170
+
171
+ ### Local fidelity
172
+
173
+ The local gateway stands in for the deployed Gateway, so:
174
+
175
+ - **No Cedar policy evaluation.** Every tool is visible to the agent regardless of policies. Use the `serve` target to exercise policies against the deployed Gateway.
176
+ - **Tool-name prefixing is preserved.** Each local MCP server's tools are exposed as `<target-name>___<tool-name>`, matching what the deployed Gateway emits. This keeps the agent's system prompt and the Cedar action names you reference consistent across local and deployed runs.
@@ -7,7 +7,7 @@ when:
7
7
  - ts#mcp-server
8
8
  - py#mcp-server
9
9
  ---
10
- import { FileTree } from '@astrojs/starlight/components';
10
+ import { FileTree, Tabs, TabItem } from '@astrojs/starlight/components';
11
11
  import Link from '@components/link.astro';
12
12
  import RunGenerator from '@components/run-generator.astro';
13
13
  import GeneratorParameters from '@components/generator-parameters.astro';
@@ -22,7 +22,7 @@ The generator sets up all the necessary wiring so your agent can discover and in
22
22
 
23
23
  Before using this generator, ensure you have:
24
24
 
25
- 1. A Python project with a <Link path="guides/py-agent">Strands Agent</Link> component
25
+ 1. A Python project with a <Link path="guides/py-agent">Python Agent</Link> component (Strands or LangChain)
26
26
  2. A project with an MCP server component (either <Link path="guides/ts-mcp-server">`ts#mcp-server`</Link> or <Link path="guides/py-mcp-server">`py#mcp-server`</Link>)
27
27
  3. Both components created with `infra: agentcore`
28
28
 
@@ -48,30 +48,37 @@ The generator creates a shared `agent_connection` Python project at `packages/co
48
48
  - \<scope>\_agent\_connection
49
49
  - \_\_init\_\_.py Re-exports per-connection clients
50
50
  - core
51
- - agentcore\_mcp\_client.py Core AgentCore MCP client
51
+ - agentcore\_endpoints.py Framework-agnostic ARN/URL resolution
52
+ - agentcore\_mcp\_transport.py Framework-agnostic MCP transport
53
+ - agentcore\_mcp\_client\_\<framework>.py MCP client wrapping the transport for your agent's framework
54
+ - auth/ Framework-agnostic SigV4 / session-forwarding `httpx.Auth`
52
55
  - app
53
- - \<mcp\_server\_name>\_client.py Per-connection client for each MCP server
56
+ - \<mcp\_server\_name>\_client\_\<framework>.py Per-connection client for each MCP server
54
57
 
55
58
  </FileTree>
56
59
 
60
+ The client suffix matches your agent's framework (`_strands` or `_langchain`).
61
+
57
62
  Additionally, the generator:
58
63
  - Transforms your agent's `agent.py` to import and use the MCP server's tools via a class-based client
59
64
  - Adds the `agent_connection` project as a workspace dependency of your agent project
60
- - Updates the agent's `serve-local` target to depend on the MCP server's serve target
65
+ - Updates the agent's `dev` target to depend on the MCP server's serve target
61
66
 
62
67
  ## Using the Connected MCP Server
63
68
 
64
69
  The generator transforms your agent's `agent.py` to use the MCP server's tools:
65
70
 
66
- ```python title="packages/my-project/my_module/agent/agent.py" {4,10-14}
71
+ <Tabs syncKey="agent-framework">
72
+ <TabItem label="Strands" _filter={{ framework: 'strands' }}>
73
+ ```python title="packages/my-project/my_module/agent/agent.py" {4,9-13}
67
74
  from contextlib import contextmanager
68
75
  from strands import Agent
69
76
 
70
- from my_scope_agent_connection import MyMcpServerClient
77
+ from my_scope_agent_connection import MyMcpServerClientStrands
71
78
 
72
79
  @contextmanager
73
- def get_agent(session_id: str):
74
- my_mcp_server = MyMcpServerClient.create(session_id=session_id)
80
+ def get_agent():
81
+ my_mcp_server = MyMcpServerClientStrands.create()
75
82
  with (
76
83
  my_mcp_server,
77
84
  ):
@@ -81,7 +88,29 @@ def get_agent(session_id: str):
81
88
  )
82
89
  ```
83
90
 
84
- The `session_id` parameter is plumbed through from the caller, ensuring consistency for [Bedrock AgentCore Observability](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability.html).
91
+ The Strands client is a context manager, entered in a `with` block around the agent.
92
+ </TabItem>
93
+ <TabItem label="LangChain" _filter={{ framework: 'langchain' }}>
94
+ ```python title="packages/my-project/my_module/agent/agent.py" {4,8,13}
95
+ from langchain.agents import create_agent
96
+ from langchain_aws import ChatBedrockConverse
97
+
98
+ from my_scope_agent_connection import MyMcpServerClientLangChain
99
+
100
+ def get_agent():
101
+ my_mcp_server = MyMcpServerClientLangChain.create()
102
+ return create_agent(
103
+ model=ChatBedrockConverse(model=MODEL_ID, region_name=REGION),
104
+ system_prompt="...",
105
+ tools=[*my_mcp_server],
106
+ )
107
+ ```
108
+
109
+ The LangChain client returns a list of tools loaded via [`langchain-mcp-adapters`](https://docs.langchain.com/oss/python/langchain/mcp). Each tool opens a fresh MCP session per call, so the tools stay usable for the agent's lifetime — no `with` block is needed.
110
+ </TabItem>
111
+ </Tabs>
112
+
113
+ The AgentCore session ID is propagated to the MCP server automatically via the `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id` header for both frameworks, ensuring consistency for [Bedrock AgentCore Observability](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability.html).
85
114
 
86
115
  ## Infrastructure
87
116
 
@@ -136,12 +165,12 @@ The MCP server's AgentCore runtime ARN is automatically registered in the `agent
136
165
 
137
166
  ## Local Development
138
167
 
139
- The generator configures the agent's `serve-local` target to:
168
+ The generator configures the agent's `dev` target to:
140
169
  1. Start the connected MCP server(s) automatically
141
- 2. Set `SERVE_LOCAL=true` so the generated client uses direct HTTP transport instead of AgentCore
170
+ 2. Set `LOCAL_DEV=true` so the generated client uses direct HTTP transport instead of AgentCore
142
171
 
143
172
  Run the agent locally with:
144
173
 
145
- <NxCommands commands={["<agent-name>-serve-local <project-name>"]} />
174
+ <NxCommands commands={["<agent-name>-dev <project-name>"]} />
146
175
 
147
176
  This will start both the agent and all connected MCP servers, with the agent connecting to the MCP servers directly via HTTP on their assigned local ports.