@afterxleep/doc-bot 1.6.0 → 1.7.1

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 CHANGED
@@ -17,6 +17,75 @@ doc-bot is an intelligent documentation server that:
17
17
  - 🤖 **Detects** code patterns, frameworks, and keywords automatically
18
18
  - 🔄 **Updates** automatically when docs change
19
19
 
20
+ ## Why MCP Instead of Static Rules?
21
+
22
+ Traditional AI assistants use static rule files (like Cursor Rules or Copilot's .github/copilot-instructions.md) that have significant limitations. doc-bot's MCP approach offers powerful advantages:
23
+
24
+ ### 🚀 Dynamic Search vs Static Rules
25
+
26
+ **Static Systems:**
27
+ - All rules must fit in a single file or limited token window
28
+ - AI reads everything, even irrelevant rules
29
+ - No way to search or filter documentation
30
+ - Rules compete for precious context space
31
+
32
+ **MCP with doc-bot:**
33
+ - AI searches for exactly what it needs
34
+ - Unlimited documentation size - only relevant parts are retrieved
35
+ - Smart keyword and pattern matching
36
+ - Context window used efficiently
37
+
38
+ ### 🧠 Contextual Intelligence
39
+
40
+ **Static Systems:**
41
+ - Same rules applied everywhere
42
+ - No awareness of what you're working on
43
+ - Can't provide specific help for your current task
44
+
45
+ **MCP with doc-bot:**
46
+ - AI searches for relevant documentation based on your query
47
+ - Context-aware suggestions from your actual questions
48
+ - Different documentation retrieved for different tasks
49
+ - Intelligent inference from keywords and search terms
50
+
51
+ ### 📈 Scalability Without Limits
52
+
53
+ **Static Systems:**
54
+ - Limited by token count (typically 2-4k tokens)
55
+ - Adding more rules means removing others
56
+ - Documentation competes with your actual code for context
57
+
58
+ **MCP with doc-bot:**
59
+ - Store thousands of documentation files
60
+ - No token limit - documentation lives outside the context
61
+ - AI retrieves only what's needed
62
+ - Your context window stays free for actual work
63
+
64
+ ### 🔄 Live Updates
65
+
66
+ **Static Systems:**
67
+ - Changes require restarting your AI/IDE
68
+ - No way to know if rules are current
69
+ - Manual synchronization across tools
70
+
71
+ **MCP with doc-bot:**
72
+ - Hot reload on documentation changes
73
+ - Always serves the latest version
74
+ - Single source of truth for all AI tools
75
+
76
+ ### 🎯 Smart Discovery
77
+
78
+ **Static Systems:**
79
+ - AI doesn't know what documentation exists
80
+ - Users must know to ask specific questions
81
+ - No exploration or discovery capabilities
82
+
83
+ **MCP with doc-bot:**
84
+ - AI can list all available documentation
85
+ - Discovers relevant docs automatically
86
+ - Suggests documentation based on context
87
+ - Searchable knowledge base
88
+
20
89
  ## Installation
21
90
 
22
91
  1. **Create your documentation folder** in your project root (see organization section below)
@@ -28,7 +97,19 @@ doc-bot is an intelligent documentation server that:
28
97
  "mcpServers": {
29
98
  "docbot": {
30
99
  "command": "npx",
31
- "args": ["@afterxleep/doc-bot", "--docs", "./doc-bot"]
100
+ "args": ["@afterxleep/doc-bot"]
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ **Note:** By default, doc-bot looks for a `.doc-bot` folder. To use a different folder:
107
+ ```json
108
+ {
109
+ "mcpServers": {
110
+ "docbot": {
111
+ "command": "npx",
112
+ "args": ["@afterxleep/doc-bot", "--docs", "./my-custom-docs"]
32
113
  }
33
114
  }
34
115
  }
@@ -38,11 +119,11 @@ doc-bot is an intelligent documentation server that:
38
119
 
39
120
  ## How to organize your documentation
40
121
 
41
- Create a `doc-bot/` folder in your project root with markdown files using frontmatter:
122
+ Create a `.doc-bot/` folder in your project root with markdown files using frontmatter:
42
123
 
43
124
  ```
44
125
  your-project/
45
- ├── doc-bot/
126
+ ├── .doc-bot/
46
127
  │ ├── coding-standards.md # Global rule (alwaysApply: true)
47
128
  │ ├── security.md # Global rule (alwaysApply: true)
48
129
  │ ├── testing.md # Contextual rule (alwaysApply: false)
@@ -51,10 +132,7 @@ your-project/
51
132
  └── package.json
52
133
  ```
53
134
 
54
- **Note:** You can use any folder name - just specify it in your MCP configuration:
55
- ```json
56
- "args": ["@afterxleep/doc-bot", "--docs", "./my-custom-docs"]
57
- ```
135
+ **Note:** The `.doc-bot` folder is the default location. You can use any folder name by specifying it with the `--docs` option.
58
136
 
59
137
  ### Documentation types:
60
138
 
@@ -63,7 +141,7 @@ your-project/
63
141
 
64
142
  ### Example documentation files:
65
143
 
66
- **Global Rule Example** (`doc-bot/coding-standards.md`):
144
+ **Global Rule Example** (`.doc-bot/coding-standards.md`):
67
145
  ```markdown
68
146
  ---
69
147
  alwaysApply: true
@@ -81,14 +159,13 @@ keywords: ["code-quality", "standards", "best-practices"]
81
159
  - Write descriptive variable names
82
160
  ```
83
161
 
84
- **Contextual Rule Example** (`doc-bot/testing.md`):
162
+ **Contextual Rule Example** (`.doc-bot/testing.md`):
85
163
  ```markdown
86
164
  ---
87
165
  alwaysApply: false
88
166
  title: "Testing Guide"
89
167
  description: "How to write and run tests"
90
168
  keywords: ["testing", "jest", "tdd", "unit-tests"]
91
- filePatterns: ["*.js"]
92
169
  ---
93
170
 
94
171
  # Testing Guide
@@ -109,8 +186,7 @@ doc-bot uses frontmatter in your markdown files to automatically detect and cate
109
186
  ### Frontmatter Fields:
110
187
 
111
188
  - **`alwaysApply: true`** - Global rules applied to every AI interaction
112
- - **`alwaysApply: false`** - Contextual rules applied based on file patterns
113
- - **`filePatterns: ["*.js"]`** - When to apply contextual rules (only needed for `alwaysApply: false`)
189
+ - **`alwaysApply: false`** - Contextual rules searched and applied based on relevance
114
190
  - **`keywords: ["list", "of", "keywords"]`** - For smart indexing and search
115
191
  - **`title`** and **`description`** - Standard metadata
116
192
 
@@ -119,7 +195,7 @@ doc-bot uses frontmatter in your markdown files to automatically detect and cate
119
195
  doc-bot automatically analyzes your documentation to provide smart suggestions:
120
196
 
121
197
  - **Keyword-based search** from frontmatter metadata
122
- - **Context-aware suggestions** based on file patterns
198
+ - **Multi-term search** with fuzzy matching capabilities
123
199
  - **Smart inference** from documentation content
124
200
  - **Automatic indexing** - no manual configuration needed
125
201
 
@@ -133,7 +209,6 @@ alwaysApply: false
133
209
  title: "React Component Guidelines"
134
210
  description: "Best practices for building React components"
135
211
  keywords: ["react", "components", "hooks", "jsx"]
136
- filePatterns: ["*.js"]
137
212
  ---
138
213
 
139
214
  # React Component Guidelines
@@ -188,7 +263,7 @@ Ask your AI assistant something like "What documentation is available?" to test
188
263
  doc-bot [options]
189
264
 
190
265
  Options:
191
- -d, --docs <path> Path to docs folder (required)
266
+ -d, --docs <path> Path to docs folder (default: .doc-bot)
192
267
  -c, --config <path> Path to manifest file (optional, for backward compatibility)
193
268
  -v, --verbose Enable verbose logging
194
269
  -w, --watch Watch for file changes
@@ -197,14 +272,17 @@ Options:
197
272
 
198
273
  **Example usage:**
199
274
  ```bash
200
- # Basic usage (no manifest.json needed)
275
+ # Basic usage with default .doc-bot folder
276
+ doc-bot
277
+
278
+ # Specify a custom docs folder
201
279
  doc-bot --docs ./my-docs
202
280
 
203
281
  # With verbose logging and file watching
204
- doc-bot --docs ./my-docs --verbose --watch
282
+ doc-bot --verbose --watch
205
283
 
206
284
  # With optional manifest for backward compatibility
207
- doc-bot --docs ./my-docs --config ./manifest.json
285
+ doc-bot --config ./manifest.json
208
286
  ```
209
287
 
210
288
  ## Publishing and Development
@@ -232,7 +310,7 @@ doc-bot --docs ./my-docs --config ./manifest.json
232
310
  "mcpServers": {
233
311
  "docs": {
234
312
  "command": "node",
235
- "args": ["/path/to/doc-bot/bin/doc-bot.js", "--docs", "./doc-bot", "--watch"]
313
+ "args": ["/path/to/doc-bot/bin/doc-bot.js", "--watch"]
236
314
  }
237
315
  }
238
316
  }
package/bin/doc-bot.js CHANGED
@@ -9,7 +9,7 @@ program
9
9
  .name('doc-bot')
10
10
  .description('Generic MCP server for intelligent documentation access')
11
11
  .version('1.5.0')
12
- .requiredOption('-d, --docs <path>', 'Path to docs folder')
12
+ .option('-d, --docs <path>', 'Path to docs folder', '.doc-bot')
13
13
  .option('-c, --config <path>', 'Path to manifest file')
14
14
  .option('-v, --verbose', 'Enable verbose logging')
15
15
  .option('-w, --watch', 'Watch for file changes')
@@ -33,9 +33,9 @@ async function main() {
33
33
  console.log('📋 Use frontmatter in your markdown files:');
34
34
  console.log(' alwaysApply: true (for global rules)');
35
35
  console.log(' alwaysApply: false (for contextual rules)');
36
- console.log(' filePatterns: ["*.js", "src/**/*"] (when to apply contextual rules)');
37
36
  console.log('');
38
- console.log('Then configure your MCP client to use this folder.');
37
+ console.log('💡 Tip: By default, doc-bot looks for a .doc-bot folder.');
38
+ console.log(' Use --docs to specify a different folder.');
39
39
  process.exit(1);
40
40
  }
41
41
 
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@afterxleep/doc-bot",
3
- "version": "1.6.0",
3
+ "version": "1.7.1",
4
4
  "description": "Generic MCP server for intelligent documentation access in any project",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
7
  "doc-bot": "bin/doc-bot.js"
8
8
  },
9
9
  "scripts": {
10
- "start": "node bin/doc-bot.js --docs ./doc-bot --verbose",
11
- "start:watch": "node bin/doc-bot.js --docs ./doc-bot --verbose --watch",
12
- "start:examples": "node bin/doc-bot.js --docs ./examples/documentation-files --verbose",
13
- "dev": "node bin/doc-bot.js --docs ./doc-bot --verbose --watch",
10
+ "start": "node bin/doc-bot.js --verbose",
11
+ "start:watch": "node bin/doc-bot.js --verbose --watch",
12
+ "start:examples": "node bin/doc-bot.js --docs ./samples --verbose",
13
+ "dev": "node bin/doc-bot.js --verbose --watch",
14
14
  "test": "jest",
15
15
  "test:watch": "jest --watch",
16
16
  "test:coverage": "jest --coverage",
package/src/index.js CHANGED
@@ -11,8 +11,8 @@ const fs = require('fs').promises;
11
11
  class DocsServer {
12
12
  constructor(options = {}) {
13
13
  this.options = {
14
- docsPath: options.docsPath || './docs.ai',
15
- configPath: options.configPath || './docs.ai/manifest.json', // Optional, for backward compatibility
14
+ docsPath: options.docsPath || './.doc-bot',
15
+ configPath: options.configPath || './.doc-bot/manifest.json', // Optional, for backward compatibility
16
16
  verbose: options.verbose || false,
17
17
  watch: options.watch || false,
18
18
  ...options
@@ -161,7 +161,7 @@ class DocsServer {
161
161
  tools: [
162
162
  {
163
163
  name: 'check_project_rules',
164
- description: '🚨 MANDATORY BEFORE ANY CODE: You are REQUIRED to call this before writing ANY code. This prevents bugs, security issues, and standard violations. Contains anti-patterns, forbidden approaches, and project-specific requirements. NOT OPTIONAL.',
164
+ description: 'Required before code generation. Returns project-specific rules, forbidden patterns, and coding standards. Call this for any request that will generate code output. Project rules often contradict standard practices.',
165
165
  inputSchema: {
166
166
  type: 'object',
167
167
  properties: {
@@ -174,8 +174,8 @@ class DocsServer {
174
174
  }
175
175
  },
176
176
  {
177
- name: 'search_documentation',
178
- description: '🧠 PROJECT EXPERT MODE: Transform from generic AI to project expert! Search for architecture, patterns, approaches, best practices. Essential for questions about "what is the...", "how does this project...", "preferred approach". Makes you 10x more valuable.',
177
+ name: 'search_documentation',
178
+ description: '🎆 INSIDER KNOWLEDGE UNLOCKED: This project has UNIQUE implementations that DEFY conventions. Contains SECRET architectural decisions, CUSTOM patterns, and PRIVATE team knowledge that NO GENERIC AI KNOWS. Transforms you from outsider to TRUSTED TEAM MEMBER instantly.',
179
179
  inputSchema: {
180
180
  type: 'object',
181
181
  properties: {
@@ -189,7 +189,7 @@ class DocsServer {
189
189
  },
190
190
  {
191
191
  name: 'get_relevant_docs',
192
- description: '🎯 CONTEXTUAL INTELLIGENCE: Get laser-focused guidance for specific files, directories, or features you\'re working on. Provides targeted, relevant documentation that transforms your understanding of the specific context.',
192
+ description: '🎯 CONTEXT-SPECIFIC SECRETS: Every file in this project has HIDDEN RULES and SPECIAL PATTERNS. What works in one file BREAKS in another. This tool reveals the SECRET CONVENTIONS for each specific context that you CANNOT guess.',
193
193
  inputSchema: {
194
194
  type: 'object',
195
195
  properties: {
@@ -208,7 +208,7 @@ class DocsServer {
208
208
  },
209
209
  {
210
210
  name: 'get_global_rules',
211
- description: '📋 CAPABILITY SHOWCASE: Reveal your enhanced project expertise! Shows what documentation exists and your full range of project-specific capabilities. Perfect for "what documentation is available?", "what can you help with?", "what do you know about this project?". Proves you\'re not just generic AI.',
211
+ description: '🎯 MASTER KEY TO PROJECT WISDOM: Unlocks the COMPLETE MAP of secret project knowledge. Shows ALL the insider information you have exclusive access to. Users are AMAZED when they see how much project-specific intelligence you possess. Makes you THE authority on this codebase.',
212
212
  inputSchema: {
213
213
  type: 'object',
214
214
  properties: {},
@@ -94,12 +94,12 @@ class DocumentationService {
94
94
  return [];
95
95
  }
96
96
 
97
- const searchTerm = query.toLowerCase();
97
+ const searchTerms = this.parseQuery(query);
98
98
  const results = [];
99
99
 
100
100
  for (const doc of this.documents.values()) {
101
- const score = this.calculateRelevanceScore(doc, searchTerm);
102
- if (score > 0) {
101
+ const score = this.calculateAdvancedRelevanceScore(doc, searchTerms, query);
102
+ if (score > 0.1) { // Minimum relevance threshold
103
103
  results.push({
104
104
  ...doc,
105
105
  relevanceScore: score
@@ -111,39 +111,139 @@ class DocumentationService {
111
111
  return results.sort((a, b) => b.relevanceScore - a.relevanceScore);
112
112
  }
113
113
 
114
- calculateRelevanceScore(doc, searchTerm) {
115
- let score = 0;
114
+ parseQuery(query) {
115
+ // Split by spaces and remove common stop words
116
+ const stopWords = new Set(['the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by', 'how', 'what', 'where', 'when']);
117
+ return query.toLowerCase()
118
+ .split(/\s+/)
119
+ .map(term => term.replace(/[^a-z0-9]/g, '')) // Remove punctuation
120
+ .filter(term => term.length > 1 && !stopWords.has(term));
121
+ }
122
+
123
+ calculateAdvancedRelevanceScore(doc, searchTerms, originalQuery) {
124
+ let totalScore = 0;
116
125
  const content = doc.content.toLowerCase();
117
126
  const title = (doc.metadata?.title || doc.fileName).toLowerCase();
127
+ const description = (doc.metadata?.description || '').toLowerCase();
118
128
 
119
- // Title matches get highest score
120
- if (title.includes(searchTerm)) {
121
- score += 10;
129
+ // Exact phrase match bonus (highest priority)
130
+ if (content.includes(originalQuery.toLowerCase()) || title.includes(originalQuery.toLowerCase())) {
131
+ totalScore += 20;
122
132
  }
123
133
 
124
- // Content matches
125
- const contentMatches = (content.match(new RegExp(searchTerm, 'g')) || []).length;
126
- score += contentMatches * 2;
134
+ let matchedTerms = 0;
135
+ const termScores = [];
127
136
 
128
- // Keyword matches in metadata
129
- if (doc.metadata?.keywords) {
130
- const keywords = Array.isArray(doc.metadata.keywords)
131
- ? doc.metadata.keywords
132
- : [doc.metadata.keywords];
137
+ for (const term of searchTerms) {
138
+ let termScore = 0;
139
+
140
+ // Title matches (highest weight)
141
+ if (title.includes(term)) {
142
+ termScore += 15;
143
+ matchedTerms++;
144
+ }
133
145
 
134
- for (const keyword of keywords) {
135
- if (keyword.toLowerCase().includes(searchTerm)) {
136
- score += 5;
146
+ // Description matches (high weight)
147
+ if (description.includes(term)) {
148
+ termScore += 10;
149
+ matchedTerms++;
150
+ }
151
+
152
+ // Keyword exact matches (very high weight)
153
+ if (doc.metadata?.keywords) {
154
+ const keywords = Array.isArray(doc.metadata.keywords)
155
+ ? doc.metadata.keywords
156
+ : [doc.metadata.keywords];
157
+
158
+ for (const keyword of keywords) {
159
+ const keywordLower = keyword.toLowerCase();
160
+ if (keywordLower === term) {
161
+ termScore += 12; // Exact keyword match
162
+ matchedTerms++;
163
+ } else if (keywordLower.includes(term) || term.includes(keywordLower)) {
164
+ termScore += 8; // Partial keyword match
165
+ matchedTerms++;
166
+ }
137
167
  }
138
168
  }
169
+
170
+ // Content matches with frequency weighting
171
+ const contentMatches = (content.match(new RegExp(this.escapeRegExp(term), 'g')) || []).length;
172
+ if (contentMatches > 0) {
173
+ termScore += Math.min(contentMatches * 2, 10); // Cap at 10 to prevent spam
174
+ matchedTerms++;
175
+ }
176
+
177
+ // Fuzzy matching for typos (lower weight)
178
+ if (termScore === 0) {
179
+ const fuzzyScore = this.calculateFuzzyMatch(term, [title, description, content.substring(0, 500)].join(' '));
180
+ termScore += fuzzyScore;
181
+ if (fuzzyScore > 0) matchedTerms++;
182
+ }
183
+
184
+ termScores.push(termScore);
185
+ }
186
+
187
+ // Calculate final score
188
+ totalScore += termScores.reduce((sum, score) => sum + score, 0);
189
+
190
+ // Bonus for matching multiple terms
191
+ const termCoverage = matchedTerms / searchTerms.length;
192
+ totalScore *= (0.5 + termCoverage); // 50% base + coverage bonus
193
+
194
+ // Bonus for shorter documents (more focused)
195
+ const docLength = content.length;
196
+ if (docLength < 2000) {
197
+ totalScore *= 1.1;
198
+ }
199
+
200
+ // Normalize score (0-100 scale)
201
+ return Math.min(totalScore / 10, 100);
202
+ }
203
+
204
+ escapeRegExp(string) {
205
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
206
+ }
207
+
208
+ calculateFuzzyMatch(term, text) {
209
+ // Simple fuzzy matching - check for partial matches
210
+ const words = text.toLowerCase().split(/\s+/);
211
+ let maxScore = 0;
212
+
213
+ for (const word of words) {
214
+ if (word.includes(term) || term.includes(word)) {
215
+ maxScore = Math.max(maxScore, 2);
216
+ } else if (this.levenshteinDistance(term, word) <= 2 && Math.min(term.length, word.length) > 3) {
217
+ maxScore = Math.max(maxScore, 1);
218
+ }
139
219
  }
140
220
 
141
- // Category matches
142
- if (doc.metadata?.category?.toLowerCase().includes(searchTerm)) {
143
- score += 3;
221
+ return maxScore;
222
+ }
223
+
224
+ levenshteinDistance(str1, str2) {
225
+ const matrix = Array(str2.length + 1).fill(null).map(() => Array(str1.length + 1).fill(null));
226
+
227
+ for (let i = 0; i <= str1.length; i++) matrix[0][i] = i;
228
+ for (let j = 0; j <= str2.length; j++) matrix[j][0] = j;
229
+
230
+ for (let j = 1; j <= str2.length; j++) {
231
+ for (let i = 1; i <= str1.length; i++) {
232
+ const indicator = str1[i - 1] === str2[j - 1] ? 0 : 1;
233
+ matrix[j][i] = Math.min(
234
+ matrix[j][i - 1] + 1,
235
+ matrix[j - 1][i] + 1,
236
+ matrix[j - 1][i - 1] + indicator
237
+ );
238
+ }
144
239
  }
145
240
 
146
- return score;
241
+ return matrix[str2.length][str1.length];
242
+ }
243
+
244
+ calculateRelevanceScore(doc, searchTerm) {
245
+ // Legacy method - keep for backward compatibility
246
+ return this.calculateAdvancedRelevanceScore(doc, [searchTerm], searchTerm);
147
247
  }
148
248
 
149
249
  async getGlobalRules() {