@aws/nx-plugin-mcp 1.0.0-rc.95 → 1.0.0-rc.97

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 (66) hide show
  1. package/bin/aws-nx-mcp.js +61 -14
  2. package/docs/get_started/existing-project.mdx +6 -3
  3. package/docs/get_started/quick-start.mdx +8 -0
  4. package/docs/get_started/tutorials/dungeon-game/1.mdx +12 -14
  5. package/docs/get_started/tutorials/dungeon-game/2.mdx +10 -2
  6. package/docs/get_started/tutorials/dungeon-game/3.mdx +4 -0
  7. package/docs/get_started/tutorials/dungeon-game/4.mdx +2 -2
  8. package/docs/guides/agentcore-gateway.mdx +4 -2
  9. package/docs/guides/agentcore-harness.mdx +2 -1
  10. package/docs/guides/astro-docs.mdx +25 -7
  11. package/docs/guides/connection/py-agent-a2a.mdx +2 -0
  12. package/docs/guides/connection/py-agent-dynamodb.mdx +1 -1
  13. package/docs/guides/connection/py-agent-gateway.mdx +3 -0
  14. package/docs/guides/connection/py-agent-mcp.mdx +18 -4
  15. package/docs/guides/connection/py-agent-rdb.mdx +5 -4
  16. package/docs/guides/connection/py-fast-api-dynamodb.mdx +1 -1
  17. package/docs/guides/connection/py-fast-api-rdb.mdx +7 -2
  18. package/docs/guides/connection/py-mcp-server-dynamodb.mdx +1 -1
  19. package/docs/guides/connection/py-mcp-server-rdb.mdx +6 -6
  20. package/docs/guides/connection/react-agui.mdx +34 -25
  21. package/docs/guides/connection/react-fastapi.mdx +114 -116
  22. package/docs/guides/connection/react-py-agent.mdx +4 -0
  23. package/docs/guides/connection/react-smithy.mdx +152 -98
  24. package/docs/guides/connection/react-trpc.mdx +13 -6
  25. package/docs/guides/connection/smithy-dynamodb.mdx +2 -8
  26. package/docs/guides/connection/smithy-rdb.mdx +3 -6
  27. package/docs/guides/connection/trpc-rdb.mdx +6 -6
  28. package/docs/guides/connection/ts-agent-a2a.mdx +4 -4
  29. package/docs/guides/connection/ts-agent-dynamodb.mdx +13 -11
  30. package/docs/guides/connection/ts-agent-gateway.mdx +2 -0
  31. package/docs/guides/connection/ts-agent-mcp.mdx +19 -7
  32. package/docs/guides/connection/ts-agent-rdb.mdx +2 -2
  33. package/docs/guides/connection/ts-mcp-server-dynamodb.mdx +11 -7
  34. package/docs/guides/connection/ts-mcp-server-rdb.mdx +4 -3
  35. package/docs/guides/docker-bundling.mdx +23 -3
  36. package/docs/guides/fastapi.mdx +16 -5
  37. package/docs/guides/py-agent.mdx +129 -54
  38. package/docs/guides/py-mcp-server.mdx +3 -1
  39. package/docs/guides/py-rdb.mdx +13 -4
  40. package/docs/guides/python-lambda-function.mdx +8 -8
  41. package/docs/guides/python-project.mdx +28 -25
  42. package/docs/guides/react-website-auth.mdx +8 -8
  43. package/docs/guides/react-website.mdx +46 -27
  44. package/docs/guides/runtime-config.mdx +24 -4
  45. package/docs/guides/security.mdx +1 -1
  46. package/docs/guides/terraform-project.mdx +8 -2
  47. package/docs/guides/trpc.mdx +96 -12
  48. package/docs/guides/ts-agent.mdx +17 -3
  49. package/docs/guides/ts-dcr-proxy.mdx +24 -6
  50. package/docs/guides/ts-lambda-function.mdx +7 -1
  51. package/docs/guides/ts-mcp-server.mdx +45 -15
  52. package/docs/guides/ts-rdb.mdx +9 -2
  53. package/docs/guides/ts-smithy-api.mdx +76 -7
  54. package/docs/guides/typescript-infrastructure.mdx +24 -10
  55. package/docs/guides/typescript-project.mdx +12 -5
  56. package/docs/guides/workspace.mdx +21 -9
  57. package/docs/snippets/api/type-safe-api-integrations.mdx +2 -0
  58. package/docs/snippets/connection/a2a-infrastructure.mdx +3 -0
  59. package/docs/snippets/connection/infra-project-prerequisite.mdx +8 -0
  60. package/docs/snippets/connection/strands-agent-rdb-ssl-requirements.mdx +1 -1
  61. package/docs/snippets/connection/ts-lambda-rdb-ssl-requirements.mdx +1 -1
  62. package/docs/snippets/connection/ts-mcp-server-rdb-ssl-requirements.mdx +1 -1
  63. package/docs/snippets/required-prerequisites.mdx +1 -1
  64. package/package.json +1 -1
  65. package/src/init/schema.json +5 -0
  66. package/src/py/project/schema.json +3 -1
