Skip to content

Commit 359615c

Browse files
committed
feat: cursor file changes
1 parent 8dc12e1 commit 359615c

File tree

5 files changed

+78
-53
lines changed

5 files changed

+78
-53
lines changed

packages/blade-mcp/src/tools/createBladeCursorRules.ts

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import { join, basename } from 'path';
2-
import { existsSync, unlinkSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
2+
import { readFileSync } from 'fs';
33
import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';
44
import { z } from 'zod';
55
import {
66
BLADE_CURSOR_RULES_FILE_PATH,
77
CURSOR_RULES_VERSION,
88
analyticsToolCallEventName,
9+
getCursorRulesFileName,
910
} from '../utils/tokens.js';
1011

11-
import { hasOutDatedRules } from '../utils/generalUtils.js';
1212
import { handleError, sendAnalytics } from '../utils/analyticsUtils.js';
1313

1414
const createBladeCursorRulesToolName = 'create_blade_cursor_rules';
1515

1616
const createBladeCursorRulesToolDescription =
17-
'Creates the cursor rules for blade to help with code generation. Call this before get_blade_docs and while creating a new blade project (only when using cursor and when the frontend-blade-rules.mdc rule does not already exist).';
17+
'Creates the cursor rules for blade to help with code generation. Returns the cursor rules file content that should be created. Call this before get_blade_docs and while creating a new blade project (only when using cursor and when the frontend-blade-rules-v{version}.mdc rule does not already exist).';
1818

1919
const createBladeCursorRulesToolSchema = {
2020
currentProjectRootDirectory: z
@@ -29,30 +29,15 @@ const createBladeCursorRulesToolCallback: ToolCallback<typeof createBladeCursorR
2929
}) => {
3030
try {
3131
const ruleFileDir = join(currentProjectRootDirectory, '.cursor/rules');
32-
const ruleFilePath = join(ruleFileDir, 'frontend-blade-rules.mdc');
33-
34-
if (existsSync(ruleFilePath)) {
35-
if (hasOutDatedRules(ruleFilePath)) {
36-
// removes the outdated rules file and continues execution to generate new rule file
37-
unlinkSync(ruleFilePath);
38-
} else {
39-
return {
40-
content: [{ type: 'text', text: 'Cursor rules already exist. Doing nothing' }],
41-
};
42-
}
43-
}
32+
const cursorRulesFileName = getCursorRulesFileName();
33+
const ruleFilePath = join(ruleFileDir, cursorRulesFileName);
4434

35+
// Read the cursor rules template from the package's cursorRules directory
4536
const ruleFileTemplateContent = readFileSync(BLADE_CURSOR_RULES_FILE_PATH, 'utf8').replace(
4637
'rules_version: <!-- dynamic_version -->',
4738
`rules_version: ${CURSOR_RULES_VERSION}`,
4839
);
4940

50-
if (!existsSync(ruleFileDir)) {
51-
mkdirSync(ruleFileDir, { recursive: true });
52-
}
53-
54-
writeFileSync(ruleFilePath, ruleFileTemplateContent);
55-
5641
sendAnalytics({
5742
eventName: analyticsToolCallEventName,
5843
properties: {
@@ -66,7 +51,21 @@ const createBladeCursorRulesToolCallback: ToolCallback<typeof createBladeCursorR
6651
content: [
6752
{
6853
type: 'text',
69-
text: `Blade cursor rules created at: ${ruleFilePath}. Cursor Rules Version: ${CURSOR_RULES_VERSION}`,
54+
text: `## Blade Cursor Rules File Content
55+
56+
**File Path:** \`${ruleFilePath}\`
57+
58+
**Instructions:**
59+
1. Create the directory if it doesn't exist: \`.cursor/rules/\`
60+
2. Create a new file named \`${cursorRulesFileName}\` in that directory .
61+
3. if their is any other file with name frontend-blade-rules-v{version}.mdc delete it first and create a new file. it should only have 1 file with frontend-blade-rules
62+
4. Copy the content below into the file
63+
64+
**Cursor Rules Version:** ${CURSOR_RULES_VERSION}
65+
66+
---
67+
68+
${ruleFileTemplateContent}`,
7069
},
7170
],
7271
};

packages/blade-mcp/src/tools/getBladeComponentDocs.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
import { join, basename } from 'path';
2-
import { existsSync } from 'fs';
1+
import { basename } from 'path';
32
import { z } from 'zod';
43
import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';
5-
import {
6-
CONSUMER_CURSOR_RULES_RELATIVE_PATH,
7-
analyticsToolCallEventName,
8-
} from '../utils/tokens.js';
9-
import { hasOutDatedRules, getBladeDocsList } from '../utils/generalUtils.js';
4+
import { analyticsToolCallEventName, getCursorRulesFileName } from '../utils/tokens.js';
5+
import { getBladeDocsList } from '../utils/generalUtils.js';
106
import { handleError, sendAnalytics } from '../utils/analyticsUtils.js';
117

128
import { getBladeDocsResponseText } from '../utils/getBladeDocsResponseText.js';
@@ -30,12 +26,18 @@ const getBladeComponentDocsToolSchema = {
3026
"The working root directory of the consumer's project. Do not use root directory, do not use '.', only use absolute path to current directory",
3127
),
3228
clientName: z.enum(['claude', 'cursor', 'unknown']).default('unknown'),
29+
cursorRuleFileName: z
30+
.string()
31+
.describe(
32+
'get the name of blade cursor rules file. You can use grep to find it: `grep -l "rules_version:" .cursor/rules/*.mdc` or search for files matching `frontend-blade-rules-v*.mdc` in `.cursor/rules/` directory and then trim the string for the last name and the .mdc extension (e.g., "frontend-blade-rules-v0.0.8"). if nothing is found send 0',
33+
),
3334
};
3435

3536
const getBladeComponentDocsToolCallback: ToolCallback<typeof getBladeComponentDocsToolSchema> = ({
3637
componentsList,
3738
currentProjectRootDirectory,
3839
clientName,
40+
cursorRuleFileName,
3941
}) => {
4042
const components = componentsList.split(',').map((s) => s.trim());
4143
const invalidComponents = components.filter((comp) => !bladeComponentsList.includes(comp));
@@ -47,19 +49,18 @@ const getBladeComponentDocsToolCallback: ToolCallback<typeof getBladeComponentDo
4749
});
4850
}
4951

50-
const ruleFilePath = join(currentProjectRootDirectory, CONSUMER_CURSOR_RULES_RELATIVE_PATH);
51-
52-
if (!existsSync(ruleFilePath) && clientName === 'cursor') {
52+
if (cursorRuleFileName === '0' && clientName === 'cursor') {
5353
return handleError({
5454
toolName: getBladeComponentDocsToolName,
5555
mcpErrorMessage: `Cursor rules do not exist. Call \`${createBladeCursorRulesToolName}\` first.`,
5656
});
5757
}
5858

59-
if (hasOutDatedRules(ruleFilePath) && clientName === 'cursor') {
59+
const expectedFileName = getCursorRulesFileName().replace('.mdc', '');
60+
if (cursorRuleFileName !== expectedFileName && clientName === 'cursor') {
6061
return handleError({
6162
toolName: getBladeComponentDocsToolName,
62-
mcpErrorMessage: `Cursor rules are outdated. Call \`${createBladeCursorRulesToolName}\` first to update cursor rules`,
63+
mcpErrorMessage: `Cursor rules are outdated. Expected file name: ${expectedFileName}.mdc. Call \`${createBladeCursorRulesToolName}\` first to update cursor rules`,
6364
});
6465
}
6566

packages/blade-mcp/src/tools/getBladeGeneralDocs.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
import { existsSync, readFileSync } from 'fs';
1+
import { readFileSync } from 'fs';
22
import { join, basename } from 'path';
33
import { z } from 'zod';
44
import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';
55
import {
6-
CONSUMER_CURSOR_RULES_RELATIVE_PATH,
76
analyticsToolCallEventName,
87
GENERAL_KNOWLEDGEBASE_DIRECTORY,
8+
getCursorRulesFileName,
99
} from '../utils/tokens.js';
1010

11-
import { getBladeDocsList, hasOutDatedRules } from '../utils/generalUtils.js';
11+
import { getBladeDocsList } from '../utils/generalUtils.js';
1212
import { handleError, sendAnalytics } from '../utils/analyticsUtils.js';
1313
import { getBladeDocsResponseText } from '../utils/getBladeDocsResponseText.js';
14+
import { createBladeCursorRulesToolName } from './createBladeCursorRules.js';
1415

1516
const bladeGeneralDocsList = getBladeDocsList('general');
1617

@@ -36,11 +37,19 @@ const getBladeGeneralDocsToolSchema = {
3637
.describe(
3738
"The working root directory of the consumer's project. Do not use root directory, do not use '.', only use absolute path to current directory",
3839
),
40+
clientName: z.enum(['claude', 'cursor', 'unknown']).default('unknown'),
41+
cursorRuleFileName: z
42+
.string()
43+
.describe(
44+
'get the name of blade cursor rules file. You can use grep to find it: `grep -l "rules_version:" .cursor/rules/*.mdc` or search for files matching `frontend-blade-rules-v*.mdc` in `.cursor/rules/` directory and then trim the string for the last name and the .mdc extension (e.g., "frontend-blade-rules-v0.0.8"). if nothing is found send 0',
45+
),
3946
};
4047

4148
const getBladeGeneralDocsToolCallback: ToolCallback<typeof getBladeGeneralDocsToolSchema> = ({
4249
topicsList,
4350
currentProjectRootDirectory,
51+
clientName,
52+
cursorRuleFileName,
4453
}) => {
4554
const topics = topicsList.split(',').map((s) => s.trim());
4655
const invalidTopics = topics.filter((topic) => !bladeGeneralDocsList.includes(topic));
@@ -53,19 +62,18 @@ const getBladeGeneralDocsToolCallback: ToolCallback<typeof getBladeGeneralDocsTo
5362
});
5463
}
5564

56-
const ruleFilePath = join(currentProjectRootDirectory, CONSUMER_CURSOR_RULES_RELATIVE_PATH);
57-
58-
if (!existsSync(ruleFilePath)) {
65+
if (cursorRuleFileName === '0' && clientName === 'cursor') {
5966
return handleError({
6067
toolName: getBladeGeneralDocsToolName,
61-
mcpErrorMessage: 'Cursor rules do not exist. Call create_blade_cursor_rules first.',
68+
mcpErrorMessage: `Cursor rules do not exist. Call \`${createBladeCursorRulesToolName}\` first.`,
6269
});
6370
}
6471

65-
if (hasOutDatedRules(ruleFilePath)) {
72+
const expectedFileName = getCursorRulesFileName().replace('.mdc', '');
73+
if (cursorRuleFileName !== expectedFileName && clientName === 'cursor') {
6674
return handleError({
6775
toolName: getBladeGeneralDocsToolName,
68-
mcpErrorMessage: 'Cursor rules are outdated. Call create_blade_cursor_rules first.',
76+
mcpErrorMessage: `Cursor rules are outdated. Expected file name: ${expectedFileName}.mdc. Call \`${createBladeCursorRulesToolName}\` first to update cursor rules`,
6977
});
7078
}
7179

@@ -81,6 +89,7 @@ const getBladeGeneralDocsToolCallback: ToolCallback<typeof getBladeGeneralDocsTo
8189
toolName: getBladeGeneralDocsToolName,
8290
topicsList,
8391
rootDirectoryName: basename(currentProjectRootDirectory),
92+
clientName,
8493
},
8594
});
8695

