@aws/nx-plugin-mcp 1.0.0-rc.2 → 1.0.0-rc.21

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 (70) hide show
  1. package/bin/aws-nx-mcp.js +5919 -4776
  2. package/docs/guides/agentcore-gateway.mdx +240 -0
  3. package/docs/guides/connection/agentcore-gateway-gateway.mdx +154 -0
  4. package/docs/guides/connection/agentcore-gateway-mcp.mdx +134 -0
  5. package/docs/guides/connection/py-agent-a2a.mdx +8 -5
  6. package/docs/guides/connection/py-agent-dynamodb.mdx +116 -0
  7. package/docs/guides/connection/py-agent-gateway.mdx +161 -0
  8. package/docs/guides/connection/py-agent-mcp.mdx +7 -4
  9. package/docs/guides/connection/py-fast-api-dynamodb.mdx +56 -0
  10. package/docs/guides/connection/py-mcp-server-dynamodb.mdx +116 -0
  11. package/docs/guides/connection/react-smithy.mdx +1 -1
  12. package/docs/guides/connection/react-trpc.mdx +1 -1
  13. package/docs/guides/connection/smithy-dynamodb.mdx +68 -0
  14. package/docs/guides/connection/smithy-rdb.mdx +1 -1
  15. package/docs/guides/connection/trpc-dynamodb.mdx +62 -0
  16. package/docs/guides/connection/trpc-rdb.mdx +1 -1
  17. package/docs/guides/connection/ts-agent-a2a.mdx +8 -5
  18. package/docs/guides/connection/ts-agent-dynamodb.mdx +128 -0
  19. package/docs/guides/connection/ts-agent-gateway.mdx +152 -0
  20. package/docs/guides/connection/ts-agent-mcp.mdx +7 -4
  21. package/docs/guides/connection/ts-mcp-server-dynamodb.mdx +125 -0
  22. package/docs/guides/connection.mdx +89 -0
  23. package/docs/guides/docker-bundling.mdx +13 -7
  24. package/docs/guides/fastapi.mdx +213 -3
  25. package/docs/guides/license.mdx +264 -109
  26. package/docs/guides/local-development.mdx +76 -0
  27. package/docs/guides/nx-generator.mdx +5 -0
  28. package/docs/guides/py-agent.mdx +42 -3
  29. package/docs/guides/py-dynamodb.mdx +449 -0
  30. package/docs/guides/py-mcp-server.mdx +5 -1
  31. package/docs/guides/react-website-auth.mdx +15 -0
  32. package/docs/guides/react-website.mdx +12 -4
  33. package/docs/guides/trpc.mdx +8 -8
  34. package/docs/guides/ts-agent.mdx +40 -2
  35. package/docs/guides/ts-dynamodb.mdx +158 -0
  36. package/docs/guides/ts-mcp-server.mdx +5 -1
  37. package/docs/guides/ts-rdb.mdx +58 -10
  38. package/docs/guides/ts-smithy-api.mdx +148 -3
  39. package/docs/guides/typescript-project.mdx +5 -10
  40. package/docs/guides/workspace.mdx +8 -2
  41. package/docs/snippets/api/type-safe-api-integrations.mdx +31 -0
  42. package/docs/snippets/api/waf-configuration.mdx +1 -1
  43. package/docs/snippets/connection/dynamodb-local-development.mdx +7 -0
  44. package/docs/snippets/connection/lambda-dynamodb-access.mdx +80 -0
  45. package/docs/snippets/connection/py-dynamodb-local-development.mdx +7 -0
  46. package/docs/snippets/dynamodb/deploying-table.mdx +171 -0
  47. package/docs/snippets/dynamodb/gsi-config.mdx +38 -0
  48. package/docs/snippets/dynamodb/infrastructure.mdx +33 -0
  49. package/docs/snippets/dynamodb/serve-local-start.mdx +13 -0
  50. package/docs/snippets/dynamodb/serve-local-windows.mdx +15 -0
  51. package/docs/snippets/mcp/config.mdx +1 -1
  52. package/docs/snippets/required-prerequisites.mdx +1 -1
  53. package/generators.json +100 -1
  54. package/package.json +1 -1
  55. package/src/agentcore-gateway/gateway-connection/schema.json +26 -0
  56. package/src/agentcore-gateway/mcp-connection/schema.json +26 -0
  57. package/src/agentcore-gateway/schema.json +65 -0
  58. package/src/license/schema.json +6 -0
  59. package/src/preset/schema.json +5 -0
  60. package/src/py/agent/gateway-connection/schema.json +26 -0
  61. package/src/py/dynamodb/agent-connection/schema.json +22 -0
  62. package/src/py/dynamodb/fast-api-connection/schema.json +18 -0
  63. package/src/py/dynamodb/mcp-server-connection/schema.json +22 -0
  64. package/src/py/dynamodb/schema.json +70 -0
  65. package/src/ts/agent/gateway-connection/schema.json +26 -0
  66. package/src/ts/dynamodb/agent-connection/schema.json +22 -0
  67. package/src/ts/dynamodb/mcp-server-connection/schema.json +22 -0
  68. package/src/ts/dynamodb/schema.json +70 -0
  69. package/src/ts/dynamodb/smithy-connection/schema.json +18 -0
  70. package/src/ts/dynamodb/trpc-connection/schema.json +18 -0
