@vdpeijl/kb-mcp 0.1.2

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.
Files changed (106) hide show
  1. package/README.md +416 -0
  2. package/dist/scripts/postinstall.d.ts +3 -0
  3. package/dist/scripts/postinstall.d.ts.map +1 -0
  4. package/dist/scripts/postinstall.js +110 -0
  5. package/dist/scripts/postinstall.js.map +1 -0
  6. package/dist/src/cli.d.ts +3 -0
  7. package/dist/src/cli.d.ts.map +1 -0
  8. package/dist/src/cli.js +22 -0
  9. package/dist/src/cli.js.map +1 -0
  10. package/dist/src/commands/doctor.d.ts +3 -0
  11. package/dist/src/commands/doctor.d.ts.map +1 -0
  12. package/dist/src/commands/doctor.js +93 -0
  13. package/dist/src/commands/doctor.js.map +1 -0
  14. package/dist/src/commands/init.d.ts +3 -0
  15. package/dist/src/commands/init.d.ts.map +1 -0
  16. package/dist/src/commands/init.js +150 -0
  17. package/dist/src/commands/init.js.map +1 -0
  18. package/dist/src/commands/serve.d.ts +3 -0
  19. package/dist/src/commands/serve.d.ts.map +1 -0
  20. package/dist/src/commands/serve.js +22 -0
  21. package/dist/src/commands/serve.js.map +1 -0
  22. package/dist/src/commands/setup.d.ts +9 -0
  23. package/dist/src/commands/setup.d.ts.map +1 -0
  24. package/dist/src/commands/setup.js +115 -0
  25. package/dist/src/commands/setup.js.map +1 -0
  26. package/dist/src/commands/sources.d.ts +3 -0
  27. package/dist/src/commands/sources.d.ts.map +1 -0
  28. package/dist/src/commands/sources.js +258 -0
  29. package/dist/src/commands/sources.js.map +1 -0
  30. package/dist/src/commands/stats.d.ts +3 -0
  31. package/dist/src/commands/stats.d.ts.map +1 -0
  32. package/dist/src/commands/stats.js +48 -0
  33. package/dist/src/commands/stats.js.map +1 -0
  34. package/dist/src/commands/sync.d.ts +13 -0
  35. package/dist/src/commands/sync.d.ts.map +1 -0
  36. package/dist/src/commands/sync.js +106 -0
  37. package/dist/src/commands/sync.js.map +1 -0
  38. package/dist/src/config/index.d.ts +18 -0
  39. package/dist/src/config/index.d.ts.map +1 -0
  40. package/dist/src/config/index.js +67 -0
  41. package/dist/src/config/index.js.map +1 -0
  42. package/dist/src/config/paths.d.ts +21 -0
  43. package/dist/src/config/paths.d.ts.map +1 -0
  44. package/dist/src/config/paths.js +38 -0
  45. package/dist/src/config/paths.js.map +1 -0
  46. package/dist/src/config/schema.d.ts +133 -0
  47. package/dist/src/config/schema.d.ts.map +1 -0
  48. package/dist/src/config/schema.js +34 -0
  49. package/dist/src/config/schema.js.map +1 -0
  50. package/dist/src/db/articles.d.ts +39 -0
  51. package/dist/src/db/articles.d.ts.map +1 -0
  52. package/dist/src/db/articles.js +103 -0
  53. package/dist/src/db/articles.js.map +1 -0
  54. package/dist/src/db/chunks.d.ts +46 -0
  55. package/dist/src/db/chunks.d.ts.map +1 -0
  56. package/dist/src/db/chunks.js +129 -0
  57. package/dist/src/db/chunks.js.map +1 -0
  58. package/dist/src/db/index.d.ts +19 -0
  59. package/dist/src/db/index.d.ts.map +1 -0
  60. package/dist/src/db/index.js +86 -0
  61. package/dist/src/db/index.js.map +1 -0
  62. package/dist/src/db/schema.d.ts +10 -0
  63. package/dist/src/db/schema.d.ts.map +1 -0
  64. package/dist/src/db/schema.js +80 -0
  65. package/dist/src/db/schema.js.map +1 -0
  66. package/dist/src/db/sources.d.ts +48 -0
  67. package/dist/src/db/sources.d.ts.map +1 -0
  68. package/dist/src/db/sources.js +110 -0
  69. package/dist/src/db/sources.js.map +1 -0
  70. package/dist/src/index.d.ts +8 -0
  71. package/dist/src/index.d.ts.map +1 -0
  72. package/dist/src/index.js +87 -0
  73. package/dist/src/index.js.map +1 -0
  74. package/dist/src/search/embeddings.d.ts +22 -0
  75. package/dist/src/search/embeddings.d.ts.map +1 -0
  76. package/dist/src/search/embeddings.js +122 -0
  77. package/dist/src/search/embeddings.js.map +1 -0
  78. package/dist/src/search/index.d.ts +21 -0
  79. package/dist/src/search/index.d.ts.map +1 -0
  80. package/dist/src/search/index.js +50 -0
  81. package/dist/src/search/index.js.map +1 -0
  82. package/dist/src/sync/chunker.d.ts +15 -0
  83. package/dist/src/sync/chunker.d.ts.map +1 -0
  84. package/dist/src/sync/chunker.js +117 -0
  85. package/dist/src/sync/chunker.js.map +1 -0
  86. package/dist/src/sync/index.d.ts +24 -0
  87. package/dist/src/sync/index.d.ts.map +1 -0
  88. package/dist/src/sync/index.js +180 -0
  89. package/dist/src/sync/index.js.map +1 -0
  90. package/dist/src/sync/parser.d.ts +9 -0
  91. package/dist/src/sync/parser.d.ts.map +1 -0
  92. package/dist/src/sync/parser.js +91 -0
  93. package/dist/src/sync/parser.js.map +1 -0
  94. package/dist/src/sync/zendesk.d.ts +45 -0
  95. package/dist/src/sync/zendesk.d.ts.map +1 -0
  96. package/dist/src/sync/zendesk.js +161 -0
  97. package/dist/src/sync/zendesk.js.map +1 -0
  98. package/dist/src/utils/errors.d.ts +39 -0
  99. package/dist/src/utils/errors.d.ts.map +1 -0
  100. package/dist/src/utils/errors.js +62 -0
  101. package/dist/src/utils/errors.js.map +1 -0
  102. package/dist/src/utils/logger.d.ts +21 -0
  103. package/dist/src/utils/logger.d.ts.map +1 -0
  104. package/dist/src/utils/logger.js +25 -0
  105. package/dist/src/utils/logger.js.map +1 -0
  106. package/package.json +57 -0
