@everstateai/mcp 1.3.14 → 1.3.15
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/dist/index.js +55 -3
- package/dist/index.js.map +1 -1
- package/dist/setup/hooks/templates.d.ts.map +1 -1
- package/dist/setup/hooks/templates.js +41 -6
- package/dist/setup/hooks/templates.js.map +1 -1
- package/dist/setup/types.js +1 -1
- package/dist/setup/types.js.map +1 -1
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +208 -5
- package/dist/setup.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +57 -3
- package/src/setup/hooks/templates.ts +41 -6
- package/src/setup/types.ts +1 -1
- package/src/setup.ts +230 -7
package/src/setup.ts
CHANGED
|
@@ -551,6 +551,81 @@ async function installHooks(projectDir: string, force: boolean = false) {
|
|
|
551
551
|
logSuccess("Everstate tools added to approved commands");
|
|
552
552
|
}
|
|
553
553
|
|
|
554
|
+
// ============================================================================
|
|
555
|
+
// Stack detection
|
|
556
|
+
// ============================================================================
|
|
557
|
+
|
|
558
|
+
const STACK_DETECT: Array<{ id: string; name: string; checks: Array<{ file: string; contains?: string }> }> = [
|
|
559
|
+
{
|
|
560
|
+
id: 'react',
|
|
561
|
+
name: 'React',
|
|
562
|
+
checks: [
|
|
563
|
+
{ file: 'package.json', contains: '"react"' },
|
|
564
|
+
{ file: 'vite.config.ts' },
|
|
565
|
+
{ file: 'vite.config.js' },
|
|
566
|
+
{ file: 'next.config.js' },
|
|
567
|
+
{ file: 'next.config.mjs' },
|
|
568
|
+
{ file: 'next.config.ts' },
|
|
569
|
+
],
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
id: 'node',
|
|
573
|
+
name: 'Node.js',
|
|
574
|
+
checks: [
|
|
575
|
+
{ file: 'package.json', contains: '"express"' },
|
|
576
|
+
{ file: 'package.json', contains: '"fastify"' },
|
|
577
|
+
{ file: 'package.json', contains: '"@nestjs/core"' },
|
|
578
|
+
],
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
id: 'python',
|
|
582
|
+
name: 'Python',
|
|
583
|
+
checks: [
|
|
584
|
+
{ file: 'pyproject.toml' },
|
|
585
|
+
{ file: 'requirements.txt' },
|
|
586
|
+
{ file: 'setup.py' },
|
|
587
|
+
{ file: 'Pipfile' },
|
|
588
|
+
{ file: 'manage.py' },
|
|
589
|
+
],
|
|
590
|
+
},
|
|
591
|
+
];
|
|
592
|
+
|
|
593
|
+
function detectProjectStack(projectDir: string): { id: string; name: string } | null {
|
|
594
|
+
for (const stack of STACK_DETECT) {
|
|
595
|
+
for (const check of stack.checks) {
|
|
596
|
+
const filePath = path.join(projectDir, check.file);
|
|
597
|
+
if (!fs.existsSync(filePath)) continue;
|
|
598
|
+
|
|
599
|
+
if (check.contains) {
|
|
600
|
+
try {
|
|
601
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
602
|
+
if (content.includes(check.contains)) {
|
|
603
|
+
return { id: stack.id, name: stack.name };
|
|
604
|
+
}
|
|
605
|
+
} catch {
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
608
|
+
} else {
|
|
609
|
+
return { id: stack.id, name: stack.name };
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return null;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
async function applyStackTemplate(apiKey: string, projectId: string, stackId: string): Promise<boolean> {
|
|
617
|
+
try {
|
|
618
|
+
const response = await httpPost(
|
|
619
|
+
"https://www.everstate.ai/api/projects/apply-stack-template",
|
|
620
|
+
{ projectId, stack: stackId },
|
|
621
|
+
apiKey
|
|
622
|
+
);
|
|
623
|
+
return response && !response.error;
|
|
624
|
+
} catch {
|
|
625
|
+
return false;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
554
629
|
// ============================================================================
|
|
555
630
|
// Project config
|
|
556
631
|
// ============================================================================
|
|
@@ -559,7 +634,7 @@ async function createProjectConfig(
|
|
|
559
634
|
projectDir: string,
|
|
560
635
|
apiKey: string,
|
|
561
636
|
existingProjectId: string | null
|
|
562
|
-
): Promise<{ projectId: string; projectName: string }> {
|
|
637
|
+
): Promise<{ projectId: string; projectName: string; stack?: string }> {
|
|
563
638
|
const configPath = path.join(projectDir, ".everstate.json");
|
|
564
639
|
|
|
565
640
|
const existingConfig = readJsonFile(configPath);
|
|
@@ -586,16 +661,26 @@ async function createProjectConfig(
|
|
|
586
661
|
}
|
|
587
662
|
}
|
|
588
663
|
|
|
589
|
-
|
|
664
|
+
// Detect project stack
|
|
665
|
+
const detectedStack = detectProjectStack(projectDir);
|
|
666
|
+
|
|
667
|
+
const config: Record<string, unknown> = {
|
|
590
668
|
projectId: projectId || `proj_${Date.now()}`,
|
|
591
669
|
projectName,
|
|
592
670
|
createdAt: new Date().toISOString(),
|
|
593
671
|
version: "1.0.0",
|
|
594
672
|
};
|
|
595
673
|
|
|
674
|
+
if (detectedStack) {
|
|
675
|
+
config.stack = detectedStack.id;
|
|
676
|
+
}
|
|
677
|
+
|
|
596
678
|
writeJsonFile(configPath, config);
|
|
597
679
|
logSuccess(`Project configured: ${config.projectName}`);
|
|
598
|
-
|
|
680
|
+
if (detectedStack) {
|
|
681
|
+
logSuccess(`Detected stack: ${detectedStack.name}`);
|
|
682
|
+
}
|
|
683
|
+
return config as { projectId: string; projectName: string; stack?: string };
|
|
599
684
|
}
|
|
600
685
|
|
|
601
686
|
// ============================================================================
|
|
@@ -604,7 +689,7 @@ async function createProjectConfig(
|
|
|
604
689
|
|
|
605
690
|
function updateGitignore(projectDir: string) {
|
|
606
691
|
const gitignorePath = path.join(projectDir, ".gitignore");
|
|
607
|
-
const entries = ["# Everstate", ".claude/settings.local.json", ".claude/hooks/", ".claude/rules/"];
|
|
692
|
+
const entries = ["# Everstate", ".claude/settings.local.json", ".claude/hooks/", ".claude/rules/", ".cursor/rules/everstate.mdc", ".windsurf/rules/everstate.md"];
|
|
608
693
|
|
|
609
694
|
let content = fs.existsSync(gitignorePath) ? fs.readFileSync(gitignorePath, "utf8") : "";
|
|
610
695
|
const toAdd = entries.filter((e) => !content.includes(e.replace("# Everstate", "")));
|
|
@@ -665,6 +750,104 @@ function ensureClaudeMd(projectDir: string) {
|
|
|
665
750
|
}
|
|
666
751
|
}
|
|
667
752
|
|
|
753
|
+
// ============================================================================
|
|
754
|
+
// Cursor Rules (.cursor/rules/everstate.mdc)
|
|
755
|
+
// ============================================================================
|
|
756
|
+
|
|
757
|
+
const CURSOR_RULES_CONTENT = `---
|
|
758
|
+
description: Everstate project memory - persistent context across sessions
|
|
759
|
+
globs: "**/*"
|
|
760
|
+
alwaysApply: true
|
|
761
|
+
---
|
|
762
|
+
|
|
763
|
+
# Everstate - Project Memory
|
|
764
|
+
|
|
765
|
+
This project uses [Everstate](https://www.everstate.ai) for persistent memory across sessions.
|
|
766
|
+
|
|
767
|
+
## MCP Tools Available
|
|
768
|
+
|
|
769
|
+
You have Everstate MCP tools. Use them:
|
|
770
|
+
|
|
771
|
+
| Tool | When to Use |
|
|
772
|
+
|------|-------------|
|
|
773
|
+
| \`sync\` | **Call at the START of every conversation** to load project context |
|
|
774
|
+
| \`done\` | **Call BEFORE ending** to save session summary for next time |
|
|
775
|
+
| \`recall\` | Search past sessions: \`recall({ query: "what did we try for X?" })\` |
|
|
776
|
+
| \`log\` | Record progress: \`log({ type: "achievement", message: "..." })\` |
|
|
777
|
+
| \`everstate\` | All 100+ actions: \`everstate({ action: "help" })\` |
|
|
778
|
+
|
|
779
|
+
## Session Workflow
|
|
780
|
+
|
|
781
|
+
1. **Start**: Call \`sync()\` first thing to load context (gotchas, tasks, last session)
|
|
782
|
+
2. **During**: Use \`log()\` for progress, \`recall()\` to search memory
|
|
783
|
+
3. **End**: Call \`done({ summary: "...", nextSteps: [...] })\` to save context
|
|
784
|
+
`;
|
|
785
|
+
|
|
786
|
+
function ensureCursorRules(projectDir: string) {
|
|
787
|
+
const rulesDir = path.join(projectDir, ".cursor", "rules");
|
|
788
|
+
const rulesPath = path.join(rulesDir, "everstate.mdc");
|
|
789
|
+
|
|
790
|
+
if (!fs.existsSync(rulesDir)) {
|
|
791
|
+
fs.mkdirSync(rulesDir, { recursive: true });
|
|
792
|
+
}
|
|
793
|
+
fs.writeFileSync(rulesPath, CURSOR_RULES_CONTENT);
|
|
794
|
+
logSuccess("Created .cursor/rules/everstate.mdc");
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// ============================================================================
|
|
798
|
+
// Windsurf Rules (.windsurf/rules/everstate.md)
|
|
799
|
+
// ============================================================================
|
|
800
|
+
|
|
801
|
+
const WINDSURF_RULES_CONTENT = `# Everstate - Project Memory
|
|
802
|
+
|
|
803
|
+
This project uses [Everstate](https://www.everstate.ai) for persistent memory across sessions.
|
|
804
|
+
|
|
805
|
+
## MCP Tools Available
|
|
806
|
+
|
|
807
|
+
You have Everstate MCP tools. Use them:
|
|
808
|
+
|
|
809
|
+
| Tool | When to Use |
|
|
810
|
+
|------|-------------|
|
|
811
|
+
| \`sync\` | **Call at the START of every conversation** to load project context |
|
|
812
|
+
| \`done\` | **Call BEFORE ending** to save session summary for next time |
|
|
813
|
+
| \`recall\` | Search past sessions: \`recall({ query: "what did we try for X?" })\` |
|
|
814
|
+
| \`log\` | Record progress: \`log({ type: "achievement", message: "..." })\` |
|
|
815
|
+
| \`everstate\` | All 100+ actions: \`everstate({ action: "help" })\` |
|
|
816
|
+
|
|
817
|
+
## Session Workflow
|
|
818
|
+
|
|
819
|
+
1. **Start**: Call \`sync()\` first thing to load context (gotchas, tasks, last session)
|
|
820
|
+
2. **During**: Use \`log()\` for progress, \`recall()\` to search memory
|
|
821
|
+
3. **End**: Call \`done({ summary: "...", nextSteps: [...] })\` to save context
|
|
822
|
+
`;
|
|
823
|
+
|
|
824
|
+
function ensureWindsurfRules(projectDir: string) {
|
|
825
|
+
const rulesDir = path.join(projectDir, ".windsurf", "rules");
|
|
826
|
+
const rulesPath = path.join(rulesDir, "everstate.md");
|
|
827
|
+
|
|
828
|
+
if (!fs.existsSync(rulesDir)) {
|
|
829
|
+
fs.mkdirSync(rulesDir, { recursive: true });
|
|
830
|
+
}
|
|
831
|
+
fs.writeFileSync(rulesPath, WINDSURF_RULES_CONTENT);
|
|
832
|
+
logSuccess("Created .windsurf/rules/everstate.md");
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// ============================================================================
|
|
836
|
+
// Install rules for detected non-Claude tools
|
|
837
|
+
// ============================================================================
|
|
838
|
+
|
|
839
|
+
function installToolRules(projectDir: string, configResults: ConfigureResult[]) {
|
|
840
|
+
for (const result of configResults) {
|
|
841
|
+
if (result.status !== "configured") continue;
|
|
842
|
+
|
|
843
|
+
if (result.id === "cursor") {
|
|
844
|
+
ensureCursorRules(projectDir);
|
|
845
|
+
} else if (result.id === "windsurf") {
|
|
846
|
+
ensureWindsurfRules(projectDir);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
|
|
668
851
|
// ============================================================================
|
|
669
852
|
// Setup summary
|
|
670
853
|
// ============================================================================
|
|
@@ -673,6 +856,7 @@ function printSetupSummary(
|
|
|
673
856
|
configResults: ConfigureResult[],
|
|
674
857
|
projectDir: string,
|
|
675
858
|
apiKey: string,
|
|
859
|
+
detectedStack?: string,
|
|
676
860
|
) {
|
|
677
861
|
console.log("");
|
|
678
862
|
console.log(c("green", "╔═══════════════════════════════════════════════════════════╗"));
|
|
@@ -708,6 +892,19 @@ function printSetupSummary(
|
|
|
708
892
|
console.log(c("green", " ✓ ") + "Project config".padEnd(22) + c("dim", ".everstate.json"));
|
|
709
893
|
console.log(c("green", " ✓ ") + "Session hooks".padEnd(22) + c("dim", ".claude/hooks/"));
|
|
710
894
|
console.log(c("green", " ✓ ") + "Permissions".padEnd(22) + c("dim", ".claude/settings.local.json"));
|
|
895
|
+
// Show rules files for detected tools
|
|
896
|
+
for (const result of configResults) {
|
|
897
|
+
if (result.status !== "configured") continue;
|
|
898
|
+
if (result.id === "cursor") {
|
|
899
|
+
console.log(c("green", " ✓ ") + "Cursor rules".padEnd(22) + c("dim", ".cursor/rules/everstate.mdc"));
|
|
900
|
+
} else if (result.id === "windsurf") {
|
|
901
|
+
console.log(c("green", " ✓ ") + "Windsurf rules".padEnd(22) + c("dim", ".windsurf/rules/everstate.md"));
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
if (detectedStack) {
|
|
905
|
+
const stackName = STACK_DETECT.find(s => s.id === detectedStack)?.name || detectedStack;
|
|
906
|
+
console.log(c("green", " ✓ ") + "Stack template".padEnd(22) + c("dim", `${stackName} (gotchas + tasks)`));
|
|
907
|
+
}
|
|
711
908
|
console.log("");
|
|
712
909
|
|
|
713
910
|
// Next steps
|
|
@@ -775,8 +972,9 @@ async function runUpgrade(args: SetupArgs) {
|
|
|
775
972
|
}
|
|
776
973
|
}
|
|
777
974
|
|
|
778
|
-
logInfo("Updating hooks...");
|
|
975
|
+
logInfo("Updating hooks and rules...");
|
|
779
976
|
await installHooks(projectDir, true);
|
|
977
|
+
installToolRules(projectDir, configResults);
|
|
780
978
|
|
|
781
979
|
// Also run auto-update to install any new hook types (gotcha-check, implicit-progress)
|
|
782
980
|
try {
|
|
@@ -937,6 +1135,30 @@ export async function runSetup(argv: string[]) {
|
|
|
937
1135
|
logInfo(`Project directory: ${shortenPath(projectDir)}`);
|
|
938
1136
|
const projectConfig = await createProjectConfig(projectDir, apiKey, args.projectId);
|
|
939
1137
|
|
|
1138
|
+
// ── Step 5b: Apply stack template if detected ──────────────────
|
|
1139
|
+
if (projectConfig.stack) {
|
|
1140
|
+
const stackName = STACK_DETECT.find(s => s.id === projectConfig.stack)?.name || projectConfig.stack;
|
|
1141
|
+
let shouldApply = true;
|
|
1142
|
+
|
|
1143
|
+
if (!args.nonInteractive) {
|
|
1144
|
+
const answer = await askQuestion(
|
|
1145
|
+
` Apply ${c("bold", stackName)} starter template (gotchas + tasks)? [Y/n] `,
|
|
1146
|
+
"y"
|
|
1147
|
+
);
|
|
1148
|
+
shouldApply = answer.toLowerCase() !== "n";
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
if (shouldApply) {
|
|
1152
|
+
logInfo(`Applying ${stackName} stack template...`);
|
|
1153
|
+
const applied = await applyStackTemplate(apiKey, projectConfig.projectId, projectConfig.stack);
|
|
1154
|
+
if (applied) {
|
|
1155
|
+
logSuccess(`${stackName} gotchas and task template seeded`);
|
|
1156
|
+
} else {
|
|
1157
|
+
logSkip("Stack template will be available via: everstate({ action: 'project.apply_stack_template', params: { stack: '" + projectConfig.stack + "' } })");
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
|
|
940
1162
|
// ── Step 6: Install hooks ────────────────────────────────────────
|
|
941
1163
|
if (!args.skipHooks) {
|
|
942
1164
|
await installHooks(projectDir, args.force);
|
|
@@ -945,8 +1167,9 @@ export async function runSetup(argv: string[]) {
|
|
|
945
1167
|
// ── Step 7: Update .gitignore ────────────────────────────────────
|
|
946
1168
|
updateGitignore(projectDir);
|
|
947
1169
|
|
|
948
|
-
// ── Step 8: Create
|
|
1170
|
+
// ── Step 8: Create rules files for detected tools ──────────────────
|
|
949
1171
|
ensureClaudeMd(projectDir);
|
|
1172
|
+
installToolRules(projectDir, configResults);
|
|
950
1173
|
|
|
951
1174
|
// ── Step 9: Write version file ───────────────────────────────────
|
|
952
1175
|
const versionFile = createVersionFile("setup");
|
|
@@ -974,7 +1197,7 @@ export async function runSetup(argv: string[]) {
|
|
|
974
1197
|
}
|
|
975
1198
|
|
|
976
1199
|
// ── Summary ──────────────────────────────────────────────────────
|
|
977
|
-
printSetupSummary(configResults, projectDir, apiKey);
|
|
1200
|
+
printSetupSummary(configResults, projectDir, apiKey, projectConfig.stack);
|
|
978
1201
|
} catch (error: any) {
|
|
979
1202
|
logError(`Setup failed: ${error.message}`);
|
|
980
1203
|
process.exit(1);
|