Skip to content

Commit e05eacb

Browse files
saurabhdawareanuraghazratewarig
authored
feat(blade-mcp): add streamable transport and export (#2876)
* feat: add streamable server utils * feat: add export * feat: add sentry to utils * Create shy-pianos-count.md * chore: add back loc metric call * chore: update pkg * chore: update create_new_blade_project tool * feat(blade-mcp): blade mcp http server support (#3003) * fix: blade sse * fix: add cursor agent name * Update packages/blade-mcp/src/tools/getBladeComponentDocs.ts Co-authored-by: Anurag Hazra <[email protected]> * fix: update mcp server & tools * feat: cursor file changes * feat: ask cursor to get filename * fix: update cursor file name token --no-verfiy * chore: remove comments * feat: use grep * feat: refactor more cursor code * feat: update change log * feat: update cursor rule * chore: remove bash file * feat: userName refactor * feat: add mcp context * refactor: mcp sse context * refactor: reveiw changes & code refactor * refactor: more code * chore: more refactor * chore: update file --------- Co-authored-by: Anurag Hazra <[email protected]> * chore: rename isCursorRuleFileMissing --------- Co-authored-by: anuraghazra <[email protected]> Co-authored-by: Gaurav Tewari <[email protected]>
1 parent 7a8d1e7 commit e05eacb

24 files changed

+462
-255
lines changed

.changeset/shy-pianos-count.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@razorpay/blade-mcp": minor
3+
---
4+
5+
feat(blade-mcp): add streamable transport support utilities

.changeset/small-bobcats-attend.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@razorpay/blade-mcp': minor
3+
---
4+
5+
feat(blade-mcp): refactor `createCursorRule` , `getBladeComponentDocs` , `getBladeGeneralDocs` , `getBladePatternDocs` tools to support MCP SSE
File renamed without changes.

packages/blade-mcp/cursorRules/frontend-blade-rules.mdc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
description:
33
globs:
44
alwaysApply: true
5-
rules_version: <!-- dynamic_version -->
5+
rules_version: 0.0.8
66
---
77

88
You are Razorpay's Frontend Engineer who knows how to use our design system called "blade". Rather than using outdated knowledge of blade, you effectively use Blade MCP to learn things about blade components before answering questions or creating / updating UI code. When asked to write some frontend code, you always prefer blade components over custom components to bring consistency in the UI.

packages/blade-mcp/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "@razorpay/blade-mcp",
33
"version": "1.14.0",
44
"description": "Model Context Protocol server for Blade",
5-
"main": "dist/server.js",
5+
"main": "dist/exports.js",
66
"type": "module",
77
"bin": "dist/server.js",
88
"publishConfig": {
@@ -36,7 +36,7 @@
3636
"author": "Razorpay",
3737
"license": "MIT",
3838
"dependencies": {
39-
"@modelcontextprotocol/sdk": "1.11.0",
39+
"@modelcontextprotocol/sdk": "1.20.2",
4040
"zod": "3.24.3",
4141
"dedent": "1.6.0",
4242
"@sentry/node": "9.19.0",
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2+
import {
3+
createNewBladeProjectToolName,
4+
createNewBladeProjectToolDescription,
5+
createNewBladeProjectToolSchema,
6+
createNewBladeProjectToolCallback,
7+
} from './tools/createNewBladeProject.js';
8+
import {
9+
createBladeCursorRulesToolName,
10+
createBladeCursorRulesToolDescription,
11+
createBladeCursorRulesToolSchema,
12+
createBladeCursorRulesToolCallback,
13+
} from './tools/createBladeCursorRules.js';
14+
import {
15+
getBladeComponentDocsToolName,
16+
getBladeComponentDocsToolDescription,
17+
getBladeComponentDocsToolSchema,
18+
getBladeComponentDocsToolCallback,
19+
} from './tools/getBladeComponentDocs.js';
20+
import {
21+
hiBladeToolName,
22+
hiBladeToolDescription,
23+
hiBladeToolSchema,
24+
hiBladeToolCallback,
25+
} from './tools/hiBlade.js';
26+
import { getPackageJSONVersion } from './utils/generalUtils.js';
27+
import {
28+
getBladePatternDocsToolName,
29+
getBladePatternDocsToolDescription,
30+
getBladePatternDocsToolSchema,
31+
getBladePatternDocsToolCallback,
32+
} from './tools/getBladePatternDocs.js';
33+
import {
34+
getBladeGeneralDocsToolName,
35+
getBladeGeneralDocsToolDescription,
36+
getBladeGeneralDocsToolSchema,
37+
getBladeGeneralDocsToolCallback,
38+
} from './tools/getBladeGeneralDocs.js';
39+
import {
40+
getFigmaToCodeToolName,
41+
getFigmaToCodeToolDescription,
42+
getFigmaToCodeToolSchema,
43+
getFigmaToCodeToolCallback,
44+
} from './tools/getFigmaToCode.js';
45+
import {
46+
getChangelogToolName,
47+
getChangelogToolDescription,
48+
getChangelogToolSchema,
49+
getChangelogToolCallback,
50+
} from './tools/getChangelog.js';
51+
import {
52+
publishLinesOfCodeMetricToolName,
53+
publishLinesOfCodeMetricToolDescription,
54+
publishLinesOfCodeMetricToolSchema,
55+
publishLinesOfCodeMetricToolCallback,
56+
} from './tools/publishLinesOfCodeMetric.js';
57+
58+
export const createServer = (): McpServer => {
59+
const server = new McpServer({
60+
name: 'Blade MCP',
61+
version: getPackageJSONVersion(),
62+
});
63+
64+
server.tool(hiBladeToolName, hiBladeToolDescription, hiBladeToolSchema, hiBladeToolCallback);
65+
66+
server.tool(
67+
createNewBladeProjectToolName,
68+
createNewBladeProjectToolDescription,
69+
createNewBladeProjectToolSchema,
70+
createNewBladeProjectToolCallback,
71+
);
72+
73+
server.tool(
74+
createBladeCursorRulesToolName,
75+
createBladeCursorRulesToolDescription,
76+
createBladeCursorRulesToolSchema,
77+
createBladeCursorRulesToolCallback,
78+
);
79+
80+
server.tool(
81+
getBladeComponentDocsToolName,
82+
getBladeComponentDocsToolDescription,
83+
getBladeComponentDocsToolSchema,
84+
getBladeComponentDocsToolCallback,
85+
);
86+
87+
server.tool(
88+
getBladePatternDocsToolName,
89+
getBladePatternDocsToolDescription,
90+
getBladePatternDocsToolSchema,
91+
getBladePatternDocsToolCallback,
92+
);
93+
94+
server.tool(
95+
getBladeGeneralDocsToolName,
96+
getBladeGeneralDocsToolDescription,
97+
getBladeGeneralDocsToolSchema,
98+
getBladeGeneralDocsToolCallback,
99+
);
100+
101+
server.tool(
102+
getFigmaToCodeToolName,
103+
getFigmaToCodeToolDescription,
104+
getFigmaToCodeToolSchema,
105+
getFigmaToCodeToolCallback,
106+
);
107+
108+
server.tool(
109+
getChangelogToolName,
110+
getChangelogToolDescription,
111+
getChangelogToolSchema,
112+
getChangelogToolCallback,
113+
);
114+
115+
server.tool(
116+
publishLinesOfCodeMetricToolName,
117+
publishLinesOfCodeMetricToolDescription,
118+
publishLinesOfCodeMetricToolSchema,
119+
publishLinesOfCodeMetricToolCallback,
120+
);
121+
122+
return server;
123+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
3+
import type { StreamableHTTPServerTransportOptions } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
4+
5+
export const createStdioTransport = (): StdioServerTransport => {
6+
const transport = new StdioServerTransport();
7+
return transport;
8+
};
9+
10+
/**
11+
* Creating streamable http transport for Blade MCP server.
12+
*
13+
* ```
14+
* import { createServer, createStreamableHttpTransport } from '@razorpay/blade-mcp';
15+
*
16+
* const server = createServer();
17+
*
18+
* // somewhere in your nodejs server. Refer to https://github.com/modelcontextprotocol/typescript-sdk?tab=readme-ov-file#streamable-http
19+
* const transport = createStreamableHttpTransport();
20+
* server.connect(transport);
21+
* ```
22+
*/
23+
export const createStreamableHttpTransport = (
24+
options: StreamableHTTPServerTransportOptions,
25+
): StreamableHTTPServerTransport => {
26+
const transport = new StreamableHTTPServerTransport(options);
27+
return transport;
28+
};

packages/blade-mcp/src/exports.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { createServer } from './createServer.js';
2+
import { createStdioTransport, createStreamableHttpTransport } from './createTransport.js';
3+
import { captureException, initSentry } from './utils/sentryUtils.js';
4+
import { setMcpSseAnalyticsContext } from './utils/analyticsUtils.js';
5+
6+
export {
7+
createServer,
8+
createStdioTransport,
9+
createStreamableHttpTransport,
10+
captureException,
11+
initSentry,
12+
setMcpSseAnalyticsContext,
13+
};

packages/blade-mcp/src/replaceEnv.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const __filename = fileURLToPath(import.meta.url);
99
const __dirname = path.dirname(__filename);
1010

1111
// Define the paths to the files to be replaced
12-
const SERVER_JS_PATH = path.resolve(__dirname, '../dist/server.js');
12+
const SENTRY_UTILS_JS_PATH = path.resolve(__dirname, '../dist/utils/sentryUtils.js');
1313
const FIGMA_TO_CODE_JS_PATH = path.resolve(__dirname, '../dist/tools/getFigmaToCode.js');
1414
const ANALYTICS_UTILS_JS_PATH = path.resolve(__dirname, '../dist/utils/analyticsUtils.js');
1515

@@ -39,7 +39,7 @@ function replaceInFileSync(filePath, replacements) {
3939
async function replaceEnvironmentVariables() {
4040
try {
4141
// Replace NODE_ENV and SENTRY_DSN in server.js
42-
replaceInFileSync(SERVER_JS_PATH, [
42+
replaceInFileSync(SENTRY_UTILS_JS_PATH, [
4343
{
4444
from: /process\.env\.NODE_ENV\s*\?\?\s*['"]development['"]/g,
4545
to: `'${NODE_ENV}'`,

packages/blade-mcp/src/server.ts

Lines changed: 7 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,145 +1,19 @@
11
#!/usr/bin/env node
22

3-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5-
import * as Sentry from '@sentry/node';
6-
import {
7-
createNewBladeProjectToolName,
8-
createNewBladeProjectToolDescription,
9-
createNewBladeProjectToolSchema,
10-
createNewBladeProjectToolCallback,
11-
} from './tools/createNewBladeProject.js';
12-
import {
13-
createBladeCursorRulesToolName,
14-
createBladeCursorRulesToolDescription,
15-
createBladeCursorRulesToolSchema,
16-
createBladeCursorRulesToolCallback,
17-
} from './tools/createBladeCursorRules.js';
18-
import {
19-
getBladeComponentDocsToolName,
20-
getBladeComponentDocsToolDescription,
21-
getBladeComponentDocsToolSchema,
22-
getBladeComponentDocsToolCallback,
23-
} from './tools/getBladeComponentDocs.js';
24-
import {
25-
hiBladeToolName,
26-
hiBladeToolDescription,
27-
hiBladeToolSchema,
28-
hiBladeToolCallback,
29-
} from './tools/hiBlade.js';
30-
import { getPackageJSONVersion } from './utils/generalUtils.js';
31-
import {
32-
getBladePatternDocsToolName,
33-
getBladePatternDocsToolDescription,
34-
getBladePatternDocsToolSchema,
35-
getBladePatternDocsToolCallback,
36-
} from './tools/getBladePatternDocs.js';
37-
import {
38-
getBladeGeneralDocsToolName,
39-
getBladeGeneralDocsToolDescription,
40-
getBladeGeneralDocsToolSchema,
41-
getBladeGeneralDocsToolCallback,
42-
} from './tools/getBladeGeneralDocs.js';
43-
import {
44-
getFigmaToCodeToolName,
45-
getFigmaToCodeToolDescription,
46-
getFigmaToCodeToolSchema,
47-
getFigmaToCodeToolCallback,
48-
} from './tools/getFigmaToCode.js';
49-
import {
50-
getChangelogToolName,
51-
getChangelogToolDescription,
52-
getChangelogToolSchema,
53-
getChangelogToolCallback,
54-
} from './tools/getChangelog.js';
55-
import {
56-
publishLinesOfCodeMetricToolName,
57-
publishLinesOfCodeMetricToolDescription,
58-
publishLinesOfCodeMetricToolSchema,
59-
publishLinesOfCodeMetricToolCallback,
60-
} from './tools/publishLinesOfCodeMetric.js';
3+
import { createServer } from './createServer.js';
4+
import { createStdioTransport } from './createTransport.js';
5+
import { captureException, initSentry } from './utils/sentryUtils.js';
616

62-
Sentry.init({
63-
dsn: process.env.BLADE_MCP_SENTRY_DSN,
64-
environment: process.env.NODE_ENV ?? 'development',
65-
release: getPackageJSONVersion(),
66-
sendDefaultPii: false,
67-
});
7+
initSentry();
688

699
try {
70-
const server = new McpServer({
71-
name: 'Blade MCP',
72-
version: getPackageJSONVersion(),
73-
});
74-
75-
server.tool(hiBladeToolName, hiBladeToolDescription, hiBladeToolSchema, hiBladeToolCallback);
76-
77-
server.tool(
78-
createNewBladeProjectToolName,
79-
createNewBladeProjectToolDescription,
80-
createNewBladeProjectToolSchema,
81-
createNewBladeProjectToolCallback,
82-
);
83-
84-
server.tool(
85-
createBladeCursorRulesToolName,
86-
createBladeCursorRulesToolDescription,
87-
createBladeCursorRulesToolSchema,
88-
createBladeCursorRulesToolCallback,
89-
);
90-
91-
server.tool(
92-
getBladeComponentDocsToolName,
93-
getBladeComponentDocsToolDescription,
94-
getBladeComponentDocsToolSchema,
95-
getBladeComponentDocsToolCallback,
96-
);
97-
98-
server.tool(
99-
getBladePatternDocsToolName,
100-
getBladePatternDocsToolDescription,
101-
getBladePatternDocsToolSchema,
102-
getBladePatternDocsToolCallback,
103-
);
104-
105-
server.tool(
106-
getBladeGeneralDocsToolName,
107-
getBladeGeneralDocsToolDescription,
108-
getBladeGeneralDocsToolSchema,
109-
getBladeGeneralDocsToolCallback,
110-
);
111-
112-
server.tool(
113-
getFigmaToCodeToolName,
114-
getFigmaToCodeToolDescription,
115-
getFigmaToCodeToolSchema,
116-
getFigmaToCodeToolCallback,
117-
);
118-
119-
server.tool(
120-
getChangelogToolName,
121-
getChangelogToolDescription,
122-
getChangelogToolSchema,
123-
getChangelogToolCallback,
124-
);
125-
126-
server.tool(
127-
publishLinesOfCodeMetricToolName,
128-
publishLinesOfCodeMetricToolDescription,
129-
publishLinesOfCodeMetricToolSchema,
130-
publishLinesOfCodeMetricToolCallback,
131-
);
132-
133-
// Start receiving messages on stdin and sending messages on stdout
134-
const transport = new StdioServerTransport();
135-
136-
// Use Promise handling for async operations
10+
const server = createServer();
11+
const transport = createStdioTransport();
13712
await server.connect(transport);
138-
13913
// Why console.error? Checkout https://modelcontextprotocol.io/quickstart/server#logging-in-mcp-servers-2
14014
console.error('Blade MCP connected successfully.');
14115
} catch (error: unknown) {
142-
Sentry.captureException(error);
16+
captureException(error);
14317
console.error('Blade MCP Error', error);
14418
process.exit(1);
14519
}

0 commit comments

Comments
 (0)