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

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.
@@ -454,7 +454,6 @@ The `py#agent` generates these files:
454
454
  - session.py resolves a SessionManager for persisting conversation state
455
455
  - middleware/
456
456
  - session_id_middleware.py binds the inbound AgentCore session ID for the request
457
- - Dockerfile defines the docker image for deployment to AgentCore Runtime
458
457
  - common/constructs/
459
458
  - src
460
459
  - app/agents/story-agent/
@@ -616,7 +615,6 @@ This is the entrypoint for the agent. Because we selected `--protocol=ag-ui`, th
616
615
  ```ts
617
616
  // common/constructs/src/app/agents/story-agent/story-agent.ts
618
617
  import { Fn, Lazy, Names, RemovalPolicy, Stack } from 'aws-cdk-lib';
619
- import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
620
618
  import { Connections, IConnectable } from 'aws-cdk-lib/aws-ec2';
621
619
  import {
622
620
  BlockPublicAccess,
@@ -635,6 +633,7 @@ import { Construct } from 'constructs';
635
633
  import * as path from 'path';
636
634
  import * as url from 'url';
637
635
  import {
636
+ AgentCoreRuntime,
638
637
  AgentRuntimeArtifact,
639
638
  ProtocolType,
640
639
  Runtime,
@@ -678,7 +677,7 @@ export type StoryAgentProps = Omit<
678
677
  };
679
678
 
680
679
  export class StoryAgent extends Construct implements IGrantable, IConnectable {
681
- public readonly dockerImage: AgentRuntimeArtifact;
680
+ public readonly code: AgentRuntimeArtifact;
682
681
  public readonly agentCoreRuntime: Runtime;
683
682
  /** Default Gateway target name for this agent. */
684
683
  public readonly agentName = 'story-agent';
@@ -690,14 +689,19 @@ export class StoryAgent extends Construct implements IGrantable, IConnectable {
690
689
 
691
690
  const rc = RuntimeConfig.ensure(this);
692
691
 
693
- // Resolve the bundle output directory containing the Dockerfile and built artifacts
692
+ // Resolve the packaged code directory, uploaded as a zip asset
694
693
  const bundleDir = path.join(
695
694
  findWorkspaceRoot(url.fileURLToPath(new URL(import.meta.url))),
696
- 'dist/packages/story/docker/story-agent',
695
+ 'dist/packages/story/package/story-agent',
697
696
  );
698
697
 
699
- this.dockerImage = AgentRuntimeArtifact.fromAsset(bundleDir, {
700
- platform: Platform.LINUX_ARM64,
698
+ // The `opentelemetry-instrument` prefix auto-instruments with the AWS Distro
699
+ // for OpenTelemetry packaged alongside the code.
700
+ // https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/observability-configure.html
701
+ this.code = AgentRuntimeArtifact.fromCodeAsset({
702
+ path: bundleDir,
703
+ runtime: AgentCoreRuntime.PYTHON_3_14,
704
+ entrypoint: ['opentelemetry-instrument', 'main.py'],
701
705
  });
702
706
 
703
707
  const {
@@ -817,7 +821,7 @@ export class StoryAgent extends Construct implements IGrantable, IConnectable {
817
821
  Names.uniqueResourceName(this.agentCoreRuntime, { maxLength: 40 }),
818
822
  }),
819
823
  protocolConfiguration: ProtocolType.HTTP,
820
- agentRuntimeArtifact: this.dockerImage,
824
+ agentRuntimeArtifact: this.code,
821
825
  authorizerConfiguration: RuntimeAuthorizerConfiguration.usingCognito(
822
826
  identity.userPool,
823
827
  [identity.userPoolClient],
@@ -138,7 +138,7 @@ Before you proceed, you will need the following global dependencies:
138
138
 
139
139
  <Snippet name="required-prerequisites" />
140
140
  - [AWS Credentials](https://docs.aws.amazon.com/sdkref/latest/guide/access.html) configured to your target AWS account, since this tutorial deploys the application and invokes Amazon Bedrock
141
- - [Docker](https://www.docker.com/) (or [Finch](https://github.com/runfinch/finch)) is required for local DynamoDB development and for building the AgentCore components
141
+ - [Docker](https://www.docker.com/) (or [Finch](https://github.com/runfinch/finch)) is required for local DynamoDB development
142
142
 
143
143
  :::tip[AI Assistant Setup]
144
144
  If you use an AI Assistant such as Kiro, Kiro CLI, Cursor, Claude Code or Cline, refer to the <Link path="/get_started/building-with-ai">install the Nx Plugin for AWS MCP server</Link> page.
@@ -379,10 +379,12 @@ Use the `DockerImageAsset` with any AWS construct that accepts a container image
379
379
  Terraform's AWS provider does not have a first-class "build and push a Docker image" resource. The pattern used by the generators is:
380
380
 
381
381
  1. The project's `build` target runs `docker build`, producing a local image tagged `my-scope-my-project:latest`.
382
- 2. An `aws_ecr_repository` to hold the image.
382
+ 2. A shared ECR repository using the `core/asset-ecr` module
383
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
384
  4. The downstream resource (e.g. `aws_ecs_task_definition`) references the image by its immutable, digest-based tag.
385
385
 
386
+ Because one repository holds every image, each tag is namespaced by the image's owner as well as its digest, so images sharing the registry never collide.
387
+
386
388
  ```d2
387
389
  direction: down
388
390
 