package/bin/aws-nx-mcp.js CHANGED
@@ -21917,6 +21917,8 @@ const NX_VERSION = {
21917
21917
  "@aws/aws-distro-opentelemetry-node-autoinstrumentation": "0.12.0",
21918
21918
  "@opentelemetry/propagator-jaeger": "2.10.0",
21919
21919
  minimatch: "10.2.6",
21920
+ "deepmerge-ts": "8.0.0",
21921
+ mysql2: "3.22.0",
21920
21922
  "@aws-sdk/client-dynamodb": "3.1121.0",
21921
21923
  "@aws-sdk/client-api-gateway": "3.1121.0",
21922
21924
  "@aws-sdk/client-iam": "3.1121.0",
@@ -21924,6 +21926,7 @@ const NX_VERSION = {
21924
21926
  "@aws-sdk/client-bedrock-runtime": "3.1121.0",
21925
21927
  "@aws-sdk/client-s3": "3.1121.0",
21926
21928
  "@aws-sdk/client-sts": "3.1121.0",
21929
+ "@aws-sdk/client-cognito-identity-provider": "3.1121.0",
21927
21930
  "@aws-sdk/credential-providers": "3.1121.0",
21928
21931
  "@aws-sdk/credential-provider-cognito-identity": "3.972.69",
21929
21932
  "@aws-sdk/client-secrets-manager": "3.1121.0",
@@ -21939,14 +21942,14 @@ const NX_VERSION = {
21939
21942
  "@middy/core": "7.9.2",
21940
21943
  "@nxlv/python": "23.0.0",
21941
21944
  "@nx-extend/terraform": "10.4.1",
21942
- nx: "23.1.2",
21943
- "@nx/devkit": "23.1.2",
21944
- "@nx/js": "23.1.2",
21945
- "@nx/react": "23.1.2",
21946
- "@nx/vite": "23.1.2",
21947
- "@nx/vitest": "23.1.2",
21948
- "@nx/workspace": "23.1.2",
21949
- "create-nx-workspace": "23.1.2",
21945
+ nx: "23.2.0",
21946
+ "@nx/devkit": "23.2.0",
21947
+ "@nx/js": "23.2.0",
21948
+ "@nx/react": "23.2.0",
21949
+ "@nx/vite": "23.2.0",
21950
+ "@nx/vitest": "23.2.0",
21951
+ "@nx/workspace": "23.2.0",
21952
+ "create-nx-workspace": "23.2.0",
21950
21953
  "@swc-node/register": "1.12.1",
21951
21954
  "@swc/core": "1.16.1",
21952
21955
  "@modelcontextprotocol/sdk": "1.30.0",
@@ -22042,6 +22045,7 @@ const NX_VERSION = {
22042
22045
  vite: "8.2.2",
22043
22046
  typescript: "6.0.3",
22044
22047
  vitest: "4.1.11",
22048
+ jsdom: "27.4.0",
22045
22049
  zod: "4.5.4",
22046
22050
  ws: "8.21.3"
22047
22051
  }.nx;
@@ -55045,6 +55049,41 @@ const addToExistingProjectTool = (server, generators) => {
55045
55049
  });
55046
55050
  };
55047
55051
  //#endregion
55052
+ //#region ../nx-plugin/src/mcp-server/tools/best-practices.ts
55053
+ /**
55054
+ * Guide pages documenting behaviour that spans generators, so no single
55055
+ * generator owns them and `generator-guide` never returns them. Each is
55056
+ * described for the agent so it can pick the ones relevant to its task.
55057
+ */
55058
+ const BEST_PRACTICE_PAGES = {
55059
+ workspace: "Workspace layout, configuration and common commands",
55060
+ "typescript-project": "Conventions for TypeScript projects",
55061
+ "python-project": "Conventions for Python projects",
55062
+ security: "Security controls vended infrastructure carries, and the shared responsibility model",
55063
+ "runtime-config": "How generated projects discover one another through AWS AppConfig",
55064
+ "docker-bundling": "Building and deploying container images",
55065
+ "local-development": "Running projects locally with the serve and dev targets"
55066
+ };
55067
+ const BEST_PRACTICE_PAGE_NAMES = Object.keys(BEST_PRACTICE_PAGES);
55068
+ /**
55069
+ * Add a tool which serves the cross-cutting guide pages. Kept separate from
55070
+ * `general-guidance` so an agent fetches only the pages its task needs rather
55071
+ * than every page on every call.
55072
+ */
55073
+ const addBestPracticesTool = (server, generators) => {
55074
+ server.registerTool("best-practices", {
55075
+ title: "Best Practices",
55076
+ description: "Tool to retrieve guidance which spans generators, rather than applying to one in particular. Request the pages relevant to your task:\n" + Object.entries(BEST_PRACTICE_PAGES).map(([page, description]) => `- \`${page}\`: ${description}`).join("\n"),
55077
+ inputSchema: {
55078
+ packageManager: PackageManagerSchema.optional(),
55079
+ pages: array(_enum(BEST_PRACTICE_PAGE_NAMES)).min(1).describe("The guide pages to retrieve.")
55080
+ }
55081
+ }, async ({ packageManager, pages }) => ({ content: [{
55082
+ type: "text",
55083
+ text: await fetchGuidePages(pages, generators, packageManager)
55084
+ }] }));
55085
+ };
55086
+ //#endregion
55048
55087
  //#region ../nx-plugin/src/utils/iac-providers.ts
55049
55088
  /**
55050
55089
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
@@ -55088,9 +55127,20 @@ Refer to the \`general-guidance\` tool for full workspace documentation includin
55088
55127
  };
55089
55128
  //#endregion
55090
55129
  //#region ../nx-plugin/src/mcp-server/tools/general-guidance.ts
55130
+ /**
55131
+ * The cross-cutting pages every agent needs regardless of task, inlined here
55132
+ * so a workspace's conventions land without a second tool call. The rest are
55133
+ * served on demand by `best-practices`.
55134
+ */
55135
+ const GENERAL_GUIDANCE_PAGES = [
55136
+ "workspace",
55137
+ "typescript-project",
55138
+ "python-project"
55139
+ ];
55091
55140
  const TOOL_SELECTION_GUIDE = `## Tool Selection Guide
55092
55141
 
55093
55142
  - Use the \`general-guidance\` tool for guidance and best practices for working with Nx and the Nx Plugin for AWS.
55143
+ - Use the \`best-practices\` tool for guidance which spans generators rather than applying to one in particular, such as workspace layout, security, runtime configuration, container builds and local development.
55094
55144
  - Use the \`create-workspace-command\` tool to discover how to create a workspace to start a new project.
55095
55145
  - Use the \`add-to-existing-project\` tool when adding the plugin to an existing Nx workspace or non-Nx monorepo, or when troubleshooting configuration errors in such a workspace.
55096
55146
  - Use the \`upgrade-workspace\` tool when upgrading Nx or the Nx Plugin for AWS to a newer version.
@@ -55169,13 +55219,9 @@ ${PACKAGE_MANAGERS.map((pm) => ` \`\`\`bash
55169
55219
 
55170
55220
  ## Detailed Guides
55171
55221
 
55172
- Please refer to the below documentation for important details regarding workspaces and working with TypeScript or Python projects.
55222
+ Please refer to the below documentation for important details regarding workspaces and working with TypeScript or Python projects. Use the \`best-practices\` tool for the remaining cross-cutting guides (${BEST_PRACTICE_PAGE_NAMES.filter((p) => !GENERAL_GUIDANCE_PAGES.includes(p)).map((p) => `\`${p}\``).join(", ")}).
55173
55223
 