@@ -47,9 +47,12 @@ The generator creates a shared `agent-connection` package and modifies your agen
47
47
  - packages/common/agent-connection
48
48
  - src
49
49
  - app
50
- - \<target-agent-name>-client.ts High-level client for the connected A2A agent
50
+ - \<target-agent-name>-client-strands.ts High-level Strands client for the connected A2A agent
51
51
  - core
52
- - agentcore-a2a-client.ts Low-level AgentCore A2A client with SigV4 authentication
52
+ - agentcore-endpoints.ts Framework-agnostic ARN/URL resolution
53
+ - agentcore-fetch.ts Framework-agnostic SigV4 / JWT / session-forwarding fetch
54
+ - agentcore-a2a-client-config.ts Framework-agnostic A2A client config (signed `clientFactory`)
55
+ - agentcore-a2a-client-strands.ts Strands A2A client wrapping the config
53
56
  - index.ts Exports all clients
54
57
  - project.json
55
58
  - tsconfig.json
@@ -67,11 +70,11 @@ The generator transforms your agent's `agent.ts` to wrap the remote A2A agent as
67
70
 
68
71
  ```ts title="packages/example/src/my-agent/agent.ts" {2,5-11,14}
69
72
  import { Agent, tool } from '@strands-agents/sdk';
70
- import { RemoteAgentClient } from ':my-scope/agent-connection';
73
+ import { RemoteAgentClientStrands } from ':my-scope/agent-connection';
71
74
  import { z } from 'zod';
72
75
 
73
76
  export const getAgent = async (sessionId: string) => {
74
- const remoteAgent = await RemoteAgentClient.create(sessionId);
77
+ const remoteAgent = await RemoteAgentClientStrands.create(sessionId);
75
78
  const remoteAgentTool = tool({
76
79
  name: 'askRemoteAgent',
77
80
  description: 'Delegate a question to the remote RemoteAgent A2A agent and return its reply.',
@@ -87,7 +90,7 @@ export const getAgent = async (sessionId: string) => {
87
90
 
88
91
  The `sessionId` parameter is plumbed through from the caller, ensuring consistency for [Bedrock AgentCore Observability](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability.html).
89
92
 
90
- Under the hood, `RemoteAgentClient.create(sessionId)` returns a Strands `A2AAgent` configured with a SigV4-signing `clientFactory` when deployed to AWS, and a plain `http://localhost:<port>/` endpoint when `SERVE_LOCAL=true`.
93
+ Under the hood, `RemoteAgentClientStrands.create(sessionId)` returns a Strands `A2AAgent` configured with a SigV4-signing `clientFactory` when deployed to AWS, and a plain `http://localhost:<port>/` endpoint when `SERVE_LOCAL=true`. The signing and endpoint resolution live in the framework-agnostic `agentcore-a2a-client-config.ts`; only the thin `agentcore-a2a-client-strands.ts` depends on Strands.
91
94
 
