@aws/nx-plugin-mcp 1.0.0-rc.9 → 1.0.0-rc.91

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 (200) hide show
  1. package/bin/aws-nx-mcp.js +13439 -11631
  2. package/docs/get_started/building-with-ai.mdx +116 -0
  3. package/docs/get_started/concepts.mdx +67 -0
  4. package/docs/get_started/existing-project.mdx +180 -0
  5. package/docs/get_started/graph-builder.mdx +39 -0
  6. package/docs/get_started/quick-start.mdx +277 -0
  7. package/docs/get_started/tutorials/contribute-generator.mdx +408 -0
  8. package/docs/get_started/tutorials/dungeon-game/1.mdx +1578 -0
  9. package/docs/get_started/tutorials/dungeon-game/2.mdx +245 -0
  10. package/docs/get_started/tutorials/dungeon-game/3.mdx +66 -0
  11. package/docs/get_started/tutorials/dungeon-game/4.mdx +164 -0
  12. package/docs/get_started/tutorials/dungeon-game/overview.mdx +145 -0
  13. package/docs/get_started/tutorials/dungeon-game/wrap-up.mdx +41 -0
  14. package/docs/get_started/upgrading.mdx +157 -0
  15. package/docs/guides/agentcore-gateway.mdx +490 -0
  16. package/docs/guides/agentcore-harness.mdx +312 -0
  17. package/docs/guides/astro-docs.mdx +8 -0
  18. package/docs/guides/connection/agentcore-gateway-agent.mdx +222 -0
  19. package/docs/guides/connection/agentcore-gateway-gateway.mdx +154 -0
  20. package/docs/guides/connection/agentcore-gateway-mcp.mdx +134 -0
  21. package/docs/guides/connection/py-agent-a2a.mdx +48 -16
  22. package/docs/guides/connection/py-agent-dynamodb.mdx +115 -0
  23. package/docs/guides/connection/py-agent-gateway.mdx +182 -0
  24. package/docs/guides/connection/py-agent-mcp.mdx +43 -14
  25. package/docs/guides/connection/py-agent-rdb.mdx +169 -0
  26. package/docs/guides/connection/py-fast-api-dynamodb.mdx +56 -0
  27. package/docs/guides/connection/py-fast-api-rdb.mdx +175 -0
  28. package/docs/guides/connection/py-mcp-server-dynamodb.mdx +115 -0
  29. package/docs/guides/connection/py-mcp-server-rdb.mdx +178 -0
  30. package/docs/guides/connection/react-agentcore-gateway.mdx +112 -0
  31. package/docs/guides/connection/react-agui.mdx +33 -14
  32. package/docs/guides/connection/react-fastapi.mdx +39 -3
  33. package/docs/guides/connection/react-py-agent.mdx +10 -16
  34. package/docs/guides/connection/react-smithy.mdx +4 -4
  35. package/docs/guides/connection/react-trpc.mdx +1 -1
  36. package/docs/guides/connection/react-ts-agent.mdx +9 -9
  37. package/docs/guides/connection/smithy-dynamodb.mdx +5 -5
  38. package/docs/guides/connection/smithy-rdb.mdx +9 -9
  39. package/docs/guides/connection/trpc-dynamodb.mdx +4 -4
  40. package/docs/guides/connection/trpc-rdb.mdx +5 -5
  41. package/docs/guides/connection/ts-agent-a2a.mdx +14 -11
  42. package/docs/guides/connection/ts-agent-dynamodb.mdx +35 -36
  43. package/docs/guides/connection/ts-agent-gateway.mdx +147 -0
  44. package/docs/guides/connection/ts-agent-mcp.mdx +12 -9
  45. package/docs/guides/connection/ts-agent-rdb.mdx +61 -25
  46. package/docs/guides/connection/ts-mcp-server-dynamodb.mdx +35 -36
  47. package/docs/guides/connection/ts-mcp-server-rdb.mdx +59 -18
  48. package/docs/guides/connection.mdx +122 -5
  49. package/docs/guides/docker-bundling.mdx +82 -14
  50. package/docs/guides/fastapi.mdx +253 -12
  51. package/docs/guides/local-development.mdx +87 -0
  52. package/docs/guides/nx-generator.mdx +4 -3
  53. package/docs/guides/nx-migration.mdx +165 -0
  54. package/docs/guides/py-agent.mdx +332 -55
  55. package/docs/guides/py-dynamodb.mdx +476 -0
  56. package/docs/guides/py-mcp-server.mdx +57 -2
  57. package/docs/guides/py-rdb.mdx +269 -0
  58. package/docs/guides/python-lambda-function.mdx +1 -1
  59. package/docs/guides/python-project.mdx +31 -0
  60. package/docs/guides/react-website-auth.mdx +104 -5
  61. package/docs/guides/react-website.mdx +409 -95
  62. package/docs/guides/runtime-config.mdx +17 -4
  63. package/docs/guides/security.mdx +75 -0
  64. package/docs/guides/smithy-project.mdx +167 -0
  65. package/docs/guides/terraform-project.mdx +119 -8
  66. package/docs/guides/trpc.mdx +55 -14
  67. package/docs/guides/ts-agent.mdx +207 -23
  68. package/docs/guides/ts-dcr-proxy.mdx +569 -0
  69. package/docs/guides/ts-dynamodb.mdx +66 -242
  70. package/docs/guides/ts-lambda-function.mdx +1 -1
  71. package/docs/guides/ts-mcp-server.mdx +111 -29
  72. package/docs/guides/ts-nx-plugin.mdx +4 -4
  73. package/docs/guides/ts-rdb.mdx +116 -466
  74. package/docs/guides/ts-smithy-api.mdx +260 -16
  75. package/docs/guides/typescript-infrastructure.mdx +79 -25
  76. package/docs/guides/typescript-project.mdx +157 -24
  77. package/docs/guides/workspace.mdx +31 -2
  78. package/docs/snippets/agent/architecture.mdx +1 -1
  79. package/docs/snippets/agent/bedrock-deployment.mdx +9 -5
  80. package/docs/snippets/agent/runtime-arn.mdx +23 -2
  81. package/docs/snippets/agent/securing-your-agent.mdx +39 -0
  82. package/docs/snippets/api/access-logging.mdx +38 -0
  83. package/docs/snippets/api/cors-configuration-cdk-note.mdx +1 -1
  84. package/docs/snippets/api/cors-configuration-terraform-note.mdx +1 -1
  85. package/docs/snippets/api/type-safe-api-integrations.mdx +218 -373
  86. package/docs/snippets/api/waf-configuration.mdx +3 -3
  87. package/docs/snippets/connection/a2a-infrastructure.mdx +1 -1
  88. package/docs/snippets/connection/dynamodb-local-development.mdx +2 -2
  89. package/docs/snippets/connection/lambda-dynamodb-access.mdx +2 -2
  90. package/docs/snippets/connection/py-dynamodb-local-development.mdx +7 -0
  91. package/docs/snippets/connection/py-lambda-rdb-ssl-requirements.mdx +7 -0
  92. package/docs/snippets/connection/rdb-api-infrastructure.mdx +42 -19
  93. package/docs/snippets/dynamodb/deploying-table.mdx +176 -0
  94. package/docs/snippets/dynamodb/encryption-options.mdx +168 -0
  95. package/docs/snippets/dynamodb/gsi-config.mdx +38 -0
  96. package/docs/snippets/dynamodb/infrastructure.mdx +33 -0
  97. package/docs/snippets/dynamodb/local-dev-start.mdx +13 -0
  98. package/docs/snippets/dynamodb/local-dev-windows.mdx +15 -0
  99. package/docs/snippets/experimental-generator.mdx +8 -0
  100. package/docs/snippets/lambda-function/deploying-your-function.mdx +3 -3
  101. package/docs/snippets/mcp/architecture.mdx +1 -1
  102. package/docs/snippets/mcp/bedrock-deployment.mdx +9 -5
  103. package/docs/snippets/mcp/config.mdx +3 -2
  104. package/docs/snippets/mcp/shared-constructs.mdx +4 -5
  105. package/docs/snippets/pdk-migration/example/01-migrate-api.mdx +7 -5
  106. package/docs/snippets/pdk-migration/example/02-migrate-website.mdx +29 -10
  107. package/docs/snippets/pdk-migration/example/03-migrate-infra.mdx +4 -4
  108. package/docs/snippets/pdk-migration/faq/type-safe-api.mdx +5 -111
  109. package/docs/snippets/prerequisites.mdx +1 -4
  110. package/docs/snippets/rdb/admin-credentials.mdx +42 -0
  111. package/docs/snippets/rdb/architecture.mdx +39 -0
  112. package/docs/snippets/rdb/cluster-instances.mdx +31 -0
  113. package/docs/snippets/rdb/deletion-protection.mdx +64 -0
  114. package/docs/snippets/rdb/deploying.mdx +178 -0
  115. package/docs/snippets/rdb/encryption-key-rotation.mdx +30 -0
  116. package/docs/snippets/rdb/engine-version.mdx +63 -0
  117. package/docs/snippets/rdb/infrastructure.mdx +35 -0
  118. package/docs/snippets/rdb/logging-mysql.mdx +5 -0
  119. package/docs/snippets/rdb/logging-postgres.mdx +5 -0
  120. package/docs/snippets/rdb/performance-insights.mdx +36 -0
  121. package/docs/snippets/rdb/rds-proxy.mdx +50 -0
  122. package/docs/snippets/rdb/removal-policy.mdx +57 -0
  123. package/docs/snippets/rdb/serverless-capacity.mdx +32 -0
  124. package/docs/snippets/recommended-prerequisites.mdx +10 -0
  125. package/docs/snippets/required-prerequisites.mdx +1 -4
  126. package/docs/snippets/runtime-config-app-id-note.mdx +8 -0
  127. package/docs/snippets/shared-constructs.mdx +1 -1
  128. package/docs/snippets/trivy-image-scan.mdx +37 -0
  129. package/generators.json +170 -10
  130. package/package.json +1 -1
  131. package/src/agentcore-gateway/agent-connection/schema.json +31 -0
  132. package/src/agentcore-gateway/gateway-connection/schema.json +31 -0
  133. package/src/agentcore-gateway/mcp-connection/schema.json +31 -0
  134. package/src/agentcore-gateway/react-connection/schema.json +31 -0
  135. package/src/agentcore-gateway/schema.json +72 -0
  136. package/src/agentcore-harness/schema.json +53 -0
  137. package/src/connection/schema.json +5 -0
  138. package/src/infra/app/schema.json +5 -0
  139. package/src/init/schema.json +35 -0
  140. package/src/internal/test-matrix/schema.json +21 -0
  141. package/src/license/schema.json +5 -0
  142. package/src/open-api/json-metadata/schema.json +20 -0
  143. package/src/preset/schema.json +16 -5
  144. package/src/py/agent/a2a-connection/schema.json +5 -0
  145. package/src/py/agent/gateway-connection/schema.json +31 -0
  146. package/src/py/agent/mcp-connection/schema.json +5 -0
  147. package/src/py/agent/react-connection/schema.json +5 -0
  148. package/src/py/agent/schema.json +15 -1
  149. package/src/py/api/schema.json +5 -0
  150. package/src/py/dynamodb/agent-connection/schema.json +27 -0
  151. package/src/py/dynamodb/fast-api-connection/schema.json +23 -0
  152. package/src/py/dynamodb/mcp-server-connection/schema.json +27 -0
  153. package/src/py/dynamodb/schema.json +76 -0
  154. package/src/py/fast-api/react/schema.json +5 -0
  155. package/src/py/fast-api/schema.json +6 -0
  156. package/src/py/lambda-function/schema.json +6 -1
  157. package/src/py/mcp-server/schema.json +6 -0
  158. package/src/py/project/schema.json +6 -0
  159. package/src/py/rdb/agent-connection/schema.json +27 -0
  160. package/src/py/rdb/fast-api-connection/schema.json +23 -0
  161. package/src/py/rdb/mcp-server-connection/schema.json +27 -0
  162. package/src/py/rdb/schema.json +78 -0
  163. package/src/smithy/project/schema.json +28 -1
  164. package/src/smithy/react-connection/schema.json +5 -0
  165. package/src/smithy/ts/api/schema.json +6 -0
  166. package/src/terraform/project/schema.json +5 -0
  167. package/src/trpc/backend/schema.json +6 -0
  168. package/src/trpc/react/schema.json +5 -0
  169. package/src/ts/agent/a2a-connection/schema.json +5 -0
  170. package/src/ts/agent/gateway-connection/schema.json +31 -0
  171. package/src/ts/agent/mcp-connection/schema.json +5 -0
  172. package/src/ts/agent/react-connection/schema.json +5 -0
  173. package/src/ts/agent/schema.json +14 -0
  174. package/src/ts/api/schema.json +5 -0
  175. package/src/ts/astro-docs/schema.json +3 -3
  176. package/src/ts/dcr-proxy/schema.json +44 -0
  177. package/src/ts/docs/schema.json +3 -3
  178. package/src/ts/dynamodb/agent-connection/schema.json +5 -0
  179. package/src/ts/dynamodb/mcp-server-connection/schema.json +5 -0
  180. package/src/ts/dynamodb/schema.json +26 -2
  181. package/src/ts/dynamodb/smithy-connection/schema.json +5 -0
  182. package/src/ts/dynamodb/trpc-connection/schema.json +5 -0
  183. package/src/ts/lambda-function/schema.json +5 -0
  184. package/src/ts/lib/schema.json +5 -0
  185. package/src/ts/mcp-server/schema.json +6 -0
  186. package/src/ts/nx-generator/schema.json +5 -0
  187. package/src/ts/nx-migration/schema.json +63 -0
  188. package/src/ts/nx-plugin/schema.json +5 -0
  189. package/src/ts/rdb/agent-connection/schema.json +5 -0
  190. package/src/ts/rdb/mcp-server-connection/schema.json +5 -0
  191. package/src/ts/rdb/schema.json +7 -1
  192. package/src/ts/rdb/smithy-connection/schema.json +5 -0
  193. package/src/ts/rdb/trpc-connection/schema.json +5 -0
  194. package/src/ts/react-website/app/schema.json +12 -6
  195. package/src/ts/react-website/cognito-auth/schema.json +5 -0
  196. package/src/ts/react-website/runtime-config/schema.json +5 -0
  197. package/src/ts/website/app/schema.json +11 -6
  198. package/src/ts/website/auth/schema.json +5 -0
  199. /package/docs/snippets/connection/{lambda-rdb-ssl-requirements.mdx → ts-lambda-rdb-ssl-requirements.mdx} +0 -0
  200. /package/docs/snippets/connection/{mcp-server-rdb-ssl-requirements.mdx → ts-mcp-server-rdb-ssl-requirements.mdx} +0 -0
