@aws/nx-plugin 1.0.0-rc.18 → 1.0.0-rc.19

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 (87) hide show
  1. package/package.json +1 -1
  2. package/src/py/agent/__snapshots__/generator.spec.ts.snap +15 -6
  3. package/src/py/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +201 -0
  4. package/src/py/agent/a2a-connection/files/agent-connection/app/{__targetAgentSnakeCase___client.py.template → __targetAgentSnakeCase___client_strands.py.template} +7 -5
  5. package/src/py/agent/a2a-connection/generator.js +6 -5
  6. package/src/py/agent/a2a-connection/generator.js.map +1 -1
  7. package/src/py/agent/files/http/main.py.template +2 -2
  8. package/src/py/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +197 -0
  9. package/src/py/agent/gateway-connection/files/agent-connection/app/{__gatewaySnakeCase___client.py.template → __gatewaySnakeCase___client_strands.py.template} +6 -6
  10. package/src/py/agent/gateway-connection/generator.js +5 -5
  11. package/src/py/agent/gateway-connection/generator.js.map +1 -1
  12. package/src/py/agent/generator.js +3 -0
  13. package/src/py/agent/generator.js.map +1 -1
  14. package/src/py/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +157 -79
  15. package/src/py/agent/mcp-connection/files/agent-connection/app/{__mcpServerSnakeCase___client.py.template → __mcpServerSnakeCase___client_strands.py.template} +7 -5
  16. package/src/py/agent/mcp-connection/generator.js +5 -5
  17. package/src/py/agent/mcp-connection/generator.js.map +1 -1
  18. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +37 -3
  19. package/src/py/fast-api/files/app/__name__/main.py.template +4 -1
  20. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +13 -4
  21. package/src/smithy/project/__snapshots__/generator.spec.ts.snap +1 -0
  22. package/src/smithy/project/files/src/operations/echo.smithy.template +1 -0
  23. package/src/terraform/project/files/application/src/main.tf.template +6 -1
  24. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +35 -4
  25. package/src/trpc/backend/files/src/procedures/echo.ts.template +1 -1
  26. package/src/trpc/backend/files/src/schema/echo.ts.template +2 -2
  27. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +14 -5
  28. package/src/ts/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +256 -0
  29. package/src/ts/agent/a2a-connection/files/agent-connection/app/{__targetAgentKebabCase__-client.ts.template → __targetAgentKebabCase__-client-strands.ts.template} +5 -5
  30. package/src/ts/agent/a2a-connection/generator.js +3 -3
  31. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  32. package/src/ts/agent/files/http/router.ts.template +1 -1
  33. package/src/ts/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +220 -0
  34. package/src/ts/agent/gateway-connection/files/agent-connection/app/{__gatewayKebabCase__-client.ts.template → __gatewayKebabCase__-client-strands.ts.template} +5 -5
  35. package/src/ts/agent/gateway-connection/generator.js +3 -3
  36. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  37. package/src/ts/agent/generator.js +3 -0
  38. package/src/ts/agent/generator.js.map +1 -1
  39. package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +183 -110
  40. package/src/ts/agent/mcp-connection/files/agent-connection/app/{__mcpServerKebabCase__-client.ts.template → __mcpServerKebabCase__-client-strands.ts.template} +5 -5
  41. package/src/ts/agent/mcp-connection/generator.js +3 -3
  42. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  43. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +13 -4
  44. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +64 -24
  45. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +13 -4
  46. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +9 -3
  47. package/src/utils/agent-connection/agent-connection.d.ts +50 -24
  48. package/src/utils/agent-connection/agent-connection.js +137 -45
  49. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  50. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client-config.ts.template +93 -0
  51. package/src/utils/agent-connection/files/core-auth/agentcore-endpoints.ts.template +37 -0
  52. package/src/utils/agent-connection/files/core-auth/agentcore-fetch.ts.template +54 -0
  53. package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-transport.ts.template +41 -0
  54. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-transport.ts.template +70 -0
  55. package/src/utils/agent-connection/files/core-shared/agentcore-transport.ts.template +39 -0
  56. package/src/utils/agent-connection/files/core-strands/a2a/agentcore-a2a-client-strands.ts.template +61 -0
  57. package/src/utils/agent-connection/files/core-strands/gateway/agentcore-gateway-mcp-client-strands.ts.template +26 -0
  58. package/src/utils/agent-connection/files/core-strands/mcp/agentcore-mcp-client-strands.ts.template +27 -0
  59. package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client_config.py.template +43 -0
  60. package/src/utils/agent-connection/files/py-core-auth/agentcore_endpoints.py.template +47 -0
  61. package/src/utils/agent-connection/files/py-core-auth/auth/session.py.template +51 -0
  62. package/src/utils/agent-connection/files/py-core-gateway/agentcore_gateway_mcp_transport.py.template +28 -0
  63. package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_transport.py.template +34 -0
  64. package/src/utils/agent-connection/files/py-core-shared/agentcore_transport.py.template +40 -0
  65. package/src/utils/agent-connection/files/py-core-strands/a2a/agentcore_a2a_client_strands.py.template +66 -0
  66. package/src/utils/agent-connection/files/py-core-strands/gateway/agentcore_gateway_mcp_client_strands.py.template +22 -0
  67. package/src/utils/agent-connection/files/py-core-strands/mcp/agentcore_mcp_client_strands.py.template +30 -0
  68. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.tf.template +7 -2
  69. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +13 -4
  70. package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +9 -0
  71. package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +23 -1
  72. package/src/utils/files/terraform/src/core/runtime-config/appconfig-deployment/appconfig-deployment.tf.template +9 -3
  73. package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +7 -2
  74. package/src/utils/identity-constructs/files/terraform/core/user-identity/add-callback-url/add-callback-url.tf.template +9 -3
  75. package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +22 -8
  76. package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +10 -4
  77. package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +13 -4
  78. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client.ts.template +0 -123
  79. package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-client.ts.template +0 -78
  80. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-client.ts.template +0 -128
  81. package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client.py.template +0 -120
  82. package/src/utils/agent-connection/files/py-core-gateway/agentcore_gateway_mcp_client.py.template +0 -78
  83. package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_client.py.template +0 -89
  84. /package/src/utils/agent-connection/files/{core-runtime-config/model-errors.ts.template → core-strands/base/model-errors-strands.ts.template} +0 -0
  85. /package/src/utils/agent-connection/files/{core-runtime-config/with-session-id.ts.template → core-strands/base/with-session-id-strands.ts.template} +0 -0
  86. /package/src/utils/agent-connection/files/{py-core-runtime-config/model_errors.py.template → py-core-strands/base/model_errors_strands.py.template} +0 -0
  87. /package/src/utils/agent-connection/files/{py-core-runtime-config/with_session_id.py.template → py-core-strands/base/with_session_id_strands.py.template} +0 -0
