Skip to content

Commit d1b5631

Browse files
committed
feat: improve discoverability of MCP in 10xRules
1 parent 2d17b65 commit d1b5631

File tree

4 files changed

+165
-7
lines changed

4 files changed

+165
-7
lines changed

src/components/rule-builder/RuleBuilder.tsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import { Trash2 } from 'lucide-react';
1+
import { Trash2, Unplug } from 'lucide-react';
22
import React, { useEffect, useRef } from 'react';
33
import { transitions } from '../../styles/theme';
44
import { Accordion } from '../ui/Accordion';
55
import { useRuleBuilder } from './hooks/useRuleBuilder';
6+
import { useMCPDialog } from './hooks/useMCPDialog';
67
import { LayerItem } from './LayerItem';
8+
import { MCPDialog } from './modals/MCPDialog';
79
import { SearchInput } from './SearchInput';
810
import { SelectedRules } from './SelectedRules';
911

@@ -48,6 +50,9 @@ export const RuleBuilder: React.FC<RuleBuilderProps> = ({ className = '' }) => {
4850
const tooltipRef = useRef<HTMLDivElement>(null);
4951
const tooltipTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
5052

53+
// Use the custom hook for MCPDialog state
54+
const { isMCPDialogOpen, showMCPInstructions, hideMCPInstructions } = useMCPDialog();
55+
5156
// Calculate if we need to show "no results" message
5257
const hasNoSearchResults =
5358
isSearchActive && layers.every((layer) => !layerContainsSearchMatch(layer));
@@ -90,16 +95,26 @@ export const RuleBuilder: React.FC<RuleBuilderProps> = ({ className = '' }) => {
9095
<div className="flex justify-between items-center mb-4">
9196
<h2 className="text-xl font-semibold text-white">Rule Builder</h2>
9297

93-
{selectedLibraries.length > 0 && (
98+
<div className="flex flex-row gap-2">
9499
<button
95-
onClick={handleClearAll}
100+
onClick={showMCPInstructions}
96101
className="flex gap-2 items-center px-3 py-1.5 text-sm bg-gray-800/50 rounded-md transition-colors hover:bg-gray-700/50 text-gray-400 cursor-pointer hover:shadow-sm"
97102
title="Clear all selections"
98103
>
99-
<Trash2 className="size-4" />
100-
<span>Clear all</span>
104+
<Unplug className="size-4" />
105+
<span>Use MCP</span>
101106
</button>
102-
)}
107+
{selectedLibraries.length > 0 && (
108+
<button
109+
onClick={handleClearAll}
110+
className="flex gap-2 items-center px-3 py-1.5 text-sm bg-orange-800/50 rounded-md transition-colors hover:bg-orange-700/50 text-orange-400 cursor-pointer hover:shadow-sm"
111+
title="Clear all selections"
112+
>
113+
<Trash2 className="size-4" />
114+
<span>Clear all</span>
115+
</button>
116+
)}
117+
</div>
103118
</div>
104119

105120
<div ref={searchContainerRef} className="w-full">
@@ -173,6 +188,9 @@ export const RuleBuilder: React.FC<RuleBuilderProps> = ({ className = '' }) => {
173188
unselectLibrary={unselectLibrary}
174189
getLibraryLayerType={getLibraryLayerType}
175190
/>
191+
192+
{/* Render MCPDialog */}
193+
<MCPDialog isOpen={isMCPDialogOpen} onClose={hideMCPInstructions} />
176194
</div>
177195
);
178196
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { useState } from 'react';
2+
3+
export const useMCPDialog = () => {
4+
const [isMCPDialogOpen, setIsMCPDialogOpen] = useState(false);
5+
6+
const showMCPInstructions = () => {
7+
setIsMCPDialogOpen(true);
8+
};
9+
10+
const hideMCPInstructions = () => {
11+
setIsMCPDialogOpen(false);
12+
};
13+
14+
return {
15+
isMCPDialogOpen,
16+
showMCPInstructions,
17+
hideMCPInstructions,
18+
};
19+
};
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import React from 'react';
2+
import {
3+
ConfirmDialog,
4+
ConfirmDialogHeader,
5+
ConfirmDialogContent,
6+
ConfirmDialogActions,
7+
} from '../../ui/ConfirmDialog';
8+
9+
interface MCPDialogProps {
10+
isOpen: boolean;
11+
onClose: () => void;
12+
}
13+
14+
export const MCPDialog: React.FC<MCPDialogProps> = ({ isOpen, onClose }) => {
15+
return (
16+
<ConfirmDialog isOpen={isOpen} onClose={onClose}>
17+
<ConfirmDialogHeader>MCP Instructions</ConfirmDialogHeader>
18+
<ConfirmDialogContent>
19+
<div className="space-y-4 text-sm text-gray-300">
20+
<div className="mb-4 p-3 bg-gray-800/50 rounded-md">
21+
<h3 className="text-md font-semibold text-gray-100 mb-1">Why use MCP Integration?</h3>
22+
<p>
23+
Integrating this Model Context Protocol (MCP) server with your AI assistant (like
24+
Cursor) allows it to dynamically access and utilize a curated list of coding rules and
25+
standards.
26+
</p>
27+
<p className="mt-1">Your AI assistant can use two main capabilities:</p>
28+
<ul className="list-disc list-inside ml-4 mt-1 space-y-0.5">
29+
<li>
30+
<code className="bg-gray-900 px-1 rounded text-xs">listAvailableRules</code>: To
31+
discover all available rule sets, their names, and technology stacks.
32+
</li>
33+
<li>
34+
<code className="bg-gray-900 px-1 rounded text-xs">getRuleContent</code>: To fetch
35+
the specific coding guidelines for a chosen rule set.
36+
</li>
37+
</ul>
38+
<p className="mt-2">
39+
This enables your assistant to provide more context-aware and standardized coding
40+
suggestions.
41+
</p>
42+
</div>
43+
44+
<p>You can integrate with the 10x Rules MCP server in two ways:</p>
45+
46+
<div>
47+
<h4 className="font-semibold text-gray-100 mb-1">
48+
1. Native SSE Support (e.g., Cursor)
49+
</h4>
50+
<p>Add the MCP server URL directly to your editor's configuration:</p>
51+
<pre className="mt-1 p-2 bg-gray-800 rounded text-xs overflow-x-auto">
52+
<code>
53+
{`{
54+
"mcpServers": {
55+
"10x-rules": {
56+
"url": "https://10x-rules-mcp-server.przeprogramowani.workers.dev/sse"
57+
}
58+
}
59+
}`}
60+
</code>
61+
</pre>
62+
</div>
63+
64+
<div>
65+
<h4 className="font-semibold text-gray-100 mb-1">
66+
2. Integration via Proxy (e.g., Claude Desktop)
67+
</h4>
68+
<p>If your editor doesn't support SSE directly, use the mcp-remote proxy:</p>
69+
<ol className="list-decimal list-inside ml-4 space-y-1 mt-1">
70+
<li>
71+
Install the proxy:{' '}
72+
<code className="bg-gray-800 px-1 rounded">npm install -g mcp-remote</code>
73+
</li>
74+
<li>Configure your editor to use the proxy:</li>
75+
</ol>
76+
<pre className="mt-1 p-2 bg-gray-800 rounded text-xs overflow-x-auto">
77+
<code>
78+
{`{
79+
"mcpServers": {
80+
"10x-rules": {
81+
"command": "npx",
82+
"args": [
83+
"mcp-remote",
84+
"https://10x-rules-mcp-server.przeprogramowani.workers.dev/sse"
85+
]
86+
}
87+
}
88+
}`}
89+
</code>
90+
</pre>
91+
</div>
92+
<p>
93+
After configuring, restart your editor. The <code>listAvailableRules</code> and{' '}
94+
<code>getRuleContent</code> tools should become available.
95+
</p>
96+
<p>
97+
Full documentation of the MCP server for 10xRules can be found{' '}
98+
<a
99+
href="https://github.com/przeprogramowani/ai-rules-builder/blob/master/mcp-server/README.md"
100+
target="_blank"
101+
rel="noopener noreferrer"
102+
className="text-blue-400 hover:text-blue-300 underline"
103+
>
104+
here
105+
</a>
106+
</p>
107+
</div>
108+
</ConfirmDialogContent>
109+
<ConfirmDialogActions>
110+
<button
111+
onClick={onClose}
112+
className="px-4 py-2 text-sm rounded-md text-gray-300 bg-gray-800 hover:bg-gray-700 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500"
113+
>
114+
Close
115+
</button>
116+
</ConfirmDialogActions>
117+
</ConfirmDialog>
118+
);
119+
};
120+
121+
export default MCPDialog;

src/components/ui/ConfirmDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({ isOpen, onClose, c
6666
>
6767
<div
6868
ref={dialogRef}
69-
className="bg-gray-900 rounded-lg shadow-lg max-w-md w-full mx-4 p-4 focus:outline-none animate-fade-in"
69+
className="bg-gray-900 rounded-lg shadow-lg max-w-md lg:max-w-3xl xl:max-w-5xl mx-4 p-4 focus:outline-none animate-fade-in"
7070
tabIndex={-1}
7171
>
7272
<ConfirmDialogContext.Provider value={{ isOpen, onClose }}>

0 commit comments

Comments
 (0)