@@ -46,14 +46,14 @@ The generator modifies two files in your MCP server's source directory:
46
46
 
47
47
  </FileTree>
48
48
 
49
- Additionally, the `<mcp-server-name>-serve-local` target is updated to depend on the database's `serve-local` target.
49
+ Additionally, the `<mcp-server-name>-dev` target is updated to depend on the database's `dev` target.
50
50
 
51
- ## How It Works
51
+ ## Using the Database in MCP Tools
52
52
 
53
53
  The Prisma client is fetched inside `createServer` and available to all tools and resources registered there:
54
54
 
55
55
  ```ts title="packages/my-service/src/my-mcp/server.ts" {1,4}
56
- import { getPrisma as getMyDb } from ':my-scope/my-db';
56
+ import { getPrisma as getMyDb } from '@my-scope/my-db';
57
57
 
58
58
  export const createServer = async () => {
59
59
  const myDb = await getMyDb();
@@ -85,10 +85,21 @@ The generated MCP server construct implements `IGrantable` and `IConnectable`, s
85
85
  <Fragment slot="cdk">
86
86
 
87
87
  ```ts title="packages/infra/src/stacks/application-stack.ts"
88
- import { MyDatabase } from ':my-scope/common-constructs';
88
+ import { SecurityGroup } from 'aws-cdk-lib/aws-ec2';
89
+ import { RuntimeNetworkConfiguration } from 'aws-cdk-lib/aws-bedrockagentcore';
90
+ import { MyDatabase } from '@my-scope/common-constructs';
89
91
 
