@everystack/mcp 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/prompts/deploy.ts +1 -6
- package/src/resources/aws-setup.md +147 -44
- package/src/resources/deployment.md +4 -4
- package/src/resources/images.md +22 -2
package/package.json
CHANGED
package/src/prompts/deploy.ts
CHANGED
|
@@ -58,12 +58,7 @@ export function registerDeployPrompt(server: McpServer): void {
|
|
|
58
58
|
].join('\n') : '',
|
|
59
59
|
'## Deploy Steps',
|
|
60
60
|
'',
|
|
61
|
-
'### 1.
|
|
62
|
-
'```bash',
|
|
63
|
-
'pnpm export # Expo export (builds dist/)',
|
|
64
|
-
'```',
|
|
65
|
-
'',
|
|
66
|
-
'### 2. Deploy Infrastructure',
|
|
61
|
+
'### 1. Deploy Infrastructure',
|
|
67
62
|
'```bash',
|
|
68
63
|
`pnpm sst deploy --stage ${stage}`,
|
|
69
64
|
'```',
|
|
@@ -46,69 +46,152 @@ Your AWS account has a "root user" (the email you signed up with). The root user
|
|
|
46
46
|
|
|
47
47
|
### Create the permissions policy
|
|
48
48
|
|
|
49
|
-
This policy gives the user
|
|
49
|
+
This policy gives the user the permissions SST needs to deploy your app, scoped to your app's resources. Every statement targets your app name prefix so this user can't touch other apps in the same account.
|
|
50
50
|
|
|
51
51
|
7. Select **Attach policies directly**
|
|
52
52
|
8. Click **Create policy** (this opens a new tab)
|
|
53
53
|
9. Click the **JSON** tab
|
|
54
|
-
10. Delete anything in the editor and paste this:
|
|
54
|
+
10. Delete anything in the editor and paste this (replacing the placeholders — see table below):
|
|
55
55
|
|
|
56
56
|
```json
|
|
57
57
|
{
|
|
58
58
|
"Version": "2012-10-17",
|
|
59
59
|
"Statement": [
|
|
60
60
|
{
|
|
61
|
-
"Sid": "
|
|
61
|
+
"Sid": "SSM",
|
|
62
|
+
"Effect": "Allow",
|
|
63
|
+
"Action": "ssm:*",
|
|
64
|
+
"Resource": [
|
|
65
|
+
"arn:aws:ssm:{REGION}:{ACCOUNT_ID}:parameter/sst/*",
|
|
66
|
+
"arn:aws:ssm:{REGION}:{ACCOUNT_ID}:parameter/{APP_NAME}/*"
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"Sid": "S3",
|
|
71
|
+
"Effect": "Allow",
|
|
72
|
+
"Action": "s3:*",
|
|
73
|
+
"Resource": [
|
|
74
|
+
"arn:aws:s3:::{APP_NAME}-*-*",
|
|
75
|
+
"arn:aws:s3:::{APP_NAME}-*-*/*",
|
|
76
|
+
"arn:aws:s3:::sst-asset-*",
|
|
77
|
+
"arn:aws:s3:::sst-asset-*/*",
|
|
78
|
+
"arn:aws:s3:::sst-state-*",
|
|
79
|
+
"arn:aws:s3:::sst-state-*/*"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"Sid": "S3Protect",
|
|
84
|
+
"Effect": "Deny",
|
|
85
|
+
"Action": [
|
|
86
|
+
"s3:DeleteBucket",
|
|
87
|
+
"s3:PutBucketAcl",
|
|
88
|
+
"s3:PutBucketVersioning",
|
|
89
|
+
"s3:PutBucketEncryption",
|
|
90
|
+
"s3:PutBucketLogging"
|
|
91
|
+
],
|
|
92
|
+
"Resource": "*"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"Sid": "CF",
|
|
62
96
|
"Effect": "Allow",
|
|
63
97
|
"Action": [
|
|
64
|
-
"cloudformation:*",
|
|
65
|
-
"s3:*",
|
|
66
|
-
"lambda:*",
|
|
67
98
|
"cloudfront:*",
|
|
68
|
-
"
|
|
69
|
-
"iam:DeleteRole",
|
|
70
|
-
"iam:GetRole",
|
|
71
|
-
"iam:GetRolePolicy",
|
|
72
|
-
"iam:PassRole",
|
|
73
|
-
"iam:AttachRolePolicy",
|
|
74
|
-
"iam:DetachRolePolicy",
|
|
75
|
-
"iam:PutRolePolicy",
|
|
76
|
-
"iam:DeleteRolePolicy",
|
|
77
|
-
"iam:ListRolePolicies",
|
|
78
|
-
"iam:ListAttachedRolePolicies",
|
|
79
|
-
"iam:TagRole",
|
|
80
|
-
"iam:UntagRole",
|
|
81
|
-
"iam:CreateServiceLinkedRole",
|
|
82
|
-
"rds:*",
|
|
83
|
-
"ec2:DescribeVpcs",
|
|
84
|
-
"ec2:DescribeSubnets",
|
|
85
|
-
"ec2:DescribeSecurityGroups",
|
|
86
|
-
"ec2:DescribeRouteTables",
|
|
87
|
-
"ec2:DescribeAvailabilityZones",
|
|
88
|
-
"ec2:DescribeVpcEndpoints",
|
|
89
|
-
"ec2:CreateSecurityGroup",
|
|
90
|
-
"ec2:DeleteSecurityGroup",
|
|
91
|
-
"ec2:AuthorizeSecurityGroupIngress",
|
|
92
|
-
"ec2:RevokeSecurityGroupIngress",
|
|
93
|
-
"ec2:AuthorizeSecurityGroupEgress",
|
|
94
|
-
"ec2:RevokeSecurityGroupEgress",
|
|
95
|
-
"ec2:CreateVpcEndpoint",
|
|
96
|
-
"ec2:DeleteVpcEndpoint",
|
|
97
|
-
"ec2:CreateTags",
|
|
98
|
-
"ec2:DeleteTags",
|
|
99
|
-
"route53:*",
|
|
100
|
-
"sqs:*",
|
|
101
|
-
"ssm:*",
|
|
102
|
-
"logs:*",
|
|
103
|
-
"sts:GetCallerIdentity",
|
|
104
|
-
"sts:AssumeRole"
|
|
99
|
+
"cloudfront-keyvaluestore:*"
|
|
105
100
|
],
|
|
106
101
|
"Resource": "*"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"Sid": "Lambda",
|
|
105
|
+
"Effect": "Allow",
|
|
106
|
+
"Action": "lambda:*",
|
|
107
|
+
"Resource": "arn:aws:lambda:{REGION}:{ACCOUNT_ID}:function:{APP_NAME}-*"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"Sid": "LambdaGlobal",
|
|
111
|
+
"Effect": "Allow",
|
|
112
|
+
"Action": [
|
|
113
|
+
"lambda:CreateEventSourceMapping",
|
|
114
|
+
"lambda:DeleteEventSourceMapping",
|
|
115
|
+
"lambda:GetEventSourceMapping",
|
|
116
|
+
"lambda:ListEventSourceMappings",
|
|
117
|
+
"lambda:UpdateEventSourceMapping",
|
|
118
|
+
"lambda:ListFunctions",
|
|
119
|
+
"lambda:GetFunctionConfiguration",
|
|
120
|
+
"lambda:TagResource",
|
|
121
|
+
"lambda:UntagResource",
|
|
122
|
+
"lambda:ListTags"
|
|
123
|
+
],
|
|
124
|
+
"Resource": "*"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"Sid": "SQS",
|
|
128
|
+
"Effect": "Allow",
|
|
129
|
+
"Action": "sqs:*",
|
|
130
|
+
"Resource": "arn:aws:sqs:{REGION}:{ACCOUNT_ID}:{APP_NAME}-*"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"Sid": "IAM",
|
|
134
|
+
"Effect": "Allow",
|
|
135
|
+
"Action": "iam:*Role*",
|
|
136
|
+
"Resource": [
|
|
137
|
+
"arn:aws:iam::{ACCOUNT_ID}:role/{APP_NAME}-*",
|
|
138
|
+
"arn:aws:iam::{ACCOUNT_ID}:role/SchedulerRole-*"
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"Sid": "Scheduler",
|
|
143
|
+
"Effect": "Allow",
|
|
144
|
+
"Action": [
|
|
145
|
+
"scheduler:CreateScheduleGroup",
|
|
146
|
+
"scheduler:DeleteScheduleGroup",
|
|
147
|
+
"scheduler:GetScheduleGroup",
|
|
148
|
+
"scheduler:ListTagsForResource",
|
|
149
|
+
"scheduler:TagResource",
|
|
150
|
+
"scheduler:UntagResource"
|
|
151
|
+
],
|
|
152
|
+
"Resource": "arn:aws:scheduler:{REGION}:{ACCOUNT_ID}:schedule-group/{APP_NAME}-*"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"Sid": "Logs",
|
|
156
|
+
"Effect": "Allow",
|
|
157
|
+
"Action": "logs:*",
|
|
158
|
+
"Resource": [
|
|
159
|
+
"arn:aws:logs:{REGION}:{ACCOUNT_ID}:log-group:/aws/lambda/{APP_NAME}-*",
|
|
160
|
+
"arn:aws:logs:{REGION}:{ACCOUNT_ID}:log-group:/aws/lambda/{APP_NAME}-*:*"
|
|
161
|
+
]
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"Sid": "LogsList",
|
|
165
|
+
"Effect": "Allow",
|
|
166
|
+
"Action": "logs:DescribeLogGroups",
|
|
167
|
+
"Resource": "arn:aws:logs:{REGION}:{ACCOUNT_ID}:log-group:*"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"Sid": "Discovery",
|
|
171
|
+
"Effect": "Allow",
|
|
172
|
+
"Action": "s3:ListAllMyBuckets",
|
|
173
|
+
"Resource": "*"
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"Sid": "STS",
|
|
177
|
+
"Effect": "Allow",
|
|
178
|
+
"Action": "sts:GetCallerIdentity",
|
|
179
|
+
"Resource": "*"
|
|
107
180
|
}
|
|
108
181
|
]
|
|
109
182
|
}
|
|
110
183
|
```
|
|
111
184
|
|
|
185
|
+
Replace the placeholders with your values:
|
|
186
|
+
|
|
187
|
+
| Placeholder | Example | Where to find it |
|
|
188
|
+
|-------------|---------|-------------------|
|
|
189
|
+
| `{ACCOUNT_ID}` | `123456789012` | `aws sts get-caller-identity` |
|
|
190
|
+
| `{REGION}` | `us-east-1` | Your default AWS region |
|
|
191
|
+
| `{APP_NAME}` | `myapp` | The `name` in your `sst.config.ts` |
|
|
192
|
+
|
|
193
|
+
If your app creates additional S3 buckets outside the `{APP_NAME}-*` pattern, add them to the S3 statement.
|
|
194
|
+
|
|
112
195
|
11. Click **Next**
|
|
113
196
|
12. Name the policy: `everystack-dev-policy`
|
|
114
197
|
13. Optionally add a description: "Permissions for everystack SST deploys"
|
|
@@ -168,6 +251,26 @@ You should see something like:
|
|
|
168
251
|
|
|
169
252
|
If you see your account number and `everystack-dev`, your credentials are working. You are ready to deploy.
|
|
170
253
|
|
|
254
|
+
### What each statement does
|
|
255
|
+
|
|
256
|
+
| Statement | Actions | Scope | Purpose |
|
|
257
|
+
|-----------|---------|-------|---------|
|
|
258
|
+
| **SSM** | `ssm:*` | `sst/*` + `{APP_NAME}/*` params | SST state management + app secrets |
|
|
259
|
+
| **S3** | `s3:*` | App buckets + SST state/asset buckets | Media, client bundles, OTA updates, SST state |
|
|
260
|
+
| **S3Protect** | Deny destructive bucket ops | `*` | Prevents `DeleteBucket`, ACL/versioning/encryption/logging changes |
|
|
261
|
+
| **CF** | `cloudfront:*`, `cloudfront-keyvaluestore:*` | `*` | Router distribution + KVS cache versioning |
|
|
262
|
+
| **Lambda** | `lambda:*` | `{APP_NAME}-*` functions | API, Image, Worker Lambdas |
|
|
263
|
+
| **LambdaGlobal** | Event source mappings, list, tags | `*` | SQS-to-Lambda subscriptions, resource discovery |
|
|
264
|
+
| **SQS** | `sqs:*` | `{APP_NAME}-*` queues | Background jobs + dead-letter queues (V3) |
|
|
265
|
+
| **IAM** | `iam:*Role*` | `{APP_NAME}-*` + `SchedulerRole-*` | Lambda execution roles + EventBridge Scheduler role |
|
|
266
|
+
| **Scheduler** | Schedule group CRUD + tags | `{APP_NAME}-*` groups | EventBridge Scheduler for delayed tasks |
|
|
267
|
+
| **Logs** | `logs:*` | `/aws/lambda/{APP_NAME}-*` | CloudWatch log groups for Lambda functions |
|
|
268
|
+
| **LogsList** | `logs:DescribeLogGroups` | `*` | Log group enumeration |
|
|
269
|
+
| **Discovery** | `s3:ListAllMyBuckets` | `*` | CLI resource discovery |
|
|
270
|
+
| **STS** | `sts:GetCallerIdentity` | `*` | Identity verification |
|
|
271
|
+
|
|
272
|
+
**V2-only apps** can omit `SQS` and `Scheduler`. **V1-only apps** can omit `SQS`, `Scheduler`, `IAM`, and `Logs`.
|
|
273
|
+
|
|
171
274
|
## Production hardening
|
|
172
275
|
|
|
173
|
-
|
|
276
|
+
For production, read `everystack://security` for a three-profile model that separates infrastructure creation, day-to-day operations, and CI/CD into distinct IAM users with minimal permissions.
|
|
@@ -92,12 +92,12 @@ Each stage gets isolated resources (separate database, buckets, Lambda functions
|
|
|
92
92
|
## Deploy Flow
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
-
# 1.
|
|
96
|
-
pnpm export
|
|
97
|
-
|
|
98
|
-
# 2. Deploy infrastructure + code
|
|
95
|
+
# 1. Deploy infrastructure + code
|
|
99
96
|
pnpm sst deploy --stage dev
|
|
100
97
|
|
|
98
|
+
# 2. Export + publish app bundles
|
|
99
|
+
everystack update --stage dev
|
|
100
|
+
|
|
101
101
|
# 3. Run migrations
|
|
102
102
|
everystack db:migrate
|
|
103
103
|
|
package/src/resources/images.md
CHANGED
|
@@ -65,9 +65,29 @@ import { imagesSchema } from '@everystack/images/schema';
|
|
|
65
65
|
// Adds: image_variants table tracking generated variants
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
## S3 Origin Cache
|
|
69
|
+
|
|
70
|
+
CloudFront caches are per-region. Enable `s3Cache` to persist rendered images to S3 so the first Sharp render is the last, globally:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
export const handler = createImageHandler({
|
|
74
|
+
bucket: Resource.Media.name,
|
|
75
|
+
s3Cache: { enabled: true },
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Cache keys are deterministic from parsed params. Add a 30-day lifecycle rule on the `cache/` prefix to auto-expire stale renders. To clean up immediately when an original is deleted:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { deleteImageCache } from '@everystack/server/image';
|
|
83
|
+
await deleteImageCache(bucket, 'uploads/photo.jpg');
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
See `docs/caching.md` for full setup.
|
|
87
|
+
|
|
68
88
|
## Gotchas
|
|
69
89
|
|
|
70
90
|
- Sharp runs on Lambda ARM64 (uses Lambda layer or bundled binary)
|
|
71
|
-
- First request for a variant is slow (processing), subsequent are cached
|
|
72
|
-
-
|
|
91
|
+
- First request for a variant is slow (processing), subsequent are cached by CloudFront and S3
|
|
92
|
+
- With `s3Cache` enabled, Sharp runs once per variant globally (not once per CloudFront region)
|
|
73
93
|
- AVIF encoding is slower than WebP but produces smaller files
|