92
95
  ## Infrastructure
93
96
 
@@ -0,0 +1,128 @@
1
+ ---
2
+ title: TypeScript Agent to DynamoDB
3
+ description: Connect a TypeScript Agent to a TypeScript DynamoDB project
4
+ when:
5
+ sourceType: ts#agent
6
+ targetType: ts#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 NxCommands from '@components/nx-commands.astro';
12
+ import Infrastructure from '@components/infrastructure.astro';
13
+ import Snippet from '@components/snippet.astro';
14
+
15
+ The `connection` generator wires a <Link path="guides/ts-agent">TypeScript Agent</Link> to a <Link path="guides/ts-dynamodb">TypeScript DynamoDB</Link> project, configuring local development so both start together automatically.
16
+
17
+ ## Prerequisites
18
+
19
+ Before using this generator, ensure you have:
20
+
21
+ 1. A <Link path="guides/ts-agent">`ts#agent`</Link> project
22
+ 2. A <Link path="guides/ts-dynamodb">`ts#dynamodb`</Link> project
23
+
24
+ ## Usage
25
+
26
+ ### Run the Generator
27
+
28
+ <RunGenerator generator="connection" />
29
+
30
+ 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.
31
+
32
+ ### Options
33
+
34
+ <GeneratorParameters generator="connection" />
35
+
36
+ ## Generator Output
37
+
38
+ The generator updates the agent's `<agent-name>-serve-local` target in `project.json` to depend on the DynamoDB project's `serve-local` target. No source files are modified.
39
+
40
+ ## Using DynamoDB in Agents
41
+
42
+ Import entity factories from the DynamoDB package and use them inside your agent definition:
43
+
44
+ ```ts title="packages/my-service/src/my-agent/agent.ts"
45
+ import { createExampleEntity } from ':my-scope/my-table';
46
+
47
+ export const getAgent = async () => {
48
+ // ...
49
+ return new Agent({
50
+ tools: [
51
+ tool({
52
+ name: 'list_examples',
53
+ description: 'List all example items',
54
+ func: async () => {
55
+ const entity = await createExampleEntity();
56
+ const result = await entity.scan.go();
57
+ return result.data;
58
+ },
59
+ }),
60
+ ],
61
+ });
62
+ };
63
+ ```
64
+
65
+ ## Infrastructure
66
+
67
+ To allow the agent's Lambda function to access the DynamoDB table, grant the necessary permissions in your infrastructure.
68
+
69
+ <Infrastructure>
70
+ <Fragment slot="cdk">
71
+
72
+ ```ts title="packages/infra/src/stacks/application-stack.ts"
73
+ import { MyTable } from ':my-scope/common-constructs';
74
+
75
+ const table = new MyTable(this, 'Table');
76
+ const myAgent = new MyAgent(this, 'MyAgent');
77
+
78
+ table.grantReadWriteData(myAgent);
79
+ ```
80
+
81
+ `grantReadWriteData` grants both the DynamoDB and KMS permissions to the agent's execution role.
82
+ </Fragment>
83
+ <Fragment slot="terraform">
84
+
85
+ ```hcl title="packages/infra/src/main.tf"
86
+ module "my_table" {
87
+ source = "../../common/terraform/src/app/dynamodb/my-table"
88
+ }
89
+
90
+ resource "aws_iam_role_policy" "dynamodb_access" {
91
+ role = module.my_agent.lambda_role_name
92
+
93
+ policy = jsonencode({
94
+ Version = "2012-10-17"
95
+ Statement = [
96
+ {
97
+ Effect = "Allow"
98
+ Action = [
99
+ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
100
+ "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
101
+ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
102
+ ]
103
+ Resource = [
104
+ module.my_table.table_arn,
105
+ "${module.my_table.table_arn}/index/*",
106
+ ]
107
+ },
108
+ {
109
+ Effect = "Allow"
110
+ Action = [
111
+ "kms:Encrypt",
112
+ "kms:Decrypt",
113
+ "kms:ReEncrypt*",
114
+ "kms:GenerateDataKey*",
115
+ "kms:DescribeKey"
116
+ ]
117
+ Resource = [module.my_table.kms_key_arn]
118
+ },
119
+ ]
120
+ })
121
+ }
122
+ ```
123
+ </Fragment>
124
+ </Infrastructure>
125
+
126
+ ## Local Development
127
+
128
+ <Snippet name="connection/dynamodb-local-development" />
@@ -0,0 +1,152 @@
1
+ ---
2
+ title: TypeScript Agent to Gateway
3
+ description: Connect a TypeScript Agent to an AgentCore Gateway
4
+ when:
5
+ sourceType: ts#agent
6
+ targetType: agentcore-gateway
7
+ ---
8
+ import { FileTree } 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/ts-agent">TypeScript 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 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 TypeScript project with a <Link path="guides/ts-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 client files into your `agent-connection` package, plus a per-Gateway wrapper, and modifies your agent:
41
+
42
+ <FileTree>
43
+
44
+ - packages/common/agent-connection
45
+ - src
46
+ - core/
47
+ - agentcore-endpoints.ts Framework-agnostic ARN/URL resolution
48
+ - agentcore-gateway-mcp-transport.ts Framework-agnostic Gateway MCP transport
49
+ - agentcore-gateway-mcp-client-strands.ts Strands MCP client for the deployed Gateway
50
+ - app/
51
+ - \<gateway-kebab>-client-strands.ts Per-Gateway Strands client wrapper
52
+ - index.ts Re-exports the Gateway client
53
+
54
+ </FileTree>
55
+
56
+ Additionally, the generator:
57
+
58
+ - Modifies your agent's `agent.ts` to import the Gateway client class, call `<Gateway>ClientStrands.create()`, and register the returned client in the `tools` array
59
+ - Wires the agent's `<agent>-serve-local` target to depend on the Gateway's `<gateway>-serve-local` aggregator
60
+ - Installs the required SigV4 / MCP dependencies
61
+
62
+ ## Using the connected Gateway
63
+
64
+ The generator transforms your agent's `agent.ts` to use the Gateway client:
65
+
66
+ ```ts title="packages/example/src/my-agent/agent.ts" {2,5,8}
67
+ import { Agent } from '@strands-agents/sdk';
68
+ import { MyGatewayClientStrands } from ':my-scope/agent-connection';
69
+
70
+ export const getAgent = async () => {
71
+ const myGateway = await MyGatewayClientStrands.create();
72
+ return new Agent({
73
+ systemPrompt: '...',
74
+ tools: [myGateway],
75
+ });
76
+ };
77
+ ```
78
+
79
+ When deployed (`SERVE_LOCAL` unset), the client points at the Gateway's MCP endpoint and authenticates with SigV4. When `SERVE_LOCAL=true`, it points at the local gateway started by the Gateway project's `serve-local` target, so the same `agent.ts` works uniformly in both modes.
80
+
81
+ The session ID is propagated to downstream MCP servers automatically via the `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id` header.
82
+
83
+ ## Infrastructure
84
+
85
+ After running the generator you must grant the agent permission to invoke the Gateway.
86
+
87
+ <Infrastructure>
88
+ <Fragment slot="cdk">
89
+ ```ts title="packages/infra/src/stacks/application-stack.ts" {5}
90
+ const gateway = new MyGateway(this, 'MyGateway');
91
+ const myAgent = new MyAgent(this, 'MyAgent');
92
+
93
+ // Grant the agent permissions to invoke the Gateway
94
+ gateway.grantInvokeAccess(myAgent);
95
+ ```
96
+
97
+ 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.
98
+ </Fragment>
99
+ <Fragment slot="terraform">
100
+ ```hcl title="packages/infra/src/main.tf" {12-24}
101
+ module "my_gateway" {
102
+ source = "../../common/terraform/src/app/gateways/my-gateway"
103
+ }
104
+
105
+ module "my_agent" {
106
+ source = "../../common/terraform/src/app/agents/my-agent"
107
+ }
108
+
109
+ # Grant the agent permission to invoke the Gateway
110
+ resource "aws_iam_policy" "agent_invoke_gateway" {
111
+ name = "AgentInvokeGatewayPolicy"
112
+ policy = jsonencode({
113
+ Version = "2012-10-17"
114
+ Statement = [{
115
+ Effect = "Allow"
116
+ Action = "bedrock-agentcore:InvokeGateway"
117
+ Resource = module.my_gateway.gateway_arn
118
+ }]
119
+ })
120
+ }
121
+
122
+ resource "aws_iam_role_policy_attachment" "agent_invoke_gateway" {
123
+ role = module.my_agent.agent_core_runtime_role_arn
124
+ policy_arn = aws_iam_policy.agent_invoke_gateway.arn
125
+ }
126
+ ```
127
+
128
+ 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.
129
+ </Fragment>
130
+ </Infrastructure>
131
+
132
+ ## Local Development
133
+
134
+ The generator configures the agent's `serve-local` target to:
135
+
136
+ 1. Start the connected Gateway's local gateway and every attached MCP server
137
+ 2. Set `SERVE_LOCAL=true` so the generated client points at the local gateway instead of the deployed Gateway
138
+
139
+ Run the agent locally with:
140
+
141
+ <NxCommands commands={["<agent-name>-serve-local <project-name>"]} />
142
+
143
+ To run the agent locally **against the deployed Gateway** instead (for example, to exercise Cedar policies), use the agent's `serve` target. Without `SERVE_LOCAL` set, the client resolves the deployed Gateway URL from runtime configuration and SigV4-signs requests with your local AWS credentials:
144
+
145
+ <NxCommands commands={["<agent-name>-serve <project-name>"]} />
146
+
147
+ ### Local fidelity
148
+
149
+ The local gateway stands in for the deployed Gateway, so:
150
+
151
+ - **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.
152
+ - **Tool-name prefixing is preserved.** Each local MCP server's tools are wrapped to expose names of the form `<target-name>___<tool-name>`, matching what the deployed Gateway emits. This keeps an agent's system prompt and the Cedar action names you reference consistent across local and deployed runs.
@@ -47,9 +47,12 @@ The generator creates a shared `agent-connection` package and modifies your agen
47
47
  - packages/common/agent-connection