90
92
  const db = new MyDatabase(this, 'Db', { vpc, ... });
91
- const myMcpServer = new MyMcpServer(this, 'MyMcpServer', { vpc, ... });
93
+
94
+ const myMcpServer = new MyMcpServer(this, 'MyMcpServer', {
95
+ networkConfiguration: RuntimeNetworkConfiguration.usingVpc(this, {
96
+ vpc,
97
+ vpcSubnets: { subnetType: SubnetType.PRIVATE_WITH_EGRESS },
98
+ securityGroups: [
99
+ new SecurityGroup(this, 'MyMcpServerSecurityGroup', { vpc, allowAllOutbound: true }),
100
+ ],
101
+ }),
102
+ });
92
103
 
93
104
  db.allowDefaultPortFrom(myMcpServer);
94
105
  db.grantConnect(myMcpServer);
@@ -96,40 +107,70 @@ db.grantConnect(myMcpServer);
96
107
 
97
108
  `allowDefaultPortFrom` opens the security group rule so the MCP server runtime can reach the database port. `grantConnect` grants IAM `rds-db:connect` permission to the server's execution role.
98
109
 
110
+
99
111
  </Fragment>
100
112
  <Fragment slot="terraform">
101
113
 
102
- Pass the database module outputs into your MCP server module so it can reach the database and read its runtime configuration:
114
+ Run the MCP server inside the same VPC as the database, grant it `rds-db:connect` via `additional_iam_policy_statements`, and open the network path with a pair of security group rules. The `aws_vpc.main` and `aws_subnet` resources are defined in the database deployment guide:
103
115
 
