@aws/nx-plugin-mcp 1.0.0-rc.3 → 1.0.0-rc.30

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 (121) hide show
  1. package/bin/aws-nx-mcp.js +4312 -3360
  2. package/docs/guides/agentcore-gateway.mdx +376 -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 +47 -15
  6. package/docs/guides/connection/py-agent-dynamodb.mdx +116 -0
  7. package/docs/guides/connection/py-agent-gateway.mdx +176 -0
  8. package/docs/guides/connection/py-agent-mcp.mdx +42 -13
  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-agui.mdx +4 -4
  12. package/docs/guides/connection/react-fastapi.mdx +2 -2
  13. package/docs/guides/connection/react-py-agent.mdx +3 -3
  14. package/docs/guides/connection/react-smithy.mdx +3 -3
  15. package/docs/guides/connection/react-trpc.mdx +1 -1
  16. package/docs/guides/connection/react-ts-agent.mdx +5 -5
  17. package/docs/guides/connection/smithy-dynamodb.mdx +68 -0
  18. package/docs/guides/connection/smithy-rdb.mdx +4 -4
  19. package/docs/guides/connection/trpc-dynamodb.mdx +62 -0
  20. package/docs/guides/connection/trpc-rdb.mdx +4 -4
  21. package/docs/guides/connection/ts-agent-a2a.mdx +12 -9
  22. package/docs/guides/connection/ts-agent-dynamodb.mdx +128 -0
  23. package/docs/guides/connection/ts-agent-gateway.mdx +141 -0
  24. package/docs/guides/connection/ts-agent-mcp.mdx +11 -8
  25. package/docs/guides/connection/ts-agent-rdb.mdx +3 -3
  26. package/docs/guides/connection/ts-mcp-server-dynamodb.mdx +125 -0
  27. package/docs/guides/connection/ts-mcp-server-rdb.mdx +3 -3
  28. package/docs/guides/connection.mdx +101 -0
  29. package/docs/guides/docker-bundling.mdx +13 -7
  30. package/docs/guides/fastapi.mdx +244 -4
  31. package/docs/guides/license.mdx +264 -109
  32. package/docs/guides/local-development.mdx +87 -0
  33. package/docs/guides/nx-generator.mdx +7 -2
  34. package/docs/guides/py-agent.mdx +204 -44
  35. package/docs/guides/py-dynamodb.mdx +476 -0
  36. package/docs/guides/py-mcp-server.mdx +57 -2
  37. package/docs/guides/react-website-auth.mdx +58 -1
  38. package/docs/guides/react-website.mdx +87 -19
  39. package/docs/guides/terraform-project.mdx +1 -1
  40. package/docs/guides/trpc.mdx +45 -9
  41. package/docs/guides/ts-agent.mdx +120 -6
  42. package/docs/guides/ts-dynamodb.mdx +187 -0
  43. package/docs/guides/ts-mcp-server.mdx +62 -2
  44. package/docs/guides/ts-rdb.mdx +98 -20
  45. package/docs/guides/ts-smithy-api.mdx +183 -4
  46. package/docs/guides/typescript-infrastructure.mdx +9 -1
  47. package/docs/guides/typescript-project.mdx +5 -10
  48. package/docs/guides/workspace.mdx +8 -2
  49. package/docs/snippets/agent/bedrock-deployment.mdx +4 -0
  50. package/docs/snippets/api/access-logging.mdx +33 -0
  51. package/docs/snippets/api/type-safe-api-integrations.mdx +31 -0
  52. package/docs/snippets/api/waf-configuration.mdx +1 -1
  53. package/docs/snippets/connection/dynamodb-local-development.mdx +7 -0
  54. package/docs/snippets/connection/lambda-dynamodb-access.mdx +80 -0
  55. package/docs/snippets/connection/py-dynamodb-local-development.mdx +7 -0
  56. package/docs/snippets/dynamodb/deploying-table.mdx +171 -0
  57. package/docs/snippets/dynamodb/gsi-config.mdx +38 -0
  58. package/docs/snippets/dynamodb/infrastructure.mdx +33 -0
  59. package/docs/snippets/dynamodb/local-dev-start.mdx +13 -0
  60. package/docs/snippets/dynamodb/local-dev-windows.mdx +15 -0
  61. package/docs/snippets/mcp/bedrock-deployment.mdx +4 -0
  62. package/docs/snippets/mcp/config.mdx +2 -1
  63. package/docs/snippets/required-prerequisites.mdx +1 -1
  64. package/generators.json +100 -1
  65. package/package.json +1 -1
  66. package/src/agentcore-gateway/gateway-connection/schema.json +31 -0
  67. package/src/agentcore-gateway/mcp-connection/schema.json +31 -0
  68. package/src/agentcore-gateway/schema.json +70 -0
  69. package/src/connection/schema.json +5 -0
  70. package/src/infra/app/schema.json +5 -0
  71. package/src/license/schema.json +11 -0
  72. package/src/preset/schema.json +10 -5
  73. package/src/py/agent/a2a-connection/schema.json +5 -0
  74. package/src/py/agent/gateway-connection/schema.json +31 -0
  75. package/src/py/agent/mcp-connection/schema.json +5 -0
  76. package/src/py/agent/react-connection/schema.json +5 -0
  77. package/src/py/agent/schema.json +6 -1
  78. package/src/py/api/schema.json +5 -0
  79. package/src/py/dynamodb/agent-connection/schema.json +27 -0
  80. package/src/py/dynamodb/fast-api-connection/schema.json +23 -0
  81. package/src/py/dynamodb/mcp-server-connection/schema.json +27 -0
  82. package/src/py/dynamodb/schema.json +75 -0
  83. package/src/py/fast-api/react/schema.json +5 -0
  84. package/src/py/fast-api/schema.json +5 -0
  85. package/src/py/lambda-function/schema.json +5 -0
  86. package/src/py/mcp-server/schema.json +5 -0
  87. package/src/py/project/schema.json +5 -0
  88. package/src/smithy/project/schema.json +5 -0
  89. package/src/smithy/react-connection/schema.json +5 -0
  90. package/src/smithy/ts/api/schema.json +5 -0
  91. package/src/terraform/project/schema.json +5 -0
  92. package/src/trpc/backend/schema.json +5 -0
  93. package/src/trpc/react/schema.json +5 -0
  94. package/src/ts/agent/a2a-connection/schema.json +5 -0
  95. package/src/ts/agent/gateway-connection/schema.json +31 -0
  96. package/src/ts/agent/mcp-connection/schema.json +5 -0
  97. package/src/ts/agent/react-connection/schema.json +5 -0
  98. package/src/ts/agent/schema.json +5 -0
  99. package/src/ts/api/schema.json +5 -0
  100. package/src/ts/astro-docs/schema.json +3 -3
  101. package/src/ts/docs/schema.json +3 -3
  102. package/src/ts/dynamodb/agent-connection/schema.json +27 -0
  103. package/src/ts/dynamodb/mcp-server-connection/schema.json +27 -0
  104. package/src/ts/dynamodb/schema.json +75 -0
  105. package/src/ts/dynamodb/smithy-connection/schema.json +23 -0
  106. package/src/ts/dynamodb/trpc-connection/schema.json +23 -0
  107. package/src/ts/lambda-function/schema.json +5 -0
  108. package/src/ts/lib/schema.json +5 -0
  109. package/src/ts/mcp-server/schema.json +5 -0
  110. package/src/ts/nx-generator/schema.json +5 -0
  111. package/src/ts/nx-plugin/schema.json +5 -0
  112. package/src/ts/rdb/agent-connection/schema.json +5 -0
  113. package/src/ts/rdb/mcp-server-connection/schema.json +5 -0
  114. package/src/ts/rdb/schema.json +5 -0
  115. package/src/ts/rdb/smithy-connection/schema.json +5 -0
  116. package/src/ts/rdb/trpc-connection/schema.json +5 -0
  117. package/src/ts/react-website/app/schema.json +11 -6
  118. package/src/ts/react-website/cognito-auth/schema.json +5 -0
  119. package/src/ts/react-website/runtime-config/schema.json +5 -0
  120. package/src/ts/website/app/schema.json +11 -6
  121. package/src/ts/website/auth/schema.json +5 -0