packages/blade-mcp/src/tools/getBladePatternDocs.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
import { existsSync, readFileSync } from 'fs';
1+
import { readFileSync } from 'fs';
22
import { join, basename } from 'path';
33
import { z } from 'zod';
44
import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';
55
import {
6-
CONSUMER_CURSOR_RULES_RELATIVE_PATH,
76
analyticsToolCallEventName,
87
PATTERNS_KNOWLEDGEBASE_DIRECTORY,
8+
getCursorRulesFileName,
99
} from '../utils/tokens.js';
1010

11-
import { getBladeDocsList, hasOutDatedRules } from '../utils/generalUtils.js';
11+
import { getBladeDocsList } from '../utils/generalUtils.js';
1212
import { handleError, sendAnalytics } from '../utils/analyticsUtils.js';
1313
import { getBladeDocsResponseText } from '../utils/getBladeDocsResponseText.js';
1414
import { getBladeComponentDocsToolName } from './getBladeComponentDocs.js';
15+
import { createBladeCursorRulesToolName } from './createBladeCursorRules.js';
1516

1617
const bladePatternsList = getBladeDocsList('patterns');
1718
const whichPatternToUseGuide = readFileSync(
@@ -36,11 +37,19 @@ const getBladePatternDocsToolSchema = {
3637
.describe(
3738
"The working root directory of the consumer's project. Do not use root directory, do not use '.', only use absolute path to current directory",
3839
),
40+
clientName: z.enum(['claude', 'cursor', 'unknown']).default('unknown'),
41+
cursorRuleFileName: z
42+
.string()
43+
.describe(
44+
'get the name of blade cursor rules file. You can use grep to find it: `grep -l "rules_version:" .cursor/rules/*.mdc` or search for files matching `frontend-blade-rules-v*.mdc` in `.cursor/rules/` directory and then trim the string for the last name and the .mdc extension (e.g., "frontend-blade-rules-v0.0.8"). if nothing is found send 0',
45+
),
3946
};
4047

4148
const getBladePatternDocsToolCallback: ToolCallback<typeof getBladePatternDocsToolSchema> = ({
4249
patternsList,
4350
currentProjectRootDirectory,
51+
clientName,
52+
cursorRuleFileName,
4453
}) => {
4554
const components = patternsList.split(',').map((s) => s.trim());
4655
const invalidComponents = components.filter((comp) => !bladePatternsList.includes(comp));
@@ -55,19 +64,18 @@ const getBladePatternDocsToolCallback: ToolCallback<typeof getBladePatternDocsTo
5564
});
5665
}
5766

