diff --git a/README.md b/README.md index 6f917715..dc52af4b 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,7 @@ Projects use JSON schema files in the `agentcore/` directory: - [CLI Commands Reference](docs/commands.md) - Full command reference for scripting and CI/CD - [Configuration](docs/configuration.md) - Schema reference for config files - [Frameworks](docs/frameworks.md) - Supported frameworks and model providers +- [Gateway](docs/gateway.md) - Gateway setup, targets, and authentication - [Memory](docs/memory.md) - Memory strategies and sharing - [Local Development](docs/local-development.md) - Dev server and debugging diff --git a/docs/commands.md b/docs/commands.md index 87a3e4b9..0e8c6b5f 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -151,21 +151,114 @@ agentcore add memory \ | `--expiry ` | Event expiry (default: 30) | | `--json` | JSON output | +### add gateway + +Add a gateway to the project. Gateways act as MCP-compatible proxies that route agent requests to backend tools. + +```bash +# Interactive mode (select 'Gateway' from the menu) +agentcore add + +# No authorization (development/testing) +agentcore add gateway --name MyGateway + +# CUSTOM_JWT authorization (production) +agentcore add gateway \ + --name MyGateway \ + --authorizer-type CUSTOM_JWT \ + --discovery-url https://idp.example.com/.well-known/openid-configuration \ + --allowed-audience my-api \ + --allowed-clients my-client-id \ + --agent-client-id agent-client-id \ + --agent-client-secret agent-client-secret +``` + +| Flag | Description | +| -------------------------------- | ------------------------------------------------------------ | +| `--name ` | Gateway name | +| `--description ` | Gateway description | +| `--authorizer-type ` | `NONE` (default) or `CUSTOM_JWT` | +| `--discovery-url ` | OIDC discovery URL (required for CUSTOM_JWT) | +| `--allowed-audience ` | Comma-separated allowed audiences (required for CUSTOM_JWT) | +| `--allowed-clients ` | Comma-separated allowed client IDs (required for CUSTOM_JWT) | +| `--allowed-scopes ` | Comma-separated allowed scopes (optional for CUSTOM_JWT) | +| `--agent-client-id ` | Agent OAuth client ID for Bearer token auth (CUSTOM_JWT) | +| `--agent-client-secret ` | Agent OAuth client secret (CUSTOM_JWT) | +| `--json` | JSON output | + +### add gateway-target + +Add a gateway target to the project. Targets are backend tools exposed through a gateway as an external MCP server +endpoint. + +```bash +# Interactive mode (select 'Gateway Target' from the menu) +agentcore add + +# External MCP server endpoint +agentcore add gateway-target \ + --name WeatherTools \ + --source existing-endpoint \ + --endpoint https://mcp.example.com/mcp \ + --gateway MyGateway + +# External endpoint with OAuth outbound auth +agentcore add gateway-target \ + --name SecureTools \ + --source existing-endpoint \ + --endpoint https://api.example.com/mcp \ + --gateway MyGateway \ + --outbound-auth oauth \ + --oauth-client-id my-client \ + --oauth-client-secret my-secret \ + --oauth-discovery-url https://auth.example.com/.well-known/openid-configuration +``` + +| Flag | Description | +| -------------------------------- | ----------------------------------------------- | +| `--name ` | Target name | +| `--description ` | Target description | +| `--source ` | `existing-endpoint` | +| `--endpoint ` | MCP server endpoint URL | +| `--gateway ` | Gateway to attach target to | +| `--outbound-auth ` | `oauth`, `api-key`, or `none` | +| `--credential-name ` | Existing credential name for outbound auth | +| `--oauth-client-id ` | OAuth client ID (creates credential inline) | +| `--oauth-client-secret ` | OAuth client secret (creates credential inline) | +| `--oauth-discovery-url ` | OAuth discovery URL (creates credential inline) | +| `--oauth-scopes ` | OAuth scopes, comma-separated | +| `--json` | JSON output | + ### add identity -Add a credential provider (API key). Credentials are top-level resources in the flat resource model. +Add a credential to the project. Supports API key and OAuth credential types. ```bash +# API key credential agentcore add identity \ --name OpenAI \ --api-key sk-... + +# OAuth credential +agentcore add identity \ + --name MyOAuthProvider \ + --type oauth \ + --discovery-url https://idp.example.com/.well-known/openid-configuration \ + --client-id my-client-id \ + --client-secret my-client-secret \ + --scopes read,write ``` -| Flag | Description | -| ----------------- | --------------- | -| `--name ` | Credential name | -| `--api-key ` | API key value | -| `--json` | JSON output | +| Flag | Description | +| -------------------------- | -------------------------------- | +| `--name ` | Credential name | +| `--type ` | `api-key` (default) or `oauth` | +| `--api-key ` | API key value (api-key type) | +| `--discovery-url ` | OAuth discovery URL (oauth type) | +| `--client-id ` | OAuth client ID (oauth type) | +| `--client-secret ` | OAuth client secret (oauth type) | +| `--scopes ` | OAuth scopes, comma-separated | +| `--json` | JSON output | ### remove @@ -175,6 +268,8 @@ Remove resources from project. agentcore remove agent --name MyAgent --force agentcore remove memory --name SharedMemory agentcore remove identity --name OpenAI +agentcore remove gateway --name MyGateway +agentcore remove gateway-target --name WeatherTools # Reset everything agentcore remove all --force @@ -281,6 +376,18 @@ agentcore add memory --name SharedMemory --strategies SEMANTIC agentcore deploy -y ``` +### Gateway Setup + +```bash +agentcore add gateway --name MyGateway +agentcore add gateway-target \ + --name WeatherTools \ + --source existing-endpoint \ + --endpoint https://mcp.example.com/mcp \ + --gateway MyGateway +agentcore deploy -y +``` + ### JSON Output for Automation All commands with `--json` output structured data: diff --git a/docs/configuration.md b/docs/configuration.md index 5eb571ac..d32d41c7 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -7,6 +7,7 @@ AgentCore projects use JSON configuration files in the `agentcore/` directory. | File | Purpose | | --------------------- | ------------------------------------------- | | `agentcore.json` | Project, agents, memories, and credentials | +| `mcp.json` | Gateways, gateway targets, and MCP tools | | `aws-targets.json` | Deployment targets | | `deployed-state.json` | Runtime state (auto-managed, do not edit) | | `.env.local` | API keys for local development (gitignored) | @@ -43,6 +44,12 @@ Main project configuration using a **flat resource model**. Agents, memories, an { "type": "ApiKeyCredentialProvider", "name": "OpenAI" + }, + { + "type": "OAuthCredentialProvider", + "name": "MyOAuthProvider", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": ["read", "write"] } ] } @@ -56,7 +63,9 @@ Main project configuration using a **flat resource model**. Agents, memories, an | `version` | Yes | Schema version (integer, currently `1`) | | `agents` | Yes | Array of agent specifications | | `memories` | Yes | Array of memory resources | -| `credentials` | Yes | Array of credential providers | +| `credentials` | Yes | Array of credential providers (API key or OAuth) | + +> Gateway configuration is stored separately in `mcp.json`. See [mcp.json](#mcpjson) below. --- @@ -142,6 +151,8 @@ Strategy configuration: ## Credential Resource +### API Key Credential + ```json { "type": "ApiKeyCredentialProvider", @@ -154,8 +165,142 @@ Strategy configuration: | `type` | Yes | Always `"ApiKeyCredentialProvider"` | | `name` | Yes | Credential name (3-255 chars) | -The actual API key is stored in `.env.local` for local development and in AgentCore Identity service for deployed -environments. +### OAuth Credential + +```json +{ + "type": "OAuthCredentialProvider", + "name": "MyOAuthProvider", + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "scopes": ["read", "write"] +} +``` + +| Field | Required | Description | +| -------------- | -------- | ------------------------------------------------------ | +| `type` | Yes | Always `"OAuthCredentialProvider"` | +| `name` | Yes | Credential name (3-255 chars) | +| `discoveryUrl` | Yes | OIDC discovery URL (must be a valid URL) | +| `scopes` | No | Array of OAuth scopes | +| `vendor` | No | Credential provider vendor (default: `"CustomOauth2"`) | +| `managed` | No | Whether auto-created by the CLI (do not edit) | +| `usage` | No | `"inbound"` or `"outbound"` | + +The actual secrets (API keys, client IDs, client secrets) are stored in `.env.local` for local development and in +AgentCore Identity service for deployed environments. + +--- + +## mcp.json + +Gateway and MCP tool configuration. Gateways, their targets, and standalone MCP runtime tools are defined here. + +```json +{ + "agentCoreGateways": [ + { + "name": "MyGateway", + "description": "My gateway", + "authorizerType": "NONE", + "targets": [ + { + "name": "WeatherTools", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp" + } + ] + } + ], + "unassignedTargets": [] +} +``` + +### Top-Level Fields + +| Field | Required | Description | +| ------------------- | -------- | ------------------------------------- | +| `agentCoreGateways` | Yes | Array of gateway definitions | +| `unassignedTargets` | No | Targets not yet assigned to a gateway | + +### Gateway + +| Field | Required | Description | +| ------------------------- | -------- | ------------------------------------------------------------ | +| `name` | Yes | Gateway name (alphanumeric, hyphens, 1-63 chars) | +| `description` | No | Gateway description | +| `targets` | Yes | Array of gateway targets | +| `authorizerType` | No | `"NONE"` (default), `"AWS_IAM"`, or `"CUSTOM_JWT"` | +| `authorizerConfiguration` | No | Required when `authorizerType` is `"CUSTOM_JWT"` (see below) | + +### CUSTOM_JWT Authorizer Configuration + +```json +{ + "authorizerType": "CUSTOM_JWT", + "authorizerConfiguration": { + "customJwtAuthorizer": { + "discoveryUrl": "https://idp.example.com/.well-known/openid-configuration", + "allowedAudience": ["my-api"], + "allowedClients": ["my-client-id"], + "allowedScopes": ["read", "write"] + } + } +} +``` + +| Field | Required | Description | +| ----------------- | -------- | ---------------------------------------------------------------------- | +| `discoveryUrl` | Yes | OIDC discovery URL (must end with `/.well-known/openid-configuration`) | +| `allowedAudience` | Yes | Array of allowed audience values | +| `allowedClients` | Yes | Array of allowed client IDs (at least 1) | +| `allowedScopes` | No | Array of allowed scopes | + +### Gateway Target + +A target is a backend tool exposed through a gateway. Targets can be external MCP server endpoints or compute-backed +implementations. + +**External MCP server endpoint:** + +```json +{ + "name": "WeatherTools", + "targetType": "mcpServer", + "endpoint": "https://mcp.example.com/mcp" +} +``` + +**External endpoint with outbound auth:** + +```json +{ + "name": "SecureTools", + "targetType": "mcpServer", + "endpoint": "https://api.example.com/mcp", + "outboundAuth": { + "type": "OAUTH", + "credentialName": "MyOAuthProvider", + "scopes": ["tools:read"] + } +} +``` + +| Field | Required | Description | +| ----------------- | -------- | -------------------------------------------------------------------- | +| `name` | Yes | Target name | +| `targetType` | Yes | `"mcpServer"` or `"lambda"` | +| `endpoint` | Cond. | MCP server URL (required for external `mcpServer` targets) | +| `compute` | Cond. | Compute configuration (required for `lambda` and scaffolded targets) | +| `toolDefinitions` | Cond. | Array of tool definitions (required for `lambda` targets) | +| `outboundAuth` | No | Outbound authentication configuration | + +### Outbound Auth + +| Field | Required | Description | +| ---------------- | -------- | ---------------------------------------------------- | +| `type` | Yes | `"OAUTH"`, `"API_KEY"`, or `"NONE"` (default) | +| `credentialName` | Cond. | Credential name (required when type is not `"NONE"`) | +| `scopes` | No | OAuth scopes (for `"OAUTH"` type) | --- @@ -190,12 +335,17 @@ current list. ## .env.local -API keys for local development. This file is gitignored. +Secrets for local development. This file is gitignored. ```bash +# API key credentials AGENTCORE_CREDENTIAL_{projectName}OPENAI=sk-... AGENTCORE_CREDENTIAL_{projectName}ANTHROPIC=sk-ant-... AGENTCORE_CREDENTIAL_{projectName}GEMINI=... + +# OAuth credentials +AGENTCORE_CREDENTIAL_{projectName}{credentialName}_CLIENT_ID=my-client-id +AGENTCORE_CREDENTIAL_{projectName}{credentialName}_CLIENT_SECRET=my-client-secret ``` Environment variable names should match the credential names in your configuration. diff --git a/docs/gateway.md b/docs/gateway.md new file mode 100644 index 00000000..2ddc1c21 --- /dev/null +++ b/docs/gateway.md @@ -0,0 +1,183 @@ +# Gateway + +Gateways act as MCP-compatible proxies that route agent requests to backend tools. They handle authentication, tool +discovery, and request routing so your agents can securely access external MCP servers and APIs. + +## Quick Start + +The simplest path is to set up your gateway before creating your agent. The agent template will automatically include +the gateway client code. + +```bash +# 1. Create a project +agentcore create --name MyProject --defaults +cd MyProject + +# 2. Add a gateway +agentcore add gateway --name my-gateway + +# 3. Add a target (external MCP server) +agentcore add gateway-target \ + --source existing-endpoint \ + --name weather-tools \ + --endpoint https://mcp.example.com/mcp \ + --gateway my-gateway + +# 4. Create an agent (automatically wired to the gateway) +agentcore add agent --name MyAgent --framework Strands --model-provider Bedrock + +# 5. Deploy +agentcore deploy -y +``` + +The generated agent code includes gateway client setup, authentication, and environment variable reading out of the box. + +## Gateway Targets + +A gateway target is a backend tool exposed through a gateway — an external MCP server endpoint that the gateway proxies +requests to. + +```bash +agentcore add gateway-target \ + --source existing-endpoint \ + --name my-tools \ + --endpoint https://mcp.example.com/mcp \ + --gateway my-gateway +``` + +## Authentication + +### Inbound Authentication + +Controls how agents authenticate with the gateway. + +| Type | Description | Use Case | +| ------------ | -------------------------------------------- | -------------------- | +| `NONE` | No authentication required | Development, testing | +| `AWS_IAM` | SigV4 signed requests | AWS-native agents | +| `CUSTOM_JWT` | OIDC-based JWT validation with Bearer tokens | External IdPs, M2M | + +#### CUSTOM_JWT Setup + +```bash +agentcore add gateway \ + --name my-gateway \ + --authorizer-type CUSTOM_JWT \ + --discovery-url https://idp.example.com/.well-known/openid-configuration \ + --allowed-audience my-api \ + --allowed-clients my-client-id \ + --agent-client-id agent-client-id \ + --agent-client-secret agent-client-secret +``` + +When you provide `--agent-client-id` and `--agent-client-secret`, the CLI automatically creates a managed OAuth +credential that your agent uses to obtain Bearer tokens at runtime. + +### Outbound Authentication + +Controls how the gateway authenticates with upstream MCP servers. Configured per target. + +| Type | Description | +| --------- | ------------------------------ | +| `none` | No outbound authentication | +| `oauth` | OAuth2 client credentials flow | +| `api-key` | API key passed to upstream | + +#### OAuth Outbound Auth + +```bash +agentcore add gateway-target \ + --source existing-endpoint \ + --name secure-tools \ + --endpoint https://api.example.com/mcp \ + --gateway my-gateway \ + --outbound-auth oauth \ + --oauth-client-id my-client \ + --oauth-client-secret my-secret \ + --oauth-discovery-url https://auth.example.com/.well-known/openid-configuration +``` + +You can also reference an existing credential: + +```bash +agentcore add identity \ + --name MyOAuthProvider \ + --type oauth \ + --discovery-url https://auth.example.com/.well-known/openid-configuration \ + --client-id my-client \ + --client-secret my-secret + +agentcore add gateway-target \ + --source existing-endpoint \ + --name secure-tools \ + --endpoint https://api.example.com/mcp \ + --gateway my-gateway \ + --outbound-auth oauth \ + --credential-name MyOAuthProvider +``` + +## Adding a Gateway to an Existing Project + +If you already have agents and want to add gateway support, there are two approaches. + +### Recommended: Create a New Agent + +The simplest path is to create a new agent after configuring your gateway. The new agent template will automatically +include gateway client code with the correct authentication for your framework. + +```bash +# 1. Add gateway and targets +agentcore add gateway --name my-gateway +agentcore add gateway-target \ + --source existing-endpoint \ + --name my-tools \ + --endpoint https://mcp.example.com/mcp \ + --gateway my-gateway + +# 2. Create a new agent (picks up gateway config automatically) +agentcore add agent --name MyNewAgent --framework Strands --model-provider Bedrock + +# 3. Move your custom logic from the old agent to the new one +# Copy tool definitions, prompts, and business logic from: +# app/MyOldAgent/ → app/MyNewAgent/ + +# 4. Remove the old agent when ready +agentcore remove agent --name MyOldAgent +``` + +### Manual: Update Existing Agent Code + +If you have a heavily customized agent that can't be easily recreated, you can manually add gateway client code. The +exact code depends on your framework and gateway auth type. + +To get the correct code for your setup: + +1. Configure your gateway and targets as above. + +2. Create a temporary reference agent: + + ```bash + agentcore add agent \ + --name TempAgent \ + --framework Strands \ + --model-provider Bedrock + ``` + +3. Copy the gateway-related code from the generated agent into your existing agent: + - `app/TempAgent/mcp_client/client.py` — Gateway client with authentication + - `app/TempAgent/main.py` — Import and usage of gateway MCP clients + +4. Add the `mcp-proxy-for-aws` dependency to your agent's `pyproject.toml` (required for AWS_IAM authentication). + +5. Remove the temporary agent: + ```bash + agentcore remove agent --name TempAgent + ``` + +## Local Development + +When you have deployed gateways, `agentcore dev` automatically injects gateway environment variables into your local +agent process. See [Local Development](local-development.md#gateway-environment-variables) for details. + +Gateway env vars require a prior deployment — run `agentcore deploy` before `agentcore dev` to populate the gateway +URLs. diff --git a/docs/local-development.md b/docs/local-development.md index 42b4e5f4..c9b464eb 100644 --- a/docs/local-development.md +++ b/docs/local-development.md @@ -104,10 +104,53 @@ See [Container Builds](container-builds.md) for full details on container develo ## Dev vs Deployed Behavior -| Aspect | Local Dev | Deployed | -| ---------- | ------------- | -------------------------- | -| API Keys | `.env.local` | AgentCore Identity service | -| Memory | Not available | AgentCore Memory service | -| Networking | localhost | Public | +| Aspect | Local Dev | Deployed | +| ---------- | ---------------------------- | -------------------------- | +| API Keys | `.env.local` | AgentCore Identity service | +| Memory | Not available | AgentCore Memory service | +| Gateways | Env vars from deployed state | CDK-injected env vars | +| Networking | localhost | Public | Memory requires deployment to test fully. For local testing, you can mock these dependencies in your agent code. + +## Gateway Environment Variables + +When you have deployed gateways, `agentcore dev` automatically injects gateway environment variables into your local +agent process. This lets your local agent connect to real deployed gateways during development. + +The dev server reads `deployed-state.json` and `mcp.json` to generate: + +```bash +AGENTCORE_GATEWAY_{NAME}_URL=https://{gateway-id}.gateway.agentcore.{region}.amazonaws.com +AGENTCORE_GATEWAY_{NAME}_AUTH_TYPE=NONE|AWS_IAM|CUSTOM_JWT +``` + +The gateway name is uppercased with hyphens replaced by underscores. For example, a gateway named `my-gateway` produces: + +```bash +AGENTCORE_GATEWAY_MY_GATEWAY_URL=https://... +AGENTCORE_GATEWAY_MY_GATEWAY_AUTH_TYPE=NONE +``` + +### Requirements + +Gateway env vars require a prior deployment — the dev server reads the gateway URLs from `deployed-state.json`, which is +populated by `agentcore deploy`. If you haven't deployed yet, no gateway env vars will be set. + +### Workflow + +```bash +# 1. Add a gateway and target +agentcore add gateway --name my-gateway +agentcore add gateway-target --name my-tools --source existing-endpoint \ + --endpoint https://mcp.example.com/mcp --gateway my-gateway + +# 2. Deploy to create the gateway +agentcore deploy -y + +# 3. Run locally — gateway env vars are injected automatically +agentcore dev +``` + +Your agent code reads these env vars to connect to the gateway. The agent templates generated by the CLI already include +this wiring.