@@ -1,12 +1,14 @@
1
1
  ---
2
2
  title: FastAPI
3
3
  description: Reference documentation for FastAPI
4
- generator: py#fast-api
4
+ generator: py#api
5
5
  when:
6
6
  framework: [fastapi]
7
7
  ---
8
8
 
9
- import { FileTree, Tabs, TabItem } from '@astrojs/starlight/components';
9
+ import { FileTree, Tabs, TabItem, CardGrid } from '@astrojs/starlight/components';
10
+ import Astro from '@astrojs/react';
11
+ import ConnectionCard from '@components/connection-card.astro';
10
12
  import Link from '@components/link.astro';
11
13
  import RunGenerator from '@components/run-generator.astro';
12
14
  import GeneratorParameters from '@components/generator-parameters.astro';
@@ -26,11 +28,11 @@ The FastAPI generator creates a new FastAPI with AWS CDK or Terraform infrastruc
26
28
 
27
29
  You can generate a new FastAPI in two ways:
28
30
 
29
- <RunGenerator generator="py#fast-api" />
31
+ <RunGenerator generator="py#api" requiredParameters={{ framework: 'fastapi' }} />
30
32
 
31
33
  ### Options
32
34
 
33
- <GeneratorParameters generator="py#fast-api" />
35
+ <GeneratorParameters generator="py#api" />
34
36
 
