@everystack/mcp 0.3.2 → 0.3.3

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 (85) hide show
  1. package/dist/gates/detectors/embedded-data-bundle.d.ts +13 -0
  2. package/dist/gates/detectors/embedded-data-bundle.d.ts.map +1 -0
  3. package/dist/gates/detectors/embedded-data-bundle.js +56 -0
  4. package/dist/gates/detectors/hand-written-migration.d.ts +24 -0
  5. package/dist/gates/detectors/hand-written-migration.d.ts.map +1 -0
  6. package/dist/gates/detectors/hand-written-migration.js +54 -0
  7. package/dist/gates/detectors/secret-in-public-env.d.ts +12 -0
  8. package/dist/gates/detectors/secret-in-public-env.d.ts.map +1 -0
  9. package/dist/gates/detectors/secret-in-public-env.js +38 -0
  10. package/dist/gates/engine.d.ts +28 -0
  11. package/dist/gates/engine.d.ts.map +1 -0
  12. package/dist/gates/engine.js +74 -0
  13. package/dist/gates/registry.d.ts +14 -0
  14. package/dist/gates/registry.d.ts.map +1 -0
  15. package/dist/gates/registry.js +21 -0
  16. package/dist/gates/telemetry.d.ts +47 -0
  17. package/dist/gates/telemetry.d.ts.map +1 -0
  18. package/dist/gates/telemetry.js +121 -0
  19. package/dist/gates/types.d.ts +67 -0
  20. package/dist/gates/types.d.ts.map +1 -0
  21. package/dist/gates/types.js +14 -0
  22. package/dist/governance/cli.d.ts +57 -0
  23. package/dist/governance/cli.d.ts.map +1 -0
  24. package/dist/governance/cli.js +169 -0
  25. package/dist/governance/grounding.d.ts +78 -0
  26. package/dist/governance/grounding.d.ts.map +1 -0
  27. package/dist/governance/grounding.js +299 -0
  28. package/dist/index.cjs +11 -9
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +94 -0
  32. package/dist/project-claude-md.md +30 -16
  33. package/dist/prompts/add-feature.d.ts +3 -0
  34. package/dist/prompts/add-feature.d.ts.map +1 -0
  35. package/dist/prompts/add-feature.js +154 -0
  36. package/dist/prompts/claude-md.d.ts +12 -0
  37. package/dist/prompts/claude-md.d.ts.map +1 -0
  38. package/dist/prompts/claude-md.js +87 -0
  39. package/dist/prompts/debug.d.ts +3 -0
  40. package/dist/prompts/debug.d.ts.map +1 -0
  41. package/dist/prompts/debug.js +129 -0
  42. package/dist/prompts/deploy.d.ts +3 -0
  43. package/dist/prompts/deploy.d.ts.map +1 -0
  44. package/dist/prompts/deploy.js +118 -0
  45. package/dist/prompts/design-schema.d.ts +3 -0
  46. package/dist/prompts/design-schema.d.ts.map +1 -0
  47. package/dist/prompts/design-schema.js +97 -0
  48. package/dist/prompts/governance-setup.d.ts +9 -0
  49. package/dist/prompts/governance-setup.d.ts.map +1 -0
  50. package/dist/prompts/governance-setup.js +76 -0
  51. package/dist/prompts/index.d.ts +3 -0
  52. package/dist/prompts/index.d.ts.map +1 -0
  53. package/dist/prompts/index.js +20 -0
  54. package/dist/prompts/new-app.d.ts +3 -0
  55. package/dist/prompts/new-app.d.ts.map +1 -0
  56. package/dist/prompts/new-app.js +203 -0
  57. package/dist/prompts/runbook.d.ts +12 -0
  58. package/dist/prompts/runbook.d.ts.map +1 -0
  59. package/dist/prompts/runbook.js +70 -0
  60. package/dist/prompts/secure.d.ts +3 -0
  61. package/dist/prompts/secure.d.ts.map +1 -0
  62. package/dist/prompts/secure.js +219 -0
  63. package/dist/resources/index.d.ts +12 -0
  64. package/dist/resources/index.d.ts.map +1 -0
  65. package/dist/resources/index.js +182 -0
  66. package/dist/tools/check-environment.d.ts +25 -0
  67. package/dist/tools/check-environment.d.ts.map +1 -0
  68. package/dist/tools/check-environment.js +281 -0
  69. package/dist/tools/index.d.ts +3 -0
  70. package/dist/tools/index.d.ts.map +1 -0
  71. package/dist/tools/index.js +18 -0
  72. package/dist/tools/project-status.d.ts +28 -0
  73. package/dist/tools/project-status.d.ts.map +1 -0
  74. package/dist/tools/project-status.js +138 -0
  75. package/dist/tools/project-validate.d.ts +19 -0
  76. package/dist/tools/project-validate.d.ts.map +1 -0
  77. package/dist/tools/project-validate.js +323 -0
  78. package/dist/tools/schema-analyze.d.ts +46 -0
  79. package/dist/tools/schema-analyze.d.ts.map +1 -0
  80. package/dist/tools/schema-analyze.js +336 -0
  81. package/package.json +3 -3
  82. package/src/gates/detectors/hand-written-migration.ts +22 -13
  83. package/src/index.ts +1 -1
  84. package/src/prompts/claude-md.ts +4 -2
  85. package/src/resources/project-claude-md.md +30 -16