@@ -1,123 +0,0 @@
1
- import {
2
- ClientFactory,
3
- ClientFactoryOptions,
4
- DefaultAgentCardResolver,
5
- JsonRpcTransportFactory,
6
- } from '@a2a-js/sdk/client';
7
- import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
8
- import { A2AAgent } from '@strands-agents/sdk/a2a';
9
- import { AwsClient } from 'aws4fetch';
10
- import { getCurrentSessionId } from './session-context.js';
11
-
12
- const SESSION_HEADER = 'X-Amzn-Bedrock-AgentCore-Runtime-Session-Id';
13
-
14
- /**
15
- * Common options for creating an AgentCore A2A client.
16
- */
17
- export interface AgentCoreA2aClientOptions {
18
- /** The ARN of the Bedrock AgentCore Runtime to connect to. */
19
- agentRuntimeArn: string;
20
- /** Optional description for the remote agent. */
21
- description?: string;
22
- /** Optional friendly name for the remote agent. */
23
- name?: string;
24
- }
25
-
26
- /** Options for an IAM-authenticated A2A client. */
27
- export interface AgentCoreA2aClientIamOptions
28
- extends AgentCoreA2aClientOptions {
29
- credentialProvider?: ReturnType<typeof fromNodeProviderChain>;
30
- }
31
-
32
- /** Options for a JWT-authenticated A2A client. */
33
- export interface AgentCoreA2aClientJwtOptions
34
- extends AgentCoreA2aClientOptions {
35
- accessTokenProvider: () => Promise<string>;
36
- }
37
-
38
- /** Options for a no-auth A2A client (local dev). */
39
- export interface AgentCoreA2aClientNoAuthOptions {
40
- /** Full URL of the local A2A endpoint. */
41
- url: string;
42
- name?: string;
43
- description?: string;
44
- }
45
-
46
- interface BuildOptions {
47
- name?: string;
48
- description?: string;
49
- }
50
-
51
- /** Factory for A2A clients that forward the current async-context session. */
52
- export class AgentCoreA2aClient {
53
- /**
54
- * Construct the A2A invocations URL for an AgentCore runtime ARN and
55
- * extract the region. A2A on AgentCore is mounted at `/invocations/`
56
- * (trailing slash matters).
57
- */
58
- private static buildUrl(agentRuntimeArn: string): {
59
- region: string;
60
- url: string;
61
- } {
62
- const region = agentRuntimeArn.split(':')[3];
63
- const url = `https://bedrock-agentcore.${region}.amazonaws.com/runtimes/${encodeURIComponent(agentRuntimeArn)}/invocations/`;
64
- return { region, url };
65
- }
66
-
67
- private static build(
68
- url: string,
69
- authFetch: typeof fetch,
70
- options: BuildOptions,
71
- ): A2AAgent {
72
- const sessionFetch: typeof fetch = (input, init) => {
73
- const headers = new Headers(init?.headers);
74
- const sessionId = getCurrentSessionId();
75
- if (sessionId) headers.set(SESSION_HEADER, sessionId);
76
- return authFetch(input, { ...init, headers });
77
- };
78
- const clientFactory = new ClientFactory({
79
- ...ClientFactoryOptions.default,
80
- transports: [new JsonRpcTransportFactory({ fetchImpl: sessionFetch })],
81
- cardResolver: new DefaultAgentCardResolver({ fetchImpl: sessionFetch }),
82
- });
83
- return new A2AAgent({
84
- url,
85
- clientFactory,
86
- ...(options.name ? { name: options.name } : {}),
87
- ...(options.description ? { description: options.description } : {}),
88
- });
89
- }
90
-
91
- static withIamAuth(options: AgentCoreA2aClientIamOptions): A2AAgent {
92
- const { region, url } = AgentCoreA2aClient.buildUrl(options.agentRuntimeArn);
93
- const credentialProvider =
94
- options.credentialProvider ?? fromNodeProviderChain();
95
- const sigv4Fetch: typeof fetch = async (...args) => {
96
- const client = new AwsClient({
97
- ...(await credentialProvider()),
98
- service: 'bedrock-agentcore',
99
- region,
100
- });
101
- return client.fetch(...args);
102
- };
103
- return AgentCoreA2aClient.build(url, sigv4Fetch, options);
104
- }
105
-
106
- static withJwtAuth(options: AgentCoreA2aClientJwtOptions): A2AAgent {
107
- const { url } = AgentCoreA2aClient.buildUrl(options.agentRuntimeArn);
108
- const bearerFetch: typeof fetch = async (input, init) => {
109
- const headers = new Headers(init?.headers);
110
- headers.set(
111
- 'Authorization',
112
- `Bearer ${await options.accessTokenProvider()}`,
113
- );
114
- return fetch(input, { ...init, headers });
115
- };
116
- return AgentCoreA2aClient.build(url, bearerFetch, options);
117
- }
118
-
119
- /** For local dev — plain HTTP, no auth. */
120
- static withoutAuth(options: AgentCoreA2aClientNoAuthOptions): A2AAgent {
121
- return AgentCoreA2aClient.build(options.url, fetch, options);
122
- }
123
- }
@@ -1,78 +0,0 @@
1
- import { McpClient } from '@strands-agents/sdk';
2
- import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3
- import { AwsClient } from 'aws4fetch';
4
- import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
5
- import { getCurrentSessionId } from './session-context.js';
6
-
7
- const SESSION_HEADER = 'X-Amzn-Bedrock-AgentCore-Runtime-Session-Id';
8
-
9
- export interface AgentCoreGatewayMcpClientIamOptions {
10
- /**
11
- * The MCP URL of the AgentCore Gateway, of the form
12
- * https://<gatewayId>.gateway.bedrock-agentcore.<region>.amazonaws.com/mcp
13
- */
14
- gatewayUrl: string;
15
- /** AWS region override; by default parsed from `gatewayUrl`. */
16
- region?: string;
17
- /** AWS credential provider; defaults to the standard provider chain. */
18
- credentialProvider?: ReturnType<typeof fromNodeProviderChain>;
19
- }
20
-
21
- /**
22
- * Factory for MCP clients that connect to an AgentCore Gateway. Forwards the
23
- * current async-context session via the AgentCore session header, which the
24
- * gateway propagates to downstream MCP server targets.
25
- */
26
- export class AgentCoreGatewayMcpClient {
27
- /** Create a gateway MCP client authenticated with IAM SigV4. */
28
- static withIamAuth(options: AgentCoreGatewayMcpClientIamOptions): McpClient {
29
- const credentialProvider =
30
- options.credentialProvider ?? fromNodeProviderChain();
31
- const region =
32
- options.region ?? parseRegionFromGatewayUrl(options.gatewayUrl);
33
-
34
- const sigv4Fetch: typeof fetch = async (input, init) => {
35
- const client = new AwsClient({
36
- ...(await credentialProvider()),
37
- service: 'bedrock-agentcore',
38
- region,
39
- });
40
- return client.fetch(input, {
41
- ...init,
42
- headers: withSessionHeader(init?.headers),
43
- });
44
- };
45
- return AgentCoreGatewayMcpClient.create(options.gatewayUrl, sigv4Fetch);
46
- }
47
-
48
- /** Plain-HTTP gateway client, for the local gateway started by serve-local. */
49
- static withoutAuth(options: { gatewayUrl: string }): McpClient {
50
- const plainFetch: typeof fetch = async (input, init) =>
51
- fetch(input, { ...init, headers: withSessionHeader(init?.headers) });
52
- return AgentCoreGatewayMcpClient.create(options.gatewayUrl, plainFetch);
53
- }
54
-
55
- private static create(gatewayUrl: string, fetchFn: typeof fetch): McpClient {
56
- const transport = new StreamableHTTPClientTransport(new URL(gatewayUrl), {
57
- fetch: fetchFn,
58
- });
59
- return new McpClient({ transport });
60
- }
61
- }
62
-
63
- const withSessionHeader = (init?: RequestInit['headers']): Headers => {
64
- const headers = new Headers(init);
65
- const sessionId = getCurrentSessionId();
66
- if (sessionId) headers.set(SESSION_HEADER, sessionId);
67
- return headers;
68
- };
69
-
70
- const parseRegionFromGatewayUrl = (gatewayUrl: string): string => {
71
- const match = /\.bedrock-agentcore\.([^.]+)\.amazonaws\.com/.exec(gatewayUrl);
72
- if (!match) {
73
- throw new Error(
74
- `Cannot determine region from gateway URL '${gatewayUrl}'. Pass region explicitly.`,
75
- );
76
- }
77
- return match[1];
78
- };
@@ -1,128 +0,0 @@
1
- import { McpClient } from '@strands-agents/sdk';
2
- import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3
- import { AwsClient } from 'aws4fetch';
4
- import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
5
- import { getCurrentSessionId } from './session-context.js';
6
-
7
- const SESSION_HEADER = 'X-Amzn-Bedrock-AgentCore-Runtime-Session-Id';
8
-
9
- /**
10
- * Common options for creating an AgentCore MCP client.
11
- */
12
- export interface AgentCoreMcpClientOptions {
13
- /**
14
- * The ARN of the Bedrock AgentCore Runtime to connect to.
15
- */
16
- agentRuntimeArn: string;
17
- }
18
-
19
- /**
20
- * Options for creating an AgentCore MCP client with IAM authentication.
21
- */
22
- export interface AgentCoreMcpClientIamOptions
23
- extends AgentCoreMcpClientOptions {
24
- /**
25
- * Optional AWS credential provider. If not provided, uses the default
26
- * credential provider chain from the AWS SDK.
27
- */
28
- credentialProvider?: ReturnType<typeof fromNodeProviderChain>;
29
- }
30
-
31
- /**
32
- * Options for creating an AgentCore MCP client with JWT authentication.
33
- */
34
- export interface AgentCoreMcpClientJwtOptions
35
- extends AgentCoreMcpClientOptions {
36
- /**
37
- * A function which returns the JWT access token used to authenticate.
38
- */
39
- accessTokenProvider: () => Promise<string>;
40
- }
41
-
42
- /**
43
- * Options for creating an MCP client with no auth (local dev).
44
- */
45
- export interface AgentCoreMcpClientNoAuthOptions {
46
- /** Full URL of the local MCP endpoint. */
47
- url: string;
48
- }
49
-
50
- interface CreateOptions {
51
- url: string;
52
- buildHeaders?: () => Promise<Record<string, string>>;
53
- fetch?: typeof fetch;
54
- }
55
-
56
- /** Factory for MCP clients that forward the current async-context session. */
57
- export class AgentCoreMcpClient {
58
- /**
59
- * Construct the invocation URL for an AgentCore runtime ARN and extract
60
- * the region. ARN format: arn:partition:service:region:account-id:resource
61
- */
62
- private static buildUrl(agentRuntimeArn: string): {
63
- region: string;
64
- url: string;
65
- } {
66
- const region = agentRuntimeArn.split(':')[3];
67
- const url = `https://bedrock-agentcore.${region}.amazonaws.com/runtimes/${encodeURIComponent(agentRuntimeArn)}/invocations?qualifier=DEFAULT`;
68
- return { region, url };
69
- }
70
-
71
- private static create(options: CreateOptions): McpClient {
72
- const {
73
- url,
74
- buildHeaders = async (): Promise<Record<string, string>> => ({}),
75
- fetch: customFetch,
76
- } = options;
77
- const fetchWithHeaders: typeof fetch = async (input, init) => {
78
- const headers = new Headers(init?.headers);
79
- const sessionId = getCurrentSessionId();
80
- if (sessionId) headers.set(SESSION_HEADER, sessionId);
81
- const extra = await buildHeaders();
82
- for (const k of Object.keys(extra)) {
83
- headers.set(k, extra[k]);
84
- }
85
- return (customFetch ?? fetch)(input, { ...init, headers });
86
- };
87
- const transport = new StreamableHTTPClientTransport(new URL(url), {
88
- fetch: fetchWithHeaders,
89
- });
90
- return new McpClient({ transport });
91
- }
92
-
93
- /**
94
- * SigV4-authenticated client for a Bedrock AgentCore runtime.
95
- */
96
- static withIamAuth(options: AgentCoreMcpClientIamOptions): McpClient {
97
- const { region, url } = AgentCoreMcpClient.buildUrl(options.agentRuntimeArn);
98
- const credentialProvider =
99
- options.credentialProvider ?? fromNodeProviderChain();
100
- const sigv4Fetch: typeof fetch = async (...args) => {
101
- const client = new AwsClient({
102
- ...(await credentialProvider()),
103
- service: 'bedrock-agentcore',
104
- region,
105
- });
106
- return client.fetch(...args);
107
- };
108
- return AgentCoreMcpClient.create({ url, fetch: sigv4Fetch });
109
- }
110
-
111
- /**
112
- * Bearer-authenticated client for a Bedrock AgentCore runtime.
113
- */
114
- static withJwtAuth(options: AgentCoreMcpClientJwtOptions): McpClient {
115
- const { url } = AgentCoreMcpClient.buildUrl(options.agentRuntimeArn);
116
- return AgentCoreMcpClient.create({
117
- url,
118
- buildHeaders: async () => ({
119
- Authorization: `Bearer ${await options.accessTokenProvider()}`,
120
- }),
121
- });
122
- }
123
-
124
- /** For local dev — plain HTTP, no auth. */
125
- static withoutAuth(options: AgentCoreMcpClientNoAuthOptions): McpClient {
126
- return AgentCoreMcpClient.create({ url: options.url });
127
- }
128
- }
@@ -1,120 +0,0 @@
1
- from collections.abc import Callable
2
- from urllib.parse import quote
3
-
4
- import boto3
5
- import httpx
6
- from a2a.client import ClientConfig
7
- from strands.agent.a2a_agent import A2AAgent
8
-
9
- from .auth import SigV4HTTPXAuth
10
- from .session_context import get_current_session_id
11
-
12
- SESSION_HEADER = "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id"
13
-
14
-
15
- class _SessionHeaderAuth(httpx.Auth):
16
- """Stamps the AgentCore session header from the current async context."""
17
-
18
- requires_request_body = True
19
- requires_response_body = True
20
-
21
- def __init__(self, inner: httpx.Auth | None = None):
22
- self._inner = inner
23
-
24
- def auth_flow(self, request: httpx.Request): # type: ignore[override]
25
- sid = get_current_session_id()
26
- if sid:
27
- request.headers[SESSION_HEADER] = sid
28
- if self._inner is None:
29
- yield request
30
- return
31
- yield from self._inner.auth_flow(request)
32
-
33
-
34
- class AgentCoreA2aClient:
35
- """Factory for A2A clients that forward the current async-context session."""
36
-
37
- @staticmethod
38
- def _build_url(agent_runtime_arn: str) -> tuple[str, str]:
39
- """Extract region from ARN and construct the A2A invocations URL.
40
-
41
- ARN format: arn:partition:service:region:account-id:resource
42
- A2A on AgentCore is mounted at `/invocations/` (trailing slash matters).
43
- """
44
- region = agent_runtime_arn.split(":")[3]
45
- encoded_arn = quote(agent_runtime_arn, safe="")
46
- url = (
47
- f"https://bedrock-agentcore.{region}.amazonaws.com/runtimes/"
48
- f"{encoded_arn}/invocations/"
49
- )
50
- return region, url
51
-
52
- @staticmethod
53
- def _build(
54
- url: str,
55
- auth: httpx.Auth | None,
56
- headers: dict | None,
57
- *,
58
- name: str | None,
59
- description: str | None,
60
- ) -> A2AAgent:
61
- httpx_client = httpx.AsyncClient(
62
- auth=_SessionHeaderAuth(auth),
63
- headers=headers or {},
64
- timeout=120,
65
- )
66
- client_config = ClientConfig(httpx_client=httpx_client, streaming=False)
67
- kwargs: dict = {"endpoint": url, "client_config": client_config}
68
- if name:
69
- kwargs["name"] = name
70
- if description:
71
- kwargs["description"] = description
72
- return A2AAgent(**kwargs)
73
-
74
- @staticmethod
75
- def with_iam_auth(
76
- agent_runtime_arn: str,
77
- *,
78
- name: str | None = None,
79
- description: str | None = None,
80
- ) -> A2AAgent:
81
- """SigV4-authenticated client for a Bedrock AgentCore runtime."""
82
- region, url = AgentCoreA2aClient._build_url(agent_runtime_arn)
83
- credentials = boto3.Session(region_name=region).get_credentials()
84
- return AgentCoreA2aClient._build(
85
- url,
86
- SigV4HTTPXAuth(credentials, "bedrock-agentcore", region),
87
- None,
88
- name=name,
89
- description=description,
90
- )
91
-
92
- @staticmethod
93
- def with_jwt_auth(
94
- agent_runtime_arn: str,
95
- access_token_provider: Callable[[], str],
96
- *,
97
- name: str | None = None,
98
- description: str | None = None,
99
- ) -> A2AAgent:
100
- """Bearer-authenticated client for a Bedrock AgentCore runtime."""
101
- _, url = AgentCoreA2aClient._build_url(agent_runtime_arn)
102
- return AgentCoreA2aClient._build(
103
- url,
104
- None,
105
- {"Authorization": f"Bearer {access_token_provider()}"},
106
- name=name,
107
- description=description,
108
- )
109
-
110
- @staticmethod
111
- def without_auth(
112
- url: str,
113
- *,
114
- name: str | None = None,
115
- description: str | None = None,
116
- ) -> A2AAgent:
117
- """Plain-HTTP client — for local dev."""
118
- return AgentCoreA2aClient._build(
119
- url, None, None, name=name, description=description
120
- )
@@ -1,78 +0,0 @@
1
- import re
2
-
3
- import boto3
4
- import httpx
5
- from mcp.client.streamable_http import streamablehttp_client
6
- from strands.tools.mcp.mcp_client import MCPClient
7
-
8
- from .auth import SigV4HTTPXAuth
9
- from .session_context import get_current_session_id
10
-
11
- SESSION_HEADER = "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id"
12
-
13
-
14
- class _SessionHeaderAuth(httpx.Auth):
15
- """Stamps the AgentCore session header from the current async context."""
16
-
17
- requires_request_body = True
18
- requires_response_body = True
19
-
20
- def __init__(self, inner: httpx.Auth | None = None):
21
- self._inner = inner
22
-
23
- def auth_flow(self, request: httpx.Request): # type: ignore[override]
24
- sid = get_current_session_id()
25
- if sid:
26
- request.headers[SESSION_HEADER] = sid
27
- if self._inner is None:
28
- yield request
29
- return
30
- yield from self._inner.auth_flow(request)
31
-
32
-
33
- def _parse_region_from_gateway_url(gateway_url: str) -> str:
34
- match = re.search(r"\.bedrock-agentcore\.([^.]+)\.amazonaws\.com", gateway_url)
35
- if not match:
36
- raise ValueError(
37
- f"Cannot determine region from gateway URL '{gateway_url}'. "
38
- "Pass region explicitly."
39
- )
40
- return match.group(1)
41
-
42
-
43
- class AgentCoreGatewayMCPClient:
44
- """Factory for MCP clients that connect to an AgentCore Gateway. Forwards
45
- the current async-context session via the AgentCore session header, which
46
- the gateway propagates to downstream MCP server targets.
47
- """
48
-
49
- @staticmethod
50
- def with_iam_auth(
51
- gateway_url: str,
52
- region: str | None = None,
53
- ) -> MCPClient:
54
- """Create a gateway MCP client authenticated with IAM SigV4."""
55
- resolved_region = region or _parse_region_from_gateway_url(gateway_url)
56
- credentials = boto3.Session(region_name=resolved_region).get_credentials()
57
- return _create_client(
58
- gateway_url,
59
- _SessionHeaderAuth(
60
- SigV4HTTPXAuth(credentials, "bedrock-agentcore", resolved_region),
61
- ),
62
- )
63
-
64
- @staticmethod
65
- def without_auth(gateway_url: str) -> MCPClient:
66
- """Plain-HTTP gateway client, for the local gateway started by serve-local."""
67
- return _create_client(gateway_url, _SessionHeaderAuth())
68
-
69
-
70
- def _create_client(gateway_url: str, auth: httpx.Auth) -> MCPClient:
71
- return MCPClient(
72
- lambda: streamablehttp_client(
73
- gateway_url,
74
- auth=auth,
75
- timeout=120,
76
- terminate_on_close=False,
77
- )
78
- )
@@ -1,89 +0,0 @@
1
- from collections.abc import Callable
2
-
3
- import boto3
4
- import httpx
5
- from mcp.client.streamable_http import streamablehttp_client
6
- from strands.tools.mcp.mcp_client import MCPClient
7
-
8
- from .auth import SigV4HTTPXAuth
9
- from .session_context import get_current_session_id
10
-
11
- SESSION_HEADER = "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id"
12
-
13
-
14
- class _SessionHeaderAuth(httpx.Auth):
15
- """Stamps the AgentCore session header from the current async context."""
16
-
17
- requires_request_body = True
18
- requires_response_body = True
19
-
20
- def __init__(self, inner: httpx.Auth | None = None):
21
- self._inner = inner
22
-
23
- def auth_flow(self, request: httpx.Request): # type: ignore[override]
24
- sid = get_current_session_id()
25
- if sid:
26
- request.headers[SESSION_HEADER] = sid
27
- if self._inner is None:
28
- yield request
29
- return
30
- yield from self._inner.auth_flow(request)
31
-
32
-
33
- class AgentCoreMCPClient:
34
- """Factory for MCP clients that forward the current async-context session."""
35
-
36
- @staticmethod
37
- def _build_url(agent_runtime_arn: str) -> tuple[str, str]:
38
- """Extract region from ARN and construct the invocation URL.
39
-
40
- ARN format: arn:partition:service:region:account-id:resource
41
- """
42
- region = agent_runtime_arn.split(":")[3]
43
- encoded_arn = agent_runtime_arn.replace(":", "%3A").replace("/", "%2F")
44
- url = (
45
- f"https://bedrock-agentcore.{region}.amazonaws.com/runtimes/"
46
- f"{encoded_arn}/invocations?qualifier=DEFAULT"
47
- )
48
- return region, url
49
-
50
- @staticmethod
51
- def _create(url: str, auth: httpx.Auth | None = None) -> MCPClient:
52
- return MCPClient(
53
- lambda: streamablehttp_client(
54
- url,
55
- auth=_SessionHeaderAuth(auth),
56
- timeout=120,
57
- terminate_on_close=False,
58
- )
59
- )
60
-
61
- @staticmethod
62
- def with_iam_auth(agent_runtime_arn: str) -> MCPClient:
63
- """SigV4-authenticated client for a Bedrock AgentCore runtime."""
64
- region, url = AgentCoreMCPClient._build_url(agent_runtime_arn)
65
- credentials = boto3.Session(region_name=region).get_credentials()
66
- return AgentCoreMCPClient._create(
67
- url, SigV4HTTPXAuth(credentials, "bedrock-agentcore", region)
68
- )
69
-
70
- @staticmethod
71
- def with_jwt_auth(
72
- agent_runtime_arn: str, access_token_provider: Callable[[], str]
73
- ) -> MCPClient:
74
- """Bearer-authenticated client for a Bedrock AgentCore runtime."""
75
- _, url = AgentCoreMCPClient._build_url(agent_runtime_arn)
76
- return MCPClient(
77
- lambda: streamablehttp_client(
78
- url,
79
- auth=_SessionHeaderAuth(),
80
- headers={"Authorization": f"Bearer {access_token_provider()}"},
81
- timeout=120,
82
- terminate_on_close=False,
83
- )
84
- )
85
-
86
- @staticmethod
87
- def without_auth(url: str) -> MCPClient:
88
- """Plain-HTTP client — for local dev."""
89
- return AgentCoreMCPClient._create(url)