@everystack/mcp 0.3.2 → 0.4.0

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.
Files changed (104) hide show
  1. package/dist/adding-database.md +36 -23
  2. package/dist/cli.md +44 -3
  3. package/dist/core.md +19 -1
  4. package/dist/database-operations.md +236 -0
  5. package/dist/derived-objects.md +225 -0
  6. package/dist/gates/detectors/embedded-data-bundle.d.ts +13 -0
  7. package/dist/gates/detectors/embedded-data-bundle.d.ts.map +1 -0
  8. package/dist/gates/detectors/embedded-data-bundle.js +56 -0
  9. package/dist/gates/detectors/hand-written-migration.d.ts +24 -0
  10. package/dist/gates/detectors/hand-written-migration.d.ts.map +1 -0
  11. package/dist/gates/detectors/hand-written-migration.js +54 -0
  12. package/dist/gates/detectors/secret-in-public-env.d.ts +12 -0
  13. package/dist/gates/detectors/secret-in-public-env.d.ts.map +1 -0
  14. package/dist/gates/detectors/secret-in-public-env.js +38 -0
  15. package/dist/gates/engine.d.ts +28 -0
  16. package/dist/gates/engine.d.ts.map +1 -0
  17. package/dist/gates/engine.js +74 -0
  18. package/dist/gates/registry.d.ts +14 -0
  19. package/dist/gates/registry.d.ts.map +1 -0
  20. package/dist/gates/registry.js +21 -0
  21. package/dist/gates/telemetry.d.ts +47 -0
  22. package/dist/gates/telemetry.d.ts.map +1 -0
  23. package/dist/gates/telemetry.js +121 -0
  24. package/dist/gates/types.d.ts +67 -0
  25. package/dist/gates/types.d.ts.map +1 -0
  26. package/dist/gates/types.js +14 -0
  27. package/dist/governance/cli.d.ts +57 -0
  28. package/dist/governance/cli.d.ts.map +1 -0
  29. package/dist/governance/cli.js +169 -0
  30. package/dist/governance/grounding.d.ts +78 -0
  31. package/dist/governance/grounding.d.ts.map +1 -0
  32. package/dist/governance/grounding.js +299 -0
  33. package/dist/index.cjs +119 -107
  34. package/dist/index.d.ts +2 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +94 -0
  37. package/dist/project-claude-md.md +35 -18
  38. package/dist/prompts/add-feature.d.ts +3 -0
  39. package/dist/prompts/add-feature.d.ts.map +1 -0
  40. package/dist/prompts/add-feature.js +154 -0
  41. package/dist/prompts/claude-md.d.ts +12 -0
  42. package/dist/prompts/claude-md.d.ts.map +1 -0
  43. package/dist/prompts/claude-md.js +87 -0
  44. package/dist/prompts/debug.d.ts +3 -0
  45. package/dist/prompts/debug.d.ts.map +1 -0
  46. package/dist/prompts/debug.js +129 -0
  47. package/dist/prompts/deploy.d.ts +3 -0
  48. package/dist/prompts/deploy.d.ts.map +1 -0
  49. package/dist/prompts/deploy.js +118 -0
  50. package/dist/prompts/design-schema.d.ts +3 -0
  51. package/dist/prompts/design-schema.d.ts.map +1 -0
  52. package/dist/prompts/design-schema.js +97 -0
  53. package/dist/prompts/governance-setup.d.ts +9 -0
  54. package/dist/prompts/governance-setup.d.ts.map +1 -0
  55. package/dist/prompts/governance-setup.js +76 -0
  56. package/dist/prompts/index.d.ts +3 -0
  57. package/dist/prompts/index.d.ts.map +1 -0
  58. package/dist/prompts/index.js +20 -0
  59. package/dist/prompts/new-app.d.ts +3 -0
  60. package/dist/prompts/new-app.d.ts.map +1 -0
  61. package/dist/prompts/new-app.js +203 -0
  62. package/dist/prompts/runbook.d.ts +12 -0
  63. package/dist/prompts/runbook.d.ts.map +1 -0
  64. package/dist/prompts/runbook.js +70 -0
  65. package/dist/prompts/secure.d.ts +3 -0
  66. package/dist/prompts/secure.d.ts.map +1 -0
  67. package/dist/prompts/secure.js +219 -0
  68. package/dist/resources/index.d.ts +12 -0
  69. package/dist/resources/index.d.ts.map +1 -0
  70. package/dist/resources/index.js +182 -0
  71. package/dist/schema-patterns.md +92 -106
  72. package/dist/tools/check-environment.d.ts +25 -0
  73. package/dist/tools/check-environment.d.ts.map +1 -0
  74. package/dist/tools/check-environment.js +281 -0
  75. package/dist/tools/index.d.ts +3 -0
  76. package/dist/tools/index.d.ts.map +1 -0
  77. package/dist/tools/index.js +18 -0
  78. package/dist/tools/project-status.d.ts +28 -0
  79. package/dist/tools/project-status.d.ts.map +1 -0
  80. package/dist/tools/project-status.js +138 -0
  81. package/dist/tools/project-validate.d.ts +19 -0
  82. package/dist/tools/project-validate.d.ts.map +1 -0
  83. package/dist/tools/project-validate.js +323 -0
  84. package/dist/tools/schema-analyze.d.ts +46 -0
  85. package/dist/tools/schema-analyze.d.ts.map +1 -0
  86. package/dist/tools/schema-analyze.js +336 -0
  87. package/package.json +3 -3
  88. package/src/gates/detectors/hand-written-migration.ts +29 -13
  89. package/src/index.ts +1 -1
  90. package/src/prompts/add-feature.ts +4 -4
  91. package/src/prompts/claude-md.ts +4 -2
  92. package/src/prompts/debug.ts +3 -4
  93. package/src/prompts/deploy.ts +17 -8
  94. package/src/prompts/design-schema.ts +45 -59
  95. package/src/prompts/new-app.ts +21 -19
  96. package/src/prompts/secure.ts +3 -3
  97. package/src/resources/adding-database.md +36 -23
  98. package/src/resources/cli.md +44 -3
  99. package/src/resources/core.md +19 -1
  100. package/src/resources/database-operations.md +236 -0
  101. package/src/resources/derived-objects.md +225 -0
  102. package/src/resources/index.ts +15 -1
  103. package/src/resources/project-claude-md.md +35 -18
  104. package/src/resources/schema-patterns.md +92 -106