104
116
  ```hcl title="packages/infra/src/main.tf"
105
117
  module "my_database" {
106
118
  source = "../../common/terraform/src/app/dbs/my-database"
107
- vpc_id = module.vpc.vpc_id
108
- database_subnet_ids = module.vpc.private_isolated_subnet_ids
119
+ vpc_id = aws_vpc.main.id
120
+ database_subnet_ids = aws_subnet.database[*].id
121
+ lambda_subnet_ids = aws_subnet.private[*].id
109
122
  }
110
123
 
111
124
  module "my_mcp_server" {
112
- source = "../../common/terraform/src/app/mcp-servers/my-mcp-server"
125
+ source = "../../common/terraform/src/app/mcp-servers/my-mcp-server"
126
+ enable_vpc = true
127
+ vpc_id = aws_vpc.main.id
128
+ subnet_ids = aws_subnet.private[*].id
129
+
130
+ appconfig_application_id = module.runtime_config_appconfig.application_id
131
+ appconfig_application_arn = module.runtime_config_appconfig.application_arn
132
+
133
+ additional_iam_policy_statements = [
134
+ {
135
+ Effect = "Allow"
136
+ Action = ["rds-db:connect"]
137
+ Resource = [
138
+ "arn:aws:rds-db:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:dbuser:${module.my_database.connect_resource_id}/${module.my_database.database_runtime_user}"
139
+ ]
140
+ }
141
+ ]
142
+ }
143
+
144
+ resource "aws_vpc_security_group_ingress_rule" "mcp_server_to_database" {
145
+ description = "Allow the MCP server runtime to connect to the database"
146
+ security_group_id = module.my_database.security_group_id
147
+ referenced_security_group_id = module.my_mcp_server.security_group_id
148
+ from_port = module.my_database.cluster_port
149
+ to_port = module.my_database.cluster_port
150
+ ip_protocol = "tcp"
151
+ }
113
152
 
114
- appconfig_application_id = module.my_database.appconfig_application_id
115
- database_cluster_resource_id = module.my_database.cluster_resource_id
116
- database_runtime_user = module.my_database.database_runtime_user
117
- database_security_group_id = module.my_database.security_group_id
118
- database_port = module.my_database.cluster_port
153
+ resource "aws_vpc_security_group_egress_rule" "mcp_server_to_database" {
154
+ description = "Allow outbound traffic from the MCP server runtime to the database"
155
+ security_group_id = module.my_mcp_server.security_group_id
156
+ referenced_security_group_id = module.my_database.security_group_id
157
+ from_port = module.my_database.cluster_port
158
+ to_port = module.my_database.cluster_port
159
+ ip_protocol = "tcp"
119
160
  }
120
161
  ```
121
162
 
