Skip to content

Commit 8be11a7

Browse files
authored
Anthropic Bedrock Python | MCP | SSE | ECS (#4)
* add project * move readme * move readme * add mermaid * update readme * remove old infra file * add dependencies * update ALB command * update health check path
1 parent 2d54dc4 commit 8be11a7

21 files changed

+1519
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Model Context Protocol (MCP) Service with AWS CDK
2+
3+
## Architecture Overview
4+
5+
```mermaid
6+
flowchart LR
7+
subgraph aws[AWS]
8+
alb[Application Load Balancer]
9+
10+
subgraph vpc[VPC]
11+
server[MCP Server\nECS Service]
12+
client[MCP Client / Bedrock Agent\nECS Service]
13+
end
14+
15+
subgraph services[AWS Services]
16+
bedrock[Bedrock]
17+
end
18+
end
19+
20+
internet((Internet))
21+
22+
%% Connections
23+
internet <--> alb
24+
alb --> client
25+
client <--> bedrock
26+
client <--> server
27+
28+
%% Styling
29+
style aws fill:#f5f5f5,stroke:#232F3E,stroke-width:2px
30+
style vpc fill:#E8F4FA,stroke:#147EBA,stroke-width:2px
31+
style services fill:#E8F4FA,stroke:#147EBA,stroke-width:2px
32+
33+
style alb fill:#FF9900,color:#fff,stroke:#FF9900
34+
style server fill:#2196f3,color:#fff,stroke:#2196f3
35+
style client fill:#2196f3,color:#fff,stroke:#2196f3
36+
style bedrock fill:#FF9900,color:#fff,stroke:#FF9900
37+
style internet fill:#fff,stroke:#666,stroke-width:2px
38+
39+
%% Link styling
40+
linkStyle default stroke:#666,stroke-width:2px
41+
```
42+
43+
## Prerequisites
44+
45+
- AWS CLI configured
46+
- Docker installed
47+
- Node.js (for CDK)
48+
- Python 3.11+
49+
- UV package manager
50+
51+
## Project Structure
52+
```
53+
.
54+
├── docker/ # Docker configurations
55+
├── infra/ # Infrastructure code
56+
│ └── mcp-sse-cdk/ # CDK application
57+
├── src/ # Application code
58+
└── requirements.txt # Project dependencies
59+
```
60+
61+
## Setup Instructions
62+
63+
1. **Install Dependencies**
64+
```bash
65+
# Create and activate virtual environment
66+
uv venv
67+
source .venv/bin/activate
68+
69+
# Install project dependencies
70+
uv pip install -r requirements.txt
71+
```
72+
73+
2. **Build Docker Images**
74+
```bash
75+
# Get AWS account ID
76+
export AWS_ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
77+
export AWS_REGION=us-east-1
78+
79+
# Create ECR repository if it doesn't exist
80+
aws ecr create-repository --repository-name mcp-sse
81+
82+
# Login to ECR
83+
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com
84+
85+
# Build images locally
86+
docker build -f docker/server/Dockerfile -t server-image .
87+
docker build -f docker/client/Dockerfile -t client-image .
88+
89+
# Tag images for ECR
90+
docker tag server-image ${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com/mcp-sse:server-image
91+
docker tag client-image ${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com/mcp-sse:client-image
92+
93+
# Push images to ECR
94+
docker push ${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com/mcp-sse:server-image
95+
docker push ${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com/mcp-sse:client-image
96+
```
97+
98+
3. **Deploy Infrastructure**
99+
```bash
100+
# Navigate to CDK directory
101+
cd infra/mcp-sse-cdk
102+
103+
# Install CDK dependencies
104+
uv pip install -r requirements.txt
105+
106+
# Bootstrap CDK (first time only)
107+
cdk bootstrap
108+
109+
# Synthesize CloudFormation template
110+
cdk synth
111+
112+
# Deploy stack
113+
cdk deploy
114+
```
115+
116+
4. **Verify Deployment**
117+
```bash
118+
# Get Load Balancer DNS
119+
export ALB_DNS=$(aws elbv2 describe-load-balancers --query 'LoadBalancers[*].DNSName' --output text)
120+
121+
# Test health endpoint
122+
curl http://${ALB_DNS}/health
123+
124+
# Test query endpoint
125+
curl -X POST http://${ALB_DNS}/query \
126+
-H "Content-Type: application/json" \
127+
-d '{"text": "Get me a greeting for Sarah"}'
128+
129+
# output: {"response":"I'll help you get a greeting for Sarah using the greeting function.
130+
#[Calling tool greeting with args {'name': 'Sarah'}]
131+
#Hello Sarah! 👋 Hope you're having a wonderful day!"}%
132+
```
133+
134+
## Cleanup
135+
136+
To avoid incurring charges, clean up resources:
137+
```bash
138+
# Delete CDK stack
139+
cd infra/mcp-sse-cdk
140+
cdk destroy
141+
142+
# Delete ECR images
143+
aws ecr delete-repository --repository-name mcp-sse --force
144+
```
145+
146+
## Troubleshooting
147+
148+
1. **Container Health Checks**
149+
- Verify target group health in EC2 Console
150+
- Ensure security group rules allow traffic
151+
152+
2. **Service Connect Issues**
153+
- Verify namespace creation in Cloud Map
154+
- Check service discovery endpoints
155+
156+
3. **Bedrock Access**
157+
- Verify IAM role permissions
158+
- Check regional endpoints
159+
- Validate model ARNs
160+
161+
For more detailed information, consult the AWS documentation or raise an issue in the repository.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM ghcr.io/astral-sh/uv:bookworm
2+
3+
# Set working directory
4+
WORKDIR /app
5+
6+
# Install dependencies
7+
COPY ./src/client-requirements.txt .
8+
RUN uv venv
9+
RUN uv pip install -r client-requirements.txt
10+
11+
# Copy client code
12+
COPY ./src/client.py .
13+
14+
# Expose port 8080
15+
EXPOSE 8080
16+
17+
# Command to run the client
18+
CMD ["uv", "run", "client.py"]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM ghcr.io/astral-sh/uv:bookworm
2+
# Set working directory
3+
WORKDIR /app
4+
5+
# Copy requirements and install dependencies
6+
COPY ./src/server-requirements.txt .
7+
RUN uv venv
8+
RUN uv pip install -r server-requirements.txt
9+
10+
# Copy server code
11+
COPY ./src/server.py .
12+
13+
# Expose port 8000
14+
EXPOSE 8000
15+
16+
# Command to run the server
17+
CMD ["uv", "run", "server.py", "--transport", "sse", "--port", "8000"]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
*.swp
2+
package-lock.json
3+
__pycache__
4+
.pytest_cache
5+
.venv
6+
*.egg-info
7+
8+
# CDK asset staging directory
9+
.cdk.staging
10+
cdk.out
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
# Welcome to your CDK Python project!
3+
4+
This is a blank project for CDK development with Python.
5+
6+
The `cdk.json` file tells the CDK Toolkit how to execute your app.
7+
8+
This project is set up like a standard Python project. The initialization
9+
process also creates a virtualenv within this project, stored under the `.venv`
10+
directory. To create the virtualenv it assumes that there is a `python3`
11+
(or `python` for Windows) executable in your path with access to the `venv`
12+
package. If for any reason the automatic creation of the virtualenv fails,
13+
you can create the virtualenv manually.
14+
15+
To manually create a virtualenv on MacOS and Linux:
16+
17+
```
18+
$ python3 -m venv .venv
19+
```
20+
21+
After the init process completes and the virtualenv is created, you can use the following
22+
step to activate your virtualenv.
23+
24+
```
25+
$ source .venv/bin/activate
26+
```
27+
28+
If you are a Windows platform, you would activate the virtualenv like this:
29+
30+
```
31+
% .venv\Scripts\activate.bat
32+
```
33+
34+
Once the virtualenv is activated, you can install the required dependencies.
35+
36+
```
37+
$ pip install -r requirements.txt
38+
```
39+
40+
At this point you can now synthesize the CloudFormation template for this code.
41+
42+
```
43+
$ cdk synth
44+
```
45+
46+
To add additional dependencies, for example other CDK libraries, just add
47+
them to your `setup.py` file and rerun the `pip install -r requirements.txt`
48+
command.
49+
50+
## Useful commands
51+
52+
* `cdk ls` list all stacks in the app
53+
* `cdk synth` emits the synthesized CloudFormation template
54+
* `cdk deploy` deploy this stack to your default AWS account/region
55+
* `cdk diff` compare deployed stack with current state
56+
* `cdk docs` open CDK documentation
57+
58+
Enjoy!
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env python3
2+
from mcp_sse_cdk.mcp_sse_cdk_stack import McpSseCdkStack
3+
from aws_cdk import App
4+
5+
6+
app = App()
7+
McpSseCdkStack(app, "McpSseCdkStack")
8+
app.synth()
9+
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
{
2+
"app": "python3 app.py",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"requirements*.txt",
11+
"source.bat",
12+
"**/__init__.py",
13+
"**/__pycache__",
14+
"tests"
15+
]
16+
},
17+
"context": {
18+
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
19+
"@aws-cdk/core:checkSecretUsage": true,
20+
"@aws-cdk/core:target-partitions": [
21+
"aws",
22+
"aws-cn"
23+
],
24+
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
25+
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
26+
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
27+
"@aws-cdk/aws-iam:minimizePolicies": true,
28+
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
29+
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
30+
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
31+
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
32+
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
33+
"@aws-cdk/core:enablePartitionLiterals": true,
34+
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
35+
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
36+
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
37+
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
38+
"@aws-cdk/aws-route53-patters:useCertificate": true,
39+
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
40+
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
41+
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
42+
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
43+
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
44+
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
45+
"@aws-cdk/aws-redshift:columnId": true,
46+
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
47+
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
48+
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
49+
"@aws-cdk/aws-kms:aliasNameRef": true,
50+
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
51+
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
52+
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
53+
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
54+
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
55+
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
56+
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
57+
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
58+
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
59+
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
60+
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
61+
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
62+
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
63+
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
64+
"@aws-cdk/aws-eks:nodegroupNameAttribute": true,
65+
"@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
66+
"@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
67+
"@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false,
68+
"@aws-cdk/aws-s3:keepNotificationInImportedBucket": false,
69+
"@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": false,
70+
"@aws-cdk/aws-ecs:disableEcsImdsBlocking": true,
71+
"@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true,
72+
"@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true,
73+
"@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true,
74+
"@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true,
75+
"@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true,
76+
"@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true,
77+
"@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true,
78+
"@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true,
79+
"@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": true,
80+
"@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": true,
81+
"@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": true,
82+
"@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": true,
83+
"@aws-cdk/core:enableAdditionalMetadataCollection": true,
84+
"@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": false,
85+
"@aws-cdk/aws-s3:setUniqueReplicationRoleName": true,
86+
"@aws-cdk/aws-events:requireEventBusPolicySid": true,
87+
"@aws-cdk/aws-dynamodb:retainTableReplica": true
88+
}
89+
}

modules/anthropic-bedrock-python-ecs-mcp/infra/mcp-sse-cdk/mcp_sse_cdk/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)