@@ -0,0 +1,219 @@
1
+ import { z } from 'zod';
2
+ export function registerSecurePrompt(server) {
3
+ server.prompt('secure', 'Set up security for an everystack project: AWS IAM profiles, JWT auth, RLS policies, and edge verification.', {
4
+ features: z.string().optional().describe('Comma-separated security features to set up (e.g., "aws,rls,auth"). Defaults to all.'),
5
+ projectPath: z.string().optional().describe('Absolute path to project root'),
6
+ }, async ({ features, projectPath }) => {
7
+ const allFeatures = ['aws', 'rls', 'auth', 'edge'];
8
+ const requested = features
9
+ ? features.split(',').map((f) => f.trim().toLowerCase())
10
+ : allFeatures;
11
+ return {
12
+ messages: [
13
+ {
14
+ role: 'user',
15
+ content: {
16
+ type: 'text',
17
+ text: [
18
+ `Set up security for ${projectPath ? 'the project at ' + projectPath : 'my everystack project'}.`,
19
+ `Features: ${requested.join(', ')}`,
20
+ '',
21
+ '## Instructions',
22
+ '',
23
+ '1. Read everystack://security for the complete security model.',
24
+ '2. Read everystack://auth for JWT authentication details.',
25
+ projectPath ? `3. Run project_validate with projectPath="${projectPath}" to find existing security gaps.` : '',
26
+ projectPath ? `4. Run schema_analyze with projectPath="${projectPath}" to check schema security.` : '',
27
+ '',
28
+ requested.includes('aws') ? [
29
+ '## AWS IAM Profiles',
30
+ '',
31
+ 'Set up three named AWS profiles with least-privilege permissions:',
32
+ '',
33
+ '### 1. everystack-create (Infrastructure Creation)',
34
+ '',
35
+ '**When:** First deploy only. Disable after infrastructure exists.',
36
+ '',
37
+ '```ini',
38
+ '# ~/.aws/credentials',
39
+ '[everystack-create]',
40
+ 'aws_access_key_id = ...',
41
+ 'aws_secret_access_key = ...',
42
+ '```',
43
+ '',
44
+ 'Permissions needed:',
45
+ '- CloudFormation (create stacks)',
46
+ '- S3 (create buckets)',
47
+ '- CloudFront (create distributions)',
48
+ '- Lambda (create functions)',
49
+ '- RDS (create clusters)',
50
+ '- IAM (create roles — scoped to everystack-* prefix)',
51
+ '- VPC (create VPC, subnets, security groups)',
52
+ '- SQS (create queues)',
53
+ '',
54
+ '**After first deploy:** Delete or deactivate these access keys.',
55
+ '',
56
+ '### 2. everystack-manage (Day-to-Day CLI)',
57
+ '',
58
+ '**When:** Development, running CLI commands, migrations.',
59
+ '',
60
+ 'Permissions needed:',
61
+ '- Lambda:InvokeFunction (for CLI → Lambda operations)',
62
+ '- S3:PutObject/GetObject (for OTA updates)',
63
+ '- CloudWatch:GetLogEvents (for log tailing)',
64
+ '- SSM:GetParameter (for secret access)',
65
+ '',
66
+ '**Cannot:** Create or delete infrastructure, modify IAM, access RDS directly.',
67
+ '',
68
+ '### 3. everystack-deploy (CI/CD)',
69
+ '',
70
+ '**When:** Automated deployments from CI/CD pipelines.',
71
+ '',
72
+ 'Permissions needed:',
73
+ '- CloudFormation:UpdateStack (update existing, not create new)',
74
+ '- Lambda:UpdateFunctionCode',
75
+ '- S3:PutObject (deploy assets)',
76
+ '- CloudFront:CreateInvalidation',
77
+ '',
78
+ '**Cannot:** Create new infrastructure, modify IAM, access secrets.',
79
+ '',
80
+ ].join('\n') : '',
81
+ requested.includes('auth') ? [
82
+ '## JWT Authentication',
83
+ '',
84
+ 'Read everystack://auth for full details.',
85
+ '',
86
+ '### Setup',
87
+ '',
88
+ '1. Generate a strong JWT secret:',
89
+ '```bash',
90
+ 'pnpm sst secret set JwtSecret "$(openssl rand -base64 32)" --stage dev',
91
+ '```',
92
+ '',
93
+ '2. Create auth handlers:',
94
+ '```typescript',
95
+ "import { createAuthHandlers } from '@everystack/auth';",
96
+ '',
97
+ 'const auth = createAuthHandlers(db, schema, jwtSecret, {',
98
+ " mode: 'postgres',",
99
+ ' sql,',
100
+ ' cookies: { allowedOrigins: ["https://your-web-origin"] }, // HttpOnly cookies for web — Origin allowlist required (fail-closed)',
101
+ '});',
102
+ '```',
103
+ '',
104
+ '3. Wire into Lambda handler with auth routes.',
105
+ '',
106
+ '4. Create AuthProvider in lib/auth-context.tsx.',
107
+ '',
108
+ '### Token Lifecycle',
109
+ '',
110
+ '- Access tokens: short-lived (15 min default)',
111
+ '- Refresh tokens: long-lived (7 days default)',
112
+ '- Auto-refresh on 401 via client interceptor',
113
+ '',
114
+ ].join('\n') : '',
115
+ requested.includes('rls') ? [
116
+ '## Row-Level Security (RLS)',
117
+ '',
118
+ 'Read everystack://security for the mental model and templates.',
119
+ '',
120
+ '### How RLS Works in everystack',
121
+ '',
122
+ '1. Client sends JWT in Authorization header',
123
+ '2. Handler verifies JWT, extracts claims',
124
+ '3. `pgSettings` sets PostgreSQL session variables:',
125
+ ' - `SET LOCAL ROLE authenticated`',
126
+ ' - `set_config(\'request.jwt.claims\', \'{"sub":"...","role":"..."}\', true)`',
127
+ '4. Query runs inside a transaction with those settings',
128
+ '5. RLS policies read the claims and filter rows',
129
+ '',
130
+ '### Step-by-Step',
131
+ '',
132
+ '1. **Create roles** (one-time migration):',
133
+ '```sql',
134
+ 'CREATE ROLE anon NOLOGIN;',
135
+ 'CREATE ROLE authenticated NOLOGIN;',
136
+ 'CREATE ROLE admin NOLOGIN;',
137
+ 'GRANT anon, authenticated, admin TO authenticator;',
138
+ '```',
139
+ '',
140
+ '2. **Enable RLS on every table:**',
141
+ '```sql',
142
+ 'ALTER TABLE table_name ENABLE ROW LEVEL SECURITY;',
143
+ '```',
144
+ '',
145
+ '3. **Grant minimum permissions:**',
146
+ '```sql',
147
+ 'GRANT SELECT ON table_name TO anon;',
148
+ 'GRANT SELECT, INSERT, UPDATE, DELETE ON table_name TO authenticated;',
149
+ 'GRANT ALL ON table_name TO admin;',
150
+ '```',
151
+ '',
152
+ '4. **Create policies per access pattern:**',
153
+ '',
154
+ '**Public read (soft-delete aware):**',
155
+ '```sql',
156
+ "CREATE POLICY \"anon_select\" ON table_name FOR SELECT TO anon",
157
+ ' USING (deleted_at IS NULL);',
158
+ '```',
159
+ '',
160
+ '**Own rows only:**',
161
+ '```sql',
162
+ "CREATE POLICY \"own_rows_select\" ON table_name FOR SELECT TO authenticated",
163
+ " USING (user_id = (current_setting('request.jwt.claims', true)::json->>'sub')::uuid);",
164
+ '```',
165
+ '',
166
+ '**Admin full access:**',
167
+ '```sql',
168
+ "CREATE POLICY \"admin_all\" ON table_name FOR ALL TO admin USING (true);",
169
+ '```',
170
+ '',
171
+ '5. **Configure pgSettings in handler:**',
172
+ '```typescript',
173
+ 'pgSettings: (user) => ({',
174
+ " role: user?.role === 'admin' ? 'admin' : user ? 'authenticated' : 'anon',",
175
+ " 'request.jwt.claims': JSON.stringify(user || { role: 'anon' }),",
176
+ '}),',
177
+ '```',
178
+ '',
179
+ '### Testing RLS',
180
+ '',
181
+ '```sql',
182
+ '-- Test as authenticated user',
183
+ 'BEGIN;',
184
+ 'SET LOCAL ROLE authenticated;',
185
+ "SELECT set_config('request.jwt.claims',",
186
+ " '{\"sub\": \"user-uuid\", \"role\": \"authenticated\"}', true);",
187
+ 'SELECT * FROM posts; -- should only return own posts',
188
+ 'ROLLBACK;',
189
+ '```',
190
+ '',
191
+ ].join('\n') : '',
192
+ requested.includes('edge') ? [
193
+ '## Edge JWT Verification',
194
+ '',
195
+ 'Verify JWTs at the CDN edge before requests reach Lambda:',
196
+ '',
197
+ '- CloudFront function validates JWT signature (HS256)',
198
+ '- Rejects expired or malformed tokens at the edge',
199
+ '- Reduces Lambda invocations for unauthorized requests',
200
+ '- See everystack://deployment for CloudFront function setup',
201
+ '',
202
+ ].join('\n') : '',
203
+ '## Verification',
204
+ '',
205
+ 'After setup, verify security:',
206
+ '',
207
+ '1. Run project_validate to check for gaps',
208
+ '2. Test unauthenticated access returns 401',
209
+ '3. Test cross-user data isolation with RLS',
210
+ '4. Verify JWT claims propagate through pgSettings',
211
+ '5. Check `.env` files are not committed',
212
+ '6. Confirm `everystack-create` profile is disabled',
213
+ ].filter(Boolean).join('\n'),
214
+ },
215
+ },
216
+ ],
217
+ };
218
+ });
219
+ }
@@ -0,0 +1,12 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ declare function loadResource(filename: string): string;
3
+ interface ResourceDef {
4
+ uri: string;
5
+ name: string;
6
+ description: string;
7
+ filename: string;
8
+ }
9
+ declare const RESOURCES: ResourceDef[];
10
+ export declare function registerResources(server: McpServer): void;
11
+ export { RESOURCES, loadResource };
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmBzE,iBAAS,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,UAAU,WAAW;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,QAAA,MAAM,SAAS,EAAE,WAAW,EAoL3B,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAOzD;AAED,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,182 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join, dirname } from 'node:path';
3
+ // Resolve the directory containing resource files.
4
+ // tsx (our runtime) polyfills __dirname in ESM. ts-jest uses CJS where __dirname is native.
5
+ // We use a dynamic eval to avoid import.meta.url appearing in CJS output (which would throw).
6
+ function getResourcesDir() {
7
+ // In CJS (ts-jest), __dirname is a global
8
+ try {
9
+ return globalThis.__dirname
10
+ || eval('__dirname');
11
+ }
12
+ catch {
13
+ // In pure ESM, fall back to import.meta.url
14
+ const { fileURLToPath } = require('node:url');
15
+ return dirname(fileURLToPath(eval('import.meta.url')));
16
+ }
17
+ }
18
+ const RESOURCES_DIR = getResourcesDir();
19
+ function loadResource(filename) {
20
+ return readFileSync(join(RESOURCES_DIR, filename), 'utf-8');
21
+ }
22
+ const RESOURCES = [
23
+ // Beginner — plain English intro, read first for new users
24
+ {
25
+ uri: 'everystack://getting-started',
26
+ name: 'Getting Started (Beginners)',
27
+ description: 'Plain English intro for complete beginners. What everystack is, what the tiers mean, what each prerequisite is and why. Read this FIRST for users with no programming experience or no existing project.',
28
+ filename: 'getting-started.md',
29
+ },
30
+ // Beginner — AWS account and credential setup
31
+ {
32
+ uri: 'everystack://aws-setup',
33
+ name: 'AWS Setup (Beginners)',
34
+ description: 'Step-by-step AWS account creation and IAM credential setup for beginners. Read when check_environment reports missing AWS credentials.',
35
+ filename: 'aws-setup.md',
36
+ },
37
+ // Beginner — first local run walkthrough
38
+ {
39
+ uri: 'everystack://first-run',
40
+ name: 'First Run (Beginners)',
41
+ description: 'What happens when you run your app locally for the first time. Explains Metro bundler, hot reload, opening in browser or phone, and common first-run errors. Read after scaffolding a new project.',
42
+ filename: 'first-run.md',
43
+ },
44
+ // Beginner — V2 transition guide (adding database to existing app)
45
+ {
46
+ uri: 'everystack://adding-database',
47
+ name: 'Adding a Database (V2 Transition)',
48
+ description: 'Guide for adding PostgreSQL, API handler, and authentication to an existing Expo app. Read this when a feature needs data persistence or user accounts. Covers PostgreSQL setup, V2 package installation, schema creation, handler config, auth flow, migrations, and RLS security.',
49
+ filename: 'adding-database.md',
50
+ },
51
+ // Core — read these first (for developers)
52
+ {
53
+ uri: 'everystack://core',
54
+ name: 'everystack Core Architecture',
55
+ description: 'Architecture, package map, V1-V2-V3 tiers, key patterns, project conventions, handler overview, CLI commands. Read this first.',
56
+ filename: 'core.md',
57
+ },
58
+ {
59
+ uri: 'everystack://security',
60
+ name: 'everystack Security',
61
+ description: 'Three-layer security model (Edge/API/Database), AWS IAM profiles (Create/Manage/Deploy), RLS guide with copy-paste policies, deployment checklist. Read before any auth or deployment guidance.',
62
+ filename: 'security.md',
63
+ },
64
+ // Detail — load on demand
65
+ {
66
+ uri: 'everystack://handler-options',
67
+ name: 'Handler Options Reference',
68
+ description: 'Complete createHandler() options: auth, relations, rpc, hooks, pgSettings, softDelete, naming, exposedTables, hiddenColumns, protectedFields, rowOwnership, cache.',
69
+ filename: 'handler-options.md',
70
+ },
71
+ {
72
+ uri: 'everystack://query-protocol',
73
+ name: 'Query Protocol',
74
+ description: 'PostgREST query protocol: filters (eq, neq, gt, lt, like, ilike, is, in), negation, logical groups (or, and), column selection, relation embedding, ordering, pagination, aggregates, JSON path filtering.',
75
+ filename: 'query-protocol.md',
76
+ },
77
+ {
78
+ uri: 'everystack://client-api',
79
+ name: 'Client API',
80
+ description: 'Typed client: createClient(), query builder (.from, .eq, .select, .order, .limit), mutations (.insert, .update, .delete), token refresh, error handling.',
81
+ filename: 'client-api.md',
82
+ },
83
+ {
84
+ uri: 'everystack://auth',
85
+ name: 'Authentication',
86
+ description: 'JWT auth: createAuthHandlers(), signup/signin/refresh flows, HS256 edge verification, OAuth, password hashing, token lifecycle, AuthProvider React context.',
87
+ filename: 'auth.md',
88
+ },
89
+ {
90
+ uri: 'everystack://schema-patterns',
91
+ name: 'Schema Design Patterns',
92
+ description: 'Drizzle schema design: pgTable, column types, relations, indexes, timestamps, soft delete, UUID vs serial, migration workflow, drizzle-kit commands.',
93
+ filename: 'schema-patterns.md',
94
+ },
95
+ {
96
+ uri: 'everystack://deployment',
97
+ name: 'Deployment Guide',
98
+ description: 'SST deployment: sst.config.ts setup, secrets, stages (dev/production), CloudFront, Lambda configuration, VPC, RDS Aurora Serverless, resource linking.',
99
+ filename: 'deployment.md',
100
+ },
101
+ {
102
+ uri: 'everystack://admin',
103
+ name: 'Admin Dashboard',
104
+ description: 'Declarative admin: AdminRoot, AdminLayout, resource config, field types, EverystackAdapter, presets, custom widgets, navigation.',
105
+ filename: 'admin.md',
106
+ },
107
+ {
108
+ uri: 'everystack://jobs',
109
+ name: 'Background Jobs',
110
+ description: 'SQS background workers: createWorkerHandler, publishJob, job types, dead letter queue, cron scheduling, Postgres materialization adapter.',
111
+ filename: 'jobs.md',
112
+ },
113
+ {
114
+ uri: 'everystack://storage',
115
+ name: 'File Storage',
116
+ description: 'S3 file storage: createStorageHandler, presigned uploads, MIME validation, CDN delivery, ownership enforcement, client upload flow.',
117
+ filename: 'storage.md',
118
+ },
119
+ {
120
+ uri: 'everystack://logging',
121
+ name: 'Logging & Analytics',
122
+ description: 'Structured logging: log levels, crash reports, analytics events, S3 log storage, CloudWatch ingestion trigger, client SDK, admin dashboard integration.',
123
+ filename: 'logging.md',
124
+ },
125
+ {
126
+ uri: 'everystack://security-device',
127
+ name: 'Device Security',
128
+ description: 'Device attestation: Apple App Attest, Google Play Integrity, RS256 device keys, biometric auth, certificate pinning.',
129
+ filename: 'security-device.md',
130
+ },
131
+ {
132
+ uri: 'everystack://testing',
133
+ name: 'Testing Patterns',
134
+ description: 'Testing conventions: Jest setup, TDD workflow, test file structure, mocking patterns (ESM, sharp, AWS SDK), template database isolation, integration tests.',
135
+ filename: 'testing.md',
136
+ },
137
+ {
138
+ uri: 'everystack://plugins',
139
+ name: 'Plugin Architecture',
140
+ description: 'Plugin system: createPluginLambdaHandler, Plugin type, PluginContext, composing handlers from multiple packages, plugin registration order.',
141
+ filename: 'plugins.md',
142
+ },
143
+ {
144
+ uri: 'everystack://ssr',
145
+ name: 'Server-Side Rendering',
146
+ description: 'SSR: getWebHandler, direct Drizzle queries in loaders, JSON-LD structured data, OG meta tags, cache headers, hydration debugging.',
147
+ filename: 'ssr.md',
148
+ },
149
+ {
150
+ uri: 'everystack://images',
151
+ name: 'Image Processing',
152
+ description: 'Sharp image processing: createImageHandler, on-demand resizing, format conversion, EXIF extraction, variant generation, CDN delivery.',
153
+ filename: 'images.md',
154
+ },
155
+ {
156
+ uri: 'everystack://events',
157
+ name: 'Events & WebSocket',
158
+ description: 'Real-time events: PostgreSQL LISTEN/NOTIFY, WebSocket fan-out, Lambda event bridge, client useSignal hook, table change notifications.',
159
+ filename: 'events.md',
160
+ },
161
+ {
162
+ uri: 'everystack://cli',
163
+ name: 'CLI Reference',
164
+ description: 'Full CLI command reference: update, db:migrate, db:seed, db:psql, console, logs:errors, logs:tail, logs:query, cache:purge, certs, channels, diag, analyze:ssr.',
165
+ filename: 'cli.md',
166
+ },
167
+ {
168
+ uri: 'everystack://project-claude-md',
169
+ name: 'Project CLAUDE.md Template',
170
+ description: 'Template for a project-level CLAUDE.md file. Read this and adapt it when scaffolding a new everystack app. Replace placeholders ({PROJECT_NAME}, {ONE_LINE_DESCRIPTION}, {ANNOTATED_DIRECTORY_TREE}) with actual project details.',
171
+ filename: 'project-claude-md.md',
172
+ },
173
+ ];
174
+ export function registerResources(server) {
175
+ for (const r of RESOURCES) {
176
+ const content = loadResource(r.filename);
177
+ server.resource(r.name, r.uri, { mimeType: 'text/markdown' }, async () => ({
178
+ contents: [{ uri: r.uri, mimeType: 'text/markdown', text: content }],
179
+ }));
180
+ }
181
+ }
182
+ export { RESOURCES, loadResource };