58-
const ruleFilePath = join(currentProjectRootDirectory, CONSUMER_CURSOR_RULES_RELATIVE_PATH);
59-
60-
if (!existsSync(ruleFilePath)) {
67+
if (cursorRuleFileName === '0' && clientName === 'cursor') {
6168
return handleError({
6269
toolName: getBladePatternDocsToolName,
63-
mcpErrorMessage: 'Cursor rules do not exist. Call create_blade_cursor_rules first.',
70+
mcpErrorMessage: `Cursor rules do not exist. Call \`${createBladeCursorRulesToolName}\` first.`,
6471
});
6572
}
6673

67-
if (hasOutDatedRules(ruleFilePath)) {
74+
const expectedFileName = getCursorRulesFileName().replace('.mdc', '');
75+
if (cursorRuleFileName !== expectedFileName && clientName === 'cursor') {
6876
return handleError({
6977
toolName: getBladePatternDocsToolName,
70-
mcpErrorMessage: 'Cursor rules are outdated. Call create_blade_cursor_rules first.',
78+
mcpErrorMessage: `Cursor rules are outdated. Expected file name: ${expectedFileName}.mdc. Call \`${createBladeCursorRulesToolName}\` first to update cursor rules`,
7179
});
7280
}
7381

@@ -84,6 +92,7 @@ const getBladePatternDocsToolCallback: ToolCallback<typeof getBladePatternDocsTo
8492
toolName: getBladePatternDocsToolName,
8593
patternsList,
8694
rootDirectoryName: basename(currentProjectRootDirectory),
95+
clientName,
8796
},
8897
});
8998

packages/blade-mcp/src/utils/tokens.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ const BLADE_CURSOR_RULES_FILE_PATH = join(
1616
CURSOR_RULES_TEMPLATE_DIRECTORY,
1717
'frontend-blade-rules.mdc',
1818
);
19-
const CONSUMER_CURSOR_RULES_RELATIVE_PATH = '.cursor/rules/frontend-blade-rules.mdc';
19+
20+
// Generate cursor rules file name with version
21+
const getCursorRulesFileName = (): string => {
22+
return `frontend-blade-rules-v${CURSOR_RULES_VERSION}.mdc`;
23+
};
24+
25+
const CONSUMER_CURSOR_RULES_RELATIVE_PATH = `.cursor/rules/${getCursorRulesFileName()}`;
2026

2127
// Blade Template
2228
const BASE_BLADE_TEMPLATE_DIRECTORY = join(PROJECT_ROOT_DIRECTORY, 'base-blade-template');
@@ -40,4 +46,5 @@ export {
4046
PATTERNS_KNOWLEDGEBASE_DIRECTORY,
4147
GENERAL_KNOWLEDGEBASE_DIRECTORY,
4248
analyticsToolCallEventName,
49+
getCursorRulesFileName,
4350
};

0 commit comments

Comments
 (0)