package/README.md ADDED
@@ -0,0 +1,416 @@
1
+ # @vdpeijl/kb-mcp
2
+
3
+ MCP (Model Context Protocol) server that indexes multiple Zendesk Help Center knowledge bases and exposes them as searchable tools for AI coding assistants.
4
+
5
+ ## Features
6
+
7
+ - šŸ” **Vector Search**: Semantic search using Ollama embeddings (nomic-embed-text)
8
+ - šŸ“š **Multiple Sources**: Index and search across multiple Zendesk knowledge bases
9
+ - šŸ”„ **Incremental Sync**: Efficient updates - only process changed articles
10
+ - šŸš€ **Easy Setup**: Interactive CLI wizard for first-time configuration
11
+ - šŸŽÆ **MCP Compatible**: Works with Claude Code, Cursor, Windsurf, Continue.dev, and Zed
12
+
13
+ ## Prerequisites
14
+
15
+ ### Node.js 20+
16
+
17
+ Check your version:
18
+ ```bash
19
+ node --version
20
+ ```
21
+
22
+ If you need to install or update Node.js, visit [nodejs.org](https://nodejs.org)
23
+
24
+ ### Ollama
25
+
26
+ Ollama is required for generating embeddings.
27
+
28
+ **macOS:**
29
+ ```bash
30
+ brew install ollama
31
+ ```
32
+
33
+ **Linux:**
34
+ ```bash
35
+ curl -fsSL https://ollama.com/install.sh | sh
36
+ ```
37
+
38
+ **Arch Linux:**
39
+ ```bash
40
+ pacman -S ollama
41
+ ```
42
+
43
+ **Start Ollama and pull the embedding model:**
44
+ ```bash
45
+ ollama serve &
46
+ ollama pull nomic-embed-text
47
+ ```
48
+
49
+ ## Installation
50
+
51
+ ### From npm (once published)
52
+
53
+ ```bash
54
+ npm install -g @vdpeijl/kb-mcp
55
+ ```
56
+
57
+ ### From source (during development)
58
+
59
+ ```bash
60
+ git clone https://github.com/paragin/kb-mcp.git
61
+ cd kb-mcp
62
+ npm install
63
+ npm run build
64
+ npm link
65
+ ```
66
+
67
+ ## Quick Start
68
+
69
+ ### 1. Run interactive setup
70
+
71
+ ```bash
72
+ kb-mcp init
73
+ ```
74
+
75
+ This will:
76
+ - Check if Ollama is running
77
+ - Verify the embedding model is available
78
+ - Help you add your first knowledge base
79
+ - Create the configuration file
80
+
81
+ ### 2. Sync your knowledge base
82
+
83
+ ```bash
84
+ kb-mcp sync
85
+ ```
86
+
87
+ This will:
88
+ - Fetch all articles from your Zendesk Help Center
89
+ - Parse HTML content
90
+ - Split into chunks (~500 tokens with overlap)
91
+ - Generate embeddings using Ollama
92
+ - Store in a local SQLite database with vector search
93
+
94
+ ### 3. Configure your MCP client
95
+
96
+ ```bash
97
+ kb-mcp setup cursor # or: claude-code, windsurf, continue, zed
98
+ ```
99
+
100
+ Copy the printed configuration to your MCP client's config file.
101
+
102
+ ### 4. Restart your MCP client
103
+
104
+ The knowledge base will now be available for search!
105
+
106
+ ## Commands
107
+
108
+ ### `kb-mcp init`
109
+
110
+ Interactive setup wizard. Creates configuration and helps you add your first knowledge base.
111
+
112
+ ### `kb-mcp sync`
113
+
114
+ Sync all enabled knowledge bases. Only processes articles that have changed since the last sync.
115
+
116
+ **Options:**
117
+ - `--source <id>` - Sync specific source only
118
+ - `--full` - Full re-sync (re-embed everything)
119
+
120
+ **Examples:**
121
+ ```bash
122
+ kb-mcp sync # Sync all enabled sources
123
+ kb-mcp sync --source myco # Sync specific source
124
+ kb-mcp sync --full # Full re-sync
125
+ ```
126
+
127
+ ### `kb-mcp sources`
128
+
129
+ Manage knowledge base sources.
130
+
131
+ **Subcommands:**
132
+ - `list` - List all sources with stats (default)
133
+ - `add` - Add a new source (interactive or with flags)
134
+ - `remove <id>` - Remove a source and its data
135
+ - `enable <id>` - Enable a disabled source
136
+ - `disable <id>` - Disable without removing data
137
+
138
+ **Examples:**
139
+ ```bash
140
+ kb-mcp sources # List all sources
141
+ kb-mcp sources add # Interactive add
142
+ kb-mcp sources add --id myco --name "My Company" --url https://support.myco.com --locale en-us
143
+ kb-mcp sources remove myco # Remove source
144
+ kb-mcp sources disable myco # Disable source
145
+ kb-mcp sources enable myco # Enable source
146
+ ```
147
+
148
+ ### `kb-mcp serve`
149
+
150
+ Start the MCP server (stdio). This is normally called by your MCP client, not manually.
151
+
152
+ ### `kb-mcp setup [client]`
153
+
154
+ Print MCP client configuration. Supports: claude-code, cursor, windsurf, continue, zed.
155
+
156
+ **Examples:**
157
+ ```bash
158
+ kb-mcp setup # List all clients
159
+ kb-mcp setup cursor # Show config for Cursor
160
+ ```
161
+
162
+ ### `kb-mcp doctor`
163
+
164
+ Run diagnostics to check:
165
+ - Node.js version
166
+ - Configuration validity
167
+ - Ollama connection
168
+ - Embedding model availability
169
+ - Database accessibility
170
+ - sqlite-vec extension
171
+
172
+ ### `kb-mcp stats`
173
+
174
+ Show database statistics:
175
+ - Total sources, articles, chunks
176
+ - Database file size
177
+ - Per-source breakdown
178
+
179
+ ## MCP Client Configuration
180
+
181
+ ### Claude Code
182
+
183
+ Add to `~/.claude/claude_desktop_config.json`:
184
+
185
+ ```json
186
+ {
187
+ "mcpServers": {
188
+ "knowledge-base": {
189
+ "command": "kb-mcp",
190
+ "args": ["serve"]
191
+ }
192
+ }
193
+ }
194
+ ```
195
+
196
+ ### Cursor
197
+
198
+ Go to **Settings → Features → MCP Servers**, then add:
199
+
200
+ ```json
201
+ {
202
+ "mcpServers": {
203
+ "knowledge-base": {
204
+ "command": "kb-mcp",
205
+ "args": ["serve"]
206
+ }
207
+ }
208
+ }
209
+ ```
210
+
211
+ ### Windsurf
212
+
213
+ Add to `~/.codeium/windsurf/mcp_config.json`:
214
+
215
+ ```json
216
+ {
217
+ "mcpServers": {
218
+ "knowledge-base": {
219
+ "command": "kb-mcp",
220
+ "args": ["serve"]
221
+ }
222
+ }
223
+ }
224
+ ```
225
+
226
+ ### Continue.dev
227
+
228
+ Add to `~/.continue/config.json`:
229
+
230
+ ```json
231
+ {
232
+ "experimental": {
233
+ "modelContextProtocolServers": [
234
+ {
235
+ "transport": {
236
+ "type": "stdio",
237
+ "command": "kb-mcp",
238
+ "args": ["serve"]
239
+ }
240
+ }
241
+ ]
242
+ }
243
+ }
244
+ ```
245
+
246
+ ### Zed
247
+
248
+ Add to `~/.config/zed/settings.json`:
249
+
250
+ ```json
251
+ {
252
+ "context_servers": {
253
+ "knowledge-base": {
254
+ "command": {
255
+ "path": "kb-mcp",
256
+ "args": ["serve"]
257
+ }
258
+ }
259
+ }
260
+ }
261
+ ```
262
+
263
+ ## MCP Tools
264
+
265
+ The server exposes two tools to MCP clients:
266
+
267
+ ### `search_knowledge_base`
268
+
269
+ Search the knowledge base for documentation, guides, and help articles.
270
+
271
+ **Parameters:**
272
+ - `query` (required): Natural language search query
273
+ - `sources` (optional): Filter by source IDs (array of strings)
274
+ - `limit` (optional): Maximum results (default: 5, max: 20)
275
+
276
+ **Example usage in Claude Code:**
277
+ > "Search the knowledge base for how to create a new user account"
278
+
279
+ ### `list_sources`
280
+
281
+ List all configured knowledge base sources and their sync status.
282
+
283
+ **Example usage in Claude Code:**
284
+ > "List available knowledge bases"
285
+
286
+ ## Configuration
287
+
288
+ Configuration is stored in XDG-compliant locations:
289
+
290
+ - **Config**: `~/.config/kb-mcp/config.json`
291
+ - **Data**: `~/.local/share/kb-mcp/kb.sqlite`
292
+ - **Logs**: `~/.local/share/kb-mcp/logs/`
293
+
294
+ On Windows, these paths use `%APPDATA%` and `%LOCALAPPDATA%` instead.
295
+
296
+ ### Config file structure
297
+
298
+ ```json
299
+ {
300
+ "ollama": {
301
+ "baseUrl": "http://localhost:11434",
302
+ "model": "nomic-embed-text"
303
+ },
304
+ "sync": {
305
+ "chunkSize": 500,
306
+ "chunkOverlap": 50
307
+ },
308
+ "sources": [
309
+ {
310
+ "id": "myco",
311
+ "name": "My Company",
312
+ "baseUrl": "https://support.myco.com",
313
+ "locale": "en-us",
314
+ "enabled": true
315
+ }
316
+ ]
317
+ }
318
+ ```
319
+
320
+ ## Debug Logging
321
+
322
+ Enable debug logging with the `DEBUG` environment variable:
323
+
324
+ ```bash
325
+ DEBUG=kb-mcp:* kb-mcp sync
326
+ ```
327
+
328
+ Available namespaces:
329
+ - `kb-mcp:sync` - Sync operations
330
+ - `kb-mcp:embed` - Embedding generation
331
+ - `kb-mcp:search` - Search operations
332
+ - `kb-mcp:mcp` - MCP server
333
+ - `kb-mcp:db` - Database operations
334
+ - `kb-mcp:cli` - CLI commands
335
+
336
+ ## Troubleshooting
337
+
338
+ ### Cannot connect to Ollama
339
+
340
+ Make sure Ollama is running:
341
+ ```bash
342
+ ollama serve
343
+ ```
344
+
345
+ Check if it's accessible:
346
+ ```bash
347
+ curl http://localhost:11434/api/tags
348
+ ```
349
+
350
+ ### Model not found
351
+
352
+ Pull the embedding model:
353
+ ```bash
354
+ ollama pull nomic-embed-text
355
+ ```
356
+
357
+ ### sqlite-vec extension not loaded
358
+
359
+ Try reinstalling:
360
+ ```bash
361
+ npm install -g @vdpeijl/kb-mcp --force
362
+ ```
363
+
364
+ Or manually download from: https://github.com/asg017/sqlite-vec/releases
365
+
366
+ ### Rate limited by Zendesk
367
+
368
+ The sync process includes exponential backoff for rate limiting. If you're still hitting limits, try:
369
+ - Syncing one source at a time: `kb-mcp sync --source <id>`
370
+ - Waiting a few minutes between syncs
371
+
372
+ ## Testing
373
+
374
+ ### Test MCP server with Inspector
375
+
376
+ ```bash
377
+ npx @modelcontextprotocol/inspector kb-mcp serve
378
+ ```
379
+
380
+ This opens a web interface where you can:
381
+ - See available tools
382
+ - Call tools with test queries
383
+ - Inspect responses
384
+
385
+ ## Development
386
+
387
+ ### Publishing a new version
388
+
389
+ This project uses GitHub Actions to automatically publish to npm when the version changes in `package.json`.
390
+
391
+ To release a new version:
392
+
393
+ ```bash
394
+ # Bump version (choose one)
395
+ npm version patch # Bug fixes (0.1.0 → 0.1.1)
396
+ npm version minor # New features (0.1.0 → 0.2.0)
397
+ npm version major # Breaking changes (0.1.0 → 1.0.0)
398
+
399
+ # Push to GitHub (this triggers the publish workflow)
400
+ git push origin main --follow-tags
401
+ ```
402
+
403
+ The GitHub Action will automatically:
404
+ - Build the project
405
+ - Publish to npm
406
+ - Create a GitHub release
407
+
408
+ See [.github/workflows/README.md](.github/workflows/README.md) for setup instructions.
409
+
410
+ ## License
411
+
412
+ MIT
413
+
414
+ ## Author
415
+
416
+ vdpeijl
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=postinstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postinstall.d.ts","sourceRoot":"","sources":["../../scripts/postinstall.ts"],"names":[],"mappings":""}
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env node
2
+ import { mkdir, chmod } from 'node:fs/promises';
3
+ import { get } from 'node:https';
4
+ import { join, dirname } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { createGunzip } from 'node:zlib';
7
+ import { extract } from 'tar';
8
+ const __dirname = dirname(fileURLToPath(import.meta.url));
9
+ const SQLITE_VEC_VERSION = '0.1.6';
10
+ // Map platform to archive name and extracted file
11
+ const PLATFORM_MAP = {
12
+ 'darwin-arm64': {
13
+ archive: 'sqlite-vec-0.1.6-loadable-macos-aarch64.tar.gz',
14
+ file: 'vec0.dylib',
15
+ },
16
+ 'darwin-x64': {
17
+ archive: 'sqlite-vec-0.1.6-loadable-macos-x86_64.tar.gz',
18
+ file: 'vec0.dylib',
19
+ },
20
+ 'linux-x64': {
21
+ archive: 'sqlite-vec-0.1.6-loadable-linux-x86_64.tar.gz',
22
+ file: 'vec0.so',
23
+ },
24
+ 'win32-x64': {
25
+ archive: 'sqlite-vec-0.1.6-loadable-windows-x86_64.tar.gz',
26
+ file: 'vec0.dll',
27
+ },
28
+ };
29
+ function getPlatformKey() {
30
+ const platform = process.platform;
31
+ const arch = process.arch;
32
+ return `${platform}-${arch}`;
33
+ }
34
+ function downloadAndExtract(url, dest) {
35
+ return new Promise((resolve, reject) => {
36
+ get(url, (response) => {
37
+ // Handle redirects
38
+ if (response.statusCode === 302 || response.statusCode === 301) {
39
+ const redirectUrl = response.headers.location;
40
+ if (!redirectUrl) {
41
+ reject(new Error('Redirect without location header'));
42
+ return;
43
+ }
44
+ // Recursively handle redirect
45
+ downloadAndExtract(redirectUrl, dest).then(resolve).catch(reject);
46
+ return;
47
+ }
48
+ if (response.statusCode !== 200) {
49
+ reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
50
+ return;
51
+ }
52
+ // Create gunzip stream
53
+ const gunzip = createGunzip();
54
+ // Create tar extract stream
55
+ const extractor = extract({
56
+ cwd: dest,
57
+ strip: 0, // Don't strip directories
58
+ });
59
+ // Pipe the response through gunzip and tar extract
60
+ response
61
+ .pipe(gunzip)
62
+ .pipe(extractor)
63
+ .on('finish', () => resolve())
64
+ .on('error', (err) => reject(err));
65
+ }).on('error', (err) => {
66
+ reject(err);
67
+ });
68
+ });
69
+ }
70
+ async function main() {
71
+ try {
72
+ const platformKey = getPlatformKey();
73
+ const platformInfo = PLATFORM_MAP[platformKey];
74
+ if (!platformInfo) {
75
+ throw new Error(`Unsupported platform: ${platformKey}. ` +
76
+ `Supported platforms: ${Object.keys(PLATFORM_MAP).join(', ')}`);
77
+ }
78
+ const { archive, file } = platformInfo;
79
+ const url = `https://github.com/asg017/sqlite-vec/releases/download/v${SQLITE_VEC_VERSION}/${archive}`;
80
+ const nativeDir = join(__dirname, '..', 'native');
81
+ console.log(`Downloading sqlite-vec for ${platformKey}...`);
82
+ console.log(`URL: ${url}`);
83
+ // Ensure native directory exists
84
+ await mkdir(nativeDir, { recursive: true });
85
+ // Download and extract
86
+ await downloadAndExtract(url, nativeDir);
87
+ // Verify the file exists
88
+ const extractedFile = join(nativeDir, file);
89
+ console.log(`āœ“ sqlite-vec extracted to ${extractedFile}`);
90
+ // Make executable on Unix-like systems
91
+ if (process.platform !== 'win32') {
92
+ await chmod(extractedFile, 0o755);
93
+ }
94
+ }
95
+ catch (error) {
96
+ if (error instanceof Error) {
97
+ console.error(`āœ— Failed to download sqlite-vec: ${error.message}`);
98
+ // Don't fail installation, just warn
99
+ console.warn('⚠ sqlite-vec extension not installed. You may need to manually download it.');
100
+ console.warn(` Visit: https://github.com/asg017/sqlite-vec/releases/tag/v${SQLITE_VEC_VERSION}`);
101
+ }
102
+ else {
103
+ console.error('āœ— Unknown error during postinstall');
104
+ }
105
+ // Exit with 0 to not break npm install
106
+ process.exit(0);
107
+ }
108
+ }
109
+ main();
110
+ //# sourceMappingURL=postinstall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postinstall.js","sourceRoot":"","sources":["../../scripts/postinstall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ import { defineCommand, runMain } from 'citty';
3
+ import { exitWithError } from './utils/errors.js';
4
+ const main = defineCommand({
5
+ meta: {
6
+ name: 'kb-mcp',
7
+ version: '0.1.0',
8
+ description: 'MCP server for searching Zendesk knowledge bases',
9
+ },
10
+ subCommands: {
11
+ serve: () => import('./commands/serve.js').then(m => m.default),
12
+ init: () => import('./commands/init.js').then(m => m.default),
13
+ sync: () => import('./commands/sync.js').then(m => m.default),
14
+ sources: () => import('./commands/sources.js').then(m => m.default),
15
+ setup: () => import('./commands/setup.js').then(m => m.default),
16
+ doctor: () => import('./commands/doctor.js').then(m => m.default),
17
+ stats: () => import('./commands/stats.js').then(m => m.default),
18
+ },
19
+ });
20
+ // Run CLI
21
+ runMain(main).catch(exitWithError);
22
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,IAAI,GAAG,aAAa,CAAC;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,kDAAkD;KAChE;IACD,WAAW,EAAE;QACX,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/D,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7D,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC7D,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACnE,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/D,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QACjE,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;KAChE;CACF,CAAC,CAAC;AAEH,UAAU;AACV,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("citty").CommandDef<import("citty").ArgsDef>;
2
+ export default _default;
3
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/commands/doctor.ts"],"names":[],"mappings":";AAMA,wBA2FG"}
@@ -0,0 +1,93 @@
1
+ import { defineCommand } from 'citty';
2
+ import { getDatabase } from '../db/index.js';
3
+ import { checkOllamaConnection, checkModelAvailable } from '../search/embeddings.js';
4
+ import { configExists, loadConfig } from '../config/index.js';
5
+ import { exitWithError } from '../utils/errors.js';
6
+ export default defineCommand({
7
+ meta: {
8
+ name: 'doctor',
9
+ description: 'Check system requirements and configuration',
10
+ },
11
+ async run() {
12
+ try {
13
+ console.log('\nšŸ„ Running diagnostics...\n');
14
+ let allGood = true;
15
+ // Check Node.js version
16
+ const nodeVersion = process.version;
17
+ const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
18
+ if (majorVersion >= 20) {
19
+ console.log(`āœ“ Node.js ${nodeVersion} (>= 20.0.0)`);
20
+ }
21
+ else {
22
+ console.log(`āœ— Node.js ${nodeVersion} (requires >= 20.0.0)`);
23
+ allGood = false;
24
+ }
25
+ // Check config exists
26
+ if (configExists()) {
27
+ console.log('āœ“ Configuration file exists');
28
+ try {
29
+ const config = await loadConfig();
30
+ console.log('āœ“ Configuration is valid');
31
+ // Check Ollama connection
32
+ const ollamaConnected = await checkOllamaConnection(config.ollama);
33
+ if (ollamaConnected) {
34
+ console.log(`āœ“ Ollama running at ${config.ollama.baseUrl}`);
35
+ // Check model available
36
+ const modelAvailable = await checkModelAvailable(config.ollama);
37
+ if (modelAvailable) {
38
+ console.log(`āœ“ Model '${config.ollama.model}' available`);
39
+ }
40
+ else {
41
+ console.log(`āœ— Model '${config.ollama.model}' not found`);
42
+ console.log(`\n Pull it with:`);
43
+ console.log(` ollama pull ${config.ollama.model}\n`);
44
+ allGood = false;
45
+ }
46
+ }
47
+ else {
48
+ console.log(`āœ— Cannot connect to Ollama at ${config.ollama.baseUrl}`);
49
+ console.log(`\n Make sure Ollama is running:`);
50
+ console.log(` ollama serve\n`);
51
+ allGood = false;
52
+ }
53
+ }
54
+ catch (error) {
55
+ console.log(`āœ— Configuration error: ${error instanceof Error ? error.message : 'Unknown error'}`);
56
+ allGood = false;
57
+ }
58
+ }
59
+ else {
60
+ console.log('āœ— Configuration file not found');
61
+ console.log(`\n Run 'kb-mcp init' to create configuration\n`);
62
+ allGood = false;
63
+ }
64
+ // Check database
65
+ try {
66
+ const db = await getDatabase();
67
+ console.log('āœ“ Database accessible');
68
+ // Check sqlite-vec extension
69
+ const versionQuery = db.prepare('SELECT vec_version() as version');
70
+ const result = versionQuery.get();
71
+ console.log(`āœ“ sqlite-vec extension loaded (v${result.version})`);
72
+ }
73
+ catch (error) {
74
+ console.log('āœ— Database error');
75
+ console.log(`\n ${error instanceof Error ? error.message : 'Unknown error'}\n`);
76
+ allGood = false;
77
+ }
78
+ console.log();
79
+ if (allGood) {
80
+ console.log('āœ… All checks passed!\n');
81
+ process.exit(0);
82
+ }
83
+ else {
84
+ console.log('āš ļø Some checks failed. Please fix the issues above.\n');
85
+ process.exit(1);
86
+ }
87
+ }
88
+ catch (error) {
89
+ exitWithError(error);
90
+ }
91
+ },
92
+ });
93
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("citty").CommandDef<import("citty").ArgsDef>;
2
+ export default _default;
3
+ //# sourceMappingURL=init.d.ts.map