docs-agent 1.1.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/CHANGELOG.md +47 -0
- package/LICENSE +21 -0
- package/README.md +239 -0
- package/docs/DEPLOYMENT.md +142 -0
- package/docs/mcp-client-prompt.md +26 -0
- package/docs/reference.md +258 -0
- package/env.example +47 -0
- package/package.json +67 -0
- package/src/CodeSearch.js +125 -0
- package/src/DocsAgent.js +728 -0
- package/src/FileUtility.js +130 -0
- package/src/GitHubApi.js +337 -0
- package/src/LLM.js +463 -0
- package/src/UrlValidator.js +190 -0
- package/src/api.js +107 -0
- package/src/cli.js +0 -0
- package/src/config/principles.diataxis.js +28 -0
- package/src/config/principles.first.js +11 -0
- package/src/config/prompt.docs.vs.code.js +52 -0
- package/src/config/prompt.edit.disruptive.js +9 -0
- package/src/config/prompt.edit.js +40 -0
- package/src/config/prompt.extract.code.js +45 -0
- package/src/config/prompt.formatting.js +38 -0
- package/src/config/prompt.gen.referencedocs.js +181 -0
- package/src/config/prompt.linking.js +14 -0
- package/src/config/prompt.prioritize.js +24 -0
- package/src/config/prompt.relatedfiles.js +14 -0
- package/src/config/prompt.review.js +23 -0
- package/src/config/prompt.scoring.js +9 -0
- package/src/config/prompt.writing.js +13 -0
- package/src/config/rules.linking.js +10 -0
- package/src/index.js +49 -0
- package/src/lib.js +4 -0
- package/src/mcp.js +268 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
`docs-agent` is an AI-powered agent for continuous documentation improvement. It analyzes, reviews, and edits documentation files using advanced LLMs (Gemini, Claude, etc.), following the Diátaxis documentation framework. It exposes its functionality via an HTTP API, an MCP (Model Context Protocol) server, and a programmatic Node.js interface.
|
|
2
|
+
|
|
3
|
+
## 1. MCP Server Tools
|
|
4
|
+
|
|
5
|
+
The MCP server exposes the following tools for integration with Model Context Protocol clients:
|
|
6
|
+
|
|
7
|
+
### `reviewDocs`
|
|
8
|
+
|
|
9
|
+
- **Description:** Reviews documentation quality following the Diátaxis framework.
|
|
10
|
+
- **Parameters:**
|
|
11
|
+
- `filepath` (`string`): Absolute path to the docs file.
|
|
12
|
+
- `filename` (`string`, optional): Relative path from project root.
|
|
13
|
+
- `projectStructure` (`string`, optional): Project structure in markdown list format.
|
|
14
|
+
- `customInstructions` (`string`, optional): Additional instructions.
|
|
15
|
+
- `glossaryFile` (`string`, optional): Path to glossary file.
|
|
16
|
+
- `relatedFiles` (`string[]`, optional): Absolute filepaths of related docs files.
|
|
17
|
+
- `allowDisruptiveChanges` (`boolean`, optional, default: false): Allow major restructuring.
|
|
18
|
+
- **Returns:** `{ content: [{ type: "text", text: string }] }`
|
|
19
|
+
|
|
20
|
+
### `improveDocs`
|
|
21
|
+
|
|
22
|
+
- **Description:** Improves documentation quality following the Diátaxis framework.
|
|
23
|
+
- **Parameters:**
|
|
24
|
+
- `filepath` (`string`): Absolute path to the docs file.
|
|
25
|
+
- `filename` (`string`, optional): Relative path from project root.
|
|
26
|
+
- `projectStructure` (`string`, optional): Project structure in markdown list format.
|
|
27
|
+
- `customInstructions` (`string`, optional): Additional instructions.
|
|
28
|
+
- `glossaryFile` (`string`, optional): Path to glossary file.
|
|
29
|
+
- `relatedFiles` (`string[]`, optional): Absolute filepaths of related docs files.
|
|
30
|
+
- `allowDisruptiveChanges` (`boolean`, optional, default: false): Allow major restructuring.
|
|
31
|
+
- **Returns:** `{ content: [{ type: "text", text: string }] }`
|
|
32
|
+
|
|
33
|
+
### `editDocs`
|
|
34
|
+
|
|
35
|
+
- **Description:** Edits documentation according to the provided plan.
|
|
36
|
+
- **Parameters:**
|
|
37
|
+
- `filepath` (`string`): Absolute path to the docs file.
|
|
38
|
+
- `editPlan` (`string`): Specific changes to be made to the documentation.
|
|
39
|
+
- `filename` (`string`, optional): Relative path from project root.
|
|
40
|
+
- `projectStructure` (`string`, optional): Project structure in markdown list format.
|
|
41
|
+
- `customInstructions` (`string`, optional): Additional instructions.
|
|
42
|
+
- `glossaryFile` (`string`, optional): Path to glossary file.
|
|
43
|
+
- `relatedFiles` (`string[]`, optional): Absolute filepaths of related docs files.
|
|
44
|
+
- **Returns:** `{ content: [{ type: "text", text: string }] }`
|
|
45
|
+
|
|
46
|
+
### `linkifyDocs`
|
|
47
|
+
|
|
48
|
+
- **Description:** Improves internal linking to related files and glossary concepts.
|
|
49
|
+
- **Parameters:**
|
|
50
|
+
- `filepath` (`string`): Absolute path to the docs file.
|
|
51
|
+
- `filename` (`string`, optional): Relative path from project root.
|
|
52
|
+
- `projectStructure` (`string`, optional): Project structure in markdown list format.
|
|
53
|
+
- `customInstructions` (`string`, optional): Additional instructions.
|
|
54
|
+
- `glossaryFile` (`string`, optional): Path to glossary file.
|
|
55
|
+
- `relatedFiles` (`string[]`, optional): Absolute filepaths of related docs files.
|
|
56
|
+
- **Returns:** `{ content: [{ type: "text", text: string }] }`
|
|
57
|
+
|
|
58
|
+
### `auditDocsAgainstCode`
|
|
59
|
+
|
|
60
|
+
- **Description:** Audits documentation against the corresponding codebase for accuracy and completeness.
|
|
61
|
+
- **Parameters:**
|
|
62
|
+
- `docsContentFilePath` (`string`): Absolute path to the docs file to audit.
|
|
63
|
+
- `repoUrl` (`string`): GitHub repository URL for the reference source code.
|
|
64
|
+
- `projectStructure` (`string`, optional): Project structure in markdown list format.
|
|
65
|
+
- `customInstructions` (`string`, optional): Additional instructions.
|
|
66
|
+
- **Returns:** `{ content: [{ type: "text", text: string }] }`
|
|
67
|
+
|
|
68
|
+
### `generateReferenceDocs` (Experimental)
|
|
69
|
+
|
|
70
|
+
- **Description:** Generates reference documentation for the given codebase/content.
|
|
71
|
+
- **Parameters:**
|
|
72
|
+
- `referenceSourceCodeFiles` (`string[]`): Remote URLs of the necessary source code files.
|
|
73
|
+
- `repoUrl` (`string`, optional): GitHub repository URL.
|
|
74
|
+
- `interfaceType` (`"library" | "http" | "mcp" | "cli" | "rpc" | "other"`, optional): Type of interface.
|
|
75
|
+
- `relatedFileUrls` (`string[]`, optional): Remote URLs of related code files.
|
|
76
|
+
- `projectStructure` (`string`, optional): Project structure in markdown list format.
|
|
77
|
+
- `customInstructions` (`string`, optional): Additional instructions.
|
|
78
|
+
- `knowledgeBase` (`string`, optional): Higher-level architecture context (not included in output).
|
|
79
|
+
- **Returns:** `{ content: [{ type: "text", text: string }] }`
|
|
80
|
+
- **Note:** This tool is experimental and disabled by default.
|
|
81
|
+
|
|
82
|
+
----
|
|
83
|
+
|
|
84
|
+
## 2. Node.js Library API
|
|
85
|
+
|
|
86
|
+
### Example Usage
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
const docsAgent = new DocsAgent();
|
|
90
|
+
const editedDocsPageContent = await docsAgent.reviewPrioritizeAndEdit(contentToEdit, {
|
|
91
|
+
projectStructure: "- src/\n - DocsAgent.js\n - api.js\n - mcp.js\n - LLM.js\n - config/\n - principles.diataxis.js",
|
|
92
|
+
customInstructions: "make sure the final output is a hugo markdown file"
|
|
93
|
+
});
|
|
94
|
+
console.log(editedDocsPageContent);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### DocsAgent Class
|
|
98
|
+
|
|
99
|
+
The main class for documentation improvement operations.
|
|
100
|
+
|
|
101
|
+
#### Constructor
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
new DocsAgent();
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
- Initializes a new DocsAgent instance.
|
|
108
|
+
|
|
109
|
+
#### Methods
|
|
110
|
+
|
|
111
|
+
##### `reviewPrioritizeAndEdit(content, context = {}, customInstructions, isFileWriteAllowed)`
|
|
112
|
+
|
|
113
|
+
- **Description:** Plans and executes the documentation improvement process: review, prioritize, and edit.
|
|
114
|
+
- **Parameters:**
|
|
115
|
+
- `content` (`string`): The documentation content to improve. If not provided, `context.filepath` is required.
|
|
116
|
+
- `context` (`object`):
|
|
117
|
+
- `filepath` (`string`): Absolute or relative path to the docs file.
|
|
118
|
+
- `filename` (`string`): Name of the docs file.
|
|
119
|
+
- `projectStructure` (`string`): Project structure in markdown list format.
|
|
120
|
+
- `glossaryFile` (`string`): Path to glossary file for consistent terminology.
|
|
121
|
+
- `relatedFiles` (`string[]`): Absolute filepaths to related documentation files.
|
|
122
|
+
- `allowDisruptiveChanges` (`boolean`): Allow major restructuring (default: false).
|
|
123
|
+
- `customInstructions` (`string`): Additional instructions for the improvement process.
|
|
124
|
+
- `isFileWriteAllowed` (`boolean`): If true, saves original and edited files to disk.
|
|
125
|
+
- **Returns:** `Promise<string>` (the improved documentation content).
|
|
126
|
+
|
|
127
|
+
##### `review(content, context, customInstructions)`
|
|
128
|
+
|
|
129
|
+
- **Description:** Reviews documentation and suggests improvements.
|
|
130
|
+
- **Parameters:**
|
|
131
|
+
- `content` (`string`): Documentation to review.
|
|
132
|
+
- `context` (`object`): Context for the review (see above).
|
|
133
|
+
- `customInstructions` (`string`): Additional instructions.
|
|
134
|
+
- **Returns:** `Promise<string>` (review summary, rating, suggestions, strengths).
|
|
135
|
+
|
|
136
|
+
##### `prioritize(content, review, context, customInstructions)`
|
|
137
|
+
|
|
138
|
+
- **Description:** Breaks down the review into prioritized editing tasks.
|
|
139
|
+
- **Parameters:**
|
|
140
|
+
- `content` (`string`): Documentation to review.
|
|
141
|
+
- `review` (`string`): Review output.
|
|
142
|
+
- `context` (`object`): Context for prioritization.
|
|
143
|
+
- `customInstructions` (`string`): Additional instructions.
|
|
144
|
+
- **Returns:** `Promise<string>` (prioritized editing plan).
|
|
145
|
+
|
|
146
|
+
##### `edit(content, editPlan, context, customInstructions)`
|
|
147
|
+
|
|
148
|
+
- **Description:** Edits documentation according to the provided plan.
|
|
149
|
+
- **Parameters:**
|
|
150
|
+
- `content` (`string`): Documentation to edit.
|
|
151
|
+
- `editPlan` (`string`): Editing plan.
|
|
152
|
+
- `context` (`object`): Context for editing.
|
|
153
|
+
- `customInstructions` (`string`): Additional instructions.
|
|
154
|
+
- **Returns:** `Promise<string>` (edited documentation).
|
|
155
|
+
|
|
156
|
+
##### `linkify(content, context, customInstructions)`
|
|
157
|
+
|
|
158
|
+
- **Description:** Improves internal linking to related files and glossary concepts.
|
|
159
|
+
- **Parameters:**
|
|
160
|
+
- `content` (`string`): Documentation to linkify.
|
|
161
|
+
- `context` (`object`): Context for linking.
|
|
162
|
+
- `customInstructions` (`string`): Additional instructions.
|
|
163
|
+
- **Returns:** `Promise<string>` (content with improved links).
|
|
164
|
+
|
|
165
|
+
##### `generateReferenceDocs(referenceSourceCodeFiles, context, customInstructions)`
|
|
166
|
+
|
|
167
|
+
- **Description:** Generates reference documentation for the given content.
|
|
168
|
+
- **Parameters:**
|
|
169
|
+
- `referenceSourceCodeFiles` (`string[]`): Remote URLs of the necessary source code files.
|
|
170
|
+
- `context` (`object`): Context for generation.
|
|
171
|
+
- `interfaceType` (`string`): Type of interface ("library", "http", "mcp", "cli", "rpc", or "other").
|
|
172
|
+
- `repoUrl` (`string`): URL of the repository.
|
|
173
|
+
- `projectStructure` (`string`): Project structure in markdown list format.
|
|
174
|
+
- `relatedFileUrls` (`string[]`): Remote URLs of related code files.
|
|
175
|
+
- `knowledgeBase` (`string`): Higher-level architecture context (not included in output).
|
|
176
|
+
- `customInstructions` (`string`): Additional instructions.
|
|
177
|
+
- **Returns:** `Promise<string>` (reference documentation).
|
|
178
|
+
|
|
179
|
+
##### `auditDocsAgainstCode(docsContentFilePath, context, customInstructions)`
|
|
180
|
+
|
|
181
|
+
- **Description:** Audits documentation against the corresponding codebase for accuracy and completeness.
|
|
182
|
+
- **Parameters:**
|
|
183
|
+
- `docsContentFilePath` (`string`): Absolute path to the docs file to audit.
|
|
184
|
+
- `context` (`object`): Context for the audit.
|
|
185
|
+
- `repoUrl` (`string`): GitHub repository URL for the reference source code.
|
|
186
|
+
- `projectStructure` (`string`): Project structure in markdown list format.
|
|
187
|
+
- `customInstructions` (`string`): Additional instructions.
|
|
188
|
+
- **Returns:** `Promise<string>` (audit report with discrepancies and suggestions).
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## 3. HTTP API
|
|
193
|
+
|
|
194
|
+
The HTTP API is served via Express (default port: 3001).
|
|
195
|
+
|
|
196
|
+
### Endpoints
|
|
197
|
+
|
|
198
|
+
#### `POST /review`
|
|
199
|
+
|
|
200
|
+
- **Request Body:** `{ content: string, filename?: string }`
|
|
201
|
+
- **Response:** Review summary, rating, suggestions, strengths.
|
|
202
|
+
|
|
203
|
+
#### `POST /prioritize`
|
|
204
|
+
|
|
205
|
+
- **Request Body:** `{ content: string, review: string }`
|
|
206
|
+
- **Response:** Prioritized actionable instructions.
|
|
207
|
+
|
|
208
|
+
#### `POST /edit`
|
|
209
|
+
|
|
210
|
+
- **Request Body:** `{ content: string, editPlan?: string, filename?: string }`
|
|
211
|
+
- **Response:** Edited documentation content.
|
|
212
|
+
|
|
213
|
+
#### `GET /health`
|
|
214
|
+
|
|
215
|
+
- **Response:** Service status, version, uptime, memory, CPU usage.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Prompts and Principles
|
|
220
|
+
|
|
221
|
+
The agent uses a set of configurable prompts and principles (in `src/config/`) to guide its review, prioritization, editing, and linking operations. These include:
|
|
222
|
+
|
|
223
|
+
- Diátaxis documentation principles
|
|
224
|
+
- Technical accuracy principles
|
|
225
|
+
- Writing and formatting style guides
|
|
226
|
+
- Linking rules
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Environment Variables
|
|
231
|
+
|
|
232
|
+
- `GITHUB_TOKEN` - GitHub personal access token
|
|
233
|
+
- `REVIEW_AI_SERVICE` (Default: `gemini`) - AI service to be used for the documentation analysis part e.g. gemini, anthropic, etc.
|
|
234
|
+
- `REVIEW_AI_MODEL` (Default: `gemini-2.5-pro-preview-05-06`) - AI model to be used for the documentation analysis part
|
|
235
|
+
- `PREFERRED_AI_SERVICE` (Default: `anthropic`) - Preferred AI service
|
|
236
|
+
- `PREFERRED_AI_MODEL` (Default: `claude-3-5-sonnet-20240620`) - Preferred AI model
|
|
237
|
+
- `GOOGLE_GENERATIVE_AI_API_KEY` - Google AI API key
|
|
238
|
+
- `ANTHROPIC_API_KEY` - Anthropic API key
|
|
239
|
+
- `OPENAI_API_KEY` - OpenAI API key
|
|
240
|
+
- `OLLAMA_API_KEY` - Ollama API key
|
|
241
|
+
- `OLLAMA_API_URL` - Ollama API URL
|
|
242
|
+
- `API_DISABLED` - Must not be "true" to serve the project as an HTTP API
|
|
243
|
+
- `MCP_DISABLED` - Must not be "true" to serve the project as an MCP server
|
|
244
|
+
- `MAX_CHANGES` - Maximum number of changes allowed
|
|
245
|
+
- `ALLOW_DISRUPTIVE_CHANGES` - Whether to allow disruptive changes
|
|
246
|
+
- `MAX_TOKENS` - Maximum tokens for LLM requests
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Folder and File Structure
|
|
251
|
+
|
|
252
|
+
- `src/DocsAgent.js`: Main agent logic.
|
|
253
|
+
- `src/LLM.js`: LLM interface.
|
|
254
|
+
- `src/api.js`: HTTP API server.
|
|
255
|
+
- `src/mcp.js`: MCP server and tool definitions.
|
|
256
|
+
- `src/config/`: Prompts, principles, and configuration.
|
|
257
|
+
- `test/`: Tests and fixtures.
|
|
258
|
+
- `docs/`: Documentation.
|
package/env.example
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
MCP_DISABLED=false
|
|
2
|
+
API_DISABLED=true
|
|
3
|
+
API_KEY=docs_agent_api_key_here
|
|
4
|
+
MAX_CHANGES=1
|
|
5
|
+
RESULTS_WEBHOOK_KEY=api_key_to_send_back_results_via_webhook
|
|
6
|
+
ALLOW_DISRUPTIVE_CHANGES=false
|
|
7
|
+
PREFERRED_AI_SERVICE=anthropic
|
|
8
|
+
PREFERRED_AI_MODEL=claude-3-5-sonnet-20240620
|
|
9
|
+
REVIEW_AI_SERVICE=gemini
|
|
10
|
+
REVIEW_AI_MODEL=gemini-2.5-pro-preview-05-06
|
|
11
|
+
MAX_TOKENS=8000
|
|
12
|
+
OLLAMA_API_KEY=sk-ollama-1234567890
|
|
13
|
+
OLLAMA_API_URL=http://localhost:11434/api/generateGEMINI_API_KEY=#deprecated
|
|
14
|
+
GOOGLE_GENERATIVE_AI_API_KEY=
|
|
15
|
+
OPENAI_API_KEY=sk-proj-1234567890
|
|
16
|
+
ANTHROPIC_API_KEY=sk-ant-api03-1234567890
|
|
17
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.braintrust.dev/otel
|
|
18
|
+
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <Your API Key>, x-bt-parent=project_id:<Your Project ID>"
|
|
19
|
+
# GitHub
|
|
20
|
+
GITHUB_TOKEN=your_github_personal_access_token_here
|
|
21
|
+
#For staging and testing servers only
|
|
22
|
+
SMEE_PROXY_ENDPOINT_REVIEW=#proxy to route POST request to /review
|
|
23
|
+
SMEE_PROXY_ENDPOINT_PRIORITIZE=#proxy to route POST request to /prioritize
|
|
24
|
+
SMEE_PROXY_ENDPOINT_EDIT=#proxy to route POST request to /edit
|
|
25
|
+
SMEE_PROXY_ENDPOINT_LINK=#proxy to route POST request to /link
|
|
26
|
+
SMEE_PROXY_ENDPOINT_AUDIT=#proxy to route POST request to /audit
|
|
27
|
+
# Webhook SSRF Protection - Comma-separated list of exact allowed webhook URLs
|
|
28
|
+
# Only exact URL matches are allowed (scheme + host + path + query)
|
|
29
|
+
# Examples:
|
|
30
|
+
# ALLOWED_WEBHOOK_URLS=https://integrating.app.url/api/comment
|
|
31
|
+
ALLOWED_WEBHOOK_URLS=http://localhost:3000/api/comment #All endpoints where you want to send the AI responses back
|
|
32
|
+
|
|
33
|
+
# Remote file fetch allowlist for FileUtility (comma-separated hostnames)
|
|
34
|
+
# Built-in allowed: github.com, raw.githubusercontent.com, gist.github.com, gitlab.com
|
|
35
|
+
# Add custom hosts here if needed (no wildcards)
|
|
36
|
+
# Example:
|
|
37
|
+
# REMOTE_FILE_ALLOWED_HOSTS=raw.githubusercontent.com,gitlab.example.com
|
|
38
|
+
REMOTE_FILE_ALLOWED_HOSTS=
|
|
39
|
+
|
|
40
|
+
# Enable custom remote hosts (set to "true" to allow hosts from REMOTE_FILE_ALLOWED_HOSTS)
|
|
41
|
+
# Default: false (only built-in GitHub/GitLab hosts allowed)
|
|
42
|
+
REMOTE_FILE_ALLOW_CUSTOM_HOSTS=false
|
|
43
|
+
|
|
44
|
+
# File Access Control (built-in, no configuration needed)
|
|
45
|
+
# API mode: Restricts local file access to public/ subdirectory only
|
|
46
|
+
# MCP mode: Allows unrestricted local file access (relies on MCP client permissions)
|
|
47
|
+
# Both modes: Allow validated remote file access (GitHub/GitLab URLs only)
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "docs-agent",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Docs-Agent leverages AI to avoid outdated documentation, fix issues related to comprehensiblity or technical accuracy.",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"files": ["src", "README.md", "LICENSE", "CHANGELOG.md", "env.example", "docs"],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "mocha test/**/*.test.js",
|
|
11
|
+
"start": "node src/index.js",
|
|
12
|
+
"proxy": "./node_modules/.bin/smee -u $SMEE_PROXY_ENDPOINT_REVIEW -t https://$HOSTNAME-3000.csb.app/review & ./node_modules/.bin/smee -u $SMEE_PROXY_ENDPOINT_PRIORITIZE -t https://$HOSTNAME-3000.csb.app/prioritize & ./node_modules/.bin/smee -u $SMEE_PROXY_ENDPOINT_EDIT -t https://$HOSTNAME-3000.csb.app/edit & ./node_modules/.bin/smee -u $SMEE_PROXY_ENDPOINT_LINK -t https://$HOSTNAME-3000.csb.app/link & ./node_modules/.bin/smee -u $SMEE_PROXY_ENDPOINT_AUDIT -t https://$HOSTNAME-3000.csb.app/audit",
|
|
13
|
+
"staging": "npm run proxy & PORT=3000 npm start",
|
|
14
|
+
"mcp-list": "MCP_DISABLED=false API_DISABLED=true npx @modelcontextprotocol/inspector --cli node src/index.js --method tools/list",
|
|
15
|
+
"mcp-run": "MCP_DISABLED=false API_DISABLED=true npx @modelcontextprotocol/inspector --cli node src/index.js --method tools/call --tool-name improveDocs --tool-arg filepath=./test/fixtures/docs.input.js"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@ai-sdk/anthropic": "^1.2.12",
|
|
19
|
+
"@ai-sdk/google": "^1.2.19",
|
|
20
|
+
"@ai-sdk/openai": "^1.3.22",
|
|
21
|
+
"@modelcontextprotocol/sdk": "^1.10.2",
|
|
22
|
+
"@octokit/core": "^7.0.3",
|
|
23
|
+
"@octokit/plugin-retry": "^8.0.1",
|
|
24
|
+
"@octokit/plugin-throttling": "^11.0.1",
|
|
25
|
+
"@vercel/otel": "^1.13.0",
|
|
26
|
+
"ai": "^4.0.0",
|
|
27
|
+
"dotenv": "^16.5.0",
|
|
28
|
+
"express": "^5.1.0",
|
|
29
|
+
"js-tiktoken": "^1.0.20",
|
|
30
|
+
"zod": "^3.25.76"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@modelcontextprotocol/inspector": "^0.15.0",
|
|
34
|
+
"chai": "^5.2.0",
|
|
35
|
+
"chai-http": "^5.1.2",
|
|
36
|
+
"mocha": "^11.1.0",
|
|
37
|
+
"sinon": "^20.0.0",
|
|
38
|
+
"smee-client": "^4.3.1"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=20.0.0"
|
|
42
|
+
},
|
|
43
|
+
"author": "",
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "https://github.com/rudderlabs/docs-agent"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://github.com/rudderlabs/docs-agent#readme",
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/rudderlabs/docs-agent/issues"
|
|
51
|
+
},
|
|
52
|
+
"keywords": [
|
|
53
|
+
"docs",
|
|
54
|
+
"diataxis",
|
|
55
|
+
"documentation",
|
|
56
|
+
"agent",
|
|
57
|
+
"mcp",
|
|
58
|
+
"ai",
|
|
59
|
+
"technical-writing",
|
|
60
|
+
"mcp",
|
|
61
|
+
"mcp-server",
|
|
62
|
+
"mcp-agent",
|
|
63
|
+
"ai-agent",
|
|
64
|
+
"ai-assistant",
|
|
65
|
+
"technical-documentation"
|
|
66
|
+
]
|
|
67
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search in codebase
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import GitHubApi from './GitHubApi.js';
|
|
6
|
+
import * as FileUtility from './FileUtility.js';
|
|
7
|
+
|
|
8
|
+
class CodeSearch {
|
|
9
|
+
constructor(options={}) {
|
|
10
|
+
this.searchSpace = options.searchSpace || "github";
|
|
11
|
+
this.repository = options.repository;
|
|
12
|
+
this.fetchContent = options.fetchContent || false;
|
|
13
|
+
this.maxResults = options.maxResults || 10;
|
|
14
|
+
this.scoreThreshold = options.scoreThreshold || 0;
|
|
15
|
+
this.cache = options.cache || true;
|
|
16
|
+
if(this.searchSpace === "github"){
|
|
17
|
+
this.githubApi = new GitHubApi();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Search for code in the codebase
|
|
23
|
+
* Query language: https://docs.github.com/en/search-github/searching-on-github/searching-code
|
|
24
|
+
* @param {string} query - The search query e.g. "keyword" | "symbol:keyword" | "repo:owner/repo"
|
|
25
|
+
* @param {object} [context={}] - Additional context
|
|
26
|
+
* @param {boolean} [context.fetchContent=false] - Whether to fetch the complete file content
|
|
27
|
+
* @param {string} [context.repository] - Repository path, supports both remote or local repository paths e.g. "https://github.com/owner/repo" or "/home/user/repo-folder"
|
|
28
|
+
* @param {string} [context.sha] - SHA of the search result (if available e.g. dsf2w32.. or main)
|
|
29
|
+
* @param {number} [context.scoreThreshold=0] - Minimum relevance score (0-1)
|
|
30
|
+
* @param {number} [context.maxResults=10] - Maximum number of results to return
|
|
31
|
+
* @param {boolean} [context.cache=true] - Whether to use caching
|
|
32
|
+
* @returns {Promise<Array<Object>>} searchResults - Array of search results with search results containing filepath and metadata
|
|
33
|
+
* @returns {Promise<string>} searchResults[].path - Relative path to the file
|
|
34
|
+
* @returns {Promise<string>} searchResults[].repository - Full repository path, supports both remote or local repository paths
|
|
35
|
+
* @returns {Promise<number>} searchResults[].score - Relevance score of the search result (0-1)
|
|
36
|
+
* @returns {Promise<string>} searchResults[].sha - SHA of the search result (if available e.g. dsf2w32.. or main)
|
|
37
|
+
* @returns {Promise<string>} searchResults[].filepath - Absolute file path to the file
|
|
38
|
+
*/
|
|
39
|
+
async execute(query, context={}) {
|
|
40
|
+
if(!context.repository){
|
|
41
|
+
context.repository = this.repository;
|
|
42
|
+
}
|
|
43
|
+
if(context.fetchContent === undefined){
|
|
44
|
+
context.fetchContent = this.fetchContent;
|
|
45
|
+
}
|
|
46
|
+
if(context.cache === undefined){
|
|
47
|
+
context.cache = this.cache;
|
|
48
|
+
}
|
|
49
|
+
let searchResults = [];
|
|
50
|
+
if(this.searchSpace === "github"){
|
|
51
|
+
searchResults = await this.githubApi.searchCode(query, context);
|
|
52
|
+
} else if(this.searchSpace === "local"){
|
|
53
|
+
throw new Error("Local search is not implemented yet");
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error(`Invalid search space: ${this.searchSpace}`);
|
|
56
|
+
}
|
|
57
|
+
const rankedResults = await this.rankResults(searchResults, context);
|
|
58
|
+
if(!context.fetchContent) {
|
|
59
|
+
return rankedResults;
|
|
60
|
+
}
|
|
61
|
+
const fileContents = await this.getFileContent(rankedResults);
|
|
62
|
+
const reRankedResults = await this.reRankResults(fileContents);
|
|
63
|
+
return reRankedResults;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Rank and filter search results based on relevance score
|
|
68
|
+
* @param {Array<Object>} searchResults - Array of search results
|
|
69
|
+
* @param {Object} context - Context object
|
|
70
|
+
* @param {number} context.scoreThreshold - Minimum relevance score (0-1)
|
|
71
|
+
* @param {number} context.maxResults - Maximum number of results to return
|
|
72
|
+
* @returns {Array<Object>} rankedResults - Array of ranked search results
|
|
73
|
+
*/
|
|
74
|
+
async rankResults(searchResults, context) {
|
|
75
|
+
const {
|
|
76
|
+
scoreThreshold = this.scoreThreshold,
|
|
77
|
+
maxResults = this.maxResults
|
|
78
|
+
} = context;
|
|
79
|
+
const rankedResults = [];
|
|
80
|
+
for(const result of searchResults) {
|
|
81
|
+
if(result.score < scoreThreshold) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if(maxResults > 0 && rankedResults.length >= maxResults) {
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
rankedResults.push(result);
|
|
88
|
+
}
|
|
89
|
+
return rankedResults;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get file content from the search results and add it to the search results
|
|
94
|
+
* @param {Array<Object>} searchResults - Array of search results
|
|
95
|
+
* @returns {Array<Object>} searchResults - Array of search results with file content
|
|
96
|
+
*/
|
|
97
|
+
async getFileContent(searchResults) {
|
|
98
|
+
const fileContents = [];
|
|
99
|
+
for(const result of searchResults) {
|
|
100
|
+
let fileContent;
|
|
101
|
+
if(this.searchSpace === "github"){
|
|
102
|
+
fileContent = await this.githubApi.getFileContent(result.repository, result.path, result.sha);
|
|
103
|
+
} else {
|
|
104
|
+
fileContent = await FileUtility.readFile(result.path);
|
|
105
|
+
}
|
|
106
|
+
fileContents.push({
|
|
107
|
+
...result,
|
|
108
|
+
content: fileContent
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return fileContents;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Rerank search results based on file content
|
|
116
|
+
* @param {Array<Object>} searchResults - Array of search results
|
|
117
|
+
* @returns {Array<Object>} reRankedResults - Array of reranked search results
|
|
118
|
+
*/
|
|
119
|
+
async reRankResults(searchResults) {
|
|
120
|
+
//TODO: Implement reranking logic
|
|
121
|
+
return searchResults;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export default CodeSearch;
|