gitlab-docs-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +130 -0
  3. package/data/gitlab-docs/documents.json +38252 -0
  4. package/data/gitlab-docs/index_meta.json +6 -0
  5. package/dist/bin.js +2 -0
  6. package/dist/config.d.ts +24 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +54 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/content/cache.d.ts +51 -0
  11. package/dist/content/cache.d.ts.map +1 -0
  12. package/dist/content/cache.js +60 -0
  13. package/dist/content/cache.js.map +1 -0
  14. package/dist/content/cache.test.d.ts +2 -0
  15. package/dist/content/cache.test.d.ts.map +1 -0
  16. package/dist/content/cache.test.js +58 -0
  17. package/dist/content/cache.test.js.map +1 -0
  18. package/dist/content/index.d.ts +3 -0
  19. package/dist/content/index.d.ts.map +1 -0
  20. package/dist/content/index.js +3 -0
  21. package/dist/content/index.js.map +1 -0
  22. package/dist/content/parser.d.ts +32 -0
  23. package/dist/content/parser.d.ts.map +1 -0
  24. package/dist/content/parser.js +72 -0
  25. package/dist/content/parser.js.map +1 -0
  26. package/dist/content/parser.test.d.ts +2 -0
  27. package/dist/content/parser.test.d.ts.map +1 -0
  28. package/dist/content/parser.test.js +71 -0
  29. package/dist/content/parser.test.js.map +1 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +92 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/search/document.d.ts +11 -0
  35. package/dist/search/document.d.ts.map +1 -0
  36. package/dist/search/document.js +47 -0
  37. package/dist/search/document.js.map +1 -0
  38. package/dist/search/engine.d.ts +41 -0
  39. package/dist/search/engine.d.ts.map +1 -0
  40. package/dist/search/engine.js +200 -0
  41. package/dist/search/engine.js.map +1 -0
  42. package/dist/search/flexsearch-wrapper.d.ts +51 -0
  43. package/dist/search/flexsearch-wrapper.d.ts.map +1 -0
  44. package/dist/search/flexsearch-wrapper.js +55 -0
  45. package/dist/search/flexsearch-wrapper.js.map +1 -0
  46. package/dist/search/index.d.ts +4 -0
  47. package/dist/search/index.d.ts.map +1 -0
  48. package/dist/search/index.js +4 -0
  49. package/dist/search/index.js.map +1 -0
  50. package/dist/tools/getDocPage.d.ts +8 -0
  51. package/dist/tools/getDocPage.d.ts.map +1 -0
  52. package/dist/tools/getDocPage.js +48 -0
  53. package/dist/tools/getDocPage.js.map +1 -0
  54. package/dist/tools/index.d.ts +5 -0
  55. package/dist/tools/index.d.ts.map +1 -0
  56. package/dist/tools/index.js +5 -0
  57. package/dist/tools/index.js.map +1 -0
  58. package/dist/tools/listDocSections.d.ts +8 -0
  59. package/dist/tools/listDocSections.d.ts.map +1 -0
  60. package/dist/tools/listDocSections.js +17 -0
  61. package/dist/tools/listDocSections.js.map +1 -0
  62. package/dist/tools/registry.d.ts +14 -0
  63. package/dist/tools/registry.d.ts.map +1 -0
  64. package/dist/tools/registry.js +64 -0
  65. package/dist/tools/registry.js.map +1 -0
  66. package/dist/tools/registry.test.d.ts +2 -0
  67. package/dist/tools/registry.test.d.ts.map +1 -0
  68. package/dist/tools/registry.test.js +45 -0
  69. package/dist/tools/registry.test.js.map +1 -0
  70. package/dist/tools/searchGitLabDocs.d.ts +19 -0
  71. package/dist/tools/searchGitLabDocs.d.ts.map +1 -0
  72. package/dist/tools/searchGitLabDocs.js +25 -0
  73. package/dist/tools/searchGitLabDocs.js.map +1 -0
  74. package/dist/types/index.d.ts +2 -0
  75. package/dist/types/index.d.ts.map +1 -0
  76. package/dist/types/index.js +2 -0
  77. package/dist/types/index.js.map +1 -0
  78. package/dist/types/models.d.ts +57 -0
  79. package/dist/types/models.d.ts.map +1 -0
  80. package/dist/types/models.js +41 -0
  81. package/dist/types/models.js.map +1 -0
  82. package/dist/utils/constants.d.ts +31 -0
  83. package/dist/utils/constants.d.ts.map +1 -0
  84. package/dist/utils/constants.js +38 -0
  85. package/dist/utils/constants.js.map +1 -0
  86. package/dist/utils/constants.test.d.ts +2 -0
  87. package/dist/utils/constants.test.d.ts.map +1 -0
  88. package/dist/utils/constants.test.js +16 -0
  89. package/dist/utils/constants.test.js.map +1 -0
  90. package/dist/utils/errors.d.ts +22 -0
  91. package/dist/utils/errors.d.ts.map +1 -0
  92. package/dist/utils/errors.js +43 -0
  93. package/dist/utils/errors.js.map +1 -0
  94. package/dist/utils/errors.test.d.ts +2 -0
  95. package/dist/utils/errors.test.d.ts.map +1 -0
  96. package/dist/utils/errors.test.js +55 -0
  97. package/dist/utils/errors.test.js.map +1 -0
  98. package/dist/utils/index.d.ts +5 -0
  99. package/dist/utils/index.d.ts.map +1 -0
  100. package/dist/utils/index.js +5 -0
  101. package/dist/utils/index.js.map +1 -0
  102. package/dist/utils/logger.d.ts +23 -0
  103. package/dist/utils/logger.d.ts.map +1 -0
  104. package/dist/utils/logger.js +44 -0
  105. package/dist/utils/logger.js.map +1 -0
  106. package/dist/utils/logger.test.d.ts +2 -0
  107. package/dist/utils/logger.test.d.ts.map +1 -0
  108. package/dist/utils/logger.test.js +71 -0
  109. package/dist/utils/logger.test.js.map +1 -0
  110. package/dist/utils/performance.d.ts +53 -0
  111. package/dist/utils/performance.d.ts.map +1 -0
  112. package/dist/utils/performance.js +130 -0
  113. package/dist/utils/performance.js.map +1 -0
  114. package/dist/utils/performance.test.d.ts +2 -0
  115. package/dist/utils/performance.test.d.ts.map +1 -0
  116. package/dist/utils/performance.test.js +75 -0
  117. package/dist/utils/performance.test.js.map +1 -0
  118. package/package.json +75 -0
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "document_count": 2494,
4
+ "created_at": "2025-12-06T22:10:11.500Z",
5
+ "source_repo": "https://gitlab.com/gitlab-org/gitlab-docs"
6
+ }
package/dist/bin.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import './index.js';
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Configuration schema with validation
4
+ */
5
+ declare const ConfigSchema: z.ZodObject<{
6
+ indexPath: z.ZodString;
7
+ search: z.ZodObject<{
8
+ minScore: z.ZodNumber;
9
+ }, z.core.$strip>;
10
+ cache: z.ZodObject<{
11
+ maxSizeMB: z.ZodNumber;
12
+ maxEntries: z.ZodNumber;
13
+ ttlMinutes: z.ZodNumber;
14
+ }, z.core.$strip>;
15
+ }, z.core.$strip>;
16
+ export type Config = z.infer<typeof ConfigSchema>;
17
+ /**
18
+ * Load and validate configuration from environment variables
19
+ * @throws {IndexNotFoundError} If index path doesn't exist
20
+ * @throws {z.ZodError} If configuration is invalid
21
+ */
22
+ export declare function loadConfig(): Config;
23
+ export {};
24
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAqBxB;;GAEG;AACH,QAAA,MAAM,YAAY;;;;;;;;;;iBAUhB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CA2BnC"}
package/dist/config.js ADDED
@@ -0,0 +1,54 @@
1
+ import { config as dotenvConfig } from 'dotenv';
2
+ import { z } from 'zod';
3
+ import { join, dirname } from 'path';
4
+ import { existsSync } from 'fs';
5
+ import { fileURLToPath } from 'url';
6
+ import { IndexNotFoundError } from './utils/errors.js';
7
+ import { DEFAULT_INDEX_PATH, INDEX_META_FILE, DEFAULT_CACHE_SIZE_MB, DEFAULT_CACHE_ENTRIES, DEFAULT_CACHE_TTL_MINUTES, MIN_SEARCH_SCORE, } from './utils/constants.js';
8
+ dotenvConfig();
9
+ // Get the directory where this module is located
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+ const PROJECT_ROOT = join(__dirname, '..');
13
+ /**
14
+ * Configuration schema with validation
15
+ */
16
+ const ConfigSchema = z.object({
17
+ indexPath: z.string().min(1),
18
+ search: z.object({
19
+ minScore: z.number().min(0).max(10),
20
+ }),
21
+ cache: z.object({
22
+ maxSizeMB: z.number().int().positive(),
23
+ maxEntries: z.number().int().positive(),
24
+ ttlMinutes: z.number().int().positive(),
25
+ }),
26
+ });
27
+ /**
28
+ * Load and validate configuration from environment variables
29
+ * @throws {IndexNotFoundError} If index path doesn't exist
30
+ * @throws {z.ZodError} If configuration is invalid
31
+ */
32
+ export function loadConfig() {
33
+ // Determine index path - use PROJECT_ROOT instead of process.cwd()
34
+ const indexPath = process.env.GITLAB_DOCS_INDEX_PATH || join(PROJECT_ROOT, DEFAULT_INDEX_PATH);
35
+ // Verify index exists
36
+ const metaPath = join(indexPath, INDEX_META_FILE);
37
+ if (!existsSync(metaPath)) {
38
+ throw new IndexNotFoundError(indexPath);
39
+ }
40
+ // Parse and validate configuration
41
+ const config = ConfigSchema.parse({
42
+ indexPath,
43
+ search: {
44
+ minScore: parseFloat(process.env.GITLAB_DOCS_MIN_SCORE || String(MIN_SEARCH_SCORE)),
45
+ },
46
+ cache: {
47
+ maxSizeMB: parseInt(process.env.GITLAB_DOCS_CACHE_SIZE_MB || String(DEFAULT_CACHE_SIZE_MB), 10),
48
+ maxEntries: parseInt(process.env.GITLAB_DOCS_CACHE_ENTRIES || String(DEFAULT_CACHE_ENTRIES), 10),
49
+ ttlMinutes: parseInt(process.env.GITLAB_DOCS_CACHE_TTL_MIN || String(DEFAULT_CACHE_TTL_MINUTES), 10),
50
+ },
51
+ });
52
+ return config;
53
+ }
54
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,CAAC;AAEf,iDAAiD;AACjD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;KACpC,CAAC;IACF,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;QACtC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;QACvC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;KACxC,CAAC;CACH,CAAC,CAAC;AAIH;;;;GAIG;AACH,MAAM,UAAU,UAAU;IACxB,mEAAmE;IACnE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,IAAI,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC;IAE/F,sBAAsB;IACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAClD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED,mCAAmC;IACnC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC;QAChC,SAAS;QACT,MAAM,EAAE;YACN,QAAQ,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAC;SACpF;QACD,KAAK,EAAE;YACL,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,MAAM,CAAC,qBAAqB,CAAC,EAAE,EAAE,CAAC;YAC/F,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,MAAM,CAAC,qBAAqB,CAAC,EAAE,EAAE,CAAC;YAChG,UAAU,EAAE,QAAQ,CAClB,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,MAAM,CAAC,yBAAyB,CAAC,EAC1E,EAAE,CACH;SACF;KACF,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Options for configuring the content cache
3
+ */
4
+ export interface CacheOptions {
5
+ /** Maximum cache size in megabytes */
6
+ maxSizeMB: number;
7
+ /** Maximum number of cache entries */
8
+ maxEntries: number;
9
+ /** Time-to-live for cache entries in minutes */
10
+ ttlMinutes: number;
11
+ }
12
+ /**
13
+ * LRU cache for storing parsed document content
14
+ * Reduces repeated parsing and improves response times
15
+ */
16
+ export declare class ContentCache {
17
+ private cache;
18
+ /**
19
+ * Creates a new content cache with the specified options
20
+ * @param options - Cache configuration options
21
+ */
22
+ constructor(options: CacheOptions);
23
+ /**
24
+ * Retrieves a cached value by key
25
+ * @param key - Cache key
26
+ * @returns Cached value or undefined if not found/expired
27
+ */
28
+ get(key: string): string | undefined;
29
+ /**
30
+ * Stores a value in the cache
31
+ * @param key - Cache key
32
+ * @param value - Value to cache
33
+ */
34
+ set(key: string, value: string): void;
35
+ /**
36
+ * Checks if a key exists in the cache
37
+ * @param key - Cache key to check
38
+ * @returns True if key exists and hasn't expired
39
+ */
40
+ has(key: string): boolean;
41
+ /**
42
+ * Clears all entries from the cache
43
+ */
44
+ clear(): void;
45
+ /**
46
+ * Returns the current number of entries in the cache
47
+ * @returns Number of cached entries
48
+ */
49
+ size(): number;
50
+ }
51
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/content/cache.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAA2B;IAExC;;;OAGG;gBACS,OAAO,EAAE,YAAY;IAWjC;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIpC;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;OAGG;IACH,IAAI,IAAI,MAAM;CAGf"}
@@ -0,0 +1,60 @@
1
+ import { LRUCache } from 'lru-cache';
2
+ /**
3
+ * LRU cache for storing parsed document content
4
+ * Reduces repeated parsing and improves response times
5
+ */
6
+ export class ContentCache {
7
+ cache;
8
+ /**
9
+ * Creates a new content cache with the specified options
10
+ * @param options - Cache configuration options
11
+ */
12
+ constructor(options) {
13
+ this.cache = new LRUCache({
14
+ max: options.maxEntries,
15
+ maxSize: options.maxSizeMB * 1024 * 1024,
16
+ sizeCalculation: (value) => value.length,
17
+ ttl: options.ttlMinutes * 60 * 1000,
18
+ updateAgeOnGet: true,
19
+ updateAgeOnHas: false,
20
+ });
21
+ }
22
+ /**
23
+ * Retrieves a cached value by key
24
+ * @param key - Cache key
25
+ * @returns Cached value or undefined if not found/expired
26
+ */
27
+ get(key) {
28
+ return this.cache.get(key);
29
+ }
30
+ /**
31
+ * Stores a value in the cache
32
+ * @param key - Cache key
33
+ * @param value - Value to cache
34
+ */
35
+ set(key, value) {
36
+ this.cache.set(key, value);
37
+ }
38
+ /**
39
+ * Checks if a key exists in the cache
40
+ * @param key - Cache key to check
41
+ * @returns True if key exists and hasn't expired
42
+ */
43
+ has(key) {
44
+ return this.cache.has(key);
45
+ }
46
+ /**
47
+ * Clears all entries from the cache
48
+ */
49
+ clear() {
50
+ this.cache.clear();
51
+ }
52
+ /**
53
+ * Returns the current number of entries in the cache
54
+ * @returns Number of cached entries
55
+ */
56
+ size() {
57
+ return this.cache.size;
58
+ }
59
+ }
60
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/content/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAcrC;;;GAGG;AACH,MAAM,OAAO,YAAY;IACf,KAAK,CAA2B;IAExC;;;OAGG;IACH,YAAY,OAAqB;QAC/B,IAAI,CAAC,KAAK,GAAG,IAAI,QAAQ,CAAC;YACxB,GAAG,EAAE,OAAO,CAAC,UAAU;YACvB,OAAO,EAAE,OAAO,CAAC,SAAS,GAAG,IAAI,GAAG,IAAI;YACxC,eAAe,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM;YACxC,GAAG,EAAE,OAAO,CAAC,UAAU,GAAG,EAAE,GAAG,IAAI;YACnC,cAAc,EAAE,IAAI;YACpB,cAAc,EAAE,KAAK;SACtB,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,GAAW,EAAE,KAAa;QAC5B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cache.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.d.ts","sourceRoot":"","sources":["../../src/content/cache.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ContentCache } from '../content/cache.js';
3
+ describe('ContentCache', () => {
4
+ it('should store and retrieve values', () => {
5
+ const cache = new ContentCache({
6
+ maxSizeMB: 1,
7
+ maxEntries: 10,
8
+ ttlMinutes: 5,
9
+ });
10
+ cache.set('key1', 'value1');
11
+ expect(cache.get('key1')).toBe('value1');
12
+ });
13
+ it('should return undefined for missing keys', () => {
14
+ const cache = new ContentCache({
15
+ maxSizeMB: 1,
16
+ maxEntries: 10,
17
+ ttlMinutes: 5,
18
+ });
19
+ expect(cache.get('nonexistent')).toBeUndefined();
20
+ });
21
+ it('should check key existence', () => {
22
+ const cache = new ContentCache({
23
+ maxSizeMB: 1,
24
+ maxEntries: 10,
25
+ ttlMinutes: 5,
26
+ });
27
+ cache.set('key1', 'value1');
28
+ expect(cache.has('key1')).toBe(true);
29
+ expect(cache.has('key2')).toBe(false);
30
+ });
31
+ it('should clear all entries', () => {
32
+ const cache = new ContentCache({
33
+ maxSizeMB: 1,
34
+ maxEntries: 10,
35
+ ttlMinutes: 5,
36
+ });
37
+ cache.set('key1', 'value1');
38
+ cache.set('key2', 'value2');
39
+ expect(cache.size()).toBe(2);
40
+ cache.clear();
41
+ expect(cache.size()).toBe(0);
42
+ expect(cache.has('key1')).toBe(false);
43
+ });
44
+ it('should respect max entries limit', () => {
45
+ const cache = new ContentCache({
46
+ maxSizeMB: 1,
47
+ maxEntries: 2,
48
+ ttlMinutes: 5,
49
+ });
50
+ cache.set('key1', 'value1');
51
+ cache.set('key2', 'value2');
52
+ cache.set('key3', 'value3'); // Should evict key1
53
+ expect(cache.has('key1')).toBe(false);
54
+ expect(cache.has('key2')).toBe(true);
55
+ expect(cache.has('key3')).toBe(true);
56
+ });
57
+ });
58
+ //# sourceMappingURL=cache.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.test.js","sourceRoot":"","sources":["../../src/content/cache.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './parser.js';
2
+ export * from './cache.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './parser.js';
2
+ export * from './cache.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Markdown parser using remark for GitLab documentation
3
+ * Handles GitHub Flavored Markdown and frontmatter extraction
4
+ */
5
+ export declare class MarkdownParser {
6
+ private processor;
7
+ constructor();
8
+ /**
9
+ * Parses markdown content using remark
10
+ * @param content - Raw markdown content
11
+ * @returns Processed markdown string
12
+ */
13
+ parse(content: string): Promise<string>;
14
+ /**
15
+ * Strips markdown formatting for search indexing
16
+ * Removes headers, bold, italic, links, code blocks, and list markers
17
+ * @param content - Markdown content to strip
18
+ * @returns Plain text without markdown formatting
19
+ */
20
+ stripMarkdown(content: string): string;
21
+ /**
22
+ * Extracts YAML frontmatter from markdown content
23
+ * Parses simple key: value pairs from frontmatter block
24
+ * @param content - Markdown content with optional frontmatter
25
+ * @returns Object containing frontmatter data and remaining content
26
+ */
27
+ extractFrontmatter(content: string): {
28
+ data: Record<string, unknown>;
29
+ content: string;
30
+ };
31
+ }
32
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/content/parser.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAC;;IAWlB;;;;OAIG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK7C;;;;;OAKG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAYtC;;;;;OAKG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;CAwBxF"}
@@ -0,0 +1,72 @@
1
+ import { unified } from 'unified';
2
+ import remarkParse from 'remark-parse';
3
+ import remarkGfm from 'remark-gfm';
4
+ import remarkStringify from 'remark-stringify';
5
+ /**
6
+ * Markdown parser using remark for GitLab documentation
7
+ * Handles GitHub Flavored Markdown and frontmatter extraction
8
+ */
9
+ export class MarkdownParser {
10
+ processor;
11
+ constructor() {
12
+ this.processor = unified().use(remarkParse).use(remarkGfm).use(remarkStringify, {
13
+ bullet: '-',
14
+ emphasis: '*',
15
+ strong: '*',
16
+ listItemIndent: 'one',
17
+ });
18
+ }
19
+ /**
20
+ * Parses markdown content using remark
21
+ * @param content - Raw markdown content
22
+ * @returns Processed markdown string
23
+ */
24
+ async parse(content) {
25
+ const file = await this.processor.process(content);
26
+ return String(file);
27
+ }
28
+ /**
29
+ * Strips markdown formatting for search indexing
30
+ * Removes headers, bold, italic, links, code blocks, and list markers
31
+ * @param content - Markdown content to strip
32
+ * @returns Plain text without markdown formatting
33
+ */
34
+ stripMarkdown(content) {
35
+ // Remove markdown syntax for search indexing
36
+ return content
37
+ .replace(/#{1,6}\s/g, '') // Headers
38
+ .replace(/\*\*(.+?)\*\*/g, '$1') // Bold
39
+ .replace(/\*(.+?)\*/g, '$1') // Italic
40
+ .replace(/\[(.+?)\]\(.+?\)/g, '$1') // Links
41
+ .replace(/`{1,3}(.+?)`{1,3}/g, '$1') // Code
42
+ .replace(/^\s*[-*+]\s/gm, '') // Lists
43
+ .trim();
44
+ }
45
+ /**
46
+ * Extracts YAML frontmatter from markdown content
47
+ * Parses simple key: value pairs from frontmatter block
48
+ * @param content - Markdown content with optional frontmatter
49
+ * @returns Object containing frontmatter data and remaining content
50
+ */
51
+ extractFrontmatter(content) {
52
+ const frontmatterRegex = /^---\s*\n([\s\S]*?)\n---\s*\n/;
53
+ const match = content.match(frontmatterRegex);
54
+ if (!match) {
55
+ return { data: {}, content };
56
+ }
57
+ const frontmatter = match[1];
58
+ const data = {};
59
+ // Simple YAML parsing (key: value)
60
+ for (const line of frontmatter.split('\n')) {
61
+ const [key, ...valueParts] = line.split(':');
62
+ if (key && valueParts.length) {
63
+ data[key.trim()] = valueParts.join(':').trim();
64
+ }
65
+ }
66
+ return {
67
+ data,
68
+ content: content.replace(frontmatterRegex, ''),
69
+ };
70
+ }
71
+ }
72
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/content/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAE/C;;;GAGG;AACH,MAAM,OAAO,cAAc;IACjB,SAAS,CAAC;IAElB;QACE,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,eAAe,EAAE;YAC9E,MAAM,EAAE,GAAG;YACX,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,GAAG;YACX,cAAc,EAAE,KAAK;SACtB,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK,CAAC,OAAe;QACzB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACH,aAAa,CAAC,OAAe;QAC3B,6CAA6C;QAC7C,OAAO,OAAO;aACX,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,UAAU;aACnC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC,OAAO;aACvC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,SAAS;aACrC,OAAO,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC,QAAQ;aAC3C,OAAO,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC,OAAO;aAC3C,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,QAAQ;aACrC,IAAI,EAAE,CAAC;IACZ,CAAC;IAED;;;;;OAKG;IACH,kBAAkB,CAAC,OAAe;QAChC,MAAM,gBAAgB,GAAG,+BAA+B,CAAC;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAE9C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;QAC/B,CAAC;QAED,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,IAAI,GAA4B,EAAE,CAAC;QAEzC,mCAAmC;QACnC,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7C,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;gBAC7B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YACjD,CAAC;QACH,CAAC;QAED,OAAO;YACL,IAAI;YACJ,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC;SAC/C,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parser.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.test.d.ts","sourceRoot":"","sources":["../../src/content/parser.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,71 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { MarkdownParser } from '../content/parser.js';
3
+ describe('MarkdownParser', () => {
4
+ const parser = new MarkdownParser();
5
+ describe('stripMarkdown', () => {
6
+ it('should remove headers', () => {
7
+ const input = '# Header 1\n## Header 2';
8
+ const result = parser.stripMarkdown(input);
9
+ expect(result).toBe('Header 1\nHeader 2');
10
+ });
11
+ it('should remove bold formatting', () => {
12
+ const input = 'This is **bold** text';
13
+ const result = parser.stripMarkdown(input);
14
+ expect(result).toBe('This is bold text');
15
+ });
16
+ it('should remove italic formatting', () => {
17
+ const input = 'This is *italic* text';
18
+ const result = parser.stripMarkdown(input);
19
+ expect(result).toBe('This is italic text');
20
+ });
21
+ it('should remove links', () => {
22
+ const input = '[Link text](https://example.com)';
23
+ const result = parser.stripMarkdown(input);
24
+ expect(result).toBe('Link text');
25
+ });
26
+ it('should remove inline code', () => {
27
+ const input = 'Use `code` here';
28
+ const result = parser.stripMarkdown(input);
29
+ expect(result).toBe('Use code here');
30
+ });
31
+ it('should remove code blocks', () => {
32
+ const input = '```javascript\nconst x = 1;\n```';
33
+ const result = parser.stripMarkdown(input);
34
+ // Triple backticks are not fully stripped by the simple regex
35
+ expect(result).toContain('const x = 1');
36
+ });
37
+ it('should remove list markers', () => {
38
+ const input = '- Item 1\n- Item 2\n* Item 3';
39
+ const result = parser.stripMarkdown(input);
40
+ expect(result).toBe('Item 1\nItem 2\nItem 3');
41
+ });
42
+ });
43
+ describe('extractFrontmatter', () => {
44
+ it('should extract YAML frontmatter', () => {
45
+ const input = `---
46
+ title: Test Page
47
+ author: John Doe
48
+ ---
49
+ # Content`;
50
+ const result = parser.extractFrontmatter(input);
51
+ expect(result.data.title).toBe('Test Page');
52
+ expect(result.data.author).toBe('John Doe');
53
+ expect(result.content).toBe('# Content');
54
+ });
55
+ it('should handle content without frontmatter', () => {
56
+ const input = '# Just content';
57
+ const result = parser.extractFrontmatter(input);
58
+ expect(result.data).toEqual({});
59
+ expect(result.content).toBe('# Just content');
60
+ });
61
+ it('should handle values with colons', () => {
62
+ const input = `---
63
+ url: https://example.com
64
+ ---
65
+ Content`;
66
+ const result = parser.extractFrontmatter(input);
67
+ expect(result.data.url).toBe('https://example.com');
68
+ });
69
+ });
70
+ });
71
+ //# sourceMappingURL=parser.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.test.js","sourceRoot":"","sources":["../../src/content/parser.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
5
+ import { SearchEngine } from './search/engine.js';
6
+ import { DocumentTree } from './search/document.js';
7
+ import { MarkdownParser } from './content/parser.js';
8
+ import { ContentCache } from './content/cache.js';
9
+ import { loadConfig } from './config.js';
10
+ import { searchGitLabDocsTool, getDocPageTool, listDocSectionsTool, } from './tools/index.js';
11
+ import { TOOL_DEFINITIONS } from './tools/registry.js';
12
+ import { logger } from './utils/logger.js';
13
+ import { SERVER_VERSION, SERVER_NAME } from './utils/constants.js';
14
+ async function main() {
15
+ try {
16
+ // Load configuration
17
+ const config = loadConfig();
18
+ // Initialize components
19
+ const searchEngine = new SearchEngine(config.indexPath);
20
+ searchEngine.loadIndex();
21
+ const docTree = new DocumentTree();
22
+ docTree.buildFromEngine(searchEngine);
23
+ const parser = new MarkdownParser();
24
+ const cache = new ContentCache({
25
+ maxSizeMB: config.cache.maxSizeMB,
26
+ maxEntries: config.cache.maxEntries,
27
+ ttlMinutes: config.cache.ttlMinutes,
28
+ });
29
+ const context = {
30
+ searchEngine,
31
+ docTree,
32
+ parser,
33
+ cache,
34
+ config,
35
+ };
36
+ logger.info(`✅ Loaded ${searchEngine.getDocumentCount()} documents`);
37
+ logger.info(`📚 Built document tree: ${docTree.getSectionCount()} sections`);
38
+ // Create MCP server
39
+ const server = new Server({
40
+ name: SERVER_NAME,
41
+ version: SERVER_VERSION,
42
+ }, {
43
+ capabilities: {
44
+ tools: {},
45
+ },
46
+ });
47
+ // Register list_tools handler
48
+ server.setRequestHandler(ListToolsRequestSchema, () => ({
49
+ tools: TOOL_DEFINITIONS,
50
+ }));
51
+ // Register call_tool handler
52
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
53
+ const { name, arguments: args } = request.params;
54
+ try {
55
+ switch (name) {
56
+ case 'searchGitLabDocs':
57
+ return searchGitLabDocsTool(args, context);
58
+ case 'getDocPage':
59
+ return await getDocPageTool(args, context);
60
+ case 'listDocSections':
61
+ return listDocSectionsTool(args, context);
62
+ default:
63
+ throw new Error(`Unknown tool: ${name}`);
64
+ }
65
+ }
66
+ catch (error) {
67
+ const errorMessage = error instanceof Error ? error.message : String(error);
68
+ return {
69
+ content: [
70
+ {
71
+ type: 'text',
72
+ text: `Error: ${errorMessage}`,
73
+ },
74
+ ],
75
+ isError: true,
76
+ };
77
+ }
78
+ });
79
+ logger.info(`🚀 GitLab Docs MCP Server v${SERVER_VERSION}`);
80
+ logger.info(`🔍 Index: ${config.indexPath}`);
81
+ // Connect via stdio
82
+ const transport = new StdioServerTransport();
83
+ await server.connect(transport);
84
+ logger.info('✓ Server initialized successfully');
85
+ }
86
+ catch (error) {
87
+ logger.error('❌ Fatal error:', error instanceof Error ? error.message : String(error));
88
+ process.exit(1);
89
+ }
90
+ }
91
+ void main();
92
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { DocSection } from '../types/models.js';
2
+ import type { SearchEngine } from './engine.js';
3
+ export declare class DocumentTree {
4
+ private sections;
5
+ constructor();
6
+ buildFromEngine(engine: SearchEngine): void;
7
+ getAllSections(): DocSection[];
8
+ getSectionCount(): number;
9
+ getSection(name: string): DocSection | undefined;
10
+ }
11
+ //# sourceMappingURL=document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/search/document.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAA0B;;IAM1C,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAmC3C,cAAc,IAAI,UAAU,EAAE;IAI9B,eAAe,IAAI,MAAM;IAIzB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;CAGjD"}