@@ -407,7 +409,7 @@ app: Application {
407
409
  infra: Infrastructure {
408
410
  direction: right
409
411
  publish: "null_resource\nlocal-exec: docker push"
410
- repo: aws_ecr_repository
412
+ repo: "core/asset-ecr\n(shared)"
411
413
  publish -> repo: tag + push
412
414
  }
413
415
 
@@ -421,10 +423,8 @@ infra.repo -> ecr
421
423
 
422
424
 
423
425
  ```hcl
424
- resource "aws_ecr_repository" "repo" {
425
- name = "my-project-repository"
426
- image_tag_mutability = "IMMUTABLE"
427
- force_delete = true
426
+ module "asset_ecr" {
427
+ source = "../../common/terraform/src/core/asset-ecr"
428
428
  }
429
429
 
430
430
  # Invalidate the push whenever the locally-built image digest changes
@@ -433,14 +433,15 @@ data "external" "docker_digest" {
433
433
  }
434
434
 
435
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:", "")
436
+ # Content-based, immutable image tag derived from the local image digest, and
437
+ # namespaced by owner so images sharing the registry never collide
438
+ image_tag = "my-project-${replace(data.external.docker_digest.result.digest, "sha256:", "")}"
438
439
  }
439
440
 
440
441
  resource "null_resource" "docker_publish" {
441
442
  triggers = {
442
443
  docker_digest = data.external.docker_digest.result.digest
443
- repository_url = aws_ecr_repository.repo.repository_url
444
+ repository_url = module.asset_ecr.repository_url
444
445
  image_tag = local.image_tag
445
446
  }
446
447
 
@@ -455,7 +456,7 @@ resource "null_resource" "docker_publish" {
455
456
  }
456
457
  ```
457
458
 
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.
459
+ 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 shared repository uses `IMMUTABLE` tag mutability and rejects any attempt to overwrite an existing tag.
459
460
 
460
461
  :::note[Running bundle before apply]
461
462
  `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>`.
@@ -55,7 +55,7 @@ The generator will add the following files to your existing Python project. The
55
55
  - \_\_init\_\_.py Python package initialization
56
56
  - session_id_middleware.py Binds the inbound AgentCore session ID for the request
57
57
  - main.py FastAPI entry point for Bedrock AgentCore Runtime
58
- - Dockerfile Entry point for hosting your agent (excluded when `infra` is set to `None`)
58
+ - Dockerfile Container image definition (only when `infra` is `agentcore-ecr`)
59
59
  - pyproject.toml Updated with Strands dependencies
60
60
  - project.json Updated with agent serve targets
61
61
  </FileTree>
@@ -77,7 +77,7 @@ The entry point exposes your agent over the A2A protocol (Strands uses the [Stra
77
77
  - \_\_init\_\_.py Python package initialization
78
78
  - session_id_middleware.py Binds the inbound AgentCore session ID for the request
79
79
  - main.py A2A server entry point
80
- - Dockerfile Entry point for hosting your agent (excluded when `infra` is set to `None`)
80
+ - Dockerfile Container image definition (only when `infra` is `agentcore-ecr`)
81
81
  - pyproject.toml Updated with framework and A2A dependencies
82
82
  - project.json Updated with agent serve targets
83
83
  </FileTree>
@@ -99,7 +99,7 @@ The entry point exposes your agent via the [AG-UI](https://docs.ag-ui.com/) prot
99
99
  - \_\_init\_\_.py Python package initialization
100
100
  - session_id_middleware.py Binds the inbound AgentCore session ID for the request
101
101
  - main.py AG-UI server entry point
102
- - Dockerfile Entry point for hosting your agent (excluded when `infra` is set to `None`)
102
+ - Dockerfile Container image definition (only when `infra` is `agentcore-ecr`)
103
103
  - pyproject.toml Updated with framework and AG-UI dependencies
104
104
  - project.json Updated with agent serve targets
105
105
  </FileTree>
@@ -111,7 +111,9 @@ AG-UI agents can be connected to a React frontend using the <Link path="/guides/
111
111
 
112
112
  ### Infrastructure
113
113
 
114
- <OptionFilter when={{ infra: 'agentcore' }} description="Bedrock AgentCore Runtime deployment">
114
+ <Snippet name="agentcore-hosting" />
115
+
116
+ <OptionFilter when={{ infra: ['agentcore', 'agentcore-ecr'] }} description="Bedrock AgentCore Runtime deployment">
115
117
  <Snippet name="shared-constructs" />
116
118
 
117
119
  For deploying your Agent, the following files are generated:
@@ -136,6 +138,10 @@ For deploying your Agent, the following files are generated:
136
138
  - core
137
139
  - agent-core
138
140
  - runtime.tf Generic module for deploying to Bedrock AgentCore Runtime
141
+ - agent-core-code (when `infra` is `agentcore`)
142
+ - runtime.tf Packages your agent's code and delegates to `agent-core`
143
+ - agent-core-container (when `infra` is `agentcore-ecr`)
144
+ - runtime.tf Builds and publishes your agent's image and delegates to `agent-core`
139
145
  </FileTree>
140
146
  </Fragment>
141
147
  </Infrastructure>
@@ -296,7 +302,7 @@ Your agent's server protocol determines how it communicates. All options are ser
296
302
 
297
303
  The server entry point differs by framework (Strands yields a context-managed `Agent`, while LangChain drives a compiled `create_agent` graph), but the external contract for each protocol is the same.
298
304
 
299
- All protocols expose `/ping` for the AgentCore runtime health check contract. A2A agents listen on port `9000`; HTTP and AG-UI agents listen on port `8080`. The generated Dockerfile and infrastructure are configured for you.
305
+ All protocols expose `/ping` for the AgentCore runtime health check contract. A2A agents listen on port `9000`; HTTP and AG-UI agents listen on port `8080`. The generated infrastructure is configured for you.
300
306
 
301
307
  <OptionFilter when={{ protocol: 'http' }} description="FastAPI HTTP server details">
302
308
  ## FastAPI Server (HTTP protocol)
@@ -441,7 +447,7 @@ For **HTTP** agents, the chat script uses a type-safe TypeScript client generate
441
447
 
442
448
  When you customize the agent's input shape (e.g. add new fields to `InvokeInput`), update `chat.ts` to pass the new fields when invoking the agent and the rest works automatically.
443
449
 
444
- <OptionFilter when={{ infra: 'agentcore' }} description="Deployed agent chat details">
450
+ <OptionFilter when={{ infra: ['agentcore', 'agentcore-ecr'] }} description="Deployed agent chat details">
445
451
  #### Chat with your deployed agent
446
452
 
447
453
  To chat with your agent deployed to Bedrock AgentCore, set the `RUNTIME_CONFIG_APP_ID` environment variable to the AppConfig application id of the deployment (output as `RuntimeConfigApplicationId` by the deployed stack). The chat script resolves your agent's runtime ARN from runtime configuration and connects to the deployed endpoint:
@@ -473,7 +479,7 @@ aws cognito-idp admin-initiate-auth \
473
479
  </Tabs>
474
480
  </OptionFilter>
475
481
 
476
- <OptionFilter when={{ infra: 'agentcore' }} description="Bedrock AgentCore Runtime deployment details">
482
+ <OptionFilter when={{ infra: ['agentcore', 'agentcore-ecr'] }} description="Bedrock AgentCore Runtime deployment details">
477
483
  ## Deploying Your Agent to Bedrock AgentCore Runtime
478
484
 
479
485
  <Snippet name="agent/bedrock-deployment" parentHeading="Deploying Your Agent to Bedrock AgentCore Runtime" />
@@ -485,15 +491,21 @@ In order to build your Agent for Bedrock AgentCore Runtime, a `bundle` target is
485
491
  - Exports your Python dependencies to a `requirements.txt` file using `uv export`
486
492
  - Installs dependencies for the target platform (`aarch64-manylinux_2_28`) using `uv pip install`
487
493
 
494
+ <OptionFilter when={{ infra: 'agentcore' }} description="Code package target">
495
+ A `<your-agent-name>-package` target is also added, which assembles the deployable code package: the `aarch64` dependency bundle, your Python module tree, and a root `main.py` entry point. The generated infrastructure uploads this directory as a `.zip` — via `AgentRuntimeArtifact.fromCodeAsset` under CDK, or archived into the shared asset bucket under Terraform.
496
+ </OptionFilter>
497
+
498
+ <OptionFilter when={{ infra: 'agentcore-ecr' }} description="Container image build and scan">
488
499
  A `docker` target specific to your Agent is also added, which copies the `Dockerfile` and bundled artifacts into a docker context directory. This co-locates the `Dockerfile` with the built output, allowing CDK to build the Docker image directly using `AgentRuntimeArtifact.fromAsset`.
489
500
 
490
501
  ### Image Scanning
491
502
 
492
503
  <Snippet name="trivy-image-scan" parentHeading="Image Scanning" />
504
+ </OptionFilter>
493
505
 
494
506
  ### Observability
495
507
 
496
- Your agent is automatically configured with observability using the [AWS Distro for Open Telemetry](https://aws.amazon.com/otel/) (ADOT), by configuring auto-instrumentation in your `Dockerfile`.
508
+ Your agent is automatically configured with observability using the [AWS Distro for Open Telemetry](https://aws.amazon.com/otel/) (ADOT).
497
509
 
498
510
  You can find traces in the CloudWatch AWS Console, by selecting "GenAI Observability" in the menu. Note that for traces to be populated you will need to enable [Transaction Search](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Transaction-Search.html).
499
511
 
@@ -51,14 +51,16 @@ The generator will add the following files to your existing Python project:
51
51
  - server.py Main server definition with sample tools and resources
52
52
  - stdio.py Entry point for STDIO transport, useful for simple local MCP servers
53
53
  - http.py Entry point for Streamable HTTP transport, useful for hosting your MCP server
54
- - Dockerfile Entry point for hosting your MCP server (excluded when `infra` is set to `None`)
54
+ - Dockerfile Container image definition (only when `infra` is `agentcore-ecr`)
55
55
  - pyproject.toml Updated with MCP dependencies
56
56
  - project.json Updated with MCP server serve targets
57
57
  </FileTree>
58
58
 
59
59
  ### Infrastructure
60
60
 
61
- <OptionFilter when={{ infra: 'agentcore' }} description="Bedrock AgentCore Runtime deployment">
61
+ <Snippet name="agentcore-hosting" />
62
+
63
+ <OptionFilter when={{ infra: ['agentcore', 'agentcore-ecr'] }} description="Bedrock AgentCore Runtime deployment">
62
64
  <Snippet name="shared-constructs" />
63
65
 
64
66
  <Snippet name="mcp/shared-constructs" />
@@ -157,7 +159,7 @@ If you would like to run your MCP server locally using [Streamable HTTP transpor
157
159
 
158
160
  This command uses `uv run uvicorn --reload` to run your MCP server with HTTP transport (typically on port `8000`), and automatically restarts when files change.
159
161
 
160
- <OptionFilter when={{ infra: 'agentcore' }} description="Bedrock AgentCore Runtime deployment details">
162
+ <OptionFilter when={{ infra: ['agentcore', 'agentcore-ecr'] }} description="Bedrock AgentCore Runtime deployment details">
161
163
  ## Deploying Your MCP Server to Bedrock AgentCore Runtime
162
164
 
163
165
  <Snippet name="mcp/bedrock-deployment" parentHeading="Deploying Your MCP Server to Bedrock AgentCore Runtime" />
@@ -169,11 +171,17 @@ In order to build your MCP server for Bedrock AgentCore Runtime, a `bundle` targ
169
171
  - Exports your Python dependencies to a `requirements.txt` file using `uv export`
170
172
  - Installs dependencies for the target platform (`aarch64-manylinux_2_28`) using `uv pip install`
171
173
 
174
+ <OptionFilter when={{ infra: 'agentcore' }} description="Code package target">
175
+ A `<your-server-name>-package` target is also added, which assembles the deployable code package: the `aarch64` dependency bundle, your Python module tree, and a root `main.py` entry point. The generated infrastructure uploads this directory as a `.zip` — via `AgentRuntimeArtifact.fromCodeAsset` under CDK, or archived into the shared asset bucket under Terraform.
176
+ </OptionFilter>
177
+
178
+ <OptionFilter when={{ infra: 'agentcore-ecr' }} description="Container image build and scan">
172
179
  A `docker` target specific to your MCP server is also added, which copies the `Dockerfile` and bundled artifacts into a docker context directory. This co-locates the `Dockerfile` with the built output, allowing CDK to build the Docker image directly using `AgentRuntimeArtifact.fromAsset`.
173
180
 
174
181
  ### Image Scanning
175
182
 
176
183
  <Snippet name="trivy-image-scan" parentHeading="Image Scanning" />
184
+ </OptionFilter>
177
185
 
178
186
  ### Observability
179
187
 
@@ -235,7 +235,7 @@ The user identity module automatically adds the necessary <Link path="guides/rea
235
235
  </Infrastructure>
236
236
 
237
237
  :::caution[Remove localhost callback URLs for production]
238
- The generated User Pool client allows your CloudFront distribution URL (and any custom domain names configured on it) as OAuth callback/logout URLs, plus `http://localhost:4200` and `http://localhost:4300` for local development against the deployed pool.
238
+ The generated User Pool client allows your CloudFront distribution URL (and any custom domain names configured on it) as OAuth callback/logout URLs, plus each connected website's own local dev-server and preview URLs (e.g. `http://localhost:4200` and `http://localhost:4300` for the first website generated in a workspace) for local development against the deployed pool. Each website generated with `ts#website` is assigned its own distinct ports, so a workspace with multiple websites will have more than one `http://localhost:<port>` pair allow-listed here.
239
239
 
240
240
  It is recommended to **remove the `http://localhost` callback/logout URLs for production stages**, keeping the allowlist limited to your real application origins.
241
241
 
@@ -63,7 +63,7 @@ The generator will add the following files to your existing TypeScript project.
63
63
  - session.ts Resolves the SessionManager used to persist conversation state
64
64
  - client.ts Vended client for invoking your agent
65
65
  - agent-core-trpc-client.ts Client factory for connecting to agents on AgentCore Runtime
66
- - Dockerfile Entry point for hosting your agent (excluded when `infra` is set to `None`)
66
+ - Dockerfile Container image definition (only when `infra` is `agentcore-ecr`)
67
67
  - package.json Updated with Strands dependencies
68
68
  - project.json Updated with agent serve targets
69
69
  </FileTree>
@@ -81,7 +81,7 @@ The entry point uses the [Strands A2A Express Server](https://strandsagents.com/
81
81
  - index.ts A2A Express server entry point
82
82
  - agent.ts Main agent definition with sample tools
83
83
  - session.ts Resolves the SessionManager used to persist conversation state
84
- - Dockerfile Entry point for hosting your agent (excluded when `infra` is set to `None`)
84
+ - Dockerfile Container image definition (only when `infra` is `agentcore-ecr`)
85
85
  - package.json Updated with Strands and Express dependencies
86
86
  - project.json Updated with agent serve targets
87
87
  </FileTree>
@@ -99,7 +99,7 @@ The entry point uses [`@ag-ui/aws-strands`](https://www.npmjs.com/package/@ag-ui
99
99
  - index.ts AG-UI server entry point (Express + SSE)
100
100
  - agent.ts Main agent definition with sample tools
101
101
  - session.ts Resolves the SessionManager used to persist conversation state
102
- - Dockerfile Entry point for hosting your agent (excluded when `infra` is set to `None`)
102
+ - Dockerfile Container image definition (only when `infra` is `agentcore-ecr`)
103
103
  - package.json Updated with Strands and AG-UI dependencies
104
104
  - project.json Updated with agent serve targets
105
105
  </FileTree>
@@ -107,7 +107,9 @@ The entry point uses [`@ag-ui/aws-strands`](https://www.npmjs.com/package/@ag-ui
107
107
 
108
108
  ### Infrastructure
109
109
 
110
- <OptionFilter when={{ infra: 'agentcore' }} description="Bedrock AgentCore Runtime deployment">
110
+ <Snippet name="agentcore-hosting" />
111
+
112
+ <OptionFilter when={{ infra: ['agentcore', 'agentcore-ecr'] }} description="Bedrock AgentCore Runtime deployment">
111
113
  <Snippet name="shared-constructs" />
112
114
 
113
115
  For deploying your Agent, the following files are generated:
@@ -132,6 +134,10 @@ For deploying your Agent, the following files are generated:
132
134
  - core
133
135
  - agent-core
134
136
  - runtime.tf Generic module for deploying to Bedrock AgentCore Runtime
137
+ - agent-core-code (when `infra` is `agentcore`)
138
+ - runtime.tf Packages your agent's code and delegates to `agent-core`
139
+ - agent-core-container (when `infra` is `agentcore-ecr`)
140
+ - runtime.tf Builds and publishes your agent's image and delegates to `agent-core`
135
141
  </FileTree>
136
142
  </Fragment>
137
143
  </Infrastructure>
@@ -249,7 +255,7 @@ For a more in-depth guide to writing Strands agents, refer to the [Strands docum
249
255
 
250
256
  The generated `index.ts` mounts the [Strands A2A Express Server](https://strandsagents.com/docs/user-guide/concepts/multi-agent/agent-to-agent) onto an Express app so the generated agent exposes the A2A protocol endpoints alongside a `/ping` health check. The URL advertised in the agent card comes from the `AGENTCORE_RUNTIME_URL` environment variable, falling back to `http://localhost:<port>/` for local development.
251
257
 
252
- Most users will not need to modify this file — edit `agent.ts` to change tools or the system prompt. A2A agents listen on port `9000` (vs `8080` for HTTP), which the generated Dockerfile and infrastructure are already configured for.
258
+ Most users will not need to modify this file — edit `agent.ts` to change tools or the system prompt. A2A agents listen on port `9000` (vs `8080` for HTTP), which the generated infrastructure is already configured for.
253
259
  </OptionFilter>
254
260
 
255
261
  <OptionFilter when={{ protocol: 'ag-ui' }} description="AG-UI server details">
@@ -259,7 +265,7 @@ The generated `index.ts` wraps your Strands `Agent` in an [`@ag-ui/aws-strands`]
259
265
 
260
266
  AG-UI agents are designed to be consumed directly by a frontend. Use the <Link path="/guides/connection/react-agui">`connection` generator</Link> to wire your React website up to the agent with a [CopilotKit](https://docs.copilotkit.ai/aws-strands) provider and [AG-UI HttpAgent](https://docs.ag-ui.com/) client.
261
267
 
262
- Most users will not need to modify `index.ts` — edit `agent.ts` to change tools or the system prompt. AG-UI agents listen on port `8080` (same as HTTP), which the generated Dockerfile and infrastructure are already configured for.
268
+ Most users will not need to modify `index.ts` — edit `agent.ts` to change tools or the system prompt. AG-UI agents listen on port `8080` (same as HTTP), which the generated infrastructure is already configured for.
263
269
  </OptionFilter>
264
270
 
265
271
  ## Running Your Agent
@@ -290,7 +296,7 @@ Then, in another terminal, start the chat:
290
296
 
291
297
  The generator emits a `scripts/<your-agent-name>/chat.ts` for every protocol. You can customize it as you evolve the agent's input shape. It connects to the local agent by default, or to your deployed agent when `RUNTIME_CONFIG_APP_ID` is set (see [Chat with your deployed agent](#chat-with-your-deployed-agent) below).
292
298
 
293
- <OptionFilter when={{ infra: 'agentcore' }} description="Deployed agent chat details">
299
+ <OptionFilter when={{ infra: ['agentcore', 'agentcore-ecr'] }} description="Deployed agent chat details">
294
300
  #### Chat with your deployed agent
295
301
 
296
302
  To chat with your agent deployed to Bedrock AgentCore, set the `RUNTIME_CONFIG_APP_ID` environment variable to the AppConfig application id of the deployment (output as `RuntimeConfigApplicationId` by the deployed stack). The chat script resolves your agent's runtime ARN from runtime configuration and connects to the deployed endpoint:
@@ -322,7 +328,7 @@ aws cognito-idp admin-initiate-auth \
322
328
  </Tabs>
323
329
  </OptionFilter>
324
330
 
325
- <OptionFilter when={{ infra: 'agentcore' }} description="Bedrock AgentCore Runtime deployment details">
331
+ <OptionFilter when={{ infra: ['agentcore', 'agentcore-ecr'] }} description="Bedrock AgentCore Runtime deployment details">
326
332
  ## Deploying Your Agent to Bedrock AgentCore Runtime
327
333
 
328
334
  <Snippet name="agent/bedrock-deployment" parentHeading="Deploying Your Agent to Bedrock AgentCore Runtime" />
@@ -333,6 +339,13 @@ aws cognito-idp admin-initiate-auth \
333
339
 
334
340
  The bundle target uses `index.ts` as the entrypoint for the WebSocket server to host on Bedrock AgentCore Runtime.
335
341
 
342
+ <OptionFilter when={{ infra: 'agentcore' }} description="Code package target">
343
+ ### Package Target
344
+
345
+ The generator configures a `<your-agent-name>-package` target which assembles the deployable code package: the bundled `index.js` plus a vendored install of the AWS Distro for OpenTelemetry, which AgentCore requires to be present in the package. The generated infrastructure uploads this directory as a `.zip` — via `AgentRuntimeArtifact.fromCodeAsset` under CDK, or archived into the shared asset bucket under Terraform.
346
+ </OptionFilter>
347
+
348
+ <OptionFilter when={{ infra: 'agentcore-ecr' }} description="Container image build and scan">
336
349
  ### Docker Target
337
350
 
338
351
  The generator configures a `<your-agent-name>-docker` target which copies the `Dockerfile` from your agent source directory into the bundle output directory. This co-locates the `Dockerfile` with the bundled artifacts, allowing CDK to build the Docker image directly using `AgentRuntimeArtifact.fromAsset`.
@@ -342,10 +355,11 @@ A `docker` target is also generated which prepares the docker context for all ag
342
355
  ### Image Scanning
343
356
 
344
357
  <Snippet name="trivy-image-scan" parentHeading="Image Scanning" />
358
+ </OptionFilter>
345
359
 
346
360
  ### Observability
347
361
 
348
- Your agent is automatically configured with observability using the [AWS Distro for Open Telemetry](https://aws.amazon.com/otel/) (ADOT), by configuring auto-instrumentation in your `Dockerfile`.
362
+ Your agent is automatically configured with observability using the [AWS Distro for Open Telemetry](https://aws.amazon.com/otel/) (ADOT).
349
363
 
350
364
  You can find traces in the CloudWatch AWS Console, by selecting "GenAI Observability" in the menu. Note that for traces to be populated you will need to enable [Transaction Search](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Transaction-Search.html).
351
365
 
@@ -55,13 +55,15 @@ The generator will add the following files to your existing TypeScript project:
55
55
  - divide.ts Sample tool
56
56
  - resources/
57
57
  - sample-guidance.ts Sample resource
58
- - Dockerfile Entry point for hosting your MCP server (excluded when `infra` is set to `None`)
58
+ - Dockerfile Container image definition (only when `infra` is `agentcore-ecr`)
59
59
  - project.json Updated with MCP server serve target
60
60
  </FileTree>
61
61
 
62
62
  ### Infrastructure
63
63
 
64
- <OptionFilter when={{ infra: 'agentcore' }} description="Bedrock AgentCore Runtime deployment">
64
+ <Snippet name="agentcore-hosting" />
65
+
66
+ <OptionFilter when={{ infra: ['agentcore', 'agentcore-ecr'] }} description="Bedrock AgentCore Runtime deployment">
65
67
  <Snippet name="shared-constructs" />
66
68
 
67
69
  <Snippet name="mcp/shared-constructs" />
@@ -184,7 +186,7 @@ If you would like to run your MCP server locally using [Streamable HTTP transpor
184
186
 
185
187
  This command uses `tsx --watch` to automatically restart the server when files change.
186
188
 
187
- <OptionFilter when={{ infra: 'agentcore' }} description="Bedrock AgentCore Runtime deployment details">
189
+ <OptionFilter when={{ infra: ['agentcore', 'agentcore-ecr'] }} description="Bedrock AgentCore Runtime deployment details">
188
190
  ## Deploying Your MCP Server to Bedrock AgentCore Runtime
189
191
 
190
192
  <Snippet name="mcp/bedrock-deployment" parentHeading="Deploying Your MCP Server to Bedrock AgentCore Runtime" />
@@ -195,6 +197,13 @@ This command uses `tsx --watch` to automatically restart the server when files c
195
197
 
196
198
  The bundle target uses `http.ts` as the entrypoint for the Streamable HTTP MCP server to host on Bedrock AgentCore Runtime.
197
199
 
200
+ <OptionFilter when={{ infra: 'agentcore' }} description="Code package target">
201
+ ### Package Target
202
+
203
+ The generator configures a `<your-server-name>-package` target which assembles the deployable code package: the bundled `index.js` plus a vendored install of the AWS Distro for OpenTelemetry, which AgentCore requires to be present in the package. The generated infrastructure uploads this directory as a `.zip` — via `AgentRuntimeArtifact.fromCodeAsset` under CDK, or archived into the shared asset bucket under Terraform.
204
+ </OptionFilter>
205
+
206
+ <OptionFilter when={{ infra: 'agentcore-ecr' }} description="Container image build and scan">
198
207
  ### Docker Target
199
208
 
200
209
  The generator configures a `<your-server-name>-docker` target which copies the `Dockerfile` from your MCP server source directory into the bundle output directory. This co-locates the `Dockerfile` with the bundled artifacts, allowing CDK to build the Docker image directly using `AgentRuntimeArtifact.fromAsset`.
@@ -204,6 +213,7 @@ A `docker` target is also generated which prepares the docker context for all MC
204
213
  ### Image Scanning
205
214
 
206
215
  <Snippet name="trivy-image-scan" parentHeading="Image Scanning" />
216
+ </OptionFilter>
207
217
 
208
218
  ### Observability
209
219
 
@@ -6,7 +6,7 @@ import Infrastructure from '@components/infrastructure.astro';
6
6
 
7
7
  ### Infrastructure as Code
8
8
 
9
- If you selected `agentcore` for `infra`, the relevant CDK or Terraform infrastructure is generated which you can use to deploy your Agent to [Amazon Bedrock AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/agents-tools-runtime.html).
9
+ If you selected `agentcore` or `agentcore-ecr` for `infra`, the relevant CDK or Terraform infrastructure is generated which you can use to deploy your Agent to [Amazon Bedrock AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/agents-tools-runtime.html).
10
10
 
11
11
  <Infrastructure>
12
12
  <Fragment slot="cdk">
@@ -31,14 +31,39 @@ This construct uses the [`aws-cdk-lib/aws-bedrockagentcore` module](https://docs
31
31
  <Fragment slot="terraform">
32
32
  A Terraform module is generated for you, named based on the `name` you chose when running the generator, or `<ProjectName>-agent` by default.
33
33
 
34
- Pass the shared <Link path="/guides/runtime-config#writing-configuration">`runtime_config_appconfig`</Link> module's outputs into the agent module:
34
+ Pass the shared <Link path="/guides/runtime-config#writing-configuration">`runtime_config_appconfig`</Link> module's outputs into the agent module, along with the shared artefact store its packaging uses. Under the default `agentcore` packaging the agent's code is staged in the shared asset bucket, so instantiate the `core/asset-bucket` module once per deployment, as the Lambda and API modules already do:
35
35
 
36
36
  ```terraform
37
+ module "asset_bucket" {
38
+ source = "../../common/terraform/src/core/asset-bucket"
39
+ }
40
+
41
+ module "my_project_agent" {
42
+ source = "../../common/terraform/src/app/agents/my-project-agent"
43
+
44
+ appconfig_application_id = module.runtime_config_appconfig.application_id
45
+ appconfig_application_arn = module.runtime_config_appconfig.application_arn
46
+
47
+ asset_bucket_name = module.asset_bucket.bucket_name
48
+ asset_bucket_arn = module.asset_bucket.bucket_arn
49
+ }
50
+ ```
51
+
52
+ Under `agentcore-ecr` the agent's image is published to the shared asset registry instead, so pass `core/asset-ecr`'s outputs rather than the bucket's. One registry serves every container in the workspace, so no agent needs a repository of its own:
53
+
54
+ ```terraform
55
+ module "asset_ecr" {
56
+ source = "../../common/terraform/src/core/asset-ecr"
57
+ }
58
+
37
59
  module "my_project_agent" {
38
60
  source = "../../common/terraform/src/app/agents/my-project-agent"
39
61
 
40
62
  appconfig_application_id = module.runtime_config_appconfig.application_id
41
63
  appconfig_application_arn = module.runtime_config_appconfig.application_arn
64
+
65
+ asset_ecr_repository_url = module.asset_ecr.repository_url
66
+ asset_ecr_repository_arn = module.asset_ecr.repository_arn
42
67
  }
43
68
  ```
44
69
  </Fragment>
@@ -50,14 +75,6 @@ The generated agent construct grants permission to invoke all Bedrock foundation
50
75
  You may wish to scope this down to the specific model(s) your agent uses. You can find the default model used by Strands agents in the [Strands documentation](https://strandsagents.com/latest/documentation/docs/user-guide/concepts/model-providers/amazon-bedrock/#default-model); see the [Strands model providers guide](https://strandsagents.com/latest/documentation/docs/user-guide/concepts/model-providers/) for configuring a different model.
51
76
  :::
52
77
 
53
- :::caution[Docker Required]
54
- [Docker](https://www.docker.com/) is required to build and deploy your Agent. Make sure you have installed and launched Docker to avoid errors such as:
55
-
56
- ```
57
- ERROR: Cannot connect to the Docker daemon at unix://path/to/docker.sock.
58
- ```
59
- :::
60
-
61
78
  ### Authentication
62
79
 
63
80
  The generator provides an `auth` option to configure authentication for your Agent. You can choose between `IAM` (default) or `Cognito` authentication when generating your agent.
@@ -94,7 +111,11 @@ export class ExampleStack extends Stack {
94
111
  ```
95
112
  </Fragment>
96
113
  <Fragment slot="terraform">
97
- ```terraform {5-6}
114
+ ```terraform {9-10}
115
+ module "asset_bucket" {
116
+ source = "../../common/terraform/src/core/asset-bucket"
117
+ }
118
+
98
119
  # Agent
99
120
  module "my_project_agent" {
100
121
  # Relative path to the generated module in the common/terraform project
@@ -102,6 +123,10 @@ module "my_project_agent" {
102
123
 
103
124
  appconfig_application_id = module.runtime_config_appconfig.application_id
104
125
  appconfig_application_arn = module.runtime_config_appconfig.application_arn
126
+
127
+ # Under `agentcore-ecr`, pass `core/asset-ecr`'s outputs instead.
128
+ asset_bucket_name = module.asset_bucket.bucket_name
129
+ asset_bucket_arn = module.asset_bucket.bucket_arn
105
130
  }
106
131
  ```
107
132
 
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: AgentCore Runtime Hosting
3
+ ---
4
+
5
+ The `infra` option selects how your code is packaged and hosted on [Amazon Bedrock AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/agents-tools-runtime.html):
6
+
7
+ - **`agentcore`** (default) uses [direct code deployment](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-get-started-code-deploy-node.html): your built code is packaged as a `.zip`, uploaded to S3, and run on an AgentCore managed language runtime. There is no container image to build, no ECR repository to manage, and no image to push, which makes for a substantially faster build and deploy cycle.
8
+ - **`agentcore-ecr`** builds an `arm64` container image from a vended `Dockerfile` and hosts it from the shared `core/asset-ecr` registry, alongside every other container in the workspace. Choose this when you need control over the operating system image — for example to install native system libraries — or when you have an established container pipeline. This option additionally vends a Trivy image scan target (see Image Scanning below).
9
+ - **`none`** generates no infrastructure at all, so the project can only be run locally.
@@ -16,10 +16,10 @@ export class ExampleStack extends Stack {
16
16
  integrations: MyApi.defaultIntegrations(this).build(),
17
17
  });
18
18
  const website = new MyWebsite(this, 'MyWebsite');
19
- api.restrictCorsTo(website, 'http://localhost:4200');
19
+ api.restrictCorsTo(website, 'http://localhost:4200', 'http://localhost:4300');
20
20
  }
21
21
  }
22
22
  ```
23
23
 
24
- The `MyWebsite` construct can be generated using the <Link path="/guides/react-website">`ts#website` generator</Link>
24
+ The `MyWebsite` construct can be generated using the <Link path="/guides/react-website">`ts#website` generator</Link>. This example assumes the website's local dev-server and preview ports are `4200`/`4300` - check its `project.json` (or `vite.config.mts`) for the ports actually assigned to it, since each website generated this way gets its own.
25
25
  :::
@@ -24,5 +24,5 @@ module "my_api" {
24
24
  }
25
25
  }
26
26
  ```
27
- The `MyWebsite` construct can be generated using the <Link path="/guides/react-website">`ts#website` generator</Link>
27
+ The `MyWebsite` construct can be generated using the <Link path="/guides/react-website">`ts#website` generator</Link>. This example assumes the website's local ports are `4200`/`4300` - check its `project.json` (or `vite.config.mts`) for the ports actually assigned to it, since each website generated this way gets its own.
28
28
  :::
@@ -6,7 +6,7 @@ import Infrastructure from '@components/infrastructure.astro';
6
6
 
7
7
  ### Infrastructure as Code
8
8
 
9
- If you selected `agentcore` for `infra`, the relevant CDK or Terraform infrastructure is generated which you can use to deploy your MCP server to [Amazon Bedrock AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/agents-tools-runtime.html).
9
+ If you selected `agentcore` or `agentcore-ecr` for `infra`, the relevant CDK or Terraform infrastructure is generated which you can use to deploy your MCP server to [Amazon Bedrock AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/agents-tools-runtime.html).
10
10
 
11
11
  <Infrastructure>
12
12
  <Fragment slot="cdk">
@@ -32,26 +32,43 @@ This construct uses the [`aws-cdk-lib/aws-bedrockagentcore` module](https://docs
32
32
  <Fragment slot="terraform">
33
33
  A Terraform module is generated for you, named based on the `name` you chose when running the generator, or `<ProjectName>-mcp-server` by default.
34
34
 
35
- Pass the shared <Link path="/guides/runtime-config#writing-configuration">`runtime_config_appconfig`</Link> module's outputs into the MCP server module:
35
+ Pass the shared <Link path="/guides/runtime-config#writing-configuration">`runtime_config_appconfig`</Link> module's outputs into the MCP server module, along with the shared artefact store its packaging uses. Under the default `agentcore` packaging the server's code is staged in the shared asset bucket, so instantiate the `core/asset-bucket` module once per deployment, as the Lambda and API modules already do:
36
36
 
37
37
  ```terraform
38
+ module "asset_bucket" {
39
+ source = "../../common/terraform/src/core/asset-bucket"
40
+ }
41
+
38
42
  module "my_project_mcp_server" {
39
43
  source = "../../common/terraform/src/app/mcp-servers/my-project-mcp-server"
40
44
 
41
45
  appconfig_application_id = module.runtime_config_appconfig.application_id
42
46
  appconfig_application_arn = module.runtime_config_appconfig.application_arn
47
+
48
+ asset_bucket_name = module.asset_bucket.bucket_name
49
+ asset_bucket_arn = module.asset_bucket.bucket_arn
43
50
  }
44
51
  ```
45
- </Fragment>
46
- </Infrastructure>
47
52
 
48
- :::caution[Docker Required]
49
- [Docker](https://www.docker.com/) is required to build and deploy your MCP server. Make sure you have installed and launched Docker to avoid errors such as:
53
+ Under `agentcore-ecr` the server's image is published to the shared asset registry instead, so pass `core/asset-ecr`'s outputs rather than the bucket's. One registry serves every container in the workspace, so no MCP server needs a repository of its own:
50
54
 
55
+ ```terraform
56
+ module "asset_ecr" {
57
+ source = "../../common/terraform/src/core/asset-ecr"
58
+ }
59
+
60
+ module "my_project_mcp_server" {
61
+ source = "../../common/terraform/src/app/mcp-servers/my-project-mcp-server"
62
+
63
+ appconfig_application_id = module.runtime_config_appconfig.application_id
64
+ appconfig_application_arn = module.runtime_config_appconfig.application_arn
65
+
66
+ asset_ecr_repository_url = module.asset_ecr.repository_url
67
+ asset_ecr_repository_arn = module.asset_ecr.repository_arn
68
+ }
51
69
  ```
52
- ERROR: Cannot connect to the Docker daemon at unix://path/to/docker.sock.
53
- ```
54
- :::
70
+ </Fragment>
71
+ </Infrastructure>
55
72
 
56
73
  ### Authentication
57
74
 
@@ -26,6 +26,10 @@ For deploying your MCP Server, the following files are generated:
26
26
  - core
27
27
  - agent-core
28
28
  - runtime.tf Generic module for deploying to Bedrock AgentCore Runtime
29
+ - agent-core-code (when `infra` is `agentcore`)
30
+ - runtime.tf Packages your MCP Server's code and delegates to `agent-core`
31
+ - agent-core-container (when `infra` is `agentcore-ecr`)
32
+ - runtime.tf Builds and publishes your MCP Server's image and delegates to `agent-core`
29
33
  </FileTree>
30
34
  </Fragment>
31
35
  </Infrastructure>
@@ -37,7 +37,13 @@ The generated infrastructure creates two database users:
37
37
  <Fragment slot="terraform">
38
38
  The Terraform module is created in `common/terraform`. Example usage:
39
39
 
40
+ The migration Lambda is deployed as a container image, published to the shared asset registry. Instantiate the `core/asset-ecr` module once per deployment and pass its `repository_url` into every database module:
41
+
40
42
  ```hcl title="packages/infra/src/main.tf"
43
+ module "asset_ecr" {
44
+ source = "../../common/terraform/src/core/asset-ecr"
45
+ }
46
+
41
47
  module "my_database" {
42
48
  source = "../../common/terraform/src/app/dbs/my-database"
43
49
 
@@ -46,11 +52,13 @@ module "my_database" {
46
52
  database_subnet_ids = aws_subnet.database[*].id
47
53
  lambda_subnet_ids = aws_subnet.private[*].id
48
54
 
55
+ asset_ecr_repository_url = module.asset_ecr.repository_url
56
+
49
57
  tags = local.common_tags
50
58
  }
51
59
  ```
52
60
 
53
- This provisions an Aurora cluster with RDS Proxy, admin credentials, create-db-user Lambda, runtime config registration, migration Lambda, and container registry resources.
61
+ This provisions an Aurora cluster with RDS Proxy, admin credentials, create-db-user Lambda, runtime config registration, and migration Lambda.
54
62
 
55
63
  The database module registers its connection details under the `database` <Link path="guides/runtime-config">runtime configuration</Link> namespace, which the shared runtime configuration AppConfig application exposes by default.
56
64
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/nx-plugin-mcp",
3
- "version": "1.0.0-rc.91",
3
+ "version": "1.0.0-rc.93",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/awslabs/nx-plugin-for-aws.git",
@@ -55,9 +55,9 @@
55
55
  },
56
56
  "infra": {
57
57
  "type": "string",
58
- "description": "The type of infrastructure to host your Agent.",
58
+ "description": "The type of infrastructure to host your Agent. agentcore deploys your code as a zip to an AgentCore managed runtime for the fastest build and deploy cycle. agentcore-ecr builds and hosts a container image instead, for OS-level control or an established container pipeline.",
59
59
  "x-prompt": "How would you like to host your Agent server?",
60
- "enum": ["agentcore", "none"],
60
+ "enum": ["agentcore", "agentcore-ecr", "none"],
61
61
  "default": "agentcore",
62
62
  "x-priority": "important"
63
63
  },
@@ -39,9 +39,9 @@
39
39
  },
40
40
  "infra": {
41
41
  "type": "string",
42
- "description": "The type of infrastructure to host your MCP server. Select none for no hosting.",
42
+ "description": "The type of infrastructure to host your MCP server. agentcore deploys your code as a zip to an AgentCore managed runtime for the fastest build and deploy cycle. agentcore-ecr builds and hosts a container image instead, for OS-level control or an established container pipeline. Select none for no hosting.",
43
43
  "x-prompt": "How would you like to host your MCP server?",
44
- "enum": ["agentcore", "none"],
44
+ "enum": ["agentcore", "agentcore-ecr", "none"],
45
45
  "default": "agentcore",
46
46
  "x-priority": "important"
47
47
  },
@@ -55,9 +55,9 @@
55
55
  },
56
56
  "infra": {
57
57
  "type": "string",
58
- "description": "The type of infrastructure to host your Agent.",
58
+ "description": "The type of infrastructure to host your Agent. agentcore deploys your code as a zip to an AgentCore managed runtime for the fastest build and deploy cycle. agentcore-ecr builds and hosts a container image instead, for OS-level control or an established container pipeline.",
59
59
  "x-prompt": "How would you like to host your Agent server?",
60
- "enum": ["agentcore", "none"],
60
+ "enum": ["agentcore", "agentcore-ecr", "none"],
61
61
  "default": "agentcore",
62
62
  "x-priority": "important"
63
63
  },
@@ -39,9 +39,9 @@
39
39
  },
40
40
  "infra": {
41
41
  "type": "string",
42
- "description": "The type of infrastructure to host your MCP server. Select none for no hosting.",
42
+ "description": "The type of infrastructure to host your MCP server. agentcore deploys your code as a zip to an AgentCore managed runtime for the fastest build and deploy cycle. agentcore-ecr builds and hosts a container image instead, for OS-level control or an established container pipeline. Select none for no hosting.",
43
43
  "x-prompt": "How would you like to host your MCP server?",
44
- "enum": ["agentcore", "none"],
44
+ "enum": ["agentcore", "agentcore-ecr", "none"],
45
45
  "default": "agentcore",
46
46
  "x-priority": "important"
47
47
  },