@get-technology-inc/jamf-docs-mcp-server 0.0.1 → 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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +189 -29
  3. package/dist/constants.d.ts +260 -0
  4. package/dist/constants.d.ts.map +1 -0
  5. package/dist/constants.js +303 -0
  6. package/dist/constants.js.map +1 -0
  7. package/dist/index.d.ts +9 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +36 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/schemas/index.d.ts +98 -0
  12. package/dist/schemas/index.d.ts.map +1 -0
  13. package/dist/schemas/index.js +110 -0
  14. package/dist/schemas/index.js.map +1 -0
  15. package/dist/services/cache.d.ts +56 -0
  16. package/dist/services/cache.d.ts.map +1 -0
  17. package/dist/services/cache.js +189 -0
  18. package/dist/services/cache.js.map +1 -0
  19. package/dist/services/scraper.d.ts +62 -0
  20. package/dist/services/scraper.d.ts.map +1 -0
  21. package/dist/services/scraper.js +568 -0
  22. package/dist/services/scraper.js.map +1 -0
  23. package/dist/services/tokenizer.d.ts +77 -0
  24. package/dist/services/tokenizer.d.ts.map +1 -0
  25. package/dist/services/tokenizer.js +274 -0
  26. package/dist/services/tokenizer.js.map +1 -0
  27. package/dist/tools/get-article.d.ts +7 -0
  28. package/dist/tools/get-article.d.ts.map +1 -0
  29. package/dist/tools/get-article.js +195 -0
  30. package/dist/tools/get-article.js.map +1 -0
  31. package/dist/tools/get-toc.d.ts +7 -0
  32. package/dist/tools/get-toc.d.ts.map +1 -0
  33. package/dist/tools/get-toc.js +172 -0
  34. package/dist/tools/get-toc.js.map +1 -0
  35. package/dist/tools/list-products.d.ts +7 -0
  36. package/dist/tools/list-products.d.ts.map +1 -0
  37. package/dist/tools/list-products.js +132 -0
  38. package/dist/tools/list-products.js.map +1 -0
  39. package/dist/tools/search.d.ts +7 -0
  40. package/dist/tools/search.d.ts.map +1 -0
  41. package/dist/tools/search.js +212 -0
  42. package/dist/tools/search.js.map +1 -0
  43. package/dist/types.d.ts +197 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +28 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +68 -6
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Caching service for Jamf documentation
3
+ *
4
+ * Provides file-based caching with TTL support
5
+ */
6
+ import * as fs from 'fs/promises';
7
+ import * as path from 'path';
8
+ import * as crypto from 'crypto';
9
+ import { CACHE_TTL, CACHE_DIR } from '../constants.js';
10
+ /**
11
+ * File-based cache implementation
12
+ */
13
+ class FileCache {
14
+ cacheDir;
15
+ memoryCache = new Map();
16
+ constructor(cacheDir = CACHE_DIR) {
17
+ this.cacheDir = cacheDir;
18
+ }
19
+ /**
20
+ * Generate a cache key hash
21
+ */
22
+ getCacheKey(key) {
23
+ return crypto.createHash('md5').update(key).digest('hex');
24
+ }
25
+ /**
26
+ * Get the file path for a cache key
27
+ */
28
+ getCachePath(key) {
29
+ return path.join(this.cacheDir, `${this.getCacheKey(key)}.json`);
30
+ }
31
+ /**
32
+ * Ensure cache directory exists
33
+ */
34
+ async ensureCacheDir() {
35
+ try {
36
+ await fs.mkdir(this.cacheDir, { recursive: true });
37
+ }
38
+ catch {
39
+ // Directory may already exist
40
+ }
41
+ }
42
+ /**
43
+ * Get a value from cache
44
+ */
45
+ async get(key) {
46
+ // Check memory cache first
47
+ const memCached = this.memoryCache.get(key);
48
+ if (memCached) {
49
+ if (Date.now() - memCached.timestamp < memCached.ttl) {
50
+ return memCached.data;
51
+ }
52
+ // Expired, remove from memory
53
+ this.memoryCache.delete(key);
54
+ }
55
+ // Check file cache
56
+ try {
57
+ const cachePath = this.getCachePath(key);
58
+ const content = await fs.readFile(cachePath, 'utf-8');
59
+ const entry = JSON.parse(content);
60
+ // Check if expired
61
+ if (Date.now() - entry.timestamp > entry.ttl) {
62
+ await this.delete(key);
63
+ return null;
64
+ }
65
+ // Store in memory cache for faster access
66
+ this.memoryCache.set(key, entry);
67
+ return entry.data;
68
+ }
69
+ catch {
70
+ // File doesn't exist or is invalid
71
+ return null;
72
+ }
73
+ }
74
+ /**
75
+ * Set a value in cache
76
+ */
77
+ async set(key, data, ttl = CACHE_TTL.ARTICLE_CONTENT) {
78
+ await this.ensureCacheDir();
79
+ const entry = {
80
+ data,
81
+ timestamp: Date.now(),
82
+ ttl
83
+ };
84
+ // Store in memory
85
+ this.memoryCache.set(key, entry);
86
+ // Store in file
87
+ try {
88
+ const cachePath = this.getCachePath(key);
89
+ await fs.writeFile(cachePath, JSON.stringify(entry), 'utf-8');
90
+ }
91
+ catch (error) {
92
+ // Log but don't fail
93
+ console.error(`[CACHE] Failed to write cache: ${error}`);
94
+ }
95
+ }
96
+ /**
97
+ * Delete a cache entry
98
+ */
99
+ async delete(key) {
100
+ // Remove from memory
101
+ this.memoryCache.delete(key);
102
+ // Remove file
103
+ try {
104
+ await fs.unlink(this.getCachePath(key));
105
+ }
106
+ catch {
107
+ // File may not exist
108
+ }
109
+ }
110
+ /**
111
+ * Clear all cache entries
112
+ */
113
+ async clear() {
114
+ // Clear memory
115
+ this.memoryCache.clear();
116
+ // Clear files
117
+ try {
118
+ const files = await fs.readdir(this.cacheDir);
119
+ await Promise.all(files
120
+ .filter(f => f.endsWith('.json'))
121
+ .map(f => fs.unlink(path.join(this.cacheDir, f))));
122
+ }
123
+ catch {
124
+ // Directory may not exist
125
+ }
126
+ }
127
+ /**
128
+ * Get cache statistics
129
+ */
130
+ async stats() {
131
+ let fileEntries = 0;
132
+ let totalSize = 0;
133
+ try {
134
+ const files = await fs.readdir(this.cacheDir);
135
+ const jsonFiles = files.filter(f => f.endsWith('.json'));
136
+ fileEntries = jsonFiles.length;
137
+ for (const file of jsonFiles) {
138
+ const stat = await fs.stat(path.join(this.cacheDir, file));
139
+ totalSize += stat.size;
140
+ }
141
+ }
142
+ catch {
143
+ // Directory may not exist
144
+ }
145
+ return {
146
+ memoryEntries: this.memoryCache.size,
147
+ fileEntries,
148
+ totalSize
149
+ };
150
+ }
151
+ /**
152
+ * Prune expired entries
153
+ */
154
+ async prune() {
155
+ let pruned = 0;
156
+ // Prune memory cache
157
+ for (const [key, entry] of this.memoryCache.entries()) {
158
+ if (Date.now() - entry.timestamp > entry.ttl) {
159
+ this.memoryCache.delete(key);
160
+ pruned++;
161
+ }
162
+ }
163
+ // Prune file cache
164
+ try {
165
+ const files = await fs.readdir(this.cacheDir);
166
+ for (const file of files.filter(f => f.endsWith('.json'))) {
167
+ try {
168
+ const filePath = path.join(this.cacheDir, file);
169
+ const content = await fs.readFile(filePath, 'utf-8');
170
+ const entry = JSON.parse(content);
171
+ if (Date.now() - entry.timestamp > entry.ttl) {
172
+ await fs.unlink(filePath);
173
+ pruned++;
174
+ }
175
+ }
176
+ catch {
177
+ // Skip invalid files
178
+ }
179
+ }
180
+ }
181
+ catch {
182
+ // Directory may not exist
183
+ }
184
+ return pruned;
185
+ }
186
+ }
187
+ // Export singleton instance
188
+ export const cache = new FileCache();
189
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Web scraping service for Jamf documentation
3
+ *
4
+ * This module handles fetching and parsing HTML from learn.jamf.com
5
+ * (Jamf documentation has moved from docs.jamf.com to learn.jamf.com)
6
+ */
7
+ import { type ProductId } from '../constants.js';
8
+ import { type SearchResult, type ParsedArticle, type TocEntry, type SearchParams, type TokenInfo, type PaginationInfo, type ArticleSection } from '../types.js';
9
+ /**
10
+ * Search response with token and pagination info
11
+ */
12
+ export interface SearchDocumentationResult {
13
+ results: SearchResult[];
14
+ pagination: PaginationInfo;
15
+ tokenInfo: TokenInfo;
16
+ }
17
+ /**
18
+ * Search Jamf documentation using Zoomin Search API
19
+ */
20
+ export declare function searchDocumentation(params: SearchParams): Promise<SearchDocumentationResult>;
21
+ /**
22
+ * Options for fetching articles
23
+ */
24
+ export interface FetchArticleOptions {
25
+ includeRelated?: boolean;
26
+ section?: string;
27
+ maxTokens?: number;
28
+ }
29
+ /**
30
+ * Article result with token and section info
31
+ */
32
+ export interface FetchArticleResult extends ParsedArticle {
33
+ tokenInfo: TokenInfo;
34
+ sections: ArticleSection[];
35
+ }
36
+ /**
37
+ * Fetch and parse a documentation article
38
+ * Uses backend URL (learn-be.jamf.com) for pre-rendered content
39
+ */
40
+ export declare function fetchArticle(url: string, options?: FetchArticleOptions): Promise<FetchArticleResult>;
41
+ /**
42
+ * Options for fetching table of contents
43
+ */
44
+ export interface FetchTocOptions {
45
+ page?: number;
46
+ maxTokens?: number;
47
+ }
48
+ /**
49
+ * TOC result with pagination and token info
50
+ */
51
+ export interface FetchTocResult {
52
+ toc: TocEntry[];
53
+ pagination: PaginationInfo;
54
+ tokenInfo: TokenInfo;
55
+ }
56
+ /**
57
+ * Fetch table of contents for a product
58
+ * Uses backend TOC endpoint (learn-be.jamf.com/bundle/{bundleId}/toc)
59
+ */
60
+ export declare function fetchTableOfContents(product: ProductId, _version: string, // Version is not used for learn.jamf.com (always current)
61
+ options?: FetchTocOptions): Promise<FetchTocResult>;
62
+ //# sourceMappingURL=scraper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scraper.d.ts","sourceRoot":"","sources":["../../src/services/scraper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAUL,KAAK,SAAS,EAEf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,YAAY,EAEjB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AAwRrB;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,UAAU,EAAE,cAAc,CAAC;IAC3B,SAAS,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,yBAAyB,CAAC,CA+IlG;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAwF7B;AAiFD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,QAAQ,EAAE,CAAC;IAChB,UAAU,EAAE,cAAc,CAAC;IAC3B,SAAS,EAAE,SAAS,CAAC;CACtB;AA6BD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,MAAM,EAAG,0DAA0D;AAC7E,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,cAAc,CAAC,CA2FzB"}