Install
$ agentstack add mcp-aws-samples-sample-mcp-registry-infrastructure ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
MCP Registry Infrastructure
A sample for a secure, enterprise-grade infrastructure for hosting MCP (Model Context Protocol) registry files using AWS CloudFront, S3, WAF, and CloudFront signed URLs.
Overview
This sample solution provides a complete infrastructure-as-code deployment for hosting an MCP registry JSON file that Kiro and other AI assistant clients can use to discover approved MCP servers. The architecture follows AWS security best practices with three access control modes:
- Public: CloudFront serves the registry without access restrictions
- Restricted: WAF filters requests based on source IP addresses
- Signed: CloudFront signed URLs require a cryptographic token to access the registry (can be combined with IP filtering for defense-in-depth)
Architecture
Features
- Private S3 Bucket: All public access blocked, server-side encryption with AES-256
- CloudFront CDN: Global edge caching with HTTPS-only access and TLS 1.2 minimum
- Origin Access Control (OAC): Secure S3 access using SigV4 signing
- Optional WAF IP Filtering: Restrict access to specific IP ranges
- Optional Signed URL Authentication: Token-based access via CloudFront signed URLs with automated key lifecycle management
- Idempotent Deployment: Safe to run multiple times without errors
- Cache Invalidation: Automatic CloudFront cache invalidation on updates
Prerequisites
- AWS CLI configured with appropriate credentials
jqinstalled for JSON parsing- Bash shell (macOS, Linux, or WSL on Windows)
Quick Start
1. Deploy in Public Mode
./deploy.sh \
--stack-name my-mcp-registry \
--registry-file ./mcp-registry.json \
--mode public
2. Deploy with IP Restrictions
./deploy.sh \
--stack-name my-mcp-registry \
--registry-file ./mcp-registry.json \
--mode restricted \
--allowed-ips "10.0.0.0/8,192.168.1.0/24,203.0.113.50/32"
3. Deploy with Signed URL Authentication
./deploy.sh \
--stack-name my-mcp-registry \
--registry-file ./mcp-registry.json \
--mode signed
4. Deploy with Signed URL + IP Filtering (Defense-in-Depth)
./deploy.sh \
--stack-name my-mcp-registry \
--registry-file ./mcp-registry.json \
--mode signed \
--allowed-ips "10.0.0.0/8,192.168.1.0/24"
Files
| File | Description | |------|-------------| | mcp-registry-infrastructure.yaml | CloudFormation template defining all AWS resources | | deploy.sh | Idempotent deployment script | | mcp-registry.json | Sample MCP registry with AWS servers | | lambda_handler/index.py | Lambda custom resource for signed URL key lifecycle | | validate_registry.py | Schema validation script for registry files |
Deploy Script Options
Usage: deploy.sh [OPTIONS]
Required Options:
--stack-name CloudFormation stack name
--registry-file Path to mcp-registry.json file
--mode Access control mode
Optional Options:
--allowed-ips Comma-separated CIDR ranges (for restricted or signed+IP mode)
--region AWS region (default: us-east-1)
--skip-validation Skip registry file schema validation before upload
-h, --help Display help message
Exit Codes:
0 - Success
1 - Invalid arguments
2 - CloudFormation deployment failed
3 - S3 upload failed
4 - CloudFront invalidation failed
MCP Registry Format
The registry file follows the MCP registry JSON schema:
{
"servers": [
{
"server": {
"name": "server-name",
"description": "Server description",
"version": "1.0.0",
"packages": [
{
"registryType": "pypi",
"identifier": "package-name@version",
"transport": {
"type": "stdio"
}
}
]
}
}
]
}
Validating Your Registry File
uv run --with jsonschema python validate_registry.py mcp-registry.json
Updating the Registry
To update the registry after initial deployment, run the deploy script again with the updated registry file:
./deploy.sh \
--stack-name my-mcp-registry \
--registry-file ./mcp-registry.json \
--mode public
The script will:
- Update the CloudFormation stack (if template changed)
- Validate the registry file against the MCP schema
- Upload the new registry file to S3
- Invalidate the CloudFront cache
CloudFormation Outputs
After deployment, the stack provides these outputs:
| Output | Description | |--------|-------------| | BucketName | S3 bucket name for direct uploads | | DistributionId | CloudFront distribution ID | | DistributionDomainName | CloudFront domain (e.g., d1234567890.cloudfront.net) | | MCPRegistryURL | Full URL to the registry file | | WebACLArn | WAF Web ACL ARN (restricted mode only) | | SignedRegistryURL | Secrets Manager ARN containing the signed URL (signed mode only) | | PrivateKeySecretArn | Secrets Manager ARN for the RSA private key (signed mode only) |
Security
S3 Bucket Security
- All public access blocked (BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, RestrictPublicBuckets)
- Server-side encryption with AES-256
- Access logging enabled to a dedicated log bucket (90-day retention)
- Bucket policy allows only CloudFront OAC access
CloudFront Security
- HTTPS-only (ViewerProtocolPolicy: https-only)
- TLS 1.2 minimum protocol version
- GET and HEAD methods only
- Origin Access Control with SigV4 signing
- Standard access logging enabled for request-level visibility
WAF Security (Restricted Mode)
- IP-based allow list with default-block policy
- Custom 403 JSON response for blocked requests
- CloudWatch metrics enabled for monitoring
Signed URL Security (Signed Mode)
- RSA 2048-bit key pair generated by Lambda custom resource
- Private key stored in AWS Secrets Manager (never leaves your account)
- CloudFront validates signature, expiry, and key pair ID on every request
- Treat the signed URL as a secret credential — do not commit to version control
Signed URL Rotation
When using --mode signed, the signed URL acts as a bearer credential. Rotate it periodically or immediately if you suspect compromise.
Quick Rotation via Redeployment
The simplest approach — redeploy the stack and the Lambda handles the full key lifecycle automatically:
./deploy.sh --stack-name my-mcp-registry \
--registry-file ./mcp-registry.json \
--mode signed
The stack update replaces the old key group with a new one and outputs a fresh signed URL. Update the URL in your AI assistant's admin console (e.g., Kiro enterprise governance settings). There is a brief moment during the update where the old key group is removed before the new one is active — for a registry JSON file, this is typically acceptable.
Zero-Downtime Rotation (Manual)
For environments where even brief interruptions are unacceptable, you can manually add a second key group alongside the existing one using the AWS CLI. CloudFront supports up to 4 trusted key groups simultaneously.
Step 1: Generate a new key pair and register it with CloudFront Step 2: Add the new key group to the distribution alongside the old one Step 3: Update the admin console with the new signed URL Step 4: Remove the old key group and clean up resources
See the [detailed guide](GUIDE.md) for CLI commands for each step.
Emergency Revocation
# Revoke immediately by switching to public mode
./deploy.sh --stack-name my-mcp-registry \
--registry-file ./mcp-registry.json --mode public
# Then redeploy with a fresh signed URL
./deploy.sh --stack-name my-mcp-registry \
--registry-file ./mcp-registry.json --mode signed
Recommended Rotation Schedule
| Environment | Expiry | Rotation Frequency | |-------------|--------|--------------------| | Development | 365 days | Every 6 months | | Production | 90 days | Every 60 days | | High security | 30 days | Every 21 days |
Troubleshooting
Deployment Fails
- Verify AWS credentials are configured:
aws sts get-caller-identity - Check CloudFormation events in AWS Console for detailed errors
- Ensure the stack name is unique in your account/region
Registry Not Updating
- CloudFront cache invalidation takes 1-5 minutes to propagate
- Check invalidation status:
aws cloudfront list-invalidations --distribution-id
Access Denied (403)
- In restricted mode, verify your IP is in the allowed list
- In signed mode, verify the signed URL hasn't expired
- Check WAF logs in CloudWatch for blocked requests
Cleanup
To delete all resources:
# Empty the registry bucket
aws s3 rm s3://$(aws cloudformation describe-stacks \
--stack-name my-mcp-registry \
--query 'Stacks[0].Outputs[?OutputKey==`BucketName`].OutputValue' \
--output text) --recursive
# Empty the access log bucket
aws s3 rm s3://$(aws cloudformation describe-stacks \
--stack-name my-mcp-registry \
--query 'Stacks[0].Outputs[?OutputKey==`BucketName`].OutputValue' \
--output text)-access-logs --recursive
# Delete the stack
aws cloudformation delete-stack --stack-name my-mcp-registry
Cost Warning
This deployment creates AWS resources that will incur costs. The primary cost drivers are:
- Amazon CloudFront distribution (request pricing + data transfer)
- Amazon S3 storage and requests
- AWS WAF (if using restricted or signed+IP mode)
- AWS Secrets Manager (if using signed mode)
- AWS Lambda invocations (if using signed mode, only during deployment)
For a single JSON file with moderate traffic, costs are minimal. Use the AWS Pricing Calculator to estimate costs for your specific usage.
License
This project is licensed under the MIT-0 License. See the [LICENSE](LICENSE) file.
Contributing
See [CONTRIBUTING](CONTRIBUTING.md) for guidelines.
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: aws-samples
- Source: aws-samples/sample-mcp-registry-infrastructure
- License: MIT-0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.