48
48
  - src
49
49
  - app
50
- - \<mcp-server-name>-client.ts High-level client for the connected MCP server
50
+ - \<mcp-server-name>-client-strands.ts High-level Strands client for the connected MCP server
51
51
  - core
52
- - agentcore-mcp-client.ts Low-level AgentCore MCP client with SigV4/JWT authentication
52
+ - agentcore-endpoints.ts Framework-agnostic ARN/URL resolution
53
+ - agentcore-fetch.ts Framework-agnostic SigV4 / JWT / session-forwarding fetch
54
+ - agentcore-mcp-transport.ts Framework-agnostic MCP transport
55
+ - agentcore-mcp-client-strands.ts Strands MCP client wrapping the transport
53
56
  - index.ts Exports all clients
54
57
  - project.json
55
58
  - tsconfig.json
@@ -67,10 +70,10 @@ The generator transforms your agent's `agent.ts` to use the MCP server's tools:
67
70
 
68
71
  ```ts title="packages/example/src/my-agent/agent.ts" {2,5,8}
69
72
  import { Agent, tool } from '@strands-agents/sdk';
70
- import { MyMcpServerClient } from ':my-scope/agent-connection';
73
+ import { MyMcpServerClientStrands } from ':my-scope/agent-connection';
71
74
 
72
75
  export const getAgent = async (sessionId: string) => {
73
- const myMcpServerClient = await MyMcpServerClient.create(sessionId);
76
+ const myMcpServerClient = await MyMcpServerClientStrands.create(sessionId);
74
77
  return new Agent({
75
78
  systemPrompt: '...',
76
79
  tools: [myMcpServerClient],
@@ -0,0 +1,125 @@
1
+ ---
2
+ title: MCP Server to DynamoDB
3
+ description: Connect a TypeScript MCP Server to a TypeScript DynamoDB project
4
+ when:
5
+ sourceType: ts#mcp-server
6
+ targetType: ts#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 NxCommands from '@components/nx-commands.astro';
12
+ import Infrastructure from '@components/infrastructure.astro';
13
+ import Snippet from '@components/snippet.astro';
14
+
15
+ The `connection` generator wires a <Link path="guides/ts-mcp-server">TypeScript MCP Server</Link> to a <Link path="guides/ts-dynamodb">TypeScript DynamoDB</Link> project, configuring local development so both start together automatically.
16
+
17
+ ## Prerequisites
18
+
19
+ Before using this generator, ensure you have:
20
+
21
+ 1. A <Link path="guides/ts-mcp-server">`ts#mcp-server`</Link> project
22
+ 2. A <Link path="guides/ts-dynamodb">`ts#dynamodb`</Link> project
23
+
24
+ ## Usage
25
+
26
+ ### Run the Generator
27
+
28
+ <RunGenerator generator="connection" />
29
+
30
+ Select your MCP server project as the source and your DynamoDB project as the target. If the project contains multiple MCP server components, specify `sourceComponent` to disambiguate.
31
+
32
+ ### Options
33
+
34
+ <GeneratorParameters generator="connection" />
35
+
36
+ ## Generator Output
37
+
38
+ The generator updates the MCP server's `<mcp-server-name>-serve-local` target in `project.json` to depend on the DynamoDB project's `serve-local` target. No source files are modified.
39
+
40
+ ## Using DynamoDB in Tools
41
+
42
+ Import entity factories from the DynamoDB package and use them inside `createServer`:
43
+
44
+ ```ts title="packages/my-service/src/my-mcp/server.ts"
45
+ import { createExampleEntity } from ':my-scope/my-table';
46
+
47
+ export const createServer = async () => {
48
+ const server = new McpServer({ name: 'my-service', version: '1.0.0' });
49
+
50
+ server.tool('list_examples', 'List all example items', {}, async () => {
51
+ const entity = await createExampleEntity();
52
+ const result = await entity.scan.go();
53
+ return {
54
+ content: [{ type: 'text', text: JSON.stringify(result.data) }],
55
+ };
56
+ });
57
+
58
+ return server;
59
+ };
60
+ ```
61
+
62
+ ## Infrastructure
63
+
64
+ To allow the MCP server to access the DynamoDB table, grant the necessary permissions in your infrastructure.
65
+
66
+ <Infrastructure>
67
+ <Fragment slot="cdk">
68
+
69
+ ```ts title="packages/infra/src/stacks/application-stack.ts"
70
+ import { MyTable } from ':my-scope/common-constructs';
71
+
72
+ const table = new MyTable(this, 'Table');
73
+ const myMcpServer = new MyMcpServer(this, 'MyMcpServer');
74
+
75
+ table.grantReadWriteData(myMcpServer);
76
+ ```
77
+
78
+ `grantReadWriteData` grants both the DynamoDB and KMS permissions to the MCP server's execution role.
79
+ </Fragment>
80
+ <Fragment slot="terraform">
81
+
82
+ ```hcl title="packages/infra/src/main.tf"
83
+ module "my_table" {
84
+ source = "../../common/terraform/src/app/dynamodb/my-table"
85
+ }
86
+
87
+ resource "aws_iam_role_policy" "dynamodb_access" {
88
+ role = module.my_mcp_server.lambda_role_name
89
+
90
+ policy = jsonencode({
91
+ Version = "2012-10-17"
92
+ Statement = [
93
+ {
94
+ Effect = "Allow"
95
+ Action = [
96
+ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
97
+ "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
98
+ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
99
+ ]
100
+ Resource = [
101
+ module.my_table.table_arn,
102
+ "${module.my_table.table_arn}/index/*",
103
+ ]
104
+ },
105
+ {
106
+ Effect = "Allow"
107
+ Action = [
108
+ "kms:Encrypt",
109
+ "kms:Decrypt",
110
+ "kms:ReEncrypt*",
111
+ "kms:GenerateDataKey*",
112
+ "kms:DescribeKey",
113
+ ]
114
+ Resource = [module.my_table.kms_key_arn]
115
+ },
116
+ ]
117
+ })
118
+ }
119
+ ```
120
+ </Fragment>
121
+ </Infrastructure>
122
+
123
+ ## Local Development
124
+
125
+ <Snippet name="connection/dynamodb-local-development" />
@@ -119,8 +119,97 @@ The Connection generator supports the following connections:
119
119
  source="mcp"
