@arabold/docs-mcp-server 1.2.1 → 1.4.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 +193 -147
- package/dist/{chunk-KPQQOEBY.js → chunk-BD7OFN4H.js} +92 -6
- package/dist/chunk-BD7OFN4H.js.map +1 -0
- package/dist/cli.js +7 -4
- package/dist/cli.js.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +6 -3
- package/dist/chunk-KPQQOEBY.js.map +0 -1
package/README.md
CHANGED
|
@@ -17,103 +17,121 @@ The server exposes MCP tools for:
|
|
|
17
17
|
- Finding appropriate versions (`find_version`).
|
|
18
18
|
- Removing indexed documents (`remove_docs`).
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
## Usage
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Once the package is published to npm (`@arabold/docs-mcp-server`), you can run the server or the companion CLI in two main ways:
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
### Method 1: Global Installation (Recommended for CLI Usage)
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
If you haven't already, clone the project to your local machine:
|
|
26
|
+
Install the package globally using npm. This makes the `docs-server` and `docs-cli` commands directly available in your terminal.
|
|
28
27
|
|
|
28
|
+
1. **Install Globally:**
|
|
29
29
|
```bash
|
|
30
|
-
|
|
31
|
-
cd docs-mcp-server
|
|
30
|
+
npm install -g @arabold/docs-mcp-server
|
|
32
31
|
```
|
|
33
|
-
|
|
34
|
-
2. **Install dependencies:**
|
|
35
|
-
Navigate into the project directory and install the required Node.js packages:
|
|
36
|
-
|
|
32
|
+
2. **Run the Server:**
|
|
37
33
|
```bash
|
|
38
|
-
|
|
34
|
+
docs-server
|
|
39
35
|
```
|
|
40
|
-
|
|
41
|
-
3. **
|
|
42
|
-
Compile the TypeScript source code into JavaScript. The output will be placed in the `dist/` directory. This step is necessary to generate the `dist/server.js` file referenced in the installation instructions.
|
|
43
|
-
|
|
36
|
+
_(Note: You'll need to manage environment variables like `OPENAI_API_KEY` yourself when running this way, e.g., by setting them in your shell profile or using a tool like `dotenv`.)_
|
|
37
|
+
3. **Run the CLI:**
|
|
44
38
|
```bash
|
|
45
|
-
|
|
39
|
+
docs-cli <command> [options]
|
|
46
40
|
```
|
|
41
|
+
(See "CLI Command Reference" below for available commands and options.)
|
|
47
42
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
## Installation
|
|
43
|
+
This method is convenient if you plan to use the `docs-cli` frequently.
|
|
51
44
|
|
|
52
|
-
|
|
45
|
+
### Method 2: Running with Docker (Recommended for MCP Integration)
|
|
53
46
|
|
|
54
|
-
-
|
|
55
|
-
- On Windows: `%APPDATA%/Claude/claude_desktop_config.json`
|
|
47
|
+
Run the server using the pre-built Docker image available on GitHub Container Registry. This provides an isolated environment and simplifies setup.
|
|
56
48
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"mcpServers": {
|
|
60
|
-
"docs-mcp-server": {
|
|
61
|
-
"command": "node",
|
|
62
|
-
"args": ["/path/to/docs-mcp-server/dist/server.js"],
|
|
63
|
-
"env": {
|
|
64
|
-
"OPENAI_API_KEY": "sk-proj-..."
|
|
65
|
-
},
|
|
66
|
-
"disabled": false,
|
|
67
|
-
"autoApprove": []
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Running with Docker
|
|
74
|
-
|
|
75
|
-
Alternatively, you can build and run the server using Docker. This provides an isolated environment and exposes the server via HTTP endpoints.
|
|
76
|
-
|
|
77
|
-
1. **Build the Docker image:**
|
|
49
|
+
1. **Ensure Docker is installed and running.**
|
|
50
|
+
2. **Run the Server (e.g., for MCP Integration):**
|
|
78
51
|
|
|
79
52
|
```bash
|
|
80
|
-
docker
|
|
53
|
+
docker run -i --rm \
|
|
54
|
+
-e OPENAI_API_KEY="your-openai-api-key-here" \
|
|
55
|
+
-v docs-mcp-data:/data \
|
|
56
|
+
ghcr.io/arabold/docs-mcp-server:latest
|
|
81
57
|
```
|
|
82
58
|
|
|
83
|
-
|
|
59
|
+
- `-i`: Keep STDIN open, crucial for MCP communication over stdio.
|
|
60
|
+
- `--rm`: Automatically remove the container when it exits.
|
|
61
|
+
- `-e OPENAI_API_KEY="..."`: **Required.** Set your OpenAI API key.
|
|
62
|
+
- `-v docs-mcp-data:/data`: **Required for persistence.** Mounts a Docker named volume (`docs-mcp-data` is created automatically if it doesn't exist) to the container's `/data` directory, where the database is stored. You can replace `docs-mcp-data` with a specific host path if preferred (e.g., `-v /path/on/host:/data`).
|
|
63
|
+
- `ghcr.io/arabold/docs-mcp-server:latest`: Specifies the public Docker image to use.
|
|
64
|
+
|
|
65
|
+
This is the recommended approach for integrating with tools like Claude Desktop or Cline.
|
|
66
|
+
|
|
67
|
+
**Claude/Cline Configuration Example:**
|
|
68
|
+
Add the following configuration block to your MCP settings file (adjust path as needed):
|
|
69
|
+
|
|
70
|
+
- Cline: `/Users/andrerabold/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`
|
|
71
|
+
- Claude Desktop (MacOS): `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
72
|
+
- Claude Desktop (Windows): `%APPDATA%/Claude/claude_desktop_config.json`
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"mcpServers": {
|
|
77
|
+
"docs-mcp-server": {
|
|
78
|
+
"command": "docker",
|
|
79
|
+
"args": [
|
|
80
|
+
"run",
|
|
81
|
+
"-i",
|
|
82
|
+
"--rm",
|
|
83
|
+
"-e",
|
|
84
|
+
"OPENAI_API_KEY",
|
|
85
|
+
"-v",
|
|
86
|
+
"docs-mcp-data:/data",
|
|
87
|
+
"ghcr.io/arabold/docs-mcp-server:latest"
|
|
88
|
+
],
|
|
89
|
+
"env": {
|
|
90
|
+
"OPENAI_API_KEY": "sk-proj-..." // Required: Replace with your key
|
|
91
|
+
},
|
|
92
|
+
"disabled": false,
|
|
93
|
+
"autoApprove": []
|
|
94
|
+
}
|
|
95
|
+
// ... other servers might be listed here
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
84
99
|
|
|
85
|
-
|
|
100
|
+
Remember to replace `"sk-proj-..."` with your actual OpenAI API key and restart the application.
|
|
86
101
|
|
|
102
|
+
3. **Run the CLI (Requires Docker):**
|
|
103
|
+
To use the CLI commands, you can run them inside a temporary container:
|
|
87
104
|
```bash
|
|
88
|
-
docker run
|
|
105
|
+
docker run --rm \
|
|
106
|
+
-e OPENAI_API_KEY="your-openai-api-key-here" \
|
|
107
|
+
-v docs-mcp-data:/data \
|
|
108
|
+
ghcr.io/arabold/docs-mcp-server:latest \
|
|
109
|
+
npx docs-cli <command> [options]
|
|
89
110
|
```
|
|
111
|
+
(See "CLI Command Reference" below for available commands and options.)
|
|
90
112
|
|
|
91
|
-
|
|
92
|
-
- `--env-file .env`: Loads environment variables from your local `.env` file at runtime. This is the recommended way to handle secrets.
|
|
93
|
-
- `--name docs-mcp-server-container`: Assigns a name to the container for easier management.
|
|
113
|
+
This method is ideal for integrating the server into other tools and ensures a consistent runtime environment.
|
|
94
114
|
|
|
95
|
-
|
|
115
|
+
## CLI Command Reference
|
|
96
116
|
|
|
97
|
-
|
|
117
|
+
The `docs-cli` provides commands for managing the documentation index. Access it either via global installation (`docs-cli ...`) or `npx` (`npx -y --package=@arabold/docs-mcp-server docs-cli ...`).
|
|
98
118
|
|
|
99
|
-
|
|
100
|
-
- **POST Messages:** `http://localhost:8000/message` (for sending individual messages)
|
|
119
|
+
**General Help:**
|
|
101
120
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
121
|
+
```bash
|
|
122
|
+
docs-cli --help
|
|
123
|
+
# or
|
|
124
|
+
npx -y --package=@arabold/docs-mcp-server docs-cli --help
|
|
125
|
+
```
|
|
105
126
|
|
|
106
|
-
|
|
127
|
+
**Command Specific Help:** (Replace `docs-cli` with the `npx...` command if not installed globally)
|
|
107
128
|
|
|
108
129
|
```bash
|
|
109
|
-
|
|
110
|
-
docs-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
docs-
|
|
114
|
-
docs-mcp search --help
|
|
115
|
-
docs-mcp find-version --help
|
|
116
|
-
docs-mcp remove --help
|
|
130
|
+
docs-cli scrape --help
|
|
131
|
+
docs-cli search --help
|
|
132
|
+
docs-cli find-version --help
|
|
133
|
+
docs-cli remove --help
|
|
134
|
+
docs-cli list-libraries --help
|
|
117
135
|
```
|
|
118
136
|
|
|
119
137
|
### Scraping Documentation (`scrape`)
|
|
@@ -121,7 +139,7 @@ docs-mcp remove --help
|
|
|
121
139
|
Scrapes and indexes documentation from a given URL for a specific library.
|
|
122
140
|
|
|
123
141
|
```bash
|
|
124
|
-
docs-
|
|
142
|
+
docs-cli scrape <library> <url> [options]
|
|
125
143
|
```
|
|
126
144
|
|
|
127
145
|
**Options:**
|
|
@@ -137,17 +155,11 @@ docs-mcp scrape <library> <url> [options]
|
|
|
137
155
|
**Examples:**
|
|
138
156
|
|
|
139
157
|
```bash
|
|
140
|
-
# Scrape React 18.2.0 docs
|
|
141
|
-
docs-
|
|
142
|
-
|
|
143
|
-
# Scrape React docs without a specific version (indexed as unversioned)
|
|
144
|
-
docs-mcp scrape react https://react.dev/
|
|
145
|
-
|
|
146
|
-
# Scrape partial version (will be stored as 7.0.0)
|
|
147
|
-
docs-mcp scrape semver --version 7 https://github.com/npm/node-semver
|
|
158
|
+
# Scrape React 18.2.0 docs (assuming global install)
|
|
159
|
+
docs-cli scrape react --version 18.2.0 https://react.dev/
|
|
148
160
|
|
|
149
|
-
# Scrape
|
|
150
|
-
docs-mcp scrape
|
|
161
|
+
# Scrape React docs without a specific version (using npx)
|
|
162
|
+
npx -y --package=@arabold/docs-mcp-server docs-cli scrape react https://react.dev/
|
|
151
163
|
```
|
|
152
164
|
|
|
153
165
|
### Searching Documentation (`search`)
|
|
@@ -155,7 +167,7 @@ docs-mcp scrape mylib --version 2.0.0-rc.1 https://mylib.com/docs
|
|
|
155
167
|
Searches the indexed documentation for a library, optionally filtering by version.
|
|
156
168
|
|
|
157
169
|
```bash
|
|
158
|
-
docs-
|
|
170
|
+
docs-cli search <library> <query> [options]
|
|
159
171
|
```
|
|
160
172
|
|
|
161
173
|
**Options:**
|
|
@@ -172,19 +184,10 @@ docs-mcp search <library> <query> [options]
|
|
|
172
184
|
|
|
173
185
|
```bash
|
|
174
186
|
# Search latest React docs for 'hooks'
|
|
175
|
-
docs-
|
|
176
|
-
|
|
177
|
-
# Search React 18.x docs for 'hooks'
|
|
178
|
-
docs-mcp search react --version 18.x 'hooks'
|
|
179
|
-
|
|
180
|
-
# Search React 17 docs (will match 17.x.x or older if 17.x.x not found)
|
|
181
|
-
docs-mcp search react --version 17 'hooks'
|
|
187
|
+
docs-cli search react 'hooks'
|
|
182
188
|
|
|
183
|
-
# Search
|
|
184
|
-
docs-mcp search react --version 18.
|
|
185
|
-
|
|
186
|
-
# Search only unversioned React docs
|
|
187
|
-
docs-mcp search react --version "" 'hooks'
|
|
189
|
+
# Search React 18.x docs for 'hooks' (using npx)
|
|
190
|
+
npx -y --package=@arabold/docs-mcp-server docs-cli search react --version 18.x 'hooks'
|
|
188
191
|
```
|
|
189
192
|
|
|
190
193
|
### Finding Available Versions (`find-version`)
|
|
@@ -192,7 +195,7 @@ docs-mcp search react --version "" 'hooks'
|
|
|
192
195
|
Checks the index for the best matching version for a library based on a target, and indicates if unversioned documents exist.
|
|
193
196
|
|
|
194
197
|
```bash
|
|
195
|
-
docs-
|
|
198
|
+
docs-cli find-version <library> [options]
|
|
196
199
|
```
|
|
197
200
|
|
|
198
201
|
**Options:**
|
|
@@ -203,13 +206,7 @@ docs-mcp find-version <library> [options]
|
|
|
203
206
|
|
|
204
207
|
```bash
|
|
205
208
|
# Find the latest indexed version for react
|
|
206
|
-
docs-
|
|
207
|
-
|
|
208
|
-
# Find the best match for react version 17.x
|
|
209
|
-
docs-mcp find-version react --version 17.x
|
|
210
|
-
|
|
211
|
-
# Find the best match for react version 17.0.0 (may fall back to older)
|
|
212
|
-
docs-mcp find-version react --version 17.0.0
|
|
209
|
+
docs-cli find-version react
|
|
213
210
|
```
|
|
214
211
|
|
|
215
212
|
### Listing Libraries (`list-libraries`)
|
|
@@ -217,7 +214,7 @@ docs-mcp find-version react --version 17.0.0
|
|
|
217
214
|
Lists all libraries currently indexed in the store.
|
|
218
215
|
|
|
219
216
|
```bash
|
|
220
|
-
docs-
|
|
217
|
+
docs-cli list-libraries
|
|
221
218
|
```
|
|
222
219
|
|
|
223
220
|
### Removing Documentation (`remove`)
|
|
@@ -225,7 +222,7 @@ docs-mcp list-libraries
|
|
|
225
222
|
Removes indexed documents for a specific library and version.
|
|
226
223
|
|
|
227
224
|
```bash
|
|
228
|
-
docs-
|
|
225
|
+
docs-cli remove <library> [options]
|
|
229
226
|
```
|
|
230
227
|
|
|
231
228
|
**Options:**
|
|
@@ -236,10 +233,7 @@ docs-mcp remove <library> [options]
|
|
|
236
233
|
|
|
237
234
|
```bash
|
|
238
235
|
# Remove React 18.2.0 docs
|
|
239
|
-
docs-
|
|
240
|
-
|
|
241
|
-
# Remove unversioned React docs
|
|
242
|
-
docs-mcp remove react
|
|
236
|
+
docs-cli remove react --version 18.2.0
|
|
243
237
|
```
|
|
244
238
|
|
|
245
239
|
### Version Handling Summary
|
|
@@ -248,70 +242,122 @@ docs-mcp remove react
|
|
|
248
242
|
- **Searching/Finding:** Accepts specific versions, partials, or ranges (`X.Y.Z`, `X.Y`, `X`, `X.x`). Falls back to the latest older version if the target doesn't match. Omitting the version targets the latest available. Explicitly searching `--version ""` targets unversioned documents.
|
|
249
243
|
- **Unversioned Docs:** Libraries can have documentation stored without a specific version (by omitting `--version` during scrape). These can be searched explicitly using `--version ""`. The `find-version` command will also report if unversioned docs exist alongside any semver matches.
|
|
250
244
|
|
|
251
|
-
## Development
|
|
245
|
+
## Development & Advanced Setup
|
|
252
246
|
|
|
253
|
-
|
|
247
|
+
This section covers running the server/CLI directly from the source code for development purposes. The primary usage method is now via the public Docker image as described in "Method 2".
|
|
254
248
|
|
|
255
|
-
|
|
249
|
+
### Running from Source (Development)
|
|
256
250
|
|
|
257
|
-
|
|
251
|
+
This provides an isolated environment and exposes the server via HTTP endpoints.
|
|
258
252
|
|
|
259
|
-
|
|
253
|
+
1. **Clone the repository:**
|
|
254
|
+
```bash
|
|
255
|
+
git clone https://github.com/arabold/docs-mcp-server.git # Replace with actual URL if different
|
|
256
|
+
cd docs-mcp-server
|
|
257
|
+
```
|
|
258
|
+
2. **Create `.env` file:**
|
|
259
|
+
Copy the example and add your OpenAI key (see "Environment Setup" below).
|
|
260
|
+
```bash
|
|
261
|
+
cp .env.example .env
|
|
262
|
+
# Edit .env and add your OPENAI_API_KEY
|
|
263
|
+
```
|
|
264
|
+
3. **Build the Docker image:**
|
|
265
|
+
```bash
|
|
266
|
+
docker build -t docs-mcp-server .
|
|
267
|
+
```
|
|
268
|
+
4. **Run the Docker container:**
|
|
260
269
|
|
|
261
|
-
|
|
270
|
+
```bash
|
|
271
|
+
# Option 1: Using a named volume (recommended)
|
|
272
|
+
# Docker automatically creates the volume 'docs-mcp-data' if it doesn't exist on first run.
|
|
273
|
+
docker run -i --env-file .env -v docs-mcp-data:/data --name docs-mcp-server docs-mcp-server
|
|
262
274
|
|
|
263
|
-
|
|
264
|
-
-
|
|
265
|
-
|
|
266
|
-
- Commits with `BREAKING CHANGE:` in the footer or `!` after the type/scope (e.g., `feat!:`) trigger a `major` release.
|
|
267
|
-
- Other types (`chore:`, `docs:`, `style:`, `refactor:`, `test:`, etc.) do not trigger a release by themselves.
|
|
268
|
-
2. **Automation:** When commits with release-triggering types (`feat`, `fix`, `BREAKING CHANGE`) are pushed or merged to the `main` branch, the "Release" GitHub Actions workflow automatically runs `semantic-release`.
|
|
269
|
-
3. **`semantic-release` Actions:** The tool performs the following steps automatically:
|
|
270
|
-
- Determines the next semantic version number based on the commits.
|
|
271
|
-
- Updates the `CHANGELOG.md` file with the relevant commits.
|
|
272
|
-
- Updates the `version` in `package.json`.
|
|
273
|
-
- Commits the updated `CHANGELOG.md` and `package.json`.
|
|
274
|
-
- Creates a Git tag for the new version (e.g., `v1.2.3`).
|
|
275
|
-
- Publishes the package to npm.
|
|
276
|
-
- Creates a corresponding GitHub Release with the generated release notes.
|
|
275
|
+
# Option 2: Mapping to a host directory
|
|
276
|
+
# docker run -i --env-file .env -v /path/on/your/host:/data --name docs-mcp-server docs-mcp-server
|
|
277
|
+
```
|
|
277
278
|
|
|
278
|
-
|
|
279
|
+
- `-i`: Keep STDIN open even if not attached. This is crucial for interacting with the server over stdio.
|
|
280
|
+
- `--env-file .env`: Loads environment variables (like `OPENAI_API_KEY`) from your local `.env` file.
|
|
281
|
+
- `-v docs-mcp-data:/data` or `-v /path/on/your/host:/data`: **Crucial for persistence.** This mounts a Docker named volume (Docker creates `docs-mcp-data` automatically if needed) or a host directory to the `/data` directory inside the container. The `/data` directory is where the server stores its `documents.db` file (as configured by `DOCS_MCP_STORE_PATH` in the Dockerfile). This ensures your indexed documentation persists even if the container is stopped or removed.
|
|
282
|
+
- `--name docs-mcp-server`: Assigns a convenient name to the container.
|
|
279
283
|
|
|
280
|
-
|
|
281
|
-
- **Merge to `main`:** Merge your feature branches into `main` when they are ready.
|
|
284
|
+
The server inside the container now runs directly using Node.js and communicates over **stdio**.
|
|
282
285
|
|
|
283
|
-
|
|
286
|
+
This method is useful for contributing to the project or running un-published versions.
|
|
284
287
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
-
|
|
288
|
-
-
|
|
289
|
-
|
|
288
|
+
1. **Clone the repository:**
|
|
289
|
+
```bash
|
|
290
|
+
git clone https://github.com/arabold/docs-mcp-server.git # Replace with actual URL if different
|
|
291
|
+
cd docs-mcp-server
|
|
292
|
+
```
|
|
293
|
+
2. **Install dependencies:**
|
|
294
|
+
```bash
|
|
295
|
+
npm install
|
|
296
|
+
```
|
|
297
|
+
3. **Build the project:**
|
|
298
|
+
This compiles TypeScript to JavaScript in the `dist/` directory.
|
|
299
|
+
```bash
|
|
300
|
+
npm run build
|
|
301
|
+
```
|
|
302
|
+
4. **Setup Environment:**
|
|
303
|
+
Create and configure your `.env` file as described in "Environment Setup" below. This is crucial for providing the `OPENAI_API_KEY`.
|
|
290
304
|
|
|
291
|
-
|
|
305
|
+
5. **Run:**
|
|
306
|
+
- **Server (Development Mode):** `npm run dev:server` (builds, watches, and restarts)
|
|
307
|
+
- **Server (Production Mode):** `npm run start` (runs pre-built code)
|
|
308
|
+
- **CLI:** `npm run cli -- <command> [options]` or `node dist/cli.js <command> [options]`
|
|
292
309
|
|
|
293
|
-
### Environment Setup
|
|
310
|
+
### Environment Setup (for Source/Docker)
|
|
294
311
|
|
|
295
|
-
**Note:** This `.env` file setup is primarily needed when running the server
|
|
312
|
+
**Note:** This `.env` file setup is primarily needed when running the server from source or using the Docker method. When using the `npx` integration method, the `OPENAI_API_KEY` is set directly in the MCP configuration file.
|
|
296
313
|
|
|
297
314
|
1. Create a `.env` file based on `.env.example`:
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
```
|
|
302
|
-
|
|
315
|
+
```bash
|
|
316
|
+
cp .env.example .env
|
|
317
|
+
```
|
|
303
318
|
2. Update your OpenAI API key in `.env`:
|
|
304
319
|
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
|
|
320
|
+
```
|
|
321
|
+
# Required: Your OpenAI API key for generating embeddings.
|
|
322
|
+
OPENAI_API_KEY=your-api-key-here
|
|
308
323
|
|
|
309
|
-
|
|
324
|
+
# Optional: Specify a custom directory to store the SQLite database file (documents.db).
|
|
325
|
+
# If set, this path takes precedence over the default locations.
|
|
326
|
+
# Default behavior (if unset):
|
|
327
|
+
# 1. Uses './.store/' in the project root if it exists (legacy).
|
|
328
|
+
# 2. Falls back to OS-specific data directory (e.g., ~/Library/Application Support/docs-mcp-server on macOS).
|
|
329
|
+
# DOCS_MCP_STORE_PATH=/path/to/your/desired/storage/directory
|
|
330
|
+
```
|
|
310
331
|
|
|
311
|
-
|
|
332
|
+
### Debugging (from Source)
|
|
333
|
+
|
|
334
|
+
Since MCP servers communicate over stdio when run directly via Node.js, debugging can be challenging. We recommend using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector), which is available as a package script after building:
|
|
312
335
|
|
|
313
336
|
```bash
|
|
314
337
|
npx @modelcontextprotocol/inspector node dist/server.js
|
|
315
338
|
```
|
|
316
339
|
|
|
317
340
|
The Inspector will provide a URL to access debugging tools in your browser.
|
|
341
|
+
|
|
342
|
+
### Releasing
|
|
343
|
+
|
|
344
|
+
This project uses [semantic-release](https://github.com/semantic-release/semantic-release) and [Conventional Commits](https://www.conventionalcommits.org/) to automate the release process.
|
|
345
|
+
|
|
346
|
+
**How it works:**
|
|
347
|
+
|
|
348
|
+
1. **Commit Messages:** All commits merged into the `main` branch **must** follow the Conventional Commits specification.
|
|
349
|
+
2. **Automation:** The "Release" GitHub Actions workflow automatically runs `semantic-release` on pushes to `main`.
|
|
350
|
+
3. **`semantic-release` Actions:** Determines version, updates `CHANGELOG.md` & `package.json`, commits, tags, publishes to npm, and creates a GitHub Release.
|
|
351
|
+
|
|
352
|
+
**What you need to do:**
|
|
353
|
+
|
|
354
|
+
- Use Conventional Commits.
|
|
355
|
+
- Merge to `main`.
|
|
356
|
+
|
|
357
|
+
**Automation handles:** Changelog, version bumps, tags, npm publish, GitHub releases.
|
|
358
|
+
|
|
359
|
+
### Architecture
|
|
360
|
+
|
|
361
|
+
For details on the project's architecture and design principles, please see [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
362
|
+
|
|
363
|
+
_Notably, the vast majority of this project's code was generated by the AI assistant Cline, leveraging the capabilities of this very MCP server._
|
|
@@ -1279,6 +1279,17 @@ var VersionNotFoundError = class extends ToolError {
|
|
|
1279
1279
|
return this.availableVersions.sort((a, b) => semver.compare(b.version, a.version))[0];
|
|
1280
1280
|
}
|
|
1281
1281
|
};
|
|
1282
|
+
var LibraryNotFoundError = class extends ToolError {
|
|
1283
|
+
constructor(requestedLibrary, suggestions = []) {
|
|
1284
|
+
let message = `Library '${requestedLibrary}' not found.`;
|
|
1285
|
+
if (suggestions.length > 0) {
|
|
1286
|
+
message += ` Did you mean one of these: ${suggestions.join(", ")}?`;
|
|
1287
|
+
}
|
|
1288
|
+
super(message, "SearchTool");
|
|
1289
|
+
this.requestedLibrary = requestedLibrary;
|
|
1290
|
+
this.suggestions = suggestions;
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1282
1293
|
|
|
1283
1294
|
// src/tools/SearchTool.ts
|
|
1284
1295
|
var SearchTool = class {
|
|
@@ -1292,6 +1303,7 @@ var SearchTool = class {
|
|
|
1292
1303
|
`\u{1F50D} Searching ${library}@${version} for: ${query}${exactMatch ? " (exact match)" : ""}`
|
|
1293
1304
|
);
|
|
1294
1305
|
try {
|
|
1306
|
+
await this.docService.validateLibraryExists(library);
|
|
1295
1307
|
let versionToSearch = version;
|
|
1296
1308
|
if (!exactMatch) {
|
|
1297
1309
|
const versionResult = await this.docService.findBestVersion(library, version);
|
|
@@ -1306,6 +1318,16 @@ var SearchTool = class {
|
|
|
1306
1318
|
logger.info(`\u2705 Found ${results.length} matching results`);
|
|
1307
1319
|
return { results };
|
|
1308
1320
|
} catch (error) {
|
|
1321
|
+
if (error instanceof LibraryNotFoundError) {
|
|
1322
|
+
logger.info(`\u2139\uFE0F Library not found: ${error.message}`);
|
|
1323
|
+
return {
|
|
1324
|
+
results: [],
|
|
1325
|
+
error: {
|
|
1326
|
+
message: error.message,
|
|
1327
|
+
suggestions: error.suggestions
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1309
1331
|
if (error instanceof VersionNotFoundError) {
|
|
1310
1332
|
logger.info(`\u2139\uFE0F Version not found: ${error.message}`);
|
|
1311
1333
|
return {
|
|
@@ -1657,8 +1679,10 @@ var RemoveTool = class {
|
|
|
1657
1679
|
};
|
|
1658
1680
|
|
|
1659
1681
|
// src/store/DocumentManagementService.ts
|
|
1660
|
-
import { mkdirSync } from "node:fs";
|
|
1682
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
1661
1683
|
import path3 from "node:path";
|
|
1684
|
+
import envPaths from "env-paths";
|
|
1685
|
+
import Fuse from "fuse.js";
|
|
1662
1686
|
import semver3 from "semver";
|
|
1663
1687
|
|
|
1664
1688
|
// src/splitter/SemanticMarkdownSplitter.ts
|
|
@@ -11250,8 +11274,33 @@ var DocumentManagementService = class {
|
|
|
11250
11274
|
return (version ?? "").toLowerCase();
|
|
11251
11275
|
}
|
|
11252
11276
|
constructor() {
|
|
11253
|
-
|
|
11254
|
-
|
|
11277
|
+
let dbPath;
|
|
11278
|
+
let dbDir;
|
|
11279
|
+
const envStorePath = process.env.DOCS_MCP_STORE_PATH;
|
|
11280
|
+
if (envStorePath) {
|
|
11281
|
+
dbDir = envStorePath;
|
|
11282
|
+
dbPath = path3.join(dbDir, "documents.db");
|
|
11283
|
+
logger.debug(`\u{1F4BE} Using database directory from DOCS_MCP_STORE_PATH: ${dbDir}`);
|
|
11284
|
+
} else {
|
|
11285
|
+
const oldDbDir = path3.join(process.cwd(), ".store");
|
|
11286
|
+
const oldDbPath = path3.join(oldDbDir, "documents.db");
|
|
11287
|
+
const oldDbExists = existsSync(oldDbPath);
|
|
11288
|
+
if (oldDbExists) {
|
|
11289
|
+
dbPath = oldDbPath;
|
|
11290
|
+
dbDir = oldDbDir;
|
|
11291
|
+
logger.debug(`\u{1F4BE} Using legacy database path: ${dbPath}`);
|
|
11292
|
+
} else {
|
|
11293
|
+
const standardPaths = envPaths("docs-mcp-server", { suffix: "" });
|
|
11294
|
+
dbDir = standardPaths.data;
|
|
11295
|
+
dbPath = path3.join(dbDir, "documents.db");
|
|
11296
|
+
logger.debug(`\u{1F4BE} Using standard database directory: ${dbDir}`);
|
|
11297
|
+
}
|
|
11298
|
+
}
|
|
11299
|
+
try {
|
|
11300
|
+
mkdirSync(dbDir, { recursive: true });
|
|
11301
|
+
} catch (error) {
|
|
11302
|
+
logger.error(`\u26A0\uFE0F Failed to create database directory ${dbDir}: ${error}`);
|
|
11303
|
+
}
|
|
11255
11304
|
this.store = new DocumentStore(dbPath);
|
|
11256
11305
|
this.documentRetriever = new DocumentRetrieverService(this.store);
|
|
11257
11306
|
const minChunkSize = 500;
|
|
@@ -11264,16 +11313,53 @@ var DocumentManagementService = class {
|
|
|
11264
11313
|
);
|
|
11265
11314
|
this.splitter = greedySplitter;
|
|
11266
11315
|
}
|
|
11316
|
+
/**
|
|
11317
|
+
* Initializes the underlying document store.
|
|
11318
|
+
*/
|
|
11267
11319
|
async initialize() {
|
|
11268
11320
|
await this.store.initialize();
|
|
11269
11321
|
}
|
|
11322
|
+
/**
|
|
11323
|
+
* Shuts down the underlying document store.
|
|
11324
|
+
*/
|
|
11270
11325
|
async shutdown() {
|
|
11271
11326
|
logger.info("\u{1F50C} Shutting down store manager");
|
|
11272
11327
|
await this.store.shutdown();
|
|
11273
11328
|
}
|
|
11274
11329
|
/**
|
|
11275
|
-
*
|
|
11276
|
-
*
|
|
11330
|
+
* Validates if a library exists in the store (either versioned or unversioned).
|
|
11331
|
+
* Throws LibraryNotFoundError with suggestions if the library is not found.
|
|
11332
|
+
* @param library The name of the library to validate.
|
|
11333
|
+
* @throws {LibraryNotFoundError} If the library does not exist.
|
|
11334
|
+
*/
|
|
11335
|
+
async validateLibraryExists(library) {
|
|
11336
|
+
logger.info(`\u{1F50E} Validating existence of library: ${library}`);
|
|
11337
|
+
const normalizedLibrary = library.toLowerCase();
|
|
11338
|
+
const versions = await this.listVersions(normalizedLibrary);
|
|
11339
|
+
const hasUnversioned = await this.exists(normalizedLibrary, "");
|
|
11340
|
+
if (versions.length === 0 && !hasUnversioned) {
|
|
11341
|
+
logger.warn(`\u26A0\uFE0F Library '${library}' not found.`);
|
|
11342
|
+
const allLibraries = await this.listLibraries();
|
|
11343
|
+
const libraryNames = allLibraries.map((lib) => lib.library);
|
|
11344
|
+
let suggestions = [];
|
|
11345
|
+
if (libraryNames.length > 0) {
|
|
11346
|
+
const fuse = new Fuse(libraryNames, {
|
|
11347
|
+
// Configure fuse.js options if needed (e.g., threshold)
|
|
11348
|
+
// isCaseSensitive: false, // Handled by normalizing library names
|
|
11349
|
+
// includeScore: true,
|
|
11350
|
+
threshold: 0.4
|
|
11351
|
+
// Adjust threshold for desired fuzziness (0=exact, 1=match anything)
|
|
11352
|
+
});
|
|
11353
|
+
const results = fuse.search(normalizedLibrary);
|
|
11354
|
+
suggestions = results.slice(0, 3).map((result) => result.item);
|
|
11355
|
+
logger.info(`\u{1F50D} Found suggestions: ${suggestions.join(", ")}`);
|
|
11356
|
+
}
|
|
11357
|
+
throw new LibraryNotFoundError(library, suggestions);
|
|
11358
|
+
}
|
|
11359
|
+
logger.info(`\u2705 Library '${library}' confirmed to exist.`);
|
|
11360
|
+
}
|
|
11361
|
+
/**
|
|
11362
|
+
* Returns a list of all available semantic versions for a library.
|
|
11277
11363
|
*/
|
|
11278
11364
|
async listVersions(library) {
|
|
11279
11365
|
const versions = await this.store.queryUniqueVersions(library);
|
|
@@ -11438,4 +11524,4 @@ export {
|
|
|
11438
11524
|
RemoveTool,
|
|
11439
11525
|
DocumentManagementService
|
|
11440
11526
|
};
|
|
11441
|
-
//# sourceMappingURL=chunk-
|
|
11527
|
+
//# sourceMappingURL=chunk-BD7OFN4H.js.map
|