blog-zero-secrets-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@blog-zero-secrets-mcpcall get_server_info"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
AgentCore + Cognito Public Client MCP PoC
End-to-end proof of concept demonstrating two deployment modes for an MCP server on AgentCore:
Standalone — Runtime with Cognito JWT auth directly (no gateway)
Gateway — Runtime behind an AgentCore Gateway with Cognito PKCE inbound auth and IAM outbound auth
Both modes use a public Cognito client (no client_secret) with PKCE for user authentication.
Architecture
Mode A: Standalone (Runtime with direct JWT auth)
Claude Code / Kiro
│ PKCE → Cognito Hosted UI → browser
│ Bearer JWT
▼
AgentCore Runtime (CUSTOM_JWT validates token)
│
▼
MCP Server (FastMCP, Python)Mode B: Gateway (recommended)
Claude Code / Kiro
│ PKCE → Cognito Hosted UI → browser
│ Bearer JWT
▼
AgentCore Gateway (CUSTOM_JWT validates token)
│ SigV4 (gateway IAM role)
▼
AgentCore Runtime (AWS_IAM auth)
│
▼
MCP Server (FastMCP, Python)The Gateway mode provides:
Centralized authentication (gateway handles all JWT validation)
Tool discovery and semantic search across multiple targets
Protocol-level MCP routing
Separation of concerns (runtime doesn't need to know about user auth)
Related MCP server: local-kms-mcp-server
Project Structure
.
├── server/
│ ├── cognitopocmcp/ # Runtime deployed via agentcore CLI
│ │ ├── app/cognito_poc_mcp/
│ │ │ └── main.py # FastMCP server with sample tools
│ │ └── agentcore/ # agentcore CLI config
│ ├── mcp_server.py # MCP server source (standalone mode)
│ └── requirements.txt
├── src/
│ ├── config.mjs # Shared config (project name, region, helpers)
│ ├── auth.mjs # PKCE auth module (no secrets!)
│ ├── mcp-server.mjs # Stdio MCP server (proxy mode)
│ └── test-auth.mjs # Standalone auth flow test
├── scripts/
│ ├── setup-cognito.mjs # Creates Cognito pool + public client + user
│ ├── deploy.sh # Deploys runtime (standalone mode, with JWT auth)
│ ├── deploy-infrastructure.mjs # Creates gateway + IAM role + target (gateway mode)
│ ├── test-gateway.mjs # Tests gateway end-to-end
│ ├── test-deployed.mjs # Tests standalone runtime end-to-end
│ └── teardown-cognito.mjs # Deletes all infrastructure
├── .env # Generated by setup (Cognito config)
├── .mcp.json # Generated by deploy-infra (gateway URL + OAuth)
├── claude-mcp-config.json # Same as .mcp.json (for copying to Claude/Kiro)
└── package.jsonPrerequisites
# AWS CLI + credentials configured
aws sts get-caller-identity
# Node.js 20+
node --version
# AgentCore CLI
npm install -g @aws/agentcore
# Python 3.10+ (for the MCP server)
python3 --versionQuick Start: Gateway Mode (recommended)
Step 1: Install dependencies
npm installStep 2: Create Cognito infrastructure
npm run setupCreates a Cognito User Pool with a public app client (no secret), a hosted UI domain, and a test user (testuser / TestPass123!). Config is saved to .env.
Step 3: Deploy the runtime
npm run deploy-runtimeDeploys the MCP server to AgentCore Runtime using the agentcore CLI. The runtime uses default IAM auth (the gateway will authenticate users).
Step 4: Deploy the gateway
npm run deploy-infraCreates:
An IAM role for the gateway (with permission to invoke the runtime)
An AgentCore Gateway with
CUSTOM_JWTinbound auth (Cognito PKCE)A gateway target pointing at the runtime via
GATEWAY_IAM_ROLE(SigV4)
Updates .mcp.json and claude-mcp-config.json with the gateway URL.
Step 5: Test
npm run test-gatewayAuthenticates via Cognito (non-interactive using test user), then:
Verifies unauthenticated requests are rejected (401)
Initializes MCP session
Lists discovered tools
Calls tools (
greet_user,add_numbers,get_server_info)
Step 6: Connect Claude Code / Kiro
Copy the generated config:
# For Kiro — .mcp.json is already in the project root
# For Claude Code
cp claude-mcp-config.json ~/.claude/mcp.jsonThe config looks like:
{
"mcpServers": {
"cognito-poc": {
"type": "http",
"url": "https://<gateway-id>.gateway.bedrock-agentcore.<region>.amazonaws.com/mcp",
"oauth": {
"clientId": "<public-client-id>",
"callbackPort": 8976
}
}
}
}On first tool invocation, Claude/Kiro opens your browser for Cognito login. After that, tokens are cached and refreshed automatically.
Quick Start: Standalone Mode
If you don't need a gateway and want the runtime to handle JWT auth directly:
npm run setup # Create Cognito pool
npm run deploy # Deploy runtime with CUSTOM_JWT auth
npm run test-deployed # Test via PKCE (opens browser)npm Scripts
Script | Description |
| Create Cognito User Pool + public client + test user |
| Deploy MCP runtime via agentcore CLI (IAM auth, for gateway) |
| Create gateway + IAM role + target via Control Plane API |
| Deploy runtime with direct JWT auth (standalone, no gateway) |
| Test gateway end-to-end (non-interactive) |
| Test gateway with browser-based PKCE login |
| Test standalone runtime via PKCE |
| Test PKCE auth flow only (opens browser) |
| Run MCP server locally for development |
| Delete all infrastructure (gateway, IAM role, Cognito pools) |
MCP Tools Available
The sample MCP server exposes:
Tool | Description |
| Add two numbers together |
| Multiply two numbers together |
| Greet a user by name |
| Return deployment and version info |
| Analyze text and return basic statistics |
When accessed through the gateway, tool names are prefixed with the target name: mcp-runtime___add_numbers.
Cleanup
npm run teardownThis deletes:
AgentCore Gateway (targets + gateway)
Gateway IAM role
Cognito User Pool(s)
Local files (
.env,.mcp.json,claude-mcp-config.json)
The AgentCore Runtime is NOT deleted (managed separately by agentcore CLI). To remove it:
cd server/cognitopocmcp && agentcore destroyKey Concepts
Zero-secrets authentication
Cognito public client:
GenerateSecret: false— no client secret existsPKCE (
code_challenge+code_verifier) proves the requester without a shared secretOnly the
client_idis stored locally (a public identifier, not a credential)Tokens are in-memory with 1-hour expiry + auto-refresh
Gateway outbound auth
The gateway authenticates to the runtime using its own IAM role (SigV4). This avoids the complexity of OAuth machine-to-machine flows between the gateway and runtime. The IAM role has bedrock-agentcore:* permission scoped to the runtime ARN.
Portability
All environment-specific values are derived at runtime:
AWS Account ID: resolved via
STS.GetCallerIdentityGateway URL: read from
.mcp.json(generated bydeploy-infra)Runtime ARN: read from agentcore deployed state
Project constants: centralized in
src/config.mjs
To deploy in a different account/region, just configure AWS credentials and re-run the setup steps.
Security
See CONTRIBUTING for information on reporting security issues.
License
This library is licensed under the MIT-0 License. See the LICENSE file.
This server cannot be deployed
Maintenance
Related MCP Connectors
Self-hosted federated MCP gateway: one OAuth 2.1 MCP server in front of N apps, user-level scopes.
Hosted AgentLux MCP server for marketplace, identity, creator, services, and social flows.
Hosted MCP server for AI agent identity, permissions, verification, and reusable proof.
MCP-first control plane for ProAgentStore agents and private instances.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceDeploys a minimal MCP-compatible Python tool server on Amazon EKS that establishes an outbound WebSocket connection to an AgentCore Gateway. It exposes two tools (get_system_info and echo_data) for tool discovery and invocation through the MCP protocol.-
- AlicenseAqualityBmaintenanceLocal-first MCP server for per-agent key management, generating and using signing keys without external KMS.8141MIT
- AlicenseNot gradedqualityDmaintenanceDemonstrates how to secure an MCP server with OAuth 2.1 using AWS Cognito, with support for dynamic client registration and client ID metadata documents.68MIT
- FlicenseNot gradedqualityDmaintenanceA production-ready MCP server that authenticates agents via OAuth 2.1 Bearer tokens, validates JWTs with JWKS, enforces tool-level scopes and roles, and logs the full delegation chain.-