Repository navigation
Conversation
Harness export dropped every agentcore_gateway tool with a manual follow-up note, while 0.31.x generated an MCP client for it. Each gateway tool now becomes an MCP client in mcp_client/client.py that reads GATEWAY_<TOOL>_URL, signs requests with SigV4 for awsIam, sends a bearer token for OAuth client credentials, and honors @tool/* allowedTools selectors. The exported runtime gets a gateway connection per tool, so deploy grants access and sets the URL, and agentcore/.env.local carries the URL for agentcore dev. Closes #2766
Package TarballHow to installgh release download pr-2768-tarball --repo aws/agentcore-cli --pattern "*.tgz" --dir /tmp/pr-tarball
npm install -g /tmp/pr-tarball/aws-agentcore-1.0.1.tgz |
|
Claude Security Review: no high-confidence findings. (run) |
There was a problem hiding this comment.
AgentCore Harness Review
Verdict: Changes requested
I verified the deploy-side contract against the pinned @aws/agentcore-cdk@1.0.0 tarball and it lines up:
bindConnection → importedDiscoveryPrefix('GATEWAY', connectionTokenFor(connection)) produces exactly
GATEWAY_<TOKEN>_URL with the same connectionEnvToken derivation, gatewayUrlFromArn builds the same
https://<id>.gateway.bedrock-agentcore.<region>.<urlSuffix>/mcp, and ImportedGateway maps
unset/awsIam → AWS_IAM + InvokeGateway, none → NONE, oauth → CUSTOM_JWT + the OAuth token grants —
which is what each rendered client branch needs. mcp_proxy_for_aws.client.aws_iam_streamablehttp_client(endpoint, aws_service, aws_region) exists at the 1.1.0 floor, and its Python lower bound (3.10) matches the exported project's
requires-python, so uv resolution is fine. requires_access_token's sync wrapper handles being called from a
running loop, so fetching the bearer token inside transport() works. Two things to fix.
1. The gateway path can now abort an otherwise-exportable harness (src/core/project/templates/export.ts)
Before this PR, nothing about a gateway tool could fail an export — it degraded to an EXPORT_NOTES.md entry. Now
three paths throw InputValidationError and kill the whole command:
- L694-699:
CONNECTION_ID_PATTERNrejects any tool name that doesn't start with a letter.HarnessToolNameSchemais
^[a-zA-Z0-9_-]+$, so3p-toolsor_toolsis a perfectly valid harness tool name. - L762-772: two tool names that tokenize to the same env token (
my-tools+my_tools), or a tool name that collides
with an existing harness connection id. - L786-793 (
gatewayUrl): agatewayArnthat isn't an ARN. The harness schema only requiresz.string().min(1).
The message tells the user to "Rename the tool in the harness, then export again", but on the --arn path the spec
comes from the service (serviceHarness.ts L75: name: tool.name ?? tool.type), so there is nothing local to rename —
a single oddly-named gateway tool makes agentcore export harness --arn ... unusable with no workaround. Options:
- Degrade to
GATEWAY_TOOL_NOTE_CATEGORYand skip that one tool, exactly as theUSER_FEDERATIONbranch already does
(L686-699) — the rest of the harness still exports. - Derive a schema-valid connection id instead of requiring the tool name to be one (e.g. prefix/sanitize, and
disambiguate on collision), keepingnameonly for the Python docstrings/log text. - Keep the throw only for the in-project
--namepath, where the user can actually editharness.yaml.
Related, non-blocking: the collision check (L762-764) skips spec.connections entries without an id, but the CDK
still tokenizes those via connectionTokenFor → connectionIdForTarget, so an id-less connection can still shadow a
gateway tool's variable silently.
2. pyproject.toml loses its indentation for every export
src/assets/templates/export-harness-python/pyproject.toml L16-17:
{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0, < 2.0.0",
{{/if}} {{#if bedrockMantle}}"aws-bedrock-token-generator >= 1.1.0, < 2.0.0",
Neither {{#if}} nor {{/if}} is standalone on its line, so the four spaces after {{/if}} are emitted literally and
concatenate with the four before the next block. Every exported pyproject.toml — gateway tools or not — now renders
"strands-agents ... " with eight spaces. Dropping the stray four spaces after {{/if}} restores the existing
pattern. pythonSecurity.test.ts only parses the TOML, so nothing catches this.
Minor
connectionEnvToken and CONNECTION_ID_PATTERN (L778-783) are a third copy of a contract that
src/projectSchemas/v0/schemas/connections.ts explicitly marks as the single source of truth ("do not re-implement the
token derivation") and whose regex also lives in ConnectionSchema in src/projectSchemas/connections.ts. Exporting
the helper (and reusing the schema's regex) from the v1 connections.ts would keep the CLI↔CDK handshake in one place.
|
Thanks for picking this up so quickly. While waiting, we wired a SigV4 gateway client into a 1.0.1 export by hand, and the approach here matches what worked for us. A few things I noticed reading the diff:
Also, the |
What
agentcore export harnessnow exportsagentcore_gatewaytools instead of replacing them with an EXPORT_NOTES entry. Each gateway tool becomes an MCP client inmcp_client/client.pyand is added to the agent's tools inmain.py. This applies to both--nameand--arnexports.GATEWAY_<TOOL>_URL, named after the tool rather than the gateway id.awsIam(also the default whenoutboundAuthis unset) signs requests with SigV4 forbedrock-agentcorethroughmcp-proxy-for-aws.noneconnects without auth. OAuth withCLIENT_CREDENTIALSsends a bearer token from@requires_access_token.allowedToolsselectors such as@tools/*filter the gateway's tools the same way they filter remote MCP tools.connectionper tool, withidset to the tool name. Deploy then grants access and sets the URL through the existing@aws/agentcore-cdk1.0.0 connection binding. The URL is also written toagentcore/.env.localforagentcore dev.USER_FEDERATIONgateway tools still get the manual follow-up note.Why
Closes #2766. 0.31.x exported gateway tools, and 1.x dropped them.
How tested
bun test, typecheck, lint, and format all pass.awsIamandnone).agentcore devloaded the tools of both gateways and made a SigV4 tool call. The deployed runtime hadGATEWAY_TOOLS_URLset by deploy, and invoking it made a successful SigV4 gateway tool call. The stack was torn down afterwards.