@aws/nx-plugin-mcp 1.0.0-rc.11 → 1.0.0-rc.13
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.
- package/bin/aws-nx-mcp.js +2426 -2393
- package/docs/guides/agentcore-gateway.mdx +239 -0
- package/docs/guides/connection/agentcore-gateway-mcp.mdx +134 -0
- package/docs/guides/connection/py-agent-gateway.mdx +158 -0
- package/docs/guides/connection/ts-agent-gateway.mdx +150 -0
- package/docs/guides/connection.mdx +23 -0
- package/docs/guides/nx-generator.mdx +1 -0
- package/docs/guides/py-agent.mdx +42 -3
- package/docs/guides/ts-agent.mdx +40 -2
- package/generators.json +31 -1
- package/package.json +1 -1
- package/src/agentcore-gateway/mcp-connection/schema.json +26 -0
- package/src/agentcore-gateway/schema.json +65 -0
- package/src/py/agent/gateway-connection/schema.json +26 -0
- package/src/ts/agent/gateway-connection/schema.json +26 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AgentCore Gateway
|
|
3
|
+
description: Create an AgentCore Gateway project
|
|
4
|
+
generator: agentcore-gateway
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import { FileTree } from '@astrojs/starlight/components';
|
|
8
|
+
import RunGenerator from '@components/run-generator.astro';
|
|
9
|
+
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
10
|
+
import Infrastructure from '@components/infrastructure.astro';
|
|
11
|
+
import Snippet from '@components/snippet.astro';
|
|
12
|
+
import Link from '@components/link.astro';
|
|
13
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
14
|
+
import OptionFilter from '@components/option-filter.astro';
|
|
15
|
+
|
|
16
|
+
Generate an [Amazon Bedrock AgentCore Gateway](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway.html) project. An AgentCore Gateway is a managed entry point that aggregates one or more MCP server targets behind a single MCP endpoint, evaluates every tool call against a [Cedar policy engine](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/policy.html), and signs outbound traffic to MCP servers with IAM SigV4.
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### Generate an AgentCore Gateway
|
|
21
|
+
|
|
22
|
+
<RunGenerator generator="agentcore-gateway" />
|
|
23
|
+
|
|
24
|
+
### Options
|
|
25
|
+
|
|
26
|
+
<GeneratorParameters generator="agentcore-gateway" />
|
|
27
|
+
|
|
28
|
+
## Generator Output
|
|
29
|
+
|
|
30
|
+
The generator creates a new project at `packages/<name>/`, plus a CDK construct or Terraform module for the infrastructure:
|
|
31
|
+
|
|
32
|
+
<FileTree>
|
|
33
|
+
- packages/\<name>/
|
|
34
|
+
- policies/ Cedar policy source files (omitted when `cedarPolicy: false`)
|
|
35
|
+
- permit-all.cedar Default Cedar policy that permits authenticated callers from within the same AWS account
|
|
36
|
+
- README.md Reference for writing Cedar policies
|
|
37
|
+
- serve-local.ts Local gateway aggregating attached MCP servers for local development
|
|
38
|
+
- project.json Adds the \<name>-serve and \<name>-serve-local aggregator targets
|
|
39
|
+
</FileTree>
|
|
40
|
+
|
|
41
|
+
### Infrastructure
|
|
42
|
+
|
|
43
|
+
Infrastructure is generated when `infra` is `agentcore` (the default). With `infra: none` no infrastructure is generated — re-run the generator with `infra: agentcore` later to add it.
|
|
44
|
+
|
|
45
|
+
<Snippet name="shared-constructs" />
|
|
46
|
+
|
|
47
|
+
<Infrastructure>
|
|
48
|
+
<Fragment slot="cdk">
|
|
49
|
+
<FileTree>
|
|
50
|
+
- packages/common/constructs/src
|
|
51
|
+
- core
|
|
52
|
+
- agentcore-gateway/ Shared gateway construct (readiness probe, Cedar policy loading)
|
|
53
|
+
- app
|
|
54
|
+
- gateways
|
|
55
|
+
- \<name>/
|
|
56
|
+
- \<name>.ts CDK construct for deploying the Gateway
|
|
57
|
+
</FileTree>
|
|
58
|
+
</Fragment>
|
|
59
|
+
<Fragment slot="terraform">
|
|
60
|
+
<FileTree>
|
|
61
|
+
- packages/common/terraform/src
|
|
62
|
+
- app
|
|
63
|
+
- gateways
|
|
64
|
+
- \<name>/
|
|
65
|
+
- \<name>.tf Terraform module for deploying the Gateway
|
|
66
|
+
</FileTree>
|
|
67
|
+
</Fragment>
|
|
68
|
+
</Infrastructure>
|
|
69
|
+
|
|
70
|
+
The generated construct creates the following AWS resources:
|
|
71
|
+
|
|
72
|
+
- An `AgentCore::Gateway` configured for the MCP protocol with `GatewayAuthorizer.usingAwsIam()` (inbound IAM authentication)
|
|
73
|
+
- An `AgentCore::PolicyEngine` running in `ENFORCE` mode, attached to the Gateway (omitted when `cedarPolicy: false`)
|
|
74
|
+
- One `AgentCore::Policy` per `.cedar` file in `policies/`
|
|
75
|
+
|
|
76
|
+
The Gateway URL is automatically registered in the `agentcore.gateways.<ClassName>` namespace of <Link path="guides/runtime-config">Runtime Configuration</Link> so agents can discover it at runtime.
|
|
77
|
+
|
|
78
|
+
## Writing Policies
|
|
79
|
+
|
|
80
|
+
<OptionFilter when={{ cedarPolicy: true }} description="Cedar policies — cedarPolicy: true only">
|
|
81
|
+
|
|
82
|
+
Cedar is the policy language used by AgentCore Gateway to authorize tool calls. Every `tools/list` and `tools/call` request flowing through the Gateway is evaluated against the attached policy set, and the caller must have at least one matching `permit` statement (and no matching `forbid`) for the request to succeed.
|
|
83
|
+
|
|
84
|
+
Refer to the [AWS documentation on AgentCore Gateway policies](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/policy.html) for the full reference, including [common policy patterns](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/policy-common-patterns.html).
|
|
85
|
+
|
|
86
|
+
### Adding a policy
|
|
87
|
+
|
|
88
|
+
To add a policy, create a new `.cedar` file alongside `permit-all.cedar`. Each `.cedar` file in `policies/` must contain exactly **one** `permit` or `forbid` statement and is deployed as a single `AWS::BedrockAgentCore::Policy` resource. The policy resource's name is derived from the filename: `permit-all.cedar` becomes `PermitAll` (kebab/snake-case is converted to PascalCase). Files containing multiple statements produce `unexpected token 'forbid'` errors at deploy time — split them into separate files.
|
|
89
|
+
|
|
90
|
+
For example, to permit only a specific agent role to invoke a particular tool, create:
|
|
91
|
+
|
|
92
|
+
```cedar title="packages/<name>/policies/ts-agent-divide.cedar"
|
|
93
|
+
permit (
|
|
94
|
+
principal == AgentCore::IamEntity::"arn:aws:sts::<%= accountId %>:assumed-role/<%= tsAgentRoleName %>",
|
|
95
|
+
action == AgentCore::Action::"ts-mcp___divide",
|
|
96
|
+
resource == AgentCore::Gateway::"<%= gatewayArn %>"
|
|
97
|
+
);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Pass the role name in as a template variable (see <a href="#template-variables">Template variables</a> below) rather than hard-coding it. Re-synth or re-plan to deploy the new policy.
|
|
101
|
+
|
|
102
|
+
### Template variables
|
|
103
|
+
|
|
104
|
+
Policies are [EJS](https://ejs.co/) templates rendered at synth/plan time so they stay portable across accounts and Gateway redeploys:
|
|
105
|
+
|
|
106
|
+
| Variable | Substituted with |
|
|
107
|
+
| -------------------- | --------------------------------------------- |
|
|
108
|
+
| `<%= gatewayArn %>` | The deployed Gateway's ARN |
|
|
109
|
+
| `<%= accountId %>` | The AWS account this Gateway is deployed into |
|
|
110
|
+
|
|
111
|
+
Always reference these variables rather than hard-coding values.
|
|
112
|
+
|
|
113
|
+
#### Adding your own variables
|
|
114
|
+
|
|
115
|
+
Add new variables where the policies are rendered, for example to pass an agent's execution role name to the `ts-agent-divide.cedar` example above:
|
|
116
|
+
|
|
117
|
+
<Infrastructure>
|
|
118
|
+
<Fragment slot="cdk">
|
|
119
|
+
In `packages/common/constructs/src/app/gateways/<name>/<name>.ts`, pass `cedarPolicyVariables` through to the shared construct:
|
|
120
|
+
|
|
121
|
+
```ts {4-6}
|
|
122
|
+
super(scope, id, {
|
|
123
|
+
cedarPolicyPath: path.join(
|
|
124
|
+
...
|
|
125
|
+
),
|
|
126
|
+
cedarPolicyVariables: {
|
|
127
|
+
tsAgentRoleName: cdk.Token.asString(tsAgent.agentCoreRuntime.role.roleName),
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
</Fragment>
|
|
132
|
+
<Fragment slot="terraform">
|
|
133
|
+
In `packages/common/terraform/src/app/gateways/<name>/<name>.tf`, add to the `query` of the `rendered_policies` data source:
|
|
134
|
+
|
|
135
|
+
```hcl {4}
|
|
136
|
+
query = {
|
|
137
|
+
template = "${local.policies_dir}/${each.value}"
|
|
138
|
+
gatewayArn = aws_bedrockagentcore_gateway.this.gateway_arn
|
|
139
|
+
tsAgentRoleName = var.ts_agent_role_name
|
|
140
|
+
# ...
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
</Fragment>
|
|
144
|
+
</Infrastructure>
|
|
145
|
+
|
|
146
|
+
### ENFORCE mode and default-deny
|
|
147
|
+
|
|
148
|
+
The `PolicyEngine` runs in `ENFORCE` mode, which means **default-deny** semantics apply: if no `permit` statement matches the (principal, action, resource) tuple, the request is denied. Tool calls that are denied return:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
Tool Execution Denied: Tool call not allowed due to policy enforcement
|
|
152
|
+
[No policy applies to the request (denied by default).]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Additionally, the Gateway filters the response of `tools/list` so that callers only see tools they have at least one matching `permit` for: if an agent lacks permission for a given tool, the tool is hidden entirely rather than appearing and failing at call time.
|
|
156
|
+
|
|
157
|
+
### Default `permit-all.cedar`
|
|
158
|
+
|
|
159
|
+
The generator ships a default policy that permits any IAM caller from the AWS account the Gateway is deployed into:
|
|
160
|
+
|
|
161
|
+
```cedar title="packages/<name>/policies/permit-all.cedar"
|
|
162
|
+
permit (
|
|
163
|
+
principal is AgentCore::IamEntity,
|
|
164
|
+
action,
|
|
165
|
+
resource == AgentCore::Gateway::"<%= gatewayArn %>"
|
|
166
|
+
) when {
|
|
167
|
+
principal.id like "arn:aws:*::<%= accountId %>:*"
|
|
168
|
+
};
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
To lock things down further, add narrower policies alongside it. Always retain at least one matching `permit` in the policy set, otherwise default-deny will block every call.
|
|
172
|
+
|
|
173
|
+
### Policy scope reference
|
|
174
|
+
|
|
175
|
+
For Gateways generated by this plugin, all callers are IAM principals (the Gateway is configured with `GatewayAuthorizer.usingAwsIam()`):
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
principal is AgentCore::IamEntity
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Callers are evaluated as STS assumed-role ARNs with the session name stripped, so a role can be matched exactly — no wildcards needed:
|
|
182
|
+
|
|
183
|
+
```cedar
|
|
184
|
+
principal == AgentCore::IamEntity::"arn:aws:sts::<%= accountId %>:assumed-role/<%= myAgentRoleName %>"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The same value is available as `principal.id` for `when` clauses. Reserve `like` for genuine patterns, such as the account-wide match in the default `permit-all.cedar`.
|
|
188
|
+
|
|
189
|
+
Tool invocations reach the policy engine as actions with the form:
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
AgentCore::Action::"<target-name>___<tool-name>"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
where `<target-name>` is the Gateway target name (the MCP server's `mcpServerName` by default when using `gateway.addMcpServer(...)`, derived from the MCP project's class name in kebab-case — e.g. `TsMcp` → `ts-mcp`), `<tool-name>` is the MCP tool's name, and the separator is `___` (three underscores). Cedar does not support wildcards on actions — match exact actions, or omit `action ==` to match all actions.
|
|
196
|
+
|
|
197
|
+
The resource is always the Gateway itself:
|
|
198
|
+
|
|
199
|
+
```cedar
|
|
200
|
+
resource == AgentCore::Gateway::"<%= gatewayArn %>"
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Validation considerations
|
|
204
|
+
|
|
205
|
+
The generated infrastructure creates policies with `IGNORE_ALL_FINDINGS`: AgentCore's Cedar analyzer (`FAIL_ON_ANY_FINDINGS`, the service default) rejects many legitimate policies — for example, a `forbid` disabling a single tool for every caller is rejected as "Overly Restrictive", even when scoped with a `when` clause. Enforcement is unaffected; it is configured by the policy engine's `ENFORCE` mode.
|
|
206
|
+
|
|
207
|
+
One ordering constraint still applies: a policy referencing `AgentCore::Action::"<target>___<tool>"` only validates once the target has registered that tool with the Gateway, which is why the generated infrastructure creates policies after Gateway targets.
|
|
208
|
+
|
|
209
|
+
If a policy fails to deploy, CloudFormation surfaces the rejection as an opaque `Resource stabilization failed` error — run `aws bedrock-agentcore-control list-policies --policy-engine-id <id>` to retrieve the validator's `statusReasons`, which contain the actual reason.
|
|
210
|
+
|
|
211
|
+
### Example: forbid one tool while keeping a broader permit
|
|
212
|
+
|
|
213
|
+
Pair a narrow `forbid` with a broader `permit` (Cedar evaluates `forbid` over `permit`):
|
|
214
|
+
|
|
215
|
+
```cedar title="packages/<name>/policies/forbid-divide-for-py-agent.cedar"
|
|
216
|
+
forbid (
|
|
217
|
+
principal == AgentCore::IamEntity::"arn:aws:sts::<%= accountId %>:assumed-role/<%= pyAgentRoleName %>",
|
|
218
|
+
action == AgentCore::Action::"ts-mcp___divide",
|
|
219
|
+
resource == AgentCore::Gateway::"<%= gatewayArn %>"
|
|
220
|
+
);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
This denies the Python agent role from calling `ts-mcp___divide` while leaving the broader `permit-all.cedar` in place for all other callers.
|
|
224
|
+
|
|
225
|
+
</OptionFilter>
|
|
226
|
+
|
|
227
|
+
## Local Development
|
|
228
|
+
|
|
229
|
+
The generator adds a `<name>-serve-local` target to the Gateway project, which runs `serve-local.ts`: a local gateway exposing a single MCP endpoint that aggregates every attached MCP server (connected via the <Link path="guides/connection/agentcore-gateway-mcp">`agentcore-gateway#mcp-connection` generator</Link>), with tools prefixed `<target>___<tool>` to match the deployed Gateway. Running it starts the local gateway and all attached MCP servers together.
|
|
230
|
+
|
|
231
|
+
<NxCommands commands={["<name>-serve-local"]} />
|
|
232
|
+
|
|
233
|
+
See the connection guide for the full local development story.
|
|
234
|
+
|
|
235
|
+
## Next steps
|
|
236
|
+
|
|
237
|
+
- Connect an MCP server: <Link path="guides/connection/agentcore-gateway-mcp">`agentcore-gateway#mcp-connection`</Link>
|
|
238
|
+
- Connect a TypeScript Agent: <Link path="guides/connection/ts-agent-gateway">`ts#agent#gateway-connection`</Link>
|
|
239
|
+
- Connect a Python Agent: <Link path="guides/connection/py-agent-gateway">`py#agent#gateway-connection`</Link>
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: AgentCore Gateway to MCP Server
|
|
3
|
+
description: Connect an AgentCore Gateway to an MCP server
|
|
4
|
+
when:
|
|
5
|
+
sourceType: agentcore-gateway
|
|
6
|
+
targetType:
|
|
7
|
+
- ts#mcp-server
|
|
8
|
+
- py#mcp-server
|
|
9
|
+
---
|
|
10
|
+
import { FileTree } from '@astrojs/starlight/components';
|
|
11
|
+
import Link from '@components/link.astro';
|
|
12
|
+
import RunGenerator from '@components/run-generator.astro';
|
|
13
|
+
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
14
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
15
|
+
import Infrastructure from '@components/infrastructure.astro';
|
|
16
|
+
|
|
17
|
+
The `connection` generator can register an MCP server (either <Link path="guides/ts-mcp-server">TypeScript</Link> or <Link path="guides/py-mcp-server">Python</Link>) as a target of an <Link path="guides/agentcore-gateway">AgentCore Gateway</Link>.
|
|
18
|
+
|
|
19
|
+
Once connected, the Gateway aggregates the MCP server's tools into its single MCP endpoint, evaluates calls against its Cedar policy engine, and signs outbound traffic to the MCP server with IAM SigV4.
|
|
20
|
+
|
|
21
|
+
## Prerequisites
|
|
22
|
+
|
|
23
|
+
Before using this generator, ensure you have:
|
|
24
|
+
|
|
25
|
+
1. A <Link path="guides/agentcore-gateway">`agentcore-gateway`</Link> project
|
|
26
|
+
2. An MCP server component (<Link path="guides/ts-mcp-server">`ts#mcp-server`</Link> or <Link path="guides/py-mcp-server">`py#mcp-server`</Link>) created with `infra: agentcore` and `auth: iam`
|
|
27
|
+
|
|
28
|
+
The Gateway must have `protocol: mcp` and the MCP server must have `auth: iam` — the generator validates both. Non-IAM MCP servers cannot be attached because the Gateway signs outbound traffic with SigV4.
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
### Run the Generator
|
|
33
|
+
|
|
34
|
+
<RunGenerator generator="connection" />
|
|
35
|
+
|
|
36
|
+
Select the Gateway project as the source and the MCP server project as the target. If the MCP server project contains multiple components, specify `targetComponent` to disambiguate.
|
|
37
|
+
|
|
38
|
+
### Options
|
|
39
|
+
|
|
40
|
+
<GeneratorParameters generator="connection" />
|
|
41
|
+
|
|
42
|
+
## Generator Output
|
|
43
|
+
|
|
44
|
+
The generator wires existing projects together rather than emitting new source files. The following files are modified:
|
|
45
|
+
|
|
46
|
+
<FileTree>
|
|
47
|
+
|
|
48
|
+
- packages/\<gateway>
|
|
49
|
+
- project.json `<gateway>-serve-local` gains a dependency on the MCP server's `<mcp>-serve-local`
|
|
50
|
+
- serve-local.ts `ATTACHED_MCP_SERVERS` updated so the local gateway aggregates the MCP server
|
|
51
|
+
|
|
52
|
+
</FileTree>
|
|
53
|
+
|
|
54
|
+
The Gateway project's `<gateway>-serve-local` target gains a dependency on the MCP server's `<mcp>-serve-local` target, so running the Gateway locally also starts the MCP server. The MCP server is also registered in the Gateway project's `serve-local.ts` so the local gateway aggregates its tools.
|
|
55
|
+
|
|
56
|
+
## Adding the MCP server target to your stack
|
|
57
|
+
|
|
58
|
+
The generator **cannot** automatically wire the MCP server target into your infrastructure because it doesn't know which stack or module instantiates the Gateway. Add a single call to `gateway.addMcpServer(server)` yourself.
|
|
59
|
+
|
|
60
|
+
<Infrastructure>
|
|
61
|
+
<Fragment slot="cdk">
|
|
62
|
+
In the stack where you instantiate the Gateway, register the MCP server as a target:
|
|
63
|
+
|
|
64
|
+
```ts title="packages/infra/src/stacks/application-stack.ts" {5-6}
|
|
65
|
+
const myMcpServer = new MyMcpServer(this, 'MyMcpServer');
|
|
66
|
+
const myGateway = new MyGateway(this, 'MyGateway');
|
|
67
|
+
|
|
68
|
+
// Register the MCP server as a target of the Gateway. The target name
|
|
69
|
+
// defaults to the MCP server's `mcpServerName` (its class name in
|
|
70
|
+
// kebab-case, e.g. `MyMcpServer` -> `my-mcp-server`).
|
|
71
|
+
myGateway.addMcpServer(myMcpServer);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The Gateway target name (the MCP server's `mcpServerName` by default) is used as the prefix for Cedar action names — the action format is ``AgentCore::Action::"<targetName>___<toolName>"``. See the <Link path="guides/agentcore-gateway">Writing Policies section</Link>. Keep the target name short and stable; changing it later invalidates any Cedar policies that reference the old name.
|
|
75
|
+
|
|
76
|
+
To override the default target name, pass `gatewayTargetName`:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
myGateway.addMcpServer(myMcpServer, { gatewayTargetName: 'my-mcp' });
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The construct configures the target with `iamCredentialProvider.service = 'bedrock-agentcore'` so the Gateway signs outbound calls using its own execution role.
|
|
83
|
+
</Fragment>
|
|
84
|
+
<Fragment slot="terraform">
|
|
85
|
+
In the Terraform file where you instantiate the Gateway, wire the MCP server target in:
|
|
86
|
+
|
|
87
|
+
```hcl title="packages/infra/src/main.tf" {7,11-27}
|
|
88
|
+
module "my_mcp_server" {
|
|
89
|
+
source = "../../common/terraform/src/app/mcp-servers/my-mcp-server"
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module "my_gateway" {
|
|
93
|
+
source = "../../common/terraform/src/app/gateways/my-gateway"
|
|
94
|
+
policy_dependencies = [aws_bedrockagentcore_gateway_target.my_mcp_server.target_id]
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Register the MCP server as a target of the Gateway
|
|
98
|
+
resource "aws_bedrockagentcore_gateway_target" "my_mcp_server" {
|
|
99
|
+
gateway_identifier = module.my_gateway.gateway_id
|
|
100
|
+
name = "my-mcp-server"
|
|
101
|
+
|
|
102
|
+
target_configuration {
|
|
103
|
+
mcp {
|
|
104
|
+
mcp_server {
|
|
105
|
+
endpoint = "https://bedrock-agentcore.${local.aws_region}.amazonaws.com/runtimes/${urlencode(module.my_mcp_server.agent_core_runtime_arn)}/invocations?qualifier=DEFAULT"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
credential_provider_configuration {
|
|
111
|
+
gateway_iam_role {
|
|
112
|
+
service = "bedrock-agentcore"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The target `name` (`my-mcp-server` above) is used as the prefix for Cedar action names — see the <Link path="guides/agentcore-gateway">Writing Policies section</Link>. `policy_dependencies` ensures Cedar policies referencing this target's actions are created after the target has registered them.
|
|
119
|
+
</Fragment>
|
|
120
|
+
</Infrastructure>
|
|
121
|
+
|
|
122
|
+
## Local Development
|
|
123
|
+
|
|
124
|
+
Running the Gateway locally with:
|
|
125
|
+
|
|
126
|
+
<NxCommands commands={["<gateway-name>-serve-local"]} />
|
|
127
|
+
|
|
128
|
+
starts a local gateway plus every attached MCP server on its assigned local port. The local gateway exposes a single MCP endpoint that aggregates the attached servers' tools. Agents connected to the Gateway via the <Link path="guides/connection/ts-agent-gateway">TypeScript</Link> or <Link path="guides/connection/py-agent-gateway">Python</Link> gateway-connection generators point at it when running with `SERVE_LOCAL=true`.
|
|
129
|
+
|
|
130
|
+
:::caution[Local fidelity]
|
|
131
|
+
Local development uses a **local stand-in gateway** — a lightweight MCP aggregator started by the Gateway project, not the AgentCore Gateway service. As a consequence, **Cedar policies are not evaluated locally**. Every agent sees every tool on every attached MCP server. To exercise Cedar policies, run the agent's `serve` target instead (see the <Link path="guides/connection/ts-agent-gateway">TypeScript</Link> / <Link path="guides/connection/py-agent-gateway">Python</Link> agent-connection guides) so the locally-running agent calls the deployed Gateway.
|
|
132
|
+
|
|
133
|
+
Tool names are still prefixed locally as `<target-name>___<tool-name>` to match the deployed Gateway's namespacing, so an agent's system prompt and the Cedar action names you reference remain consistent across local and deployed runs.
|
|
134
|
+
:::
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Python Agent to Gateway
|
|
3
|
+
description: Connect a Python Agent to an AgentCore Gateway
|
|
4
|
+
when:
|
|
5
|
+
sourceType: py#agent
|
|
6
|
+
targetType: agentcore-gateway
|
|
7
|
+
---
|
|
8
|
+
import { FileTree } from '@astrojs/starlight/components';
|
|
9
|
+
import Link from '@components/link.astro';
|
|
10
|
+
import RunGenerator from '@components/run-generator.astro';
|
|
11
|
+
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
12
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
13
|
+
import Infrastructure from '@components/infrastructure.astro';
|
|
14
|
+
|
|
15
|
+
The `connection` generator can connect your <Link path="guides/py-agent">Python Agent</Link> to an <Link path="guides/agentcore-gateway">AgentCore Gateway</Link>.
|
|
16
|
+
|
|
17
|
+
The generator wires the agent so it authenticates to the Gateway with IAM SigV4 (via `httpx` request signing) when deployed, and connects to the local gateway started by the Gateway project when running locally.
|
|
18
|
+
|
|
19
|
+
## Prerequisites
|
|
20
|
+
|
|
21
|
+
Before using this generator, ensure you have:
|
|
22
|
+
|
|
23
|
+
1. A Python project with a <Link path="guides/py-agent">Agent</Link> component (`infra: agentcore`)
|
|
24
|
+
2. A <Link path="guides/agentcore-gateway">`agentcore-gateway`</Link> project
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
### Run the Generator
|
|
29
|
+
|
|
30
|
+
<RunGenerator generator="connection" />
|
|
31
|
+
|
|
32
|
+
Select the agent project as the source and the Gateway project as the target.
|
|
33
|
+
|
|
34
|
+
### Options
|
|
35
|
+
|
|
36
|
+
<GeneratorParameters generator="connection" />
|
|
37
|
+
|
|
38
|
+
## Generator Output
|
|
39
|
+
|
|
40
|
+
The generator emits shared core-gateway modules into your `agent_connection` Python project, plus a per-Gateway wrapper, and modifies your agent:
|
|
41
|
+
|
|
42
|
+
<FileTree>
|
|
43
|
+
|
|
44
|
+
- packages/common/agent\_connection
|
|
45
|
+
- \<scope>\_agent\_connection
|
|
46
|
+
- core/
|
|
47
|
+
- agentcore\_gateway\_mcp\_client.py SigV4 MCP client using `httpx`
|
|
48
|
+
- app/
|
|
49
|
+
- \<gateway\_snake>\_client.py Per-Gateway client wrapper
|
|
50
|
+
- \_\_init\_\_.py Re-exports the Gateway client
|
|
51
|
+
|
|
52
|
+
</FileTree>
|
|
53
|
+
|
|
54
|
+
Additionally, the generator:
|
|
55
|
+
|
|
56
|
+
- Modifies your agent's `agent.py` to import the Gateway client, enter it via a `with` block, and register its tools in `tools`
|
|
57
|
+
- Adds `agent_connection` as a workspace dependency of the agent
|
|
58
|
+
- Wires the agent's `<agent>-serve-local` target to depend on the Gateway's `<gateway>-serve-local` aggregator
|
|
59
|
+
|
|
60
|
+
## Using the connected Gateway
|
|
61
|
+
|
|
62
|
+
The generator transforms your agent's `agent.py` to use the Gateway client:
|
|
63
|
+
|
|
64
|
+
```python title="packages/example/example/my_agent/agent.py" {4,8,9-13}
|
|
65
|
+
from contextlib import contextmanager
|
|
66
|
+
from strands import Agent
|
|
67
|
+
|
|
68
|
+
from my_scope_agent_connection import MyGatewayClient
|
|
69
|
+
|
|
70
|
+
@contextmanager
|
|
71
|
+
def get_agent():
|
|
72
|
+
my_gateway = MyGatewayClient.create()
|
|
73
|
+
with (
|
|
74
|
+
my_gateway,
|
|
75
|
+
):
|
|
76
|
+
yield Agent(
|
|
77
|
+
system_prompt="...",
|
|
78
|
+
tools=[*my_gateway.list_tools_sync()],
|
|
79
|
+
)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`MyGatewayClient.create()` returns a single context-manageable client whose `list_tools_sync()` yields every tool available through the Gateway:
|
|
83
|
+
|
|
84
|
+
- **Deployed mode** (`SERVE_LOCAL` unset): a single `MCPClient` pointed at the Gateway's MCP endpoint, SigV4-signed.
|
|
85
|
+
- **Local mode** (`SERVE_LOCAL=true`): a plain-HTTP `MCPClient` pointed at the local gateway started by the Gateway project's `serve-local` target.
|
|
86
|
+
|
|
87
|
+
The session ID is propagated to downstream MCP servers automatically via the `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id` header.
|
|
88
|
+
|
|
89
|
+
## Infrastructure
|
|
90
|
+
|
|
91
|
+
After running the generator you must grant the agent permission to invoke the Gateway.
|
|
92
|
+
|
|
93
|
+
<Infrastructure>
|
|
94
|
+
<Fragment slot="cdk">
|
|
95
|
+
```ts title="packages/infra/src/stacks/application-stack.ts" {5}
|
|
96
|
+
const gateway = new MyGateway(this, 'MyGateway');
|
|
97
|
+
const myAgent = new MyAgent(this, 'MyAgent');
|
|
98
|
+
|
|
99
|
+
// Grant the agent permissions to invoke the Gateway
|
|
100
|
+
gateway.grantInvokeAccess(myAgent);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The Gateway URL is automatically registered in the `agentcore.gateways.<ClassName>` namespace of <Link path="guides/runtime-config">Runtime Configuration</Link> by the generated CDK construct, so the agent can discover it at runtime.
|
|
104
|
+
</Fragment>
|
|
105
|
+
<Fragment slot="terraform">
|
|
106
|
+
```hcl title="packages/infra/src/main.tf" {12-24}
|
|
107
|
+
module "my_gateway" {
|
|
108
|
+
source = "../../common/terraform/src/app/gateways/my-gateway"
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module "my_agent" {
|
|
112
|
+
source = "../../common/terraform/src/app/agents/my-agent"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# Grant the agent permission to invoke the Gateway
|
|
116
|
+
resource "aws_iam_policy" "agent_invoke_gateway" {
|
|
117
|
+
name = "AgentInvokeGatewayPolicy"
|
|
118
|
+
policy = jsonencode({
|
|
119
|
+
Version = "2012-10-17"
|
|
120
|
+
Statement = [{
|
|
121
|
+
Effect = "Allow"
|
|
122
|
+
Action = "bedrock-agentcore:InvokeGateway"
|
|
123
|
+
Resource = module.my_gateway.gateway_arn
|
|
124
|
+
}]
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
resource "aws_iam_role_policy_attachment" "agent_invoke_gateway" {
|
|
129
|
+
role = module.my_agent.agent_core_runtime_role_arn
|
|
130
|
+
policy_arn = aws_iam_policy.agent_invoke_gateway.arn
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The Gateway URL is automatically registered in the `agentcore.gateways.<ClassName>` namespace of <Link path="guides/runtime-config">Runtime Configuration</Link> by the generated Terraform module, so the agent can discover it at runtime.
|
|
135
|
+
</Fragment>
|
|
136
|
+
</Infrastructure>
|
|
137
|
+
|
|
138
|
+
## Local Development
|
|
139
|
+
|
|
140
|
+
The generator configures the agent's `serve-local` target to:
|
|
141
|
+
|
|
142
|
+
1. Start the connected Gateway's local gateway and every attached MCP server
|
|
143
|
+
2. Set `SERVE_LOCAL=true` so the generated client points at the local gateway instead of the deployed Gateway
|
|
144
|
+
|
|
145
|
+
Run the agent locally with:
|
|
146
|
+
|
|
147
|
+
<NxCommands commands={["<agent-name>-serve-local <project-name>"]} />
|
|
148
|
+
|
|
149
|
+
To run the agent locally **against the deployed Gateway** instead (for example, to exercise Cedar policies), use the agent's `serve` target. Without `SERVE_LOCAL` set, the client resolves the deployed Gateway URL from runtime configuration and SigV4-signs requests with your local AWS credentials:
|
|
150
|
+
|
|
151
|
+
<NxCommands commands={["<agent-name>-serve <project-name>"]} />
|
|
152
|
+
|
|
153
|
+
### Local fidelity
|
|
154
|
+
|
|
155
|
+
The local gateway stands in for the deployed Gateway, so:
|
|
156
|
+
|
|
157
|
+
- **No Cedar policy evaluation.** Every tool is visible to the agent regardless of policies. Use the `serve` target to exercise policies against the deployed Gateway.
|
|
158
|
+
- **Tool-name prefixing is preserved.** Each local MCP server's tools are exposed as `<target-name>___<tool-name>`, matching what the deployed Gateway emits. This keeps the agent's system prompt and the Cedar action names you reference consistent across local and deployed runs.
|