react-docs-mcp 1.0.0

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/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # React Docs MCP Server
2
+
3
+ AI-powered semantic search over React documentation for Claude, Cursor, and other MCP clients.
4
+
5
+ ## 🚀 Installation (One Command)
6
+
7
+ ### Claude Code
8
+ ```bash
9
+ claude mcp add --transport stdio react-docs -- npx react-docs-mcp
10
+ ```
11
+
12
+ ### Claude Desktop
13
+
14
+ Edit: `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows)
15
+
16
+ ```json
17
+ {
18
+ "mcpServers": {
19
+ "react-docs": {
20
+ "command": "npx",
21
+ "args": ["-y", "react-docs-mcp"]
22
+ }
23
+ }
24
+ }
25
+ ```
26
+
27
+ ### Cursor
28
+
29
+ **Settings** → **Features** → **MCP** → Add server:
30
+ ```json
31
+ {
32
+ "react-docs": {
33
+ "command": "npx",
34
+ "args": ["-y", "react-docs-mcp"]
35
+ }
36
+ }
37
+ ```
38
+
39
+ **That's it!** Restart your editor and ask about React.
40
+
41
+ ---
42
+
43
+ ## Features
44
+
45
+ - **🔍 Semantic Search**: AI-powered search using embeddings for conceptual matches
46
+ - **⚡ Fast Results**: In-memory vector search with hybrid keyword+semantic ranking
47
+ - **📦 Zero Config**: Works with `npx` - no installation needed
48
+ - **🤖 Local AI**: Runs embeddings locally (no API costs)
49
+ - **📝 Concise Responses**: Returns summaries instead of full documentation
50
+ - **🔄 Auto-sync**: Pulls latest docs from react.dev automatically
51
+
52
+ ## Configuration
53
+
54
+ ### For Claude Desktop
55
+
56
+ Add to your Claude Desktop configuration file:
57
+
58
+ **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
59
+ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
60
+
61
+ ```json
62
+ {
63
+ "mcpServers": {
64
+ "react-docs": {
65
+ "command": "node",
66
+ "args": ["/absolute/path/to/reactDocsMcp/dist/index.js"]
67
+ }
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### For Claude Code
73
+
74
+ Add to your MCP settings configuration:
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "react-docs": {
80
+ "command": "node",
81
+ "args": ["/absolute/path/to/reactDocsMcp/dist/index.js"]
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ ## Usage
88
+
89
+ Once configured, the server provides the following capabilities to AI agents:
90
+
91
+ ### Tools
92
+
93
+ #### `search_react_docs`
94
+
95
+ Search across React documentation.
96
+
97
+ **Parameters**:
98
+ - `query` (required): Search query string
99
+ - `section` (optional): Filter by section (learn, reference, blog, community)
100
+ - `limit` (optional): Maximum number of results (default: 10, max: 50)
101
+
102
+ **Example**:
103
+ ```
104
+ Search for "useState hook" in the learn section
105
+ ```
106
+
107
+ #### `get_doc`
108
+
109
+ Get a specific documentation page.
110
+
111
+ **Parameters**:
112
+ - `path` (required): Document path (e.g., "learn/hooks/useState")
113
+
114
+ **Example**:
115
+ ```
116
+ Get the useState documentation
117
+ ```
118
+
119
+ #### `list_sections`
120
+
121
+ List all available documentation sections.
122
+
123
+ **Example**:
124
+ ```
125
+ What sections are available?
126
+ ```
127
+
128
+ #### `update_docs`
129
+
130
+ Pull latest documentation from the Git repository.
131
+
132
+ **Example**:
133
+ ```
134
+ Update the React documentation
135
+ ```
136
+
137
+ ### Resources
138
+
139
+ The server exposes documentation as resources with the URI pattern:
140
+
141
+ ```
142
+ react-docs://{section}/{path}
143
+ ```
144
+
145
+ **Examples**:
146
+ - `react-docs://learn` - List all learn section docs
147
+ - `react-docs://learn/hooks/useState` - Get useState documentation
148
+ - `react-docs://reference/react/Component` - Get Component API reference
149
+
150
+ ## Development
151
+
152
+ ### Run in Development Mode
153
+
154
+ ```bash
155
+ npm run dev
156
+ ```
157
+
158
+ ### Build
159
+
160
+ ```bash
161
+ npm run build
162
+ ```
163
+
164
+ ### Project Structure
165
+
166
+ ```
167
+ reactDocsMcp/
168
+ ├── src/
169
+ │ ├── index.ts # MCP server entry point
170
+ │ ├── docsManager.ts # Git & file operations
171
+ │ ├── markdownParser.ts # Markdown parsing
172
+ │ ├── searchEngine.ts # Search implementation
173
+ │ ├── types.ts # TypeScript types
174
+ │ └── config.ts # Configuration
175
+ ├── data/
176
+ │ └── react-dev-repo/ # Cloned React docs (auto-created)
177
+ ├── dist/ # Compiled output
178
+ └── TECHNICAL_SPEC.md # Technical documentation
179
+ ```
180
+
181
+ ## How It Works
182
+
183
+ 1. **Initialization**: On first run, clones the official React documentation repository
184
+ 2. **Indexing**: Parses all markdown files and builds an in-memory search index
185
+ 3. **Search**: Provides keyword-based search with relevance scoring
186
+ 4. **Updates**: Can pull latest changes from the repository and re-index
187
+
188
+ ## Troubleshooting
189
+
190
+ ### Server won't start
191
+
192
+ - Ensure Node.js 18+ is installed
193
+ - Check that the build completed successfully (`npm run build`)
194
+ - Verify the path in your MCP configuration is absolute and correct
195
+
196
+ ### No search results
197
+
198
+ - The repository may still be cloning (check console output)
199
+ - Try running `update_docs` tool to refresh the index
200
+
201
+ ### Git clone fails
202
+
203
+ - Check internet connection
204
+ - Verify Git is installed and accessible
205
+ - Check firewall/proxy settings
206
+
207
+ ## Technical Details
208
+
209
+ For detailed technical information, see [TECHNICAL_SPEC.md](./TECHNICAL_SPEC.md).
210
+
211
+ ## License
212
+
213
+ MIT
214
+
215
+ ## Contributing
216
+
217
+ This is a personal project for connecting React documentation to AI coding agents. Feel free to fork and modify for your own use.
@@ -0,0 +1,28 @@
1
+ /**
2
+ * config.ts
3
+ * Centralize configuration constants
4
+ */
5
+ declare const CONFIG: {
6
+ repo: {
7
+ url: string;
8
+ localPath: string;
9
+ contentPath: string;
10
+ };
11
+ search: {
12
+ defaultLimit: number;
13
+ maxLimit: number;
14
+ minScore: number;
15
+ semanticSearchEnabled: boolean;
16
+ semanticMinSimilarity: number;
17
+ hybridKeywordWeight: number;
18
+ hybridSemanticWeight: number;
19
+ };
20
+ server: {
21
+ name: string;
22
+ version: string;
23
+ };
24
+ sections: readonly ["learn", "reference", "blog", "community"];
25
+ };
26
+ export default CONFIG;
27
+ export type Section = typeof CONFIG.sections[number];
28
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;CA2BX,CAAC;AAEF,eAAe,MAAM,CAAC;AACtB,MAAM,MAAM,OAAO,GAAG,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * config.ts
3
+ * Centralize configuration constants
4
+ */
5
+ const CONFIG = {
6
+ // Repository settings
7
+ repo: {
8
+ url: 'https://github.com/reactjs/react.dev.git',
9
+ localPath: './data/react-dev-repo',
10
+ contentPath: 'src/content',
11
+ },
12
+ // Search settings
13
+ search: {
14
+ defaultLimit: 10,
15
+ maxLimit: 50,
16
+ minScore: 0.1,
17
+ semanticSearchEnabled: true,
18
+ semanticMinSimilarity: 0.3, // Minimum cosine similarity for semantic results
19
+ hybridKeywordWeight: 0.3, // Weight for keyword search in hybrid mode
20
+ hybridSemanticWeight: 0.7, // Weight for semantic search in hybrid mode
21
+ },
22
+ // MCP server settings
23
+ server: {
24
+ name: 'react-docs-mcp',
25
+ version: '1.0.0',
26
+ },
27
+ // Content sections in the repo
28
+ sections: ['learn', 'reference', 'blog', 'community'],
29
+ };
30
+ export default CONFIG;
31
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,GAAG;IACb,sBAAsB;IACtB,IAAI,EAAE;QACJ,GAAG,EAAE,0CAA0C;QAC/C,SAAS,EAAE,uBAAuB;QAClC,WAAW,EAAE,aAAa;KAC3B;IAED,kBAAkB;IAClB,MAAM,EAAE;QACN,YAAY,EAAE,EAAE;QAChB,QAAQ,EAAE,EAAE;QACZ,QAAQ,EAAE,GAAG;QACb,qBAAqB,EAAE,IAAI;QAC3B,qBAAqB,EAAE,GAAG,EAAG,iDAAiD;QAC9E,mBAAmB,EAAE,GAAG,EAAK,2CAA2C;QACxE,oBAAoB,EAAE,GAAG,EAAI,4CAA4C;KAC1E;IAED,sBAAsB;IACtB,MAAM,EAAE;QACN,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,OAAO;KACjB;IAED,+BAA+B;IAC/B,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,CAAU;CAC/D,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * docsManager.ts
3
+ * Handle Git repository operations and file system access
4
+ */
5
+ import type { RepoStatus } from './types.js';
6
+ export declare class DocsManager {
7
+ private git;
8
+ private repoPath;
9
+ private contentPath;
10
+ private fileCache;
11
+ constructor();
12
+ /**
13
+ * Initialize the docs manager
14
+ * Checks if repo exists, clones if needed
15
+ */
16
+ initialize(): Promise<void>;
17
+ /**
18
+ * Check if repository exists locally
19
+ */
20
+ private checkRepoExists;
21
+ /**
22
+ * Clone the repository
23
+ */
24
+ private cloneRepo;
25
+ /**
26
+ * Get repository status
27
+ */
28
+ getStatus(): Promise<RepoStatus>;
29
+ /**
30
+ * Update repository (git pull)
31
+ * Returns true if updates were pulled
32
+ */
33
+ updateRepo(): Promise<boolean>;
34
+ /**
35
+ * Get all markdown files from a section
36
+ * @param section - Section name (learn, reference, etc.)
37
+ * @returns Array of file paths relative to content root
38
+ */
39
+ getDocsInSection(section: string): Promise<string[]>;
40
+ /**
41
+ * Get all markdown files across all sections
42
+ * @returns Array of file paths relative to content root
43
+ */
44
+ getAllDocs(): Promise<string[]>;
45
+ /**
46
+ * Read file content
47
+ * @param relativePath - Path relative to content root
48
+ * @returns Raw file content
49
+ */
50
+ readDoc(relativePath: string): Promise<string>;
51
+ /**
52
+ * Check if file exists
53
+ * @param relativePath - Path relative to content root
54
+ */
55
+ docExists(relativePath: string): Promise<boolean>;
56
+ }
57
+ //# sourceMappingURL=docsManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docsManager.d.ts","sourceRoot":"","sources":["../src/docsManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,qBAAa,WAAW;IACtB,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAoC;;IAQrD;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAYjC;;OAEG;YACW,eAAe;IAS7B;;OAEG;YACW,SAAS;IAevB;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC;IAsBtC;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAgCpC;;;;OAIG;IACG,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA4B1D;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAgBrC;;;;OAIG;IACG,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAYpD;;;OAGG;IACG,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAUxD"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * docsManager.ts
3
+ * Handle Git repository operations and file system access
4
+ */
5
+ import { simpleGit } from 'simple-git';
6
+ import { promises as fs } from 'fs';
7
+ import path from 'path';
8
+ import fg from 'fast-glob';
9
+ import CONFIG from './config.js';
10
+ export class DocsManager {
11
+ git;
12
+ repoPath;
13
+ contentPath;
14
+ fileCache = new Map();
15
+ constructor() {
16
+ this.repoPath = path.resolve(CONFIG.repo.localPath);
17
+ this.contentPath = path.join(this.repoPath, CONFIG.repo.contentPath);
18
+ this.git = simpleGit();
19
+ }
20
+ /**
21
+ * Initialize the docs manager
22
+ * Checks if repo exists, clones if needed
23
+ */
24
+ async initialize() {
25
+ const repoExists = await this.checkRepoExists();
26
+ if (!repoExists) {
27
+ console.log('Cloning React documentation repository...');
28
+ await this.cloneRepo();
29
+ console.log('Repository cloned successfully');
30
+ }
31
+ else {
32
+ console.log('Repository already exists');
33
+ }
34
+ }
35
+ /**
36
+ * Check if repository exists locally
37
+ */
38
+ async checkRepoExists() {
39
+ try {
40
+ await fs.access(path.join(this.repoPath, '.git'));
41
+ return true;
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ /**
48
+ * Clone the repository
49
+ */
50
+ async cloneRepo() {
51
+ try {
52
+ // Ensure parent directory exists
53
+ await fs.mkdir(path.dirname(this.repoPath), { recursive: true });
54
+ await this.git.clone(CONFIG.repo.url, this.repoPath, {
55
+ '--depth': 1, // Shallow clone for faster download
56
+ });
57
+ }
58
+ catch (error) {
59
+ throw new Error(`Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`);
60
+ }
61
+ }
62
+ /**
63
+ * Get repository status
64
+ */
65
+ async getStatus() {
66
+ const isCloned = await this.checkRepoExists();
67
+ if (!isCloned) {
68
+ return { isCloned: false };
69
+ }
70
+ try {
71
+ const git = simpleGit(this.repoPath);
72
+ const log = await git.log({ maxCount: 1 });
73
+ return {
74
+ isCloned: true,
75
+ currentCommit: log.latest?.hash,
76
+ lastUpdated: log.latest?.date ? new Date(log.latest.date) : undefined,
77
+ };
78
+ }
79
+ catch (error) {
80
+ console.error('Failed to get repo status:', error);
81
+ return { isCloned: true };
82
+ }
83
+ }
84
+ /**
85
+ * Update repository (git pull)
86
+ * Returns true if updates were pulled
87
+ */
88
+ async updateRepo() {
89
+ const isCloned = await this.checkRepoExists();
90
+ if (!isCloned) {
91
+ throw new Error('Repository not cloned. Call initialize() first.');
92
+ }
93
+ try {
94
+ const git = simpleGit(this.repoPath);
95
+ const beforeHash = await git.revparse(['HEAD']);
96
+ await git.pull();
97
+ const afterHash = await git.revparse(['HEAD']);
98
+ const hasUpdates = beforeHash !== afterHash;
99
+ if (hasUpdates) {
100
+ // Clear file cache when repo is updated
101
+ this.fileCache.clear();
102
+ console.log('Repository updated successfully');
103
+ }
104
+ else {
105
+ console.log('Repository already up to date');
106
+ }
107
+ return hasUpdates;
108
+ }
109
+ catch (error) {
110
+ throw new Error(`Failed to update repository: ${error instanceof Error ? error.message : String(error)}`);
111
+ }
112
+ }
113
+ /**
114
+ * Get all markdown files from a section
115
+ * @param section - Section name (learn, reference, etc.)
116
+ * @returns Array of file paths relative to content root
117
+ */
118
+ async getDocsInSection(section) {
119
+ const cacheKey = `section:${section}`;
120
+ if (this.fileCache.has(cacheKey)) {
121
+ return this.fileCache.get(cacheKey);
122
+ }
123
+ const sectionPath = path.join(this.contentPath, section);
124
+ try {
125
+ await fs.access(sectionPath);
126
+ }
127
+ catch {
128
+ // Section doesn't exist
129
+ return [];
130
+ }
131
+ const files = await fg('**/*.md', {
132
+ cwd: sectionPath,
133
+ absolute: false,
134
+ });
135
+ // Convert to paths relative to content root
136
+ const relativePaths = files.map(file => `${section}/${file}`);
137
+ this.fileCache.set(cacheKey, relativePaths);
138
+ return relativePaths;
139
+ }
140
+ /**
141
+ * Get all markdown files across all sections
142
+ * @returns Array of file paths relative to content root
143
+ */
144
+ async getAllDocs() {
145
+ const cacheKey = 'all';
146
+ if (this.fileCache.has(cacheKey)) {
147
+ return this.fileCache.get(cacheKey);
148
+ }
149
+ const files = await fg('**/*.md', {
150
+ cwd: this.contentPath,
151
+ absolute: false,
152
+ });
153
+ this.fileCache.set(cacheKey, files);
154
+ return files;
155
+ }
156
+ /**
157
+ * Read file content
158
+ * @param relativePath - Path relative to content root
159
+ * @returns Raw file content
160
+ */
161
+ async readDoc(relativePath) {
162
+ const fullPath = path.join(this.contentPath, relativePath);
163
+ try {
164
+ return await fs.readFile(fullPath, 'utf-8');
165
+ }
166
+ catch (error) {
167
+ throw new Error(`Failed to read document at ${relativePath}: ${error instanceof Error ? error.message : String(error)}`);
168
+ }
169
+ }
170
+ /**
171
+ * Check if file exists
172
+ * @param relativePath - Path relative to content root
173
+ */
174
+ async docExists(relativePath) {
175
+ const fullPath = path.join(this.contentPath, relativePath);
176
+ try {
177
+ await fs.access(fullPath);
178
+ return true;
179
+ }
180
+ catch {
181
+ return false;
182
+ }
183
+ }
184
+ }
185
+ //# sourceMappingURL=docsManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docsManager.js","sourceRoot":"","sources":["../src/docsManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * embeddingService.ts
3
+ * Generate embeddings using transformers.js for semantic search
4
+ */
5
+ /**
6
+ * Embedding service using all-MiniLM-L6-v2 model
7
+ * This is a lightweight model (23MB) optimized for semantic similarity
8
+ */
9
+ export declare class EmbeddingService {
10
+ private pipeline;
11
+ private initialized;
12
+ private modelName;
13
+ /**
14
+ * Initialize the embedding pipeline
15
+ * Downloads model on first run (~23MB)
16
+ */
17
+ initialize(): Promise<void>;
18
+ /**
19
+ * Generate embedding for a text
20
+ * @param text - Text to embed
21
+ * @returns Vector embedding (384 dimensions for all-MiniLM-L6-v2)
22
+ */
23
+ generateEmbedding(text: string): Promise<number[]>;
24
+ /**
25
+ * Generate embeddings for multiple texts (batch processing)
26
+ * @param texts - Array of texts to embed
27
+ * @returns Array of vector embeddings
28
+ */
29
+ generateEmbeddings(texts: string[]): Promise<number[][]>;
30
+ /**
31
+ * Calculate cosine similarity between two vectors
32
+ * @param a - First vector
33
+ * @param b - Second vector
34
+ * @returns Similarity score (0-1, higher is more similar)
35
+ */
36
+ cosineSimilarity(a: number[], b: number[]): number;
37
+ /**
38
+ * Find most similar vectors to a query vector
39
+ * @param queryEmbedding - Query vector
40
+ * @param docEmbeddings - Array of document vectors with metadata
41
+ * @param topK - Number of results to return
42
+ * @returns Array of {index, similarity} sorted by similarity desc
43
+ */
44
+ findMostSimilar(queryEmbedding: number[], docEmbeddings: Array<{
45
+ embedding: number[];
46
+ index: number;
47
+ }>, topK: number): Array<{
48
+ index: number;
49
+ similarity: number;
50
+ }>;
51
+ }
52
+ //# sourceMappingURL=embeddingService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embeddingService.d.ts","sourceRoot":"","sources":["../src/embeddingService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,SAAS,CAAqC;IAEtD;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAejC;;;;OAIG;IACG,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAuBxD;;;;OAIG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAW9D;;;;;OAKG;IACH,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM;IAsBlD;;;;;;OAMG;IACH,eAAe,CACb,cAAc,EAAE,MAAM,EAAE,EACxB,aAAa,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,EAC5D,IAAI,EAAE,MAAM,GACX,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAWhD"}