122
- Ensure the MCP server's execution role has `rds-db:connect` permission and that its security group can reach the database security group on the database port.
163
+ `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module. That application exposes the `database` namespace by default, so the database module's runtime configuration entry is deployed without further configuration.
123
164
 
124
165
  </Fragment>
125
166
  </Infrastructure>
126
167
 
127
168
  ### SSL Requirements When Connecting Without RDS Proxy
128
169
 
129
- <Snippet name="connection/mcp-server-rdb-ssl-requirements" parentHeading="SSL Requirements When Connecting Without RDS Proxy" />
170
+ <Snippet name="connection/ts-mcp-server-rdb-ssl-requirements" parentHeading="SSL Requirements When Connecting Without RDS Proxy" />
130
171
 
131
172
  ## Local Development
132
173
 
133
- <NxCommands commands={["<mcp-server-name>-serve-local <project-name>"]} />
174
+ <NxCommands commands={["<mcp-server-name>-dev <project-name>"]} />
134
175
 
135
- This starts the MCP server and all connected databases. The `SERVE_LOCAL=true` environment variable causes each Prisma client to connect to its local Docker database instead of Aurora.
176
+ This starts the MCP server and all connected databases. The `LOCAL_DEV=true` environment variable causes each Prisma client to connect to its local Docker database instead of Aurora.
@@ -6,9 +6,25 @@ import Astro from '@astrojs/react';
6
6
  import { CardGrid, LinkButton } from '@astrojs/starlight/components';
7
7
  import Link from '@components/link.astro';
8
8
  import ConnectionCard from '@components/connection-card.astro';
9
+ import RunGenerator from '@components/run-generator.astro';
10
+ import GeneratorParameters from '@components/generator-parameters.astro';
9
11
 
10
12
  This generator is used to connect projects together, such as websites calling APIs. Simply select the source project (for example the project that will call your API) and target project (for example your API project), and this generator will handle integrating the two.
11
13
 
14
+ :::tip[Sketch it visually]
15
+ Prefer to design your workspace first? The <Link path="get_started/graph-builder">Graph Builder</Link> lets you drag out projects and draw the connections between them, then gives you the commands to scaffold the lot.
16
+ :::
17
+
18
+ ## Usage
19
+
20
+ ### Run the Generator
21
+
22
+ <RunGenerator generator="connection" />
23
+
24
+ ### Options
25
+
26
+ <GeneratorParameters generator="connection" />
27
+
12
28
  ### Supported Connections
13
29
 
14
30
  The Connection generator supports the following connections:
@@ -113,28 +129,55 @@ The Connection generator supports the following connections:
113
129
  target="aurora"
114
130
  />
115
131
  <ConnectionCard
116
- title="MCP Server to Relational Database"
132
+ title="TypeScript MCP Server to Relational Database"
117
133
  description="Connect a TypeScript MCP Server to an Aurora relational database"
118
134
  href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/ts-mcp-server-rdb`}
119
135
  source="mcp"
136
+ sourceBadge="typescript"
120
137
  target="aurora"
121
138
  />
122
139
  <ConnectionCard
123
- title="tRPC API to DynamoDB"
140
+ title="FastAPI to Python Relational Database"
141
+ description="Connect a FastAPI to a Python Aurora relational database"
142
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-fast-api-rdb`}
143
+ source="fastapi"
144
+ target="aurora"
145
+ targetBadge="python"
146
+ />
147
+ <ConnectionCard
148
+ title="Python Agent to Python Relational Database"
149
+ description="Connect a Python Agent to a Python Aurora relational database"
150
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-agent-rdb`}
151
+ source="strands"
152
+ sourceBadge="python"
153
+ target="aurora"
154
+ targetBadge="python"
155
+ />
156
+ <ConnectionCard
157
+ title="Python MCP Server to Python Relational Database"
158
+ description="Connect a Python MCP Server to a Python Aurora relational database"
159
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-mcp-server-rdb`}
160
+ source="mcp"
161
+ sourceBadge="python"
162
+ target="aurora"
163
+ targetBadge="python"
164
+ />
165
+ <ConnectionCard
166
+ title="tRPC API to TypeScript DynamoDB"
124
167
  description="Connect a tRPC API to a DynamoDB table"
125
168
  href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/trpc-dynamodb`}
126
169
  source="trpc"
127
170
  target="dynamodb"
128
171
  />
129
172
  <ConnectionCard
130
- title="Smithy API to DynamoDB"
173
+ title="Smithy API to TypeScript DynamoDB"
131
174
  description="Connect a Smithy API to a DynamoDB table"
132
175
  href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/smithy-dynamodb`}
133
176
  source="smithy"
134
177
  target="dynamodb"
135
178
  />
136
179
  <ConnectionCard
137
- title="TypeScript Agent to DynamoDB"
180
+ title="TypeScript Agent to TypeScript DynamoDB"
138
181
  description="Connect a TypeScript Agent to a DynamoDB table"
139
182
  href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/ts-agent-dynamodb`}
140
183
  source="strands"
@@ -142,14 +185,88 @@ The Connection generator supports the following connections:
142
185
  target="dynamodb"
143
186
  />
144
187
  <ConnectionCard
145
- title="MCP Server to DynamoDB"
188
+ title="MCP Server to TypeScript DynamoDB"
146
189
  description="Connect a TypeScript MCP Server to a DynamoDB table"