@@ -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 };
@@ -0,0 +1,25 @@
1
+ export type EnvironmentPhase = 'local' | 'deploy';
2
+ export interface PrerequisiteCheck {
3
+ name: string;
4
+ required: boolean;
5
+ status: 'found' | 'not_found';
6
+ version: string | null;
7
+ installHint: string;
8
+ tier: 'V1' | 'V2';
9
+ phase: 'local' | 'deploy';
10
+ description: string;
11
+ whyNeeded: string;
12
+ installCommands: string[];
13
+ serviceRunning?: boolean;
14
+ }
15
+ export interface EnvironmentReport {
16
+ phase: EnvironmentPhase;
17
+ prerequisites: PrerequisiteCheck[];
18
+ ready: boolean;
19
+ readyForTier: 'V1' | 'V2' | 'V3' | 'none';
20
+ suggestions: string[];
21
+ platform: 'macOS' | 'linux' | 'windows' | 'unknown';
22
+ nextSteps: string[];
23
+ }
24
+ export declare function checkEnvironment(phase?: EnvironmentPhase): EnvironmentReport;
25
+ //# sourceMappingURL=check-environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-environment.d.ts","sourceRoot":"","sources":["../../src/tools/check-environment.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,QAAQ,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,GAAG,WAAW,CAAC;IAC9B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,gBAAgB,CAAC;IACxB,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IAC1C,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACpD,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAiCD,wBAAgB,gBAAgB,CAAC,KAAK,GAAE,gBAA0B,GAAG,iBAAiB,CAgQrF"}
@@ -0,0 +1,281 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { homedir } from 'node:os';
5
+ function detectPlatform() {
6
+ const p = process.platform;
7
+ if (p === 'darwin')
8
+ return 'macOS';
9
+ if (p === 'linux')
10
+ return 'linux';
11
+ if (p === 'win32')
12
+ return 'windows';
13
+ return 'unknown';
14
+ }
15
+ function tryExec(cmd, timeout = 10000) {
16
+ try {
17
+ return execSync(cmd, { timeout, stdio: 'pipe', encoding: 'utf-8' }).trim();
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ }
23
+ function parseVersion(output, pattern) {
24
+ if (!output)
25
+ return null;
26
+ if (pattern) {
27
+ const match = output.match(pattern);
28
+ return match?.[1] ?? null;
29
+ }
30
+ return output.replace(/^v/, '');
31
+ }
32
+ function meetsMinVersion(version, major) {
33
+ if (!version)
34
+ return false;
35
+ const parsed = parseInt(version.split('.')[0], 10);
36
+ return !isNaN(parsed) && parsed >= major;
37
+ }
38
+ export function checkEnvironment(phase = 'local') {
39
+ const prerequisites = [];
40
+ const suggestions = [];
41
+ const platform = detectPlatform();
42
+ const isLocal = phase === 'local';
43
+ // Node.js
44
+ const nodeOutput = tryExec('node --version');
45
+ const nodeVersion = parseVersion(nodeOutput);
46
+ const nodeOk = meetsMinVersion(nodeVersion, 20);
47
+ prerequisites.push({
48
+ name: 'node',
49
+ required: true,
50
+ status: nodeVersion ? 'found' : 'not_found',
51
+ version: nodeVersion,
52
+ installHint: 'Install Node.js 20+ from https://nodejs.org',
53
+ tier: 'V1',
54
+ phase: 'local',
55
+ description: 'Node.js runs your code. Your app is written in TypeScript, and Node.js is the engine that executes it.',
56
+ whyNeeded: 'Without Node.js, none of the code can run.',
57
+ installCommands: platform === 'macOS'
58
+ ? ['brew install node', 'Or download from https://nodejs.org']
59
+ : platform === 'linux'
60
+ ? ['sudo apt install nodejs npm', 'Or download from https://nodejs.org']
61
+ : ['Download and install from https://nodejs.org'],
62
+ });
63
+ if (!nodeVersion) {
64
+ suggestions.push('Node.js is not installed. Install Node.js 20+ from https://nodejs.org');
65
+ }
66
+ else if (!nodeOk) {
67
+ suggestions.push(`Node.js ${nodeVersion} is installed but version 20+ is required. Upgrade at https://nodejs.org`);
68
+ }
69
+ // pnpm (recommended, not required)
70
+ const pnpmOutput = tryExec('pnpm --version');
71
+ const pnpmVersion = parseVersion(pnpmOutput);
72
+ prerequisites.push({
73
+ name: 'pnpm',
74
+ required: false,
75
+ status: pnpmVersion ? 'found' : 'not_found',
76
+ version: pnpmVersion,
77
+ installHint: 'Install pnpm: npm install -g pnpm (recommended for monorepos)',
78
+ tier: 'V1',
79
+ phase: 'local',
80
+ description: 'A faster way to install code libraries your app depends on. Recommended but not required.',
81
+ whyNeeded: 'Makes installing dependencies faster and more reliable.',
82
+ installCommands: ['npm install -g pnpm'],
83
+ });
84
+ if (!pnpmVersion) {
85
+ suggestions.push('pnpm is not installed. Recommended for monorepos: npm install -g pnpm');
86
+ }
87
+ // git
88
+ const gitOutput = tryExec('git --version');
89
+ const gitVersion = parseVersion(gitOutput, /git version (\d+\.\d+\.\d+)/);
90
+ prerequisites.push({
91
+ name: 'git',
92
+ required: true,
93
+ status: gitVersion ? 'found' : 'not_found',
94
+ version: gitVersion,
95
+ installHint: 'Install git from https://git-scm.com',
96
+ tier: 'V1',
97
+ phase: 'local',
98
+ description: 'Tracks every change to your code. Like an unlimited undo button for your entire project.',
99
+ whyNeeded: 'Without git, you cannot track changes, undo mistakes, or collaborate.',
100
+ installCommands: platform === 'macOS'
101
+ ? ['xcode-select --install']
102
+ : platform === 'linux'
103
+ ? ['sudo apt install git']
104
+ : ['Download from https://git-scm.com'],
105
+ });
106
+ if (!gitVersion) {
107
+ suggestions.push('git is not installed. Install from https://git-scm.com');
108
+ }
109
+ // Expo CLI
110
+ const expoOutput = tryExec('npx expo --version');
111
+ const expoVersion = parseVersion(expoOutput);
112
+ prerequisites.push({
113
+ name: 'expo',
114
+ required: true,
115
+ status: expoVersion ? 'found' : 'not_found',
116
+ version: expoVersion,
117
+ installHint: 'Expo is available via npx. Ensure Node.js is installed, then run: npx create-expo-app',
118
+ tier: 'V1',
119
+ phase: 'local',
120
+ description: 'The framework that makes your app work on phones, tablets, and the web from the same code.',
121
+ whyNeeded: 'Without Expo, you cannot create or run the app.',
122
+ installCommands: ['Runs via npx (no separate install needed). Requires Node.js.'],
123
+ });
124
+ if (!expoVersion) {
125
+ suggestions.push('Expo CLI not available. Ensure Node.js is installed — Expo runs via npx.');
126
+ }
127
+ // SST (deploy phase only)
128
+ const sstOutput = tryExec('npx sst version');
129
+ const sstVersion = parseVersion(sstOutput, /(\d+\.\d+\.\d+)/);
130
+ prerequisites.push({
131
+ name: 'sst',
132
+ required: !isLocal,
133
+ status: sstVersion ? 'found' : 'not_found',
134
+ version: sstVersion,
135
+ installHint: 'SST is installed as a dev dependency: pnpm add -D sst (or npx sst)',
136
+ tier: 'V1',
137
+ phase: 'deploy',
138
+ description: isLocal
139
+ ? 'Manages your cloud infrastructure. Not needed yet — you can build and run your app locally first.'
140
+ : 'Manages your cloud infrastructure. Tells AWS what servers, databases, and storage your app needs.',
141
+ whyNeeded: isLocal
142
+ ? 'Only needed when you are ready to deploy your app to the internet.'
143
+ : 'Without SST, you cannot deploy your app to the internet.',
144
+ installCommands: ['Installed as a project dependency when you create your app.'],
145
+ });
146
+ if (!sstVersion && !isLocal) {
147
+ suggestions.push('SST not found. It installs as a dev dependency: pnpm add -D sst');
148
+ }
149
+ // AWS CLI (deploy phase only)
150
+ const awsOutput = tryExec('aws --version');
151
+ const awsVersion = parseVersion(awsOutput, /aws-cli\/(\d+\.\d+\.\d+)/);
152
+ prerequisites.push({
153
+ name: 'aws-cli',
154
+ required: !isLocal,
155
+ status: awsVersion ? 'found' : 'not_found',
156
+ version: awsVersion,
157
+ installHint: 'Install AWS CLI from https://aws.amazon.com/cli/',
158
+ tier: 'V1',
159
+ phase: 'deploy',
160
+ description: isLocal
161
+ ? 'A command-line tool for Amazon Web Services. Not needed yet — you can build and run your app locally first.'
162
+ : 'A command-line tool that lets your computer talk to Amazon Web Services, where your app runs.',
163
+ whyNeeded: isLocal
164
+ ? 'Only needed when you are ready to deploy your app to the internet.'
165
+ : 'Without it, you cannot deploy or manage your app on AWS.',
166
+ installCommands: platform === 'macOS'
167
+ ? ['brew install awscli']
168
+ : platform === 'linux'
169
+ ? ['curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && unzip awscliv2.zip && sudo ./aws/install']
170
+ : ['Download from https://aws.amazon.com/cli/'],
171
+ });
172
+ if (!awsVersion && !isLocal) {
173
+ suggestions.push('AWS CLI is not installed. Install from https://aws.amazon.com/cli/');
174
+ }
175
+ // AWS credentials (deploy phase only)
176
+ const home = homedir();
177
+ const hasAwsCreds = existsSync(join(home, '.aws', 'credentials')) || existsSync(join(home, '.aws', 'config'));
178
+ prerequisites.push({
179
+ name: 'aws-credentials',
180
+ required: !isLocal,
181
+ status: hasAwsCreds ? 'found' : 'not_found',
182
+ version: null,
183
+ installHint: 'Read everystack://aws-setup for step-by-step AWS account and credential setup.',
184
+ tier: 'V1',
185
+ phase: 'deploy',
186
+ description: isLocal
187
+ ? 'A password file for your AWS account. Not needed yet — you can build and run your app locally first.'
188
+ : 'A password file that proves your computer is allowed to deploy to your AWS account.',
189
+ whyNeeded: isLocal
190
+ ? 'Only needed when you are ready to deploy your app to the internet.'
191
+ : 'Without credentials, AWS will reject all deploy commands.',
192
+ installCommands: ['Read everystack://aws-setup for full setup guide', 'aws configure'],
193
+ });
194
+ if (!hasAwsCreds && !isLocal) {
195
+ suggestions.push("AWS credentials not configured. Read everystack://aws-setup for step-by-step setup, or run 'aws configure' if you already have access keys.");
196
+ }
197
+ // PostgreSQL
198
+ const psqlOutput = tryExec('psql --version');
199
+ const psqlVersion = parseVersion(psqlOutput, /psql \(PostgreSQL\) (\d+\.\d+)/);
200
+ const pgReadyOutput = psqlVersion ? tryExec('pg_isready') : null;
201
+ const pgServiceUp = pgReadyOutput !== null && pgReadyOutput.includes('accepting connections');
202
+ prerequisites.push({
203
+ name: 'postgresql',
204
+ required: true,
205
+ status: psqlVersion ? 'found' : 'not_found',
206
+ version: psqlVersion,
207
+ serviceRunning: psqlVersion ? pgServiceUp : undefined,
208
+ installHint: 'Install PostgreSQL: brew install postgresql (macOS) or https://www.postgresql.org/download/',
209
+ tier: 'V2',
210
+ phase: 'local',
211
+ description: 'A database that stores your app data: users, posts, recipes, or whatever your app needs.',
212
+ whyNeeded: 'Without PostgreSQL, your app cannot have user accounts or saved data (needed for V2+).',
213
+ installCommands: platform === 'macOS'
214
+ ? ['brew install postgresql@16', 'brew services start postgresql@16']
215
+ : platform === 'linux'
216
+ ? ['sudo apt install postgresql', 'sudo systemctl start postgresql']
217
+ : ['Download from https://www.postgresql.org/download/'],
218
+ });
219
+ if (!psqlVersion) {
220
+ suggestions.push('PostgreSQL is not installed. Needed for V2+ (database tier). Install: brew install postgresql');
221
+ }
222
+ else if (!pgServiceUp) {
223
+ suggestions.push(platform === 'macOS'
224
+ ? 'PostgreSQL is installed but the service is not running. Start it: brew services start postgresql@16'
225
+ : platform === 'linux'
226
+ ? 'PostgreSQL is installed but the service is not running. Start it: sudo systemctl start postgresql'
227
+ : 'PostgreSQL is installed but the service is not running. Start the PostgreSQL service.');
228
+ }
229
+ // Determine readiness — in local phase, only local-phase prerequisites count
230
+ const relevant = isLocal
231
+ ? prerequisites.filter(c => c.phase === 'local')
232
+ : prerequisites;
233
+ const v1Required = relevant.filter(c => c.tier === 'V1' && c.required);
234
+ const v2Required = relevant.filter(c => c.tier === 'V2' && c.required);
235
+ const v1Ready = nodeOk && v1Required.every(c => c.status === 'found');
236
+ const v2Ready = v1Ready && v2Required.every(c => c.status === 'found');
237
+ // V3 uses same prerequisites as V2 (adds SQS/S3 which are AWS services, no local tooling)
238
+ const v3Ready = v2Ready;
239
+ const readyForTier = v3Ready ? 'V3' : v2Ready ? 'V2' : v1Ready ? 'V1' : 'none';
240
+ // Build nextSteps
241
+ const nextSteps = [];
242
+ const missing = relevant.filter(p => p.required && p.status === 'not_found');
243
+ if (missing.length === 0) {
244
+ if (isLocal) {
245
+ nextSteps.push('All local development prerequisites installed. Ready to create and run your app.');
246
+ // Hint about deploy-phase tools if not yet installed
247
+ const deployMissing = prerequisites.filter(p => p.phase === 'deploy' && p.status === 'not_found');
248
+ if (deployMissing.length > 0) {
249
+ nextSteps.push('When you are ready to put your app on the internet, run check_environment with phase "deploy" to see what else is needed.');
250
+ }
251
+ }
252
+ else {
253
+ nextSteps.push('All prerequisites installed. Ready to create a new app.');
254
+ }
255
+ }
256
+ else {
257
+ const installOrder = isLocal
258
+ ? ['node', 'git', 'pnpm', 'expo', 'postgresql']
259
+ : ['node', 'git', 'pnpm', 'aws-cli', 'aws-credentials', 'expo', 'sst', 'postgresql'];
260
+ const ordered = installOrder
261
+ .map(name => missing.find(p => p.name === name))
262
+ .filter((p) => p !== undefined);
263
+ for (const p of ordered) {
264
+ if (p.tier === 'V2') {
265
+ nextSteps.push(`Optional for now: Install ${p.name} — ${p.description.split('.')[0]}. Only needed for apps with user accounts or a database (V2+).`);
266
+ }
267
+ else {
268
+ nextSteps.push(`Install ${p.name} — ${p.description.split('.')[0]}. ${p.installCommands[0]}`);
269
+ }
270
+ }
271
+ }
272
+ return {
273
+ phase,
274
+ prerequisites,
275
+ ready: readyForTier !== 'none',
276
+ readyForTier,
277
+ suggestions,
278
+ platform,
279
+ nextSteps,
280
+ };
281
+ }
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerTools(server: McpServer): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AASzE,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAcrD"}
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ import { checkEnvironment } from './check-environment.js';
3
+ // NOTE (Brick 0): the legacy regex tools — project_status, schema_analyze,
4
+ // project_validate — are intentionally NOT registered. They predate the v3
5
+ // Model/Module surface and return wrong answers on Model-based apps (e.g. they
6
+ // report a securely-derived handler config as "all tables accessible"). They are
7
+ // rebuilt on @everystack/model in Brick 1 and re-registered there. Their source
8
+ // files remain for that rewrite to reference.
9
+ export function registerTools(server) {
10
+ server.tool('check_environment', 'Verify development prerequisites are installed (Node.js, pnpm, git, Expo, SST, AWS CLI, PostgreSQL). Run this first when a user wants to start a new project or is having setup issues. Use phase "local" (default) to check only what is needed to build and run locally. Use phase "deploy" when ready to deploy to AWS.', {
11
+ phase: z.enum(['local', 'deploy']).optional().describe('Check prerequisites for local development (default) or AWS deployment'),
12
+ }, async ({ phase }) => {
13
+ const report = checkEnvironment(phase ?? 'local');
14
+ return {
15
+ content: [{ type: 'text', text: JSON.stringify(report, null, 2) }],
16
+ };
17
+ });
18
+ }
@@ -0,0 +1,28 @@
1
+ interface ProjectStatus {
2
+ tier: 'V1' | 'V2' | 'V3' | 'unknown';
3
+ tierExplanation: string;
4
+ packages: {
5
+ installed: string[];
6
+ missing: string[];
7
+ };
8
+ files: {
9
+ sstConfig: boolean;
10
+ schemaDir: boolean;
11
+ schemaFiles: string[];
12
+ migrationsDir: boolean;
13
+ serverDir: boolean;
14
+ handlerFile: string | null;
15
+ workerFile: string | null;
16
+ imageFile: string | null;
17
+ seedFile: string | null;
18
+ };
19
+ deployment: {
20
+ sstOutputs: boolean;
21
+ stage: string | null;
22
+ secrets: string[];
23
+ };
24
+ warnings: string[];
25
+ }
26
+ export declare function analyzeProjectStatus(projectPath: string): ProjectStatus;
27
+ export {};
28
+ //# sourceMappingURL=project-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-status.d.ts","sourceRoot":"","sources":["../../src/tools/project-status.ts"],"names":[],"mappings":"AAUA,UAAU,aAAa;IACrB,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,KAAK,EAAE;QACL,SAAS,EAAE,OAAO,CAAC;QACnB,SAAS,EAAE,OAAO,CAAC;QACnB,WAAW,EAAE,MAAM,EAAE,CAAC;QACtB,aAAa,EAAE,OAAO,CAAC;QACvB,SAAS,EAAE,OAAO,CAAC;QACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,CAAC;IACF,UAAU,EAAE;QACV,UAAU,EAAE,OAAO,CAAC;QACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAgCD,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAoHvE"}