120
120
  target="aurora"
121
121
  />
122
+ <ConnectionCard
123
+ title="tRPC API to TypeScript DynamoDB"
124
+ description="Connect a tRPC API to a DynamoDB table"
125
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/trpc-dynamodb`}
126
+ source="trpc"
127
+ target="dynamodb"
128
+ />
129
+ <ConnectionCard
130
+ title="Smithy API to TypeScript DynamoDB"
131
+ description="Connect a Smithy API to a DynamoDB table"
132
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/smithy-dynamodb`}
133
+ source="smithy"
134
+ target="dynamodb"
135
+ />
136
+ <ConnectionCard
137
+ title="TypeScript Agent to TypeScript DynamoDB"
138
+ description="Connect a TypeScript Agent to a DynamoDB table"
139
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/ts-agent-dynamodb`}
140
+ source="strands"
141
+ sourceBadge="typescript"
142
+ target="dynamodb"
143
+ />
144
+ <ConnectionCard
145
+ title="MCP Server to TypeScript DynamoDB"
146
+ description="Connect a TypeScript MCP Server to a DynamoDB table"
147
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/ts-mcp-server-dynamodb`}
148
+ source="mcp"
149
+ target="dynamodb"
150
+ />
151
+ <ConnectionCard
152
+ title="FastAPI to Python DynamoDB"
153
+ description="Connect a FastAPI to a DynamoDB table"
154
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-fast-api-dynamodb`}
155
+ source="fastapi"
156
+ target="dynamodb"
157
+ targetBadge="python"
158
+ />
159
+ <ConnectionCard
160
+ title="Python Agent to Python DynamoDB"
161
+ description="Connect a Python Agent to a DynamoDB table"
162
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-agent-dynamodb`}
163
+ source="strands"
164
+ sourceBadge="python"
165
+ target="dynamodb"
166
+ targetBadge="python"
167
+ />
168
+ <ConnectionCard
169
+ title="Python MCP Server to Python DynamoDB"
170
+ description="Connect a Python MCP Server to a DynamoDB table"
171
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-mcp-server-dynamodb`}
172
+ source="mcp"
173
+ sourceBadge="python"
174
+ target="dynamodb"
175
+ targetBadge="python"
176
+ />
177
+ <ConnectionCard
178
+ title="AgentCore Gateway to MCP Server"
179
+ description="Aggregate an MCP server behind an AgentCore Gateway"
180
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/agentcore-gateway-mcp`}
181
+ source="agentcore"
182
+ target="mcp"
183
+ />
184
+ <ConnectionCard
185
+ title="AgentCore Gateway to AgentCore Gateway"
186
+ description="Aggregate an AgentCore Gateway behind another AgentCore Gateway"
187
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/agentcore-gateway-gateway`}
188
+ source="agentcore"
189
+ target="agentcore"
190
+ />
191
+ <ConnectionCard
192
+ title="TypeScript Agent to AgentCore Gateway"
193
+ description="Connect a TypeScript Agent to an AgentCore Gateway"
194
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/ts-agent-gateway`}
195
+ source="strands"
196
+ sourceBadge="typescript"
197
+ target="agentcore"
198
+ />
199
+ <ConnectionCard
200
+ title="Python Agent to AgentCore Gateway"
201
+ description="Connect a Python Agent to an AgentCore Gateway"
202
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-agent-gateway`}
203
+ source="strands"
204
+ sourceBadge="python"
205
+ target="agentcore"
206
+ />
122
207
  </CardGrid>
123
208
 
124
209
  :::note[Runtime Configuration]
125
210
  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.
126
211
  :::
212
+
213
+ :::tip[Local Development]
214
+ Connected projects can be run on your machine with the `serve` and `serve-local` targets. See the <Link path="guides/local-development">Local Development</Link> guide for details.
215
+ :::
@@ -8,7 +8,7 @@ import NxCommands from '@components/nx-commands.astro';
8
8
  import Link from '@components/link.astro';
9
9
  import Infrastructure from '@components/infrastructure.astro';
10
10
 
11
- 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">`py#fast-api`</Link> project on Amazon ECS, or deploying a containerised Express server.
11
+ 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
12
 