147
190
  href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/ts-mcp-server-dynamodb`}
148
191
  source="mcp"
149
192
  target="dynamodb"
150
193
  />
194
+ <ConnectionCard
195
+ title="FastAPI to Python DynamoDB"
196
+ description="Connect a FastAPI to a DynamoDB table"
197
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-fast-api-dynamodb`}
198
+ source="fastapi"
199
+ target="dynamodb"
200
+ targetBadge="python"
201
+ />
202
+ <ConnectionCard
203
+ title="Python Agent to Python DynamoDB"
204
+ description="Connect a Python Agent to a DynamoDB table"
205
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-agent-dynamodb`}
206
+ source="strands"
207
+ sourceBadge="python"
208
+ target="dynamodb"
209
+ targetBadge="python"
210
+ />
211
+ <ConnectionCard
212
+ title="Python MCP Server to Python DynamoDB"
213
+ description="Connect a Python MCP Server to a DynamoDB table"
214
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-mcp-server-dynamodb`}
215
+ source="mcp"
216
+ sourceBadge="python"
217
+ target="dynamodb"
218
+ targetBadge="python"
219
+ />
220
+ <ConnectionCard
221
+ title="AgentCore Gateway to MCP Server"
222
+ description="Aggregate an MCP server behind an AgentCore Gateway"
223
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/agentcore-gateway-mcp`}
224
+ source="agentcore"
225
+ target="mcp"
226
+ />
227
+ <ConnectionCard
228
+ title="AgentCore Gateway to AgentCore Gateway"
229
+ description="Aggregate an AgentCore Gateway behind another AgentCore Gateway"
230
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/agentcore-gateway-gateway`}
231
+ source="agentcore"
232
+ target="agentcore"
233
+ />
234
+ <ConnectionCard
235
+ title="TypeScript Agent to AgentCore Gateway"
236
+ description="Connect a TypeScript Agent to an AgentCore Gateway"
237
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/ts-agent-gateway`}
238
+ source="strands"
239
+ sourceBadge="typescript"
240
+ target="agentcore"
241
+ />
242
+ <ConnectionCard
243
+ title="Python Agent to AgentCore Gateway"
244
+ description="Connect a Python Agent to an AgentCore Gateway"
245
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-agent-gateway`}
246
+ source="strands"
247
+ sourceBadge="python"
248
+ target="agentcore"
249
+ />
250
+ <ConnectionCard
251
+ title="AgentCore Gateway to Agent"
252
+ description="Front an agent with an AgentCore Gateway as a runtime target"
253
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/agentcore-gateway-agent`}
254
+ source="agentcore"
255
+ target="strands"
256
+ />
257
+ <ConnectionCard
258
+ title="React Website to AgentCore Gateway"
259
+ description="Connect a React website to agents through an AgentCore Gateway"
260
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/react-agentcore-gateway`}
261
+ source="react"
262
+ target="agentcore"
263
+ />
151
264
  </CardGrid>
152
265
 
153
266
  :::note[Runtime Configuration]
154
267
  The connection generator makes use of <Link path="guides/runtime-config">Runtime Configuration</Link> to pass deploy-time values (such as API URLs, Cognito settings, and agent runtime ARNs) between generated projects and components at runtime so they can discover and connect to one another.
155
268
  :::
269
+
270
+ :::tip[Local Development]
271
+ Connected projects can be run on your machine with the `serve` and `dev` targets. See the <Link path="guides/local-development">Local Development</Link> guide for details.
272
+ :::
@@ -3,15 +3,38 @@ title: Docker Bundling
3
3
  description: Build and deploy Docker images for TypeScript and Python projects in an Nx Plugin for AWS workspace.
4
4
  ---
5
5
 
6
- import { FileTree, Tabs, TabItem } from '@astrojs/starlight/components';
6
+ import { FileTree, Tabs, TabItem, Code } from '@astrojs/starlight/components';
7
7
  import NxCommands from '@components/nx-commands.astro';
8
+ import PackageManagerShortCommand from '@components/package-manager-short-command.astro';
8
9
  import Link from '@components/link.astro';
9
10
  import Infrastructure from '@components/infrastructure.astro';
11
+ import { CONTAINER_VERSIONS } from '../../../../../../packages/nx-plugin/src/utils/versions';
12
+
13
+ export const trivyTarget = `{
14
+ "targets": {
15
+ "trivy": {
16
+ "cache": false,
17
+ "outputs": ["{workspaceRoot}/dist/{projectRoot}/trivy"],
18
+ "executor": "nx:run-commands",
19
+ "options": {
20
+ "commands": [
21
+ "rimraf dist/packages/my-project/trivy",
22
+ "make-dir dist/packages/my-project/trivy",
23
+ "ncp packages/my-project/.trivyignore dist/packages/my-project/trivy/.trivyignore",
24
+ "docker save -o dist/packages/my-project/trivy/image.tar my-scope-my-project:latest",
25
+ "docker run --rm -v \\"./dist/packages/my-project/trivy\\":/scan public.ecr.aws/aquasecurity/trivy:${CONTAINER_VERSIONS.trivy} image --input /scan/image.tar --ignorefile /scan/.trivyignore --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 --no-progress -q"
26
+ ],
27
+ "parallel": false
28
+ },
29
+ "dependsOn": ["docker"]
30
+ }
31
+ }
32
+ }`;
10
33
 
11
34
  Several generators (such as <Link path="/guides/ts-agent">`ts#agent`</Link> and <Link path="/guides/py-agent">`py#agent`</Link>) produce a Docker image that is pushed to Amazon ECR and consumed by AWS infrastructure. This guide describes the pattern they follow so that you can apply it to other use cases — for example, running a <Link path="/guides/fastapi">FastAPI</Link> project on Amazon ECS, or deploying a containerised Express server.
12
35
 
13
36
  :::tip[Docker or Finch]