35
37
  <Snippet name="api/api-choice-note" />
36
38
 
@@ -185,6 +187,216 @@ Unhandled exceptions are caught by the middleware and:
185
187
  It's recommended to specify response models for your API operations for better code generation if using the `connection` generator. <Link path="guides/connection/react-fastapi#errors">See here for more details</Link>.
186
188
  :::
187
189
 
190
+ ### Accessing the Calling User
191
+
192
+ When your API is protected by authentication, your route handlers often need to know who is calling. The generated FastAPI runs inside AWS Lambda via the [Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter), which forwards the API Gateway request context as JSON on the `x-amzn-request-context` header. You can read it from the FastAPI `Request` to extract the caller's identity.
193
+
194
+ As an example, let's add a `/me` endpoint that returns details about the calling user. We'll implement the extraction as a [FastAPI dependency](https://fastapi.tiangolo.com/tutorial/dependencies/) so it can be reused across routes. The shape of the request context — and therefore how you extract the identity — depends on both your selected `auth` method and whether you deployed a REST or HTTP API.
195
+
196
+ <OptionFilter when={{ auth: 'iam' }} description="Identity extraction for IAM-authenticated APIs">
197
+ For `IAM` authentication, we look up the caller in Cognito using the sub extracted from the API Gateway request context. Create `identity.py` alongside `main.py`:
198
+
199
+ <Tabs syncKey="http-rest">
200
+ <TabItem label="REST API" _filter={{ infra: 'rest-lambda' }}>
201
+ ```python
202
+ import json
203
+ import os
204
+ from typing import Annotated
205
+
206
+ from boto3 import client
207
+ from fastapi import Depends, HTTPException, Request
208
+ from pydantic import BaseModel
209
+
210
+ cognito = client("cognito-idp")
211
+
212
+
213
+ class Identity(BaseModel):
214
+ sub: str
215
+ username: str
216
+
217
+
218
+ def get_identity(request: Request) -> Identity:
219
+ # The Lambda Web Adapter forwards the API Gateway request context as JSON
220
+ request_context_header = request.headers.get("x-amzn-request-context")
221
+ if not request_context_header:
222
+ raise HTTPException(status_code=403, detail="Unable to determine calling user")
223
+
224
+ request_context = json.loads(request_context_header)
225
+ provider = request_context.get("identity", {}).get("cognitoAuthenticationProvider")
226
+
227
+ sub = provider.split(":")[-1] if provider else None
228
+ if not sub:
229
+ raise HTTPException(status_code=403, detail="Unable to determine calling user")
230
+
231
+ users = cognito.list_users(
232
+ # Assumes user pool id is configured in lambda environment
233
+ UserPoolId=os.environ["USER_POOL_ID"],
234
+ Limit=1,
235
+ Filter=f'sub="{sub}"',
236
+ ).get("Users", [])
237
+
238
+ if len(users) != 1:
239
+ raise HTTPException(status_code=403, detail=f"No user found with subjectId {sub}")
240
+
241
+ return Identity(sub=sub, username=users[0]["Username"])
242
+
243
+
244
+ CurrentUser = Annotated[Identity, Depends(get_identity)]
245
+ ```
246
+ </TabItem>
247
+ <TabItem label="HTTP API" _filter={{ infra: 'http-lambda' }}>
248
+ ```python
249
+ import json
250
+ import os
251
+ from typing import Annotated
252
+
253
+ from boto3 import client
254
+ from fastapi import Depends, HTTPException, Request
255
+ from pydantic import BaseModel
256
+
257
+ cognito = client("cognito-idp")
258
+
259
+
260
+ class Identity(BaseModel):
261
+ sub: str
262
+ username: str
263
+
264
+
265
+ def get_identity(request: Request) -> Identity:
266
+ # The Lambda Web Adapter forwards the API Gateway request context as JSON
267
+ request_context_header = request.headers.get("x-amzn-request-context")
268
+ if not request_context_header:
269
+ raise HTTPException(status_code=403, detail="Unable to determine calling user")
270
+
271
+ request_context = json.loads(request_context_header)
272
+ amr = (
273
+ request_context.get("authorizer", {})
274
+ .get("iam", {})
275
+ .get("cognitoIdentity", {})
276
+ .get("amr", [])
277
+ )
278
+ sign_in = next((s for s in amr if ":CognitoSignIn:" in s), None)
279
+ sub = sign_in.split(":")[-1] if sign_in else None
280
+
281
+ if not sub:
282
+ raise HTTPException(status_code=403, detail="Unable to determine calling user")
283
+
284
+ users = cognito.list_users(
285
+ # Assumes user pool id is configured in lambda environment
286
+ UserPoolId=os.environ["USER_POOL_ID"],
287
+ Limit=1,
288
+ Filter=f'sub="{sub}"',
289
+ ).get("Users", [])
290
+
291
+ if len(users) != 1:
292
+ raise HTTPException(status_code=403, detail=f"No user found with subjectId {sub}")
293
+
294
+ return Identity(sub=sub, username=users[0]["Username"])
295
+
296
+
297
+ CurrentUser = Annotated[Identity, Depends(get_identity)]
298
+ ```
299
+ </TabItem>
300
+ </Tabs>
301
+ </OptionFilter>
302
+
303
+ <OptionFilter when={{ auth: 'cognito' }} description="Identity extraction for Cognito-authenticated APIs">
304
+ With `auth: 'cognito'`, the API Gateway Cognito User Pools authorizer verifies the JWT that the caller supplies in the `Authorization` header and places the verified claims on the request context.
305
+
306
+ Create `identity.py` alongside `main.py`:
307
+
308
+ <Tabs syncKey="http-rest">
309
+ <TabItem label="REST API" _filter={{ infra: 'rest-lambda' }}>
310
+ ```python
311
+ import json
312
+ from typing import Annotated
313
+
314
+ from fastapi import Depends, HTTPException, Request
315
+ from pydantic import BaseModel
316
+
317
+
318
+ class Identity(BaseModel):
319
+ sub: str
320
+ username: str
321
+
322
+
323
+ def get_identity(request: Request) -> Identity:
324
+ # The Lambda Web Adapter forwards the API Gateway request context as JSON
325
+ request_context_header = request.headers.get("x-amzn-request-context")
326
+ if not request_context_header:
327
+ raise HTTPException(status_code=403, detail="Unable to determine calling user")
328
+
329
+ request_context = json.loads(request_context_header)
330
+ claims = request_context.get("authorizer", {}).get("claims", {})
331
+
332
+ sub = claims.get("sub")
333
+ username = claims.get("username")
334
+
335
+ if not sub or not username:
336
+ raise HTTPException(status_code=403, detail="Unable to determine calling user")
337
+
338
+ return Identity(sub=sub, username=username)
339
+
340
+
341
+ CurrentUser = Annotated[Identity, Depends(get_identity)]
342
+ ```
343
+ </TabItem>
344
+ <TabItem label="HTTP API" _filter={{ infra: 'http-lambda' }}>
345
+ HTTP APIs use a JWT authorizer which places the verified claims under `authorizer.jwt.claims`:
346
+
347
+ ```python
348
+ import json
349
+ from typing import Annotated
350
+
351
+ from fastapi import Depends, HTTPException, Request
352
+ from pydantic import BaseModel
353
+
354
+
355
+ class Identity(BaseModel):
356
+ sub: str
357
+ username: str
358
+
359
+
360
+ def get_identity(request: Request) -> Identity:
361
+ # The Lambda Web Adapter forwards the API Gateway request context as JSON
362
+ request_context_header = request.headers.get("x-amzn-request-context")
363
+ if not request_context_header:
364
+ raise HTTPException(status_code=403, detail="Unable to determine calling user")
365
+
366
+ request_context = json.loads(request_context_header)
367
+ claims = request_context.get("authorizer", {}).get("jwt", {}).get("claims", {})
368
+
369
+ sub = claims.get("sub")
370
+ username = claims.get("username")
371
+
372
+ if not sub or not username:
373
+ raise HTTPException(status_code=403, detail="Unable to determine calling user")
374
+
375
+ return Identity(sub=sub, username=username)
376
+
377
+
378
+ CurrentUser = Annotated[Identity, Depends(get_identity)]
379
+ ```
380
+ </TabItem>
381
+ </Tabs>
382
+
383
+ :::tip[No token verification required]
384
+ You don't need any JWT-verification library here — the API Gateway Cognito User Pools authorizer has already verified the signature, issuer, scopes, and expiry by the time your Lambda runs. If any of those checks fail, API Gateway returns `401 Unauthorized` and your handler is never invoked.
385
+ :::
386
+ </OptionFilter>
387
+
388
+ You can then inject the `CurrentUser` dependency into any route that needs the caller's identity:
389
+
390
+ ```python
391
+ from .identity import CurrentUser, Identity
392
+ from .init import app, tracer
393
+
394
+ @app.get("/me")
395
+ @tracer.capture_method
396
+ def me(identity: CurrentUser) -> Identity:
397
+ return identity
398
+ ```
399
+
188
400
  <OptionFilter when={{ infra: 'rest-lambda' }} description="Streaming — REST API only">
189
401
  ### Streaming
190
402
 
@@ -406,6 +618,12 @@ When using `Custom` auth, your API is protected by a Lambda Authorizer that **de
406
618
  <Snippet name="api/waf-configuration" parentHeading="WAF" />
407
619
  </OptionFilter>
408
620
 
621
+ <OptionFilter when={{ infra: 'rest-lambda' }} description="Access logging — REST APIs log requests to CloudWatch by default">
622
+ ### Access logging
623
+
624
+ <Snippet name="api/access-logging" parentHeading="Access logging" />
625
+ </OptionFilter>
626
+
409
627
  ### Integrations
410
628
 
411
629
  <Snippet name="api/type-safe-api-integrations" parentHeading="Integrations" />
@@ -509,3 +727,25 @@ This starts a local FastAPI development server with:
509
727
  ## Invoking your FastAPI
510
728
 
511
729
  To invoke your API from a React website, you can use the <Link path="guides/connection/react-fastapi">`connection` generator</Link>.
730
+
731
+ ## Connections
732
+
733
+ Use the <Link path="guides/connection">`connection`</Link> generator to integrate this project with others in your workspace. The following connections involve this project:
734
+
735
+ <CardGrid>
736
+ <ConnectionCard
737
+ title="React to FastAPI"
738
+ description="Call a Python FastAPI from a React website"
739
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/react-fastapi`}
740
+ source="react"
741
+ target="fastapi"
742
+ />
743
+ <ConnectionCard
744
+ title="FastAPI to Python DynamoDB"
745
+ description="Connect a FastAPI to a DynamoDB table"
746
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/py-fast-api-dynamodb`}
747
+ source="fastapi"
748
+ target="dynamodb"
749
+ targetBadge="python"
750
+ />
751
+ </CardGrid>