13
13
  :::tip[Docker or Finch]
14
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.
@@ -318,8 +318,8 @@ Terraform's AWS provider does not have a first-class "build and push a Docker im
318
318
 
319
319
  1. The project's `build` target runs `docker build`, producing a local image tagged `my-scope-my-project:latest`.
320
320
  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"`.
321
+ 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.
322
+ 4. The downstream resource (e.g. `aws_ecs_task_definition`) references the image by its immutable, digest-based tag.
323
323
 
324
324
  ```d2
325
325
  direction: down
@@ -361,7 +361,7 @@ infra.repo -> ecr
361
361
  ```hcl
362
362
  resource "aws_ecr_repository" "repo" {
363
363
  name = "my-project-repository"
364
- image_tag_mutability = "MUTABLE"
364
+ image_tag_mutability = "IMMUTABLE"
365
365
  force_delete = true
366
366
  }
367
367
 
@@ -370,24 +370,30 @@ data "external" "docker_digest" {
370
370
  program = ["sh", "-c", "echo '{\"digest\":\"'$(docker inspect my-scope-my-project:latest --format '{{.Id}}')'\"}'"]
371
371
  }
372
372
 
373
+ locals {
374
+ # Content-based, immutable image tag derived from the local image digest
375
+ image_tag = replace(data.external.docker_digest.result.digest, "sha256:", "")
376
+ }
377
+
373
378
  resource "null_resource" "docker_publish" {
374
379
  triggers = {
375
380
  docker_digest = data.external.docker_digest.result.digest
376
381
  repository_url = aws_ecr_repository.repo.repository_url
382
+ image_tag = local.image_tag
377
383
  }
378
384
 
379
385
  provisioner "local-exec" {
380
386
  command = <<-EOT
381
387
  aws ecr get-login-password --region ${data.aws_region.current.id} \
382
388
  | 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
389
+ docker tag my-scope-my-project:latest ${self.triggers.repository_url}:${self.triggers.image_tag}
390
+ docker push ${self.triggers.repository_url}:${self.triggers.image_tag}
385
391
  EOT
386
392
  }
387
393
  }
388
394
  ```
389
395
 
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.
396
+ 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
397
 
392
398
  :::note[Running bundle before apply]
393
399
  `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>`.