14
- The container engine used to build images is chosen at workspace creation time via the `--containerEngine` flag (`docker`, `finch`, or `infer` — the default — which auto-detects what's installed). [Finch](https://runfinch.com/) is an open-source, drop-in alternative to Docker. The selection is recorded in `aws-nx-plugin.config.mts` and applied to every generator that emits container build commands. CDK image asset builds honour the choice via the `CDK_DOCKER` environment variable.
37
+ The container engine used to build images is chosen at workspace creation time via the `--containers` flag (`docker`, `finch`, or `infer` — the default — which auto-detects what's installed). [Finch](https://runfinch.com/) is an open-source, drop-in alternative to Docker. The selection is recorded in `aws-nx-plugin.config.mts` and applied to every generator that emits container build commands. CDK image asset builds honour the choice via the `CDK_DOCKER` environment variable.
15
38
  :::
16
39
 
17
40
  ## The Pattern
@@ -43,7 +66,7 @@ The Docker build context is written to your project's `dist` folder. Your infras
43
66
  :::tip[Why bundle outside the Dockerfile?]
44
67
  Keeping the bundle step in Nx (rather than inside the `Dockerfile`) means:
45
68
 
46
- - Nx can **cache** the bundle target, so repeated builds are fast.
69
+ - Nx can **cache** the bundle target — its output is a directory on disk, so a cache hit genuinely restores it.
47
70
  - The `Dockerfile` does not need access to your monorepo, private registries, or build-time secrets.
48
71
  - The image layer is tiny — a single `COPY` of already-built artifacts, with no transitive `node_modules` or build toolchain.
49
72
  :::
@@ -59,6 +82,7 @@ Configure a `bundle` target that invokes Rolldown. If you are starting from a <L
59
82
  "targets": {
60
83
  "bundle": {
61
84
  "cache": true,
85
+ "inputs": ["default"],
62
86
  "executor": "nx:run-commands",
63
87
  "outputs": ["{workspaceRoot}/dist/{projectRoot}/bundle"],
64
88
  "options": {
@@ -84,7 +108,7 @@ export default defineConfig([
84
108
  output: {
85
109
  file: '../../dist/packages/my-project/bundle/index.js',
86
110
  format: 'cjs',
87
- inlineDynamicImports: true,
111
+ codeSplitting: false,
88
112
  },
89
113
  platform: 'node',
90
114
  },
@@ -142,7 +166,7 @@ Add a `docker` target which:
142
166
  {
143
167
  "targets": {
144
168
  "docker": {
145
- "cache": true,
169
+ "cache": false,
146
170
  "executor": "nx:run-commands",
147
171
  "options": {
148
172
  "commands": [
@@ -157,6 +181,10 @@ Add a `docker` target which:
157
181
  }
158
182
  ```
159
183
 
184
+ :::caution[Do not cache image builds]
185
+ Set `"cache": false` on image build targets. A built image is not written to an `outputs` path in the filesystem, so Nx has nothing to restore on a cache hit. Container engines cache image layers regardless, so there is no performance penalty.
186
+ :::
187
+
160
188
  :::tip[Cross-platform file copy]
161
189
  The `ncp` package provides a cross-platform file/directory copy command, avoiding `cp` (unavailable on Windows). Install it at the root of your workspace with `pnpm add -D -w ncp`.
162
190
  :::
@@ -231,7 +259,7 @@ Add a `docker` target which copies the `Dockerfile` into the bundle output direc
231
259
  {
232
260
  "targets": {
233
261
  "docker": {
234
- "cache": true,
262
+ "cache": false,
235
263
  "executor": "nx:run-commands",
236
264
  "options": {
237
265
  "commands": [
@@ -253,6 +281,40 @@ This clears the output directory, then copies both the bundle contents and the `
253
281
 
254
282
  <NxCommands commands={['docker my-project']} />
255
283
 
284
+ ## Scanning Images with Trivy
285
+
286
+ It's good practice to scan your images for known vulnerabilities. The generators that follow this pattern add a `trivy` target which scans the built image with [Trivy](https://trivy.dev/), running from the [ECR-hosted Trivy image](https://gallery.ecr.aws/aquasecurity/trivy), and exits non-zero on `HIGH` or `CRITICAL` findings.
287
+
288
+ Add a `trivy` target which `dependsOn` your `docker` target. It saves the built image to a tarball and scans it via a workspace-relative bind mount, so the same command works under both `docker` and `finch`:
289
+
290
+ <Code lang="json" code={trivyTarget} />
291
+
292
+ Each project's per-image scan targets are aggregated under a workspace-wide `trivy` target, which the vended `trivy` root script runs (`nx run-many --target trivy`).
293
+
294
+ <PackageManagerShortCommand commands={['trivy']} />
295
+
296
+ :::tip[Run Trivy in CI]
297
+ The scan is intentionally not wired into `build` since this can introduce unnecessary friction when iterating during development, as Trivy's vulnerabilty database is continually updated with new CVEs.
298
+
299
+ Instead we recommend running the above command as a dedicated step in your CI pipeline prior to deployment to production stages.
300
+ :::
301
+
302
+ :::note[Suppressing findings]
303
+ Trivy reads a `.trivyignore` file (a list of vulnerability IDs, one per line) from the root of your project. `--ignore-unfixed` skips vulnerabilities with no available fix, so the scan only fails on issues you can action by upgrading tooling in your `Dockerfile`. See the [Trivy filtering documentation](https://trivy.dev/latest/docs/configuration/filtering/#by-finding-ids) for details.
304
+ :::
305
+
306
+ :::tip[Apply the distribution's security updates]
307
+ A base image tag lags behind its distribution's security suite, so its OS packages carry vulnerabilities that already have a published fix. Upgrade them as the first step of your build, ahead of any other instruction so later layers install against the upgraded packages. For a Debian-derived base image (as used by the Node and Python images above):
308
+
309
+ ```dockerfile
310
+ RUN apt-get update && \
311
+ apt-get upgrade -y --no-install-recommends && \
312
+ rm -rf /var/lib/apt/lists/*
313
+ ```
314
+
315
+ The generated `Dockerfile`s do this for you.
316
+ :::
317
+
256
318
  ## Infrastructure
257
319
 
258
320
  Wiring the resulting build-context directory to infrastructure as code is the same for both TypeScript and Python — only the path to the build-context directory differs (`dist/packages/my-project/bundle` for TypeScript, `dist/packages/my-project/docker` for Python).
@@ -291,7 +353,7 @@ infra.asset -> ecr: cdk deploy\nbuilds + pushes
291
353
 
292
354
  ```ts
293
355
  import { DockerImageAsset, Platform } from 'aws-cdk-lib/aws-ecr-assets';
294
- import { findWorkspaceRoot } from ':my-scope/common-constructs';
356
+ import { findWorkspaceRoot } from '@my-scope/common-constructs';
295
357
  import * as path from 'path';
296
358
  import * as url from 'url';
297
359
 
@@ -305,7 +367,7 @@ const image = new DockerImageAsset(this, 'MyImage', {
305
367
  });
306
368
  ```
307
369
 
308
- The `findWorkspaceRoot` helper is generated by the <Link path="/guides/typescript-infrastructure">`ts#infra`</Link> generator and exported from `:my-scope/common-constructs`. If you are not using shared constructs, you can hardcode the path to the `dist` directory relative to where `cdk` is invoked from — typically the workspace root — and omit the `findWorkspaceRoot` call entirely.
370
+ The `findWorkspaceRoot` helper is generated by the <Link path="/guides/typescript-infrastructure">`ts#infra`</Link> generator and exported from `@my-scope/common-constructs`. If you are not using shared constructs, you can hardcode the path to the `dist` directory relative to where `cdk` is invoked from — typically the workspace root — and omit the `findWorkspaceRoot` call entirely.
309
371
 
310
372
  :::note[Running bundle before synth]
311
373
  CDK does not run the `bundle`/`docker` targets automatically — you must run `nx build my-project` (or wire the deploy target to depend on `build`) before `cdk deploy`. The generators that use this pattern declare `docker` and `bundle` as dependencies of `build` so this happens transparently.
@@ -318,8 +380,8 @@ Terraform's AWS provider does not have a first-class "build and push a Docker im
318
380
 
319
381
  1. The project's `build` target runs `docker build`, producing a local image tagged `my-scope-my-project:latest`.
320
382
  2. An `aws_ecr_repository` to hold the image.
321
- 3. A `null_resource` with a `local-exec` provisioner that authenticates to ECR, re-tags the locally-built image, and pushes it.
322
- 4. The downstream resource (e.g. `aws_ecs_task_definition`) references `"${aws_ecr_repository.repo.repository_url}:latest"`.
383
+ 3. A `null_resource` with a `local-exec` provisioner that authenticates to ECR, re-tags the locally-built image with its content digest, and pushes it.
384
+ 4. The downstream resource (e.g. `aws_ecs_task_definition`) references the image by its immutable, digest-based tag.
323
385
 
324
386
  ```d2
325
387
  direction: down
@@ -361,7 +423,7 @@ infra.repo -> ecr
361
423
  ```hcl
362
424
  resource "aws_ecr_repository" "repo" {
363
425
  name = "my-project-repository"
364
- image_tag_mutability = "MUTABLE"
426
+ image_tag_mutability = "IMMUTABLE"
365
427
  force_delete = true
366
428
  }
367
429
 
@@ -370,24 +432,30 @@ data "external" "docker_digest" {
370
432
  program = ["sh", "-c", "echo '{\"digest\":\"'$(docker inspect my-scope-my-project:latest --format '{{.Id}}')'\"}'"]
371
433
  }
372
434
 
435
+ locals {
436
+ # Content-based, immutable image tag derived from the local image digest
437
+ image_tag = replace(data.external.docker_digest.result.digest, "sha256:", "")
438
+ }
439
+
373
440
  resource "null_resource" "docker_publish" {
374
441
  triggers = {
375
442
  docker_digest = data.external.docker_digest.result.digest
376
443
  repository_url = aws_ecr_repository.repo.repository_url
444
+ image_tag = local.image_tag
377
445
  }
378
446
 
379
447
  provisioner "local-exec" {
380
448
  command = <<-EOT
381
449
  aws ecr get-login-password --region ${data.aws_region.current.id} \
382
450
  | docker login --username AWS --password-stdin ${self.triggers.repository_url}
383
- docker tag my-scope-my-project:latest ${self.triggers.repository_url}:latest
384
- docker push ${self.triggers.repository_url}:latest
451
+ docker tag my-scope-my-project:latest ${self.triggers.repository_url}:${self.triggers.image_tag}
452
+ docker push ${self.triggers.repository_url}:${self.triggers.image_tag}
385
453
  EOT
386
454
  }
387
455
  }
388
456
  ```
389
457
 
390
- The `data.external.docker_digest` block ensures the `null_resource` re-runs whenever the local image hash changes, triggering a new push on every meaningful code change.
458
+ The `data.external.docker_digest` block ensures the `null_resource` re-runs whenever the local image hash changes, triggering a new push on every meaningful code change. The image is pushed under an immutable, content-based tag derived from its digest, so the ECR repository can use `IMMUTABLE` tag mutability and reject any attempt to overwrite an existing tag.
391
459
 
392
460
  :::note[Running bundle before apply]
393
461
  `nx apply <project>` requires the image tag `my-scope-my-project:latest` to already exist locally. Run `nx build my-project` (or `nx docker my-project`) before `nx apply <project>`.