55174
- ${await fetchGuidePages([
55175
- "workspace",
55176
- "typescript-project",
55177
- "python-project"
55178
- ], generators)}
55224
+ ${await fetchGuidePages([...GENERAL_GUIDANCE_PAGES], generators)}
55179
55225
 
55180
55226
  `
55181
55227
  }] }));
@@ -55864,6 +55910,7 @@ on AWS, if the generators apply to your use case.
55864
55910
  ${TOOL_SELECTION_GUIDE}
55865
55911
  ` });
55866
55912
  addGeneralGuidanceTool(server, generators);
55913
+ addBestPracticesTool(server, generators);
55867
55914
  addCreateWorkspaceCommandTool(server);
55868
55915
  addListGeneratorsTool(server, generators);
55869
55916
  addGeneratorGuideTool(server, generators);
@@ -124,12 +124,15 @@ It creates or updates the following files:
124
124
  - tsconfig.json a root TypeScript config referencing your workspace's projects, which Nx's TypeScript sync keeps up to date
125
125
  - tsconfig.base.json the shared compiler options the plugin's TypeScript projects extend (see below for what it carries)
126
126
  - pnpm-workspace.yaml (pnpm only) allow-lists the build scripts the plugin's dependencies need (`@swc/core`, `esbuild`, `nx`, `sharp`)
127
- - package.json convenience scripts for common tasks, plus the `@aws/nx-plugin`, `@aws/nx-plugin-mcp`, `nx`, `@nx/js`, `@nx/workspace`, `typescript` and Biome dev dependencies
127
+ - package.json convenience scripts for common tasks, a `prepare` script that installs the git hooks, plus the `@aws/nx-plugin`, `@aws/nx-plugin-mcp`, `nx`, `@nx/js`, `@nx/workspace`, `typescript`, husky and Biome dev dependencies
128
128
  - biome.json default Biome formatter and linter configuration
129
+ - .git-secrets/ the vendored [git-secrets](https://github.com/awslabs/git-secrets) script, with `.gitallowed` for false positives and a `.husky/pre-commit` hook that runs it — see <Link path="guides/workspace#git-secrets">Git Secrets</Link>
129
130
  - .mcp.json configures the MCP server for supported coding agents unless disabled (also .cursor/, .kiro/, .gemini/, .vscode/ and .codex/ equivalents). It runs the workspace's own `@aws/nx-plugin-mcp`, so the server always matches the version installed in your workspace
130
131
  </FileTree>
131
132
 
132
- The <Link path="get_started/building-with-ai">MCP server</Link> configuration can be disabled with `--mcp=false`.
133
+ The <Link path="get_started/building-with-ai">MCP server</Link> configuration can be disabled with `--mcp=false`, and the credential scanning hooks with `--gitSecrets=false`.
134
+
135
+ Files you already have are preserved: an existing `.husky/pre-commit` hook or `prepare` script is left as it is, and the generator prints what to add so credential scanning runs alongside your own checks. An existing `.gitallowed` keeps every pattern it has.
133
136
 
134
137
  <Drawer title="tsconfig.base.json" trigger="Click here to see the compiler options a created tsconfig.base.json carries.">
135
138
  The plugin's TypeScript projects rely on these compiler options. If a `tsconfig.base.json` already exists it is left as-is, so if you keep your own these are the options to align with:
@@ -159,7 +162,7 @@ pnpm skips install scripts for packages that aren't allow-listed. `init` allow-l
159
162
 
160
163
  #### `nx sync` hangs, or `plugin worker ... exited before the connection was established`
161
164
 
162
- If two different `nx` versions are present in the same node_modules tree (run `npm ls nx` to confirm), their plugin-worker IPC deadlocks. The `init` generator pins the root `nx` devDependency to the version the plugin's own `@nx/*` packages resolve, but a later install of another `@nx/*` package at a different patch version can reintroduce the mismatch. Align every `nx` and `@nx/*` entry in your root `package.json` to a single version and reinstall.
165
+ If two different `nx` versions are present in the same node_modules tree (run `npm ls nx` to confirm), their plugin-worker IPC deadlocks. `init` declares the `nx` and `@nx/*` versions the plugin is built against, but it never downgrades a version your workspace already has: a workspace already on a newer `nx` keeps it, and the plugin's own `@nx/*` packages pull in their own copy alongside it. Align every `nx` and `@nx/*` entry in your root `package.json` — and, where your package manager uses one, the dependency catalog — to a single version, then reinstall.
163
166
 
164
167
  #### `ts.readConfigFile is not a function`
165
168
 
@@ -224,6 +224,14 @@ If you encounter any lint errors, you can run the following command to automatic
224
224
  <PackageManagerShortCommand commands={["lint"]} />
225
225
  :::
226
226
 
227
+ :::tip[The workspace is out of sync]
228
+ If the build reports `The workspace is out of sync`, accept the prompt to sync the workspace or run the following sync command directly before retrying the build:
229
+
230
+ <NxCommands commands={["sync"]} />
231
+
232
+ This writes the TypeScript project references and `package.json` dependency entries your imports require.
233
+ :::
234
+
227
235
  Bootstrap your infrastructure:
228
236
 
229
237
  <Infrastructure>
@@ -130,8 +130,9 @@ Below is a list of all files which have been generated by the `ts#api` generator
130
130
  - local-server.ts used when running the tRPC server locally
131
131
  - **router.ts** defines the tRPC router and all procedures
132
132
  - project.json
133
+ - vitest.config.mts test configuration
133
134
  - ...
134
- - vitest.workspace.ts
135
+ - vitest.config.mts root test configuration which discovers every project's tests
135
136
  </FileTree>
136
137
 
137
138
  Let us look at these key files:
@@ -151,13 +152,10 @@ export type AppRouter = typeof appRouter;
151
152
  ```
152
153
  The router defines the tRPC router for your API and is the place where you will declare all of your API methods. As you can see above, we have a method called `echo` with it's implementation in the `./procedures/echo.ts` file. The Lambda handler entrypoint is in `handler.ts`, which is configured automatically by the generator.
153
154
 
154
- ```ts {7-10}
155
+ ```ts {4-6}
155
156
  // packages/game-api/src/procedures/echo.ts
156
157
  import { publicProcedure } from '../init.js';
157
- import {
158
- EchoInputSchema,
159
- EchoOutputSchema,
160
- } from '../schema/echo.js';
158
+ import { EchoInputSchema, EchoOutputSchema } from '../schema/index.js';
161
159
 
162
160
  export const echo = publicProcedure
163
161
  .input(EchoInputSchema)
@@ -903,9 +901,7 @@ export class StoryAgent extends Construct implements IGrantable, IConnectable {
903
901
  }
904
902
  ```
905
903
 
906
- This configures a CDK `AgentRuntimeArtifact` which uploads your agent Docker image to ECR, and hosts it using AgentCore Runtime. Because we chose `--auth=cognito`, the construct requires the user pool/client identity and authorizes AgentCore Runtime invocations through Cognito, forwarding the caller's `Authorization` header. It also provisions the session bucket the Story Agent's `session.py` reads back at runtime — a KMS-encrypted S3 bucket with server access logs delivered to CloudWatch Logs — grants the agent read/write access to it, grants it access to invoke Bedrock models, and registers its ARN and bucket name in `RuntimeConfig` so both the agent (at runtime, via AppConfig) and the Game API (at synth time, via `invocationUrl`) can find it.
907
-
908
- You may notice an extra `Dockerfile`, that references the Docker image from the `story` project, allowing us to co-locate the Dockerfile and agent source code.
904
+ This configures a CDK `AgentRuntimeArtifact` which packages your agent's built code as a zip asset and hosts it using AgentCore Runtime. Because we chose `--auth=cognito`, the construct requires the user pool/client identity and authorizes AgentCore Runtime invocations through Cognito, forwarding the caller's `Authorization` header. It also provisions the session bucket the Story Agent's `session.py` reads back at runtime — a KMS-encrypted S3 bucket with server access logs delivered to CloudWatch Logs — grants the agent read/write access to it, grants it access to invoke Bedrock models, and registers its ARN and bucket name in `RuntimeConfig` so both the agent (at runtime, via AppConfig) and the Game API (at synth time, via `invocationUrl`) can find it.
909
905
 
910
906
  </details>
911
907
 
@@ -965,7 +961,6 @@ The `ts#mcp-server` generator generates these files.
965
961
  - sample-guidance.ts example resource
966
962
  - stdio.ts entry point for MCP with STDIO transport
967
963
  - http.ts entry point for MCP with Streamable HTTP transport
968
- - Dockerfile builds the image for AgentCore Runtime
969
964
  - rolldown.config.ts configuration for bundling the MCP server for deployment to AgentCore
970
965
  - common/constructs/
971
966
  - src
@@ -1277,9 +1272,12 @@ The `connection` generator generates/updates these files. Let us examine some of
1277
1272
  ```tsx
1278
1273
  // packages/game-ui/src/hooks/useGameApi.tsx
1279
1274
  import { useContext } from 'react';
1280
- import { GameApiTRPCContext } from '../components/GameApiClientProvider';
1275
+ import {
1276
+ GameApiTRPCContext,
1277
+ type GameApiTRPCContextValue,
1278
+ } from '../components/GameApiClientProvider';
1281
1279
 
1282
- export const useGameApi = () => {
1280
+ export const useGameApi = (): GameApiTRPCContextValue['optionsProxy'] => {
1283
1281
  const container = useContext(GameApiTRPCContext);
1284
1282
  if (!container) {
1285
1283
  throw new Error('useGameApi must be used within GameApiClientProvider');
@@ -1287,7 +1285,7 @@ export const useGameApi = () => {
1287
1285
  return container.optionsProxy;
1288
1286
  };
1289
1287
 
1290
- export const useGameApiClient = () => {
1288
+ export const useGameApiClient = (): GameApiTRPCContextValue['client'] => {
1291
1289
  const container = useContext(GameApiTRPCContext);
1292
1290
  if (!container) {
1293
1291
  throw new Error(
@@ -1559,7 +1557,7 @@ Then, run the following command for a full build:
1559
1557
 
1560
1558
  <PackageManagerShortCommand commands={["build"]} />
1561
1559
 
1562
- You will be prompted with the following:
1560
+ You may be prompted with the following:
1563
1561
 
1564
1562
  ```bash
1565
1563
  NX The workspace is out of sync
@@ -170,11 +170,19 @@ The `DungeonDb` construct registers the deployed table name in <Link path="guide
170
170
 
171
171
  There's no need to deploy to AWS to try out our API — the `dev` target runs the Game API against [DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html). Because we connected the Game API to the `DungeonDb` project in Module 1, this target also starts DynamoDB Local automatically.
172
172
 
173
- First, fix any lint issues:
173
+ The procedures and MCP server we just wrote import `@dungeon-adventure/dungeon-db`, a new cross-project import, so start by syncing the workspace:
174
+
175
+ <NxCommands commands={["sync"]} />
176
+
177
+ <Aside type="tip" title="Why this step is needed">
178
+ `nx sync` declares `@dungeon-adventure/dungeon-db` in the `game-api` and `inventory` `package.json` files and adds the matching TypeScript project references for you, saving you from needing to add this by hand when declaring dependencies between projects.
179
+ </Aside>
180
+
181
+ Then fix any lint issues:
174
182
 
175
183
  <PackageManagerShortCommand commands={["lint"]} />
176
184
 
177
- Then build the codebase:
185
+ And build the codebase:
178
186
 
179
187
  <PackageManagerShortCommand commands={["build"]} />
180
188
 
@@ -47,6 +47,10 @@ If you encounter any lint errors, run the following command to automatically fix
47
47
  <PackageManagerShortCommand commands={["lint"]} />
48
48
  </Aside>
49
49
 
50
+ <Aside type="tip" title="The workspace is out of sync">
51
+ If the build reports `The workspace is out of sync`, run `nx sync` and build again.
52
+ </Aside>
53
+
50
54
  ### Chat with your Agent
51
55
 
52
56
  The generated `agent-chat` target opens an interactive REPL against your agent. It runs standalone and connects to your locally-running agent, so first start the agent's local server in one terminal:
@@ -27,7 +27,7 @@ Start the full local stack — the game-ui dev server together with a local Game
27
27
 
28
28
  <NxCommands commands={["dev game-ui"]} />
29
29
 
30
- The `dev` target on `game-ui` has `dependsOn` on `game-api:dev` and `dungeon_adventure.story:agent-dev`, so Nx spins up every project's local server in parallel. Through the connections we set up in Module 1, those in turn boot the Inventory MCP server and DynamoDB Local. Make sure your container engine is running, then open the dev server in a browser.
30
+ The `dev` target on `game-ui` has `dependsOn` on `game-api:dev` and `dungeon_adventure.story:agent-dev`, so Nx spins up every project's local server in parallel. Through the connections we set up in Module 1, those in turn boot the Inventory MCP server and DynamoDB Local. Make sure your container engine is running, then open the dev server at `http://localhost:4200/` in a browser.
31
31
 
32
32
  <Aside type="tip" title="No login locally">
33
33
  In `local-dev` mode the `CognitoAuth` component skips the Cognito login flow (there's no user pool running locally), so you'll land straight on the game without signing in. You'll create a real account when we deploy to AWS at the end of this module.
@@ -90,7 +90,7 @@ The `$playerName` syntax tells `@tanstack/react-router` to treat `playerName` as
90
90
  </TabItem>
91
91
  </Tabs>
92
92
 
93
- Once saved, the dev server at `http://localhost:4200/` should now let you start an adventure and chat with the Story Agent.
93
+ Once saved, the dev server should now let you start an adventure and chat with the Story Agent.
94
94
 
95
95
  <Image src={gameSelectPng} alt="game-select.png" width="600" height="309" />
96
96
  <div style="margin-top: -100px; margin-left: 100px;">
@@ -42,7 +42,9 @@ The generator creates a new project at `packages/<name>/`, plus a CDK construct
42
42
  - permit-all.cedar Default Cedar policy that permits authenticated callers
43
43
  - README.md Reference for writing Cedar policies
44
44
  - local-dev.ts Local gateway for local development — aggregates attached MCP servers (`mcp`) or proxies attached agents (`http`)
45
- - project.json Adds the `serve` and `dev` targets
45
+ - package.json Declares the dependencies `local-dev.ts` imports
46
+ - tsconfig.json TypeScript configuration used by the `typecheck` target
47
+ - project.json Adds the `serve`, `dev`, `build`, `lint`, `format` and `typecheck` targets
46
48
  </FileTree>
47
49
 
48
50
  ### Infrastructure
@@ -133,7 +135,7 @@ The generated infrastructure consumes an existing Cognito user pool and client
133
135
  The generated construct requires an `identity` prop supplying the user pool and client:
134
136
 
135
137
  ```ts {7,9-11} title="packages/infra/src/stacks/application-stack.ts"
136
- import { MyGateway, UserIdentity } from ':my-scope/common-constructs';
138
+ import { MyGateway, UserIdentity } from '@my-scope/common-constructs';
137
139
 
138
140
  export class ApplicationStack extends Stack {
139
141
  constructor(scope: Construct, id: string, props?: StackProps) {
@@ -32,7 +32,8 @@ The generator creates a standalone project at `packages/<name>/`. Because AWS ru
32
32
  - packages/\<name>/
33
33
  - src/PROMPT.md The Harness system prompt
34
34
  - scripts/chat.ts Multi-turn chat client for the deployed Harness
35
- - project.json Adds the `chat` target
35
+ - tsconfig.json TypeScript configuration used by the `typecheck` target
36
+ - project.json Adds the `chat`, `build`, `lint`, `format` and `typecheck` targets
36
37
  - README.md Chat and customization instructions
37
38
  </FileTree>
38
39
 
@@ -43,7 +43,9 @@ workspace root (configurable via the `name`, `directory` and `subDirectory` opti
43
43
  - scripts
44
44
  - translate.ts Translation driver — a Strands agent with a scoped file-editor tool (omitted with `--noTranslation`)
45
45
  - translate.config.json Source/target locales, glob patterns, model id, region (omitted with `--noTranslation`)
46
+ - .gitignore Ignores Astro's build output and generated types
46
47
  - src
48
+ - content.config.ts Starlight's docs content collection definition
47
49
  - components
48
50
  - link.astro Locale-aware link component (resolves paths against the current locale)
49
51
  - snippet.astro Locale-aware snippet loader component
@@ -74,14 +76,29 @@ it. To add more languages:
74
76
  ## Translation
75
77
 
76
78
  Unless you passed `--noTranslation`, the generator adds a `translate` target to
77
- `project.json`, so you can run:
79
+ `project.json`. Which locales it translates to comes from `targetLanguages` in
80
+ `scripts/translate.config.json`, which ships empty — so start by naming the
81
+ locales you want on the command line:
78
82
 
79
83
  <NxCommands commands={[
80
- 'translate docs -- --all',
81
84
  'translate docs -- --languages jp,ko',
85
+ 'translate docs -- --languages jp,ko --dry-run',
86
+ ]} />
87
+
88
+ Once you have populated `targetLanguages` (see [Configuring
89
+ translation](#configuring-translation)), `--languages` becomes optional and the
90
+ configured locales are used:
91
+
92
+ <NxCommands commands={[
93
+ 'translate docs -- --all',
82
94
  'translate docs -- --dry-run',
83
95
  ]} />
84
96
 
97
+ :::caution[Configure your target languages first]
98
+ Without `--languages` and with `targetLanguages` still empty, the target exits
99
+ non-zero with `ERROR No target languages configured`.
100
+ :::
101
+
85
102
  When run without `--all`, the script only translates files that have changed
86
103
  since the last translation commit on the current branch — meaning you can
87
104
  safely re-run it on every docs PR without re-translating the whole site.
@@ -145,8 +162,9 @@ No CI workflow is generated out of the box — add one that:
145
162
 
146
163
  <NxCommands commands={['translate docs']} />
147
164
 
148
- 3. Commits the resulting translations back to the PR branch. The commit message
149
- must match the `translationCommitMessage` value in
150
- `scripts/translate.config.json` (default `docs: update translations`) so that
151
- subsequent incremental runs can detect the baseline commit and only
152
- re-translate the files that changed since.
165
+ 3. Commits the resulting translations back to the PR branch, using
166
+ `docs: update translations` as the commit message, so that subsequent
167
+ incremental runs can detect the baseline commit and only re-translate the
168
+ files that changed since. To use a different message, add a
169
+ `translationCommitMessage` key to `scripts/translate.config.json` and match
170
+ that value instead.
@@ -48,11 +48,13 @@ The generator creates a shared `agent_connection` Python project at `packages/co
48
48
  - \<scope>\_agent\_connection
49
49
  - \_\_init\_\_.py Re-exports per-connection clients
50
50
  - core
51
+ - \_\_init\_\_.py Python package initialization
51
52
  - agentcore\_endpoints.py Framework-agnostic ARN/URL resolution
52
53
  - agentcore\_a2a\_client\_config.py Framework-agnostic A2A client config (signed `ClientConfig`)
53
54
  - agentcore\_a2a\_client\_\<framework>.py A2A client wrapping the config for your agent's framework
54
55
  - auth/ Framework-agnostic SigV4 / session-forwarding `httpx.Auth`
55
56
  - app
57
+ - \_\_init\_\_.py Python package initialization
56
58
  - \<target\_agent\_name>\_client\_\<framework>.py Per-connection A2A client for each A2A agent
57
59
 
58
60
  </FileTree>
@@ -41,7 +41,7 @@ The generator updates the agent's `<agent-name>-dev` target in `project.json` to
41
41
  Import entity classes from the DynamoDB package and use them inside your agent tools:
42
42
 
43
43
  ```python title="packages/my_project/my_project/my_agent/agent.py"
44
- from my_scope.my_table.entities.example import ExampleModel
44
+ from my_scope_my_table.entities.example import ExampleModel
45
45
  from strands import tool
46
46
 
47
47
  @tool
@@ -50,11 +50,14 @@ The generator emits shared core-gateway modules into your `agent_connection` Pyt
50
50
  - packages/common/agent\_connection
51
51
  - \<scope>\_agent\_connection
52
52
  - core/
53
+ - \_\_init\_\_.py Python package initialization
53
54
  - agentcore\_endpoints.py Framework-agnostic ARN/URL resolution
55
+ - agentcore\_transport.py Shared AgentCore transport plumbing
54
56
  - agentcore\_gateway\_mcp\_transport.py Framework-agnostic Gateway MCP transport
55
57
  - agentcore\_gateway\_mcp\_client\_\<framework>.py Gateway MCP client for your agent's framework
56
58
  - auth/ Framework-agnostic SigV4 / session-forwarding `httpx.Auth`
57
59
  - app/
60
+ - \_\_init\_\_.py Python package initialization
58
61
  - \<gateway\_snake>\_client\_\<framework>.py Per-Gateway client wrapper
59
62
  - \_\_init\_\_.py Re-exports the Gateway client
60
63
 
@@ -13,6 +13,7 @@ import RunGenerator from '@components/run-generator.astro';
13
13
  import GeneratorParameters from '@components/generator-parameters.astro';
14
14
  import NxCommands from '@components/nx-commands.astro';
15
15
  import Infrastructure from '@components/infrastructure.astro';
16
+ import Snippet from '@components/snippet.astro';
16
17
 
17
18
  The `connection` generator can connect your <Link path="guides/py-agent">Python Agent</Link> to an MCP server (either <Link path="guides/ts-mcp-server">TypeScript</Link> or <Link path="guides/py-mcp-server">Python</Link>).
18
19
 
@@ -48,11 +49,14 @@ The generator creates a shared `agent_connection` Python project at `packages/co
48
49
  - \<scope>\_agent\_connection
49
50
  - \_\_init\_\_.py Re-exports per-connection clients
50
51
  - core
52
+ - \_\_init\_\_.py Python package initialization
51
53
  - agentcore\_endpoints.py Framework-agnostic ARN/URL resolution
54
+ - agentcore\_transport.py Shared AgentCore transport plumbing
52
55
  - agentcore\_mcp\_transport.py Framework-agnostic MCP transport
53
56
  - agentcore\_mcp\_client\_\<framework>.py MCP client wrapping the transport for your agent's framework
54
57
  - auth/ Framework-agnostic SigV4 / session-forwarding `httpx.Auth`
55
58
  - app
59
+ - \_\_init\_\_.py Python package initialization
56
60
  - \<mcp\_server\_name>\_client\_\<framework>.py Per-connection client for each MCP server
57
61
 
58
62
  </FileTree>
@@ -114,6 +118,8 @@ The AgentCore session ID is propagated to the MCP server automatically via the `
114
118
 
115
119
  ## Infrastructure
116
120
 
121
+ <Snippet name="connection/infra-project-prerequisite" />
122
+
117
123
  <Infrastructure>
118
124
  <Fragment slot="cdk">
119
125
  After running the connection generator, you need to grant the agent permission to invoke the MCP server:
@@ -126,12 +132,14 @@ const myAgent = new MyAgent(this, 'MyAgent');
126
132
  mcpServer.grantInvokeAccess(myAgent);
127
133
  ```
128
134
 
135
+ `grantInvokeAccess` wires up the AgentCore invoke actions (`InvokeAgentRuntime`, `InvokeAgentRuntimeForUser` and `InvokeAgentRuntimeWithWebSocketStream`) on the MCP server's runtime ARN.
136
+
129
137
  The MCP server's AgentCore runtime ARN is automatically registered in the `agentcore` namespace of <Link path="guides/runtime-config">Runtime Configuration</Link> by the generated CDK construct, so the agent can discover it at runtime.
130
138
  </Fragment>
131
139
  <Fragment slot="terraform">
132
140
  After running the connection generator, you need to grant the agent permission to invoke the MCP server in your Terraform configuration:
133
141
 
134
- ```hcl title="packages/infra/src/main.tf" {9-25}
142
+ ```hcl title="packages/infra/src/main.tf" {9-31}
135
143
  module "inventory_mcp_server" {
136
144
  source = "../../common/terraform/src/app/mcp-servers/inventory-mcp"
137
145
  }
@@ -146,9 +154,15 @@ resource "aws_iam_policy" "agent_invoke_mcp" {
146
154
  policy = jsonencode({
147
155
  Version = "2012-10-17"
148
156
  Statement = [{
149
- Effect = "Allow"
150
- Action = "bedrock-agentcore:InvokeAgent"
151
- Resource = module.inventory_mcp_server.agent_core_runtime_arn
157
+ Effect = "Allow"
158
+ Action = [
159
+ "bedrock-agentcore:InvokeAgentRuntime",
160
+ "bedrock-agentcore:InvokeAgentRuntimeWithWebSocketStream",
161
+ ]
162
+ Resource = [
163
+ module.inventory_mcp_server.agent_core_runtime_arn,
164
+ "${module.inventory_mcp_server.agent_core_runtime_arn}/*",
165
+ ]
152
166
  }]
153
167
  })
154
168
  }
@@ -42,7 +42,7 @@ Select your Agent project as the source and your relational database project as
42
42
  - pyproject.toml Adds the database package as a workspace dependency
43
43
  - my\_service
44
44
  - my\_agent
45
- - Dockerfile Adds the RDS CA bundle used for direct Aurora connections
45
+ - Dockerfile Adds the RDS CA bundle used for direct Aurora connections (only when the agent's `infra` is `agentcore-ecr`)
46
46
 
47
47
  </FileTree>
48
48
 
@@ -52,15 +52,16 @@ Import `session_context` from your database package and use it inside your agent
52
52
 
53
53
  ```python title="packages/my_service/my_service/my_agent/agent.py"
54
54
  from sqlmodel import select
55
- from my_scope.my_db import session_context
56
- from my_scope.my_db.models.example import ExampleModel
55
+ from my_scope_my_db import session_context
56
+ from my_scope_my_db.models.example import ExampleModel
57
57
  from strands import tool
58
58
 
59
59
  @tool
60
60
  async def list_examples() -> list:
61
61
  """List all example records."""
62
62
  async with session_context() as session:
63
- return [item.model_dump() for item in (await session.execute(select(ExampleModel))).all()]
63
+ items = (await session.execute(select(ExampleModel))).scalars().all()
64
+ return [item.model_dump() for item in items]
64
65
  ```
65
66
 
66
67
  ## Infrastructure
@@ -40,7 +40,7 @@ The generator updates the FastAPI's `project.json` to add a dependency from its
40
40
  Import entity classes from the DynamoDB package and use them inside your route handlers:
41
41
 
42
42
  ```python title="packages/my_api/my_api/api.py"
43
- from my_scope.my_table.entities.example import ExampleModel
43
+ from my_scope_my_table.entities.example import ExampleModel
44
44
 
45
45
  @app.get("/examples")
46
46
  def list_examples():
@@ -11,6 +11,7 @@ import RunGenerator from '@components/run-generator.astro';
11
11
  import GeneratorParameters from '@components/generator-parameters.astro';
12
12
  import NxCommands from '@components/nx-commands.astro';
13
13
  import Infrastructure from '@components/infrastructure.astro';
14
+ import Snippet from '@components/snippet.astro';
14
15
 
15
16
  The `connection` generator wires a <Link path="guides/fastapi">FastAPI</Link> to a <Link path="guides/py-rdb">Python Relational Database</Link> project, injecting a typed SQLModel session into your route handlers via a FastAPI dependency.
16
17
 
@@ -55,11 +56,11 @@ This generator configures an injectable [FastAPI Dependency](https://fastapi.tia
55
56
  ```python title="packages/my_api/my_api/api.py" {2,6,10}
56
57
  from sqlmodel import select
57
58
  from my_api.dependencies.my_db import MyDbSession
58
- from my_scope.my_db.models.example import ExampleModel
59
+ from my_scope_my_db.models.example import ExampleModel
59
60
 
60
61
  @app.get("/examples")
61
62
  async def list_examples(my_db: MyDbSession):
62
- return (await my_db.execute(select(ExampleModel))).all()
63
+ return (await my_db.execute(select(ExampleModel))).scalars().all()
63
64
 
64
65
  @app.post("/examples")
65
66
  async def create_example(name: str, my_db: MyDbSession):
@@ -168,6 +169,10 @@ The AppConfig application exposes the `database` namespace by default, so the da
168
169
  </Fragment>
169
170
  </Infrastructure>
170
171
 
172
+ ### SSL Requirements When Connecting Without RDS Proxy
173
+
174
+ <Snippet name="connection/py-lambda-rdb-ssl-requirements" parentHeading="SSL Requirements When Connecting Without RDS Proxy" />
175
+
171
176
  ## Local Development
172
177
 
173
178
  <NxCommands commands={["dev <project-name>"]} />
@@ -41,7 +41,7 @@ The generator updates the MCP server's `<mcp-server-name>-dev` target in `projec
41
41
  Import entity classes from the DynamoDB package and use them inside your MCP server tools:
42
42
 
43
43
  ```python title="packages/my_project/my_project/my_mcp_server/server.py"
44
- from my_scope.my_table.entities.example import ExampleModel
44
+ from my_scope_my_table.entities.example import ExampleModel
45
45
 
46
46
  @mcp.tool()
47
47
  def list_examples() -> str:
@@ -42,7 +42,7 @@ Select your MCP server project as the source and your relational database projec
42
42
  - pyproject.toml Adds the database package as a workspace dependency
43
43
  - my\_service
44
44
  - my\_mcp\_server
45
- - Dockerfile Adds the RDS CA bundle used for direct Aurora connections
45
+ - Dockerfile Adds the RDS CA bundle used for direct Aurora connections (only when the MCP server's `infra` is `agentcore-ecr`)
46
46
 
47
47
  </FileTree>
48
48
 
@@ -52,14 +52,14 @@ Import `session_context` from your database package and use it inside your MCP s
52
52
 
53
53
  ```python title="packages/my_service/my_service/my_mcp_server/server.py"
54
54
  from sqlmodel import select
55
- from my_scope.my_db import session_context
56
- from my_scope.my_db.models.example import ExampleModel
55
+ from my_scope_my_db import session_context
56
+ from my_scope_my_db.models.example import ExampleModel
57
57
 
58
58
  @mcp.tool()
59
59
  async def list_examples() -> str:
60
60
  """List all example records."""
61
61
  async with session_context() as session:
62
- items = (await session.execute(select(ExampleModel))).all()
62
+ items = (await session.execute(select(ExampleModel))).scalars().all()
63
63
  return str([item.model_dump() for item in items])
64
64
  ```
65
65
 
@@ -68,8 +68,8 @@ async def list_examples() -> str:
68
68
  Running the generator again with a different target adds the second database alongside the first. Both session contexts are available to all tools:
69
69
 
70
70
  ```python title="packages/my_service/my_service/my_mcp_server/server.py"
71
- from my_scope.my_db import session_context as my_db_session_context
72
- from my_scope.other_db import session_context as other_db_session_context
71
+ from my_scope_my_db import session_context as my_db_session_context
72
+ from my_scope_other_db import session_context as other_db_session_context
73
73
  ```
74
74
 
75
75
  ## Infrastructure