@get-technology-inc/jamf-docs-mcp-server 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +61 -139
  2. package/dist/constants.d.ts +4 -1
  3. package/dist/constants.d.ts.map +1 -1
  4. package/dist/constants.js +10 -5
  5. package/dist/constants.js.map +1 -1
  6. package/dist/index.js +4 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/resources/index.d.ts +13 -0
  9. package/dist/resources/index.d.ts.map +1 -0
  10. package/dist/resources/index.js +45 -0
  11. package/dist/resources/index.js.map +1 -0
  12. package/dist/schemas/index.d.ts +24 -61
  13. package/dist/schemas/index.d.ts.map +1 -1
  14. package/dist/schemas/index.js +18 -1
  15. package/dist/schemas/index.js.map +1 -1
  16. package/dist/services/cache.d.ts +4 -13
  17. package/dist/services/cache.d.ts.map +1 -1
  18. package/dist/services/cache.js +8 -32
  19. package/dist/services/cache.js.map +1 -1
  20. package/dist/services/metadata.d.ts +78 -0
  21. package/dist/services/metadata.d.ts.map +1 -0
  22. package/dist/services/metadata.js +349 -0
  23. package/dist/services/metadata.js.map +1 -0
  24. package/dist/services/scraper.d.ts +2 -2
  25. package/dist/services/scraper.d.ts.map +1 -1
  26. package/dist/services/scraper.js +118 -142
  27. package/dist/services/scraper.js.map +1 -1
  28. package/dist/services/search-suggestions.d.ts +27 -0
  29. package/dist/services/search-suggestions.d.ts.map +1 -0
  30. package/dist/services/search-suggestions.js +193 -0
  31. package/dist/services/search-suggestions.js.map +1 -0
  32. package/dist/services/tokenizer.d.ts +17 -1
  33. package/dist/services/tokenizer.d.ts.map +1 -1
  34. package/dist/services/tokenizer.js +122 -66
  35. package/dist/services/tokenizer.js.map +1 -1
  36. package/dist/tools/get-article.d.ts +1 -1
  37. package/dist/tools/get-article.d.ts.map +1 -1
  38. package/dist/tools/get-article.js +114 -65
  39. package/dist/tools/get-article.js.map +1 -1
  40. package/dist/tools/get-toc.d.ts +1 -1
  41. package/dist/tools/get-toc.d.ts.map +1 -1
  42. package/dist/tools/get-toc.js +71 -41
  43. package/dist/tools/get-toc.js.map +1 -1
  44. package/dist/tools/list-products.d.ts +1 -1
  45. package/dist/tools/list-products.d.ts.map +1 -1
  46. package/dist/tools/list-products.js +21 -3
  47. package/dist/tools/list-products.js.map +1 -1
  48. package/dist/tools/search.d.ts +1 -1
  49. package/dist/tools/search.d.ts.map +1 -1
  50. package/dist/tools/search.js +97 -57
  51. package/dist/tools/search.js.map +1 -1
  52. package/dist/types.d.ts +8 -17
  53. package/dist/types.d.ts.map +1 -1
  54. package/package.json +2 -2
@@ -2,13 +2,15 @@
2
2
  * Zod schemas for input validation
3
3
  */
4
4
  import { z } from 'zod';
5
- import { ResponseFormat, JAMF_PRODUCTS, CONTENT_LIMITS, TOKEN_CONFIG, PAGINATION_CONFIG, JAMF_TOPICS } from '../constants.js';
5
+ import { ResponseFormat, OutputMode, JAMF_PRODUCTS, CONTENT_LIMITS, TOKEN_CONFIG, PAGINATION_CONFIG, JAMF_TOPICS } from '../constants.js';
6
6
  // Valid product IDs
7
7
  const productIds = Object.keys(JAMF_PRODUCTS);
8
8
  // Valid topic IDs
9
9
  const topicIds = Object.keys(JAMF_TOPICS);
10
10
  // Response format enum
11
11
  const ResponseFormatSchema = z.nativeEnum(ResponseFormat);
12
+ // Output mode enum
13
+ const OutputModeSchema = z.nativeEnum(OutputMode);
12
14
  // Common maxTokens parameter schema
13
15
  const MaxTokensSchema = z.number()
14
16
  .int()
@@ -30,6 +32,9 @@ export const ListProductsInputSchema = z.object({
30
32
  maxTokens: MaxTokensSchema
31
33
  .optional()
32
34
  .describe(`Maximum tokens in response (${TOKEN_CONFIG.MIN_TOKENS}-${TOKEN_CONFIG.MAX_TOKENS_LIMIT}, default: ${TOKEN_CONFIG.DEFAULT_MAX_TOKENS})`),
35
+ outputMode: OutputModeSchema
36
+ .default(OutputMode.FULL)
37
+ .describe('Output detail level: "full" for detailed output or "compact" for brief output'),
33
38
  responseFormat: ResponseFormatSchema
34
39
  .default(ResponseFormat.MARKDOWN)
35
40
  .describe('Output format: "markdown" for human-readable or "json" for machine-readable')
@@ -63,6 +68,9 @@ export const SearchInputSchema = z.object({
63
68
  maxTokens: MaxTokensSchema
64
69
  .optional()
65
70
  .describe(`Maximum tokens in response (${TOKEN_CONFIG.MIN_TOKENS}-${TOKEN_CONFIG.MAX_TOKENS_LIMIT}, default: ${TOKEN_CONFIG.DEFAULT_MAX_TOKENS})`),
71
+ outputMode: OutputModeSchema
72
+ .default(OutputMode.FULL)
73
+ .describe('Output detail level: "full" for detailed output or "compact" for brief output'),
66
74
  responseFormat: ResponseFormatSchema
67
75
  .default(ResponseFormat.MARKDOWN)
68
76
  .describe('Output format: "markdown" for human-readable or "json" for machine-readable')
@@ -78,12 +86,18 @@ export const GetArticleInputSchema = z.object({
78
86
  section: z.string()
79
87
  .optional()
80
88
  .describe('Extract only a specific section by title or ID (e.g., "Prerequisites", "Configuration")'),
89
+ summaryOnly: z.boolean()
90
+ .default(false)
91
+ .describe('Return only article summary and outline instead of full content (token-efficient)'),
81
92
  includeRelated: z.boolean()
82
93
  .default(false)
83
94
  .describe('Include related article links in the response'),
84
95
  maxTokens: MaxTokensSchema
85
96
  .optional()
86
97
  .describe(`Maximum tokens in response (${TOKEN_CONFIG.MIN_TOKENS}-${TOKEN_CONFIG.MAX_TOKENS_LIMIT}, default: ${TOKEN_CONFIG.DEFAULT_MAX_TOKENS})`),
98
+ outputMode: OutputModeSchema
99
+ .default(OutputMode.FULL)
100
+ .describe('Output detail level: "full" for detailed output or "compact" for brief output'),
87
101
  responseFormat: ResponseFormatSchema
88
102
  .default(ResponseFormat.MARKDOWN)
89
103
  .describe('Output format: "markdown" for human-readable or "json" for machine-readable')
@@ -103,6 +117,9 @@ export const GetTocInputSchema = z.object({
103
117
  maxTokens: MaxTokensSchema
104
118
  .optional()
105
119
  .describe(`Maximum tokens in response (${TOKEN_CONFIG.MIN_TOKENS}-${TOKEN_CONFIG.MAX_TOKENS_LIMIT}, default: ${TOKEN_CONFIG.DEFAULT_MAX_TOKENS})`),
120
+ outputMode: OutputModeSchema
121
+ .default(OutputMode.FULL)
122
+ .describe('Output detail level: "full" for detailed output or "compact" for brief output'),
106
123
  responseFormat: ResponseFormatSchema
107
124
  .default(ResponseFormat.MARKDOWN)
108
125
  .describe('Output format: "markdown" for human-readable or "json" for machine-readable')
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"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"}
@@ -7,20 +7,11 @@
7
7
  * File-based cache implementation
8
8
  */
9
9
  declare class FileCache {
10
- private cacheDir;
11
- private memoryCache;
10
+ private readonly cacheDir;
11
+ private readonly memoryCache;
12
12
  constructor(cacheDir?: string);
13
- /**
14
- * Generate a cache key hash
15
- */
16
- private getCacheKey;
17
- /**
18
- * Get the file path for a cache key
19
- */
13
+ private static getCacheKey;
20
14
  private getCachePath;
21
- /**
22
- * Ensure cache directory exists
23
- */
24
15
  private ensureCacheDir;
25
16
  /**
26
17
  * Get a value from cache
@@ -29,7 +20,7 @@ declare class FileCache {
29
20
  /**
30
21
  * Set a value in cache
31
22
  */
32
- set<T>(key: string, data: T, ttl?: number): Promise<void>;
23
+ set(key: string, data: unknown, ttl?: number): Promise<void>;
33
24
  /**
34
25
  * Delete a cache entry
35
26
  */
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;GAEG;AACH,cAAM,SAAS;IACb,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAA+C;gBAEtD,QAAQ,GAAE,MAAkB;IAIxC;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;YACW,cAAc;IAQ5B;;OAEG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAiC5C;;OAEG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,GAAE,MAAkC,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB1F;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAwBzF;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;CAmC/B;AAGD,eAAO,MAAM,KAAK,WAAkB,CAAC"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH;;GAEG;AACH,cAAM,SAAS;IACb,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0C;gBAE1D,QAAQ,GAAE,MAAkB;IAIxC,OAAO,CAAC,MAAM,CAAC,WAAW;IAI1B,OAAO,CAAC,YAAY;YAIN,cAAc;IAI5B;;OAEG;IACG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAiC5C;;OAEG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,GAAE,MAAkC,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB7F;;OAEG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAa5B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAwBzF;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;CAmC/B;AAGD,eAAO,MAAM,KAAK,WAAkB,CAAC"}
@@ -16,28 +16,14 @@ class FileCache {
16
16
  constructor(cacheDir = CACHE_DIR) {
17
17
  this.cacheDir = cacheDir;
18
18
  }
19
- /**
20
- * Generate a cache key hash
21
- */
22
- getCacheKey(key) {
19
+ static getCacheKey(key) {
23
20
  return crypto.createHash('md5').update(key).digest('hex');
24
21
  }
25
- /**
26
- * Get the file path for a cache key
27
- */
28
22
  getCachePath(key) {
29
- return path.join(this.cacheDir, `${this.getCacheKey(key)}.json`);
23
+ return path.join(this.cacheDir, `${FileCache.getCacheKey(key)}.json`);
30
24
  }
31
- /**
32
- * Ensure cache directory exists
33
- */
34
25
  async ensureCacheDir() {
35
- try {
36
- await fs.mkdir(this.cacheDir, { recursive: true });
37
- }
38
- catch {
39
- // Directory may already exist
40
- }
26
+ await fs.mkdir(this.cacheDir, { recursive: true }).catch(() => { });
41
27
  }
42
28
  /**
43
29
  * Get a value from cache
@@ -45,7 +31,7 @@ class FileCache {
45
31
  async get(key) {
46
32
  // Check memory cache first
47
33
  const memCached = this.memoryCache.get(key);
48
- if (memCached) {
34
+ if (memCached !== undefined) {
49
35
  if (Date.now() - memCached.timestamp < memCached.ttl) {
50
36
  return memCached.data;
51
37
  }
@@ -90,35 +76,25 @@ class FileCache {
90
76
  }
91
77
  catch (error) {
92
78
  // Log but don't fail
93
- console.error(`[CACHE] Failed to write cache: ${error}`);
79
+ console.error(`[CACHE] Failed to write cache: ${String(error)}`);
94
80
  }
95
81
  }
96
82
  /**
97
83
  * Delete a cache entry
98
84
  */
99
85
  async delete(key) {
100
- // Remove from memory
101
86
  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
- }
87
+ await fs.unlink(this.getCachePath(key)).catch(() => { });
109
88
  }
110
89
  /**
111
90
  * Clear all cache entries
112
91
  */
113
92
  async clear() {
114
- // Clear memory
115
93
  this.memoryCache.clear();
116
- // Clear files
117
94
  try {
118
95
  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))));
96
+ const jsonFiles = files.filter(f => f.endsWith('.json'));
97
+ await Promise.all(jsonFiles.map(async (f) => { await fs.unlink(path.join(this.cacheDir, f)); }));
122
98
  }
123
99
  catch {
124
100
  // Directory may not exist
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/services/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Metadata service for Jamf documentation
3
+ *
4
+ * Dynamically fetches product versions and topic categories from the API
5
+ * with fallback to static constants.
6
+ */
7
+ import { type ProductId } from '../constants.js';
8
+ export interface ProductMetadata {
9
+ id: string;
10
+ name: string;
11
+ description: string;
12
+ bundleId: string;
13
+ latestVersion: string;
14
+ availableVersions: string[];
15
+ labelKey: string;
16
+ }
17
+ export interface TopicMetadata {
18
+ id: string;
19
+ name: string;
20
+ source: 'toc' | 'manual';
21
+ articleCount?: number;
22
+ }
23
+ export interface TocCategory {
24
+ navId: string;
25
+ title: string;
26
+ articleCount: number;
27
+ children: string[];
28
+ }
29
+ /**
30
+ * Get all products with their latest metadata
31
+ * Uses cache with fallback to static constants
32
+ */
33
+ export declare function getProductsMetadata(): Promise<ProductMetadata[]>;
34
+ /**
35
+ * Get the bundle ID for a specific product and version
36
+ * Returns the latest bundle ID if version is undefined or 'current'
37
+ */
38
+ export declare function getBundleIdForVersion(productId: ProductId, version?: string): Promise<string | null>;
39
+ /**
40
+ * Get available versions for a product
41
+ */
42
+ export declare function getAvailableVersions(productId: ProductId): Promise<string[]>;
43
+ /**
44
+ * Get all topics, combining TOC-derived from all products and manual topics
45
+ */
46
+ export declare function getTopicsMetadata(): Promise<TopicMetadata[]>;
47
+ /**
48
+ * Get products data formatted for resource response
49
+ */
50
+ export declare function getProductsResourceData(): Promise<{
51
+ description: string;
52
+ products: {
53
+ id: string;
54
+ name: string;
55
+ description: string;
56
+ latestVersion: string;
57
+ availableVersions: string[];
58
+ bundleId: string;
59
+ }[];
60
+ lastUpdated: string;
61
+ usage: string;
62
+ }>;
63
+ /**
64
+ * Get topics data formatted for resource response
65
+ */
66
+ export declare function getTopicsResourceData(): Promise<{
67
+ description: string;
68
+ totalTopics: number;
69
+ topics: {
70
+ id: string;
71
+ name: string;
72
+ source: string;
73
+ articleCount?: number;
74
+ }[];
75
+ lastUpdated: string;
76
+ usage: string;
77
+ }>;
78
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/services/metadata.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAC;AAOzB,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,KAAK,GAAG,QAAQ,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAmID;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAoCtE;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,SAAS,EACpB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsBxB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAIlF;AAmHD;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAyClE;AAMD;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE;QACR,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,QAAQ,EAAE,MAAM,CAAC;KAClB,EAAE,CAAC;IACJ,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAgBD;AAED;;GAEG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,EAAE,CAAC;IACJ,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC,CAeD"}
@@ -0,0 +1,349 @@
1
+ /**
2
+ * Metadata service for Jamf documentation
3
+ *
4
+ * Dynamically fetches product versions and topic categories from the API
5
+ * with fallback to static constants.
6
+ */
7
+ import axios from 'axios';
8
+ import * as cheerio from 'cheerio';
9
+ import { DOCS_API_URL, JAMF_PRODUCTS, JAMF_TOPICS, REQUEST_CONFIG, CACHE_TTL } from '../constants.js';
10
+ import { cache } from './cache.js';
11
+ // ============================================================================
12
+ // API Helpers
13
+ // ============================================================================
14
+ async function fetchJson(url) {
15
+ const response = await axios.get(url, {
16
+ timeout: REQUEST_CONFIG.TIMEOUT,
17
+ headers: {
18
+ 'User-Agent': REQUEST_CONFIG.USER_AGENT,
19
+ 'Accept': 'application/json'
20
+ }
21
+ });
22
+ return response.data;
23
+ }
24
+ /**
25
+ * Discover all available versions for a product
26
+ */
27
+ async function discoverProductVersions(productId) {
28
+ const product = JAMF_PRODUCTS[productId];
29
+ const versions = new Set();
30
+ try {
31
+ // Search with a broad query to find all bundle versions
32
+ const apiUrl = `${DOCS_API_URL}/api/search?q=${encodeURIComponent(product.name)}&rpp=100`;
33
+ const response = await fetchJson(apiUrl);
34
+ const versionRegex = /-(\d+\.\d+\.\d+)$/;
35
+ const bundlePrefix = `${product.bundleId}-`;
36
+ for (const wrapper of response.Results) {
37
+ const bundleId = wrapper.leading_result?.bundle_id;
38
+ // Skip if no bundle_id (null or undefined)
39
+ if (bundleId === null || bundleId === undefined) {
40
+ continue;
41
+ }
42
+ // Check if this is a versioned documentation bundle for our product
43
+ if (bundleId.startsWith(bundlePrefix) || bundleId === product.bundleId) {
44
+ const match = versionRegex.exec(bundleId);
45
+ if (match?.[1] !== undefined) {
46
+ versions.add(match[1]);
47
+ }
48
+ }
49
+ }
50
+ }
51
+ catch (error) {
52
+ console.error(`[METADATA] Error discovering versions for ${productId}:`, error);
53
+ }
54
+ // Sort versions in descending order (newest first)
55
+ return Array.from(versions).sort((a, b) => {
56
+ const partsA = a.split('.').map(Number);
57
+ const partsB = b.split('.').map(Number);
58
+ for (let i = 0; i < 3; i++) {
59
+ const diff = (partsB[i] ?? 0) - (partsA[i] ?? 0);
60
+ if (diff !== 0) {
61
+ return diff;
62
+ }
63
+ }
64
+ return 0;
65
+ });
66
+ }
67
+ /**
68
+ * Fetch latest version and metadata for a product from the API
69
+ */
70
+ async function fetchProductMetadata(productId) {
71
+ const product = JAMF_PRODUCTS[productId];
72
+ try {
73
+ // Discover all available versions
74
+ const availableVersions = await discoverProductVersions(productId);
75
+ // Search for a doc from this product to get the bundle ID and labels
76
+ const apiUrl = `${DOCS_API_URL}/api/search?q=${encodeURIComponent(product.name)}&rpp=5`;
77
+ const response = await fetchJson(apiUrl);
78
+ for (const wrapper of response.Results) {
79
+ const result = wrapper.leading_result;
80
+ const bundleId = result?.bundle_id;
81
+ // Skip if no bundle_id or doesn't match our product
82
+ if (bundleId?.startsWith(product.bundleId) !== true) {
83
+ continue;
84
+ }
85
+ // Extract version from bundle_id (e.g., "jamf-pro-documentation-11.24.0" → "11.24.0")
86
+ const versionRegex = /-(\d+\.\d+\.\d+)$/;
87
+ const versionMatch = versionRegex.exec(bundleId);
88
+ const latestVersion = versionMatch?.[1] ?? 'current';
89
+ // Find product label key
90
+ const productLabel = result?.labels?.find(l => l.key.startsWith('product-') && !l.key.includes('-'));
91
+ const labelKey = productLabel?.key ?? product.searchLabel;
92
+ return {
93
+ id: productId,
94
+ name: product.name,
95
+ description: product.description,
96
+ bundleId,
97
+ latestVersion,
98
+ availableVersions: availableVersions.length > 0 ? availableVersions : [latestVersion],
99
+ labelKey
100
+ };
101
+ }
102
+ }
103
+ catch (error) {
104
+ console.error(`[METADATA] Error fetching metadata for ${productId}:`, error);
105
+ }
106
+ return null;
107
+ }
108
+ /**
109
+ * Get all products with their latest metadata
110
+ * Uses cache with fallback to static constants
111
+ */
112
+ export async function getProductsMetadata() {
113
+ const cacheKey = 'metadata:products';
114
+ // Check cache
115
+ const cached = await cache.get(cacheKey);
116
+ if (cached !== null) {
117
+ return cached;
118
+ }
119
+ const products = [];
120
+ // Fetch metadata for each product
121
+ for (const productId of Object.keys(JAMF_PRODUCTS)) {
122
+ const metadata = await fetchProductMetadata(productId);
123
+ if (metadata !== null) {
124
+ products.push(metadata);
125
+ }
126
+ else {
127
+ // Fallback to static data
128
+ const product = JAMF_PRODUCTS[productId];
129
+ products.push({
130
+ id: productId,
131
+ name: product.name,
132
+ description: product.description,
133
+ bundleId: product.bundleId,
134
+ latestVersion: product.latestVersion,
135
+ availableVersions: [product.latestVersion],
136
+ labelKey: product.searchLabel
137
+ });
138
+ }
139
+ }
140
+ // Cache for 24 hours
141
+ await cache.set(cacheKey, products, CACHE_TTL.ARTICLE_CONTENT);
142
+ return products;
143
+ }
144
+ /**
145
+ * Get the bundle ID for a specific product and version
146
+ * Returns the latest bundle ID if version is undefined or 'current'
147
+ */
148
+ export async function getBundleIdForVersion(productId, version) {
149
+ const products = await getProductsMetadata();
150
+ const product = products.find(p => p.id === productId);
151
+ if (product === undefined) {
152
+ return null;
153
+ }
154
+ // If no version specified or 'current', return latest
155
+ if (version === undefined || version === 'current' || version === 'latest') {
156
+ return product.bundleId;
157
+ }
158
+ // Check if requested version is available
159
+ if (!product.availableVersions.includes(version)) {
160
+ console.error(`[METADATA] Version ${version} not available for ${productId}. Available: ${product.availableVersions.join(', ')}`);
161
+ return null;
162
+ }
163
+ // Construct versioned bundle ID
164
+ const baseBundle = JAMF_PRODUCTS[productId].bundleId;
165
+ return `${baseBundle}-${version}`;
166
+ }
167
+ /**
168
+ * Get available versions for a product
169
+ */
170
+ export async function getAvailableVersions(productId) {
171
+ const products = await getProductsMetadata();
172
+ const product = products.find(p => p.id === productId);
173
+ return product?.availableVersions ?? [];
174
+ }
175
+ // ============================================================================
176
+ // Topic Categories from TOC
177
+ // ============================================================================
178
+ /**
179
+ * Parse TOC HTML to extract categories
180
+ */
181
+ function parseTocCategories(tocData) {
182
+ const categories = [];
183
+ // Sort by nav ID number
184
+ const sortedEntries = Object.entries(tocData)
185
+ .filter(([key]) => key.startsWith('nav-'))
186
+ .sort((a, b) => {
187
+ const numA = parseInt(a[0].replace('nav-', ''), 10);
188
+ const numB = parseInt(b[0].replace('nav-', ''), 10);
189
+ return numA - numB;
190
+ });
191
+ for (const [navId, html] of sortedEntries) {
192
+ if (typeof html !== 'string' || !html.includes('<ul')) {
193
+ continue;
194
+ }
195
+ const $ = cheerio.load(html);
196
+ const children = [];
197
+ // Get all article titles in this section
198
+ $('a').each((_, el) => {
199
+ const title = $(el).text().trim();
200
+ if (title !== '') {
201
+ children.push(title);
202
+ }
203
+ });
204
+ if (children.length > 0) {
205
+ // First child is usually the section title
206
+ const title = children[0] ?? 'Untitled';
207
+ categories.push({
208
+ navId,
209
+ title,
210
+ articleCount: children.length,
211
+ children: children.slice(1) // Exclude the title itself
212
+ });
213
+ }
214
+ }
215
+ return categories;
216
+ }
217
+ /**
218
+ * Convert TOC category to topic ID (slug)
219
+ */
220
+ function categoryToTopicId(title) {
221
+ return title
222
+ .toLowerCase()
223
+ .replace(/[^a-z0-9\s-]/g, '')
224
+ .replace(/\s+/g, '-')
225
+ .replace(/-+/g, '-')
226
+ .replace(/^-|-$/g, '')
227
+ .slice(0, 30); // Limit length
228
+ }
229
+ /**
230
+ * Fetch topic categories from TOC for a product
231
+ */
232
+ async function fetchTopicCategories(productId) {
233
+ try {
234
+ // First get the latest bundle ID
235
+ const products = await getProductsMetadata();
236
+ const product = products.find(p => p.id === productId);
237
+ if (product === undefined) {
238
+ return [];
239
+ }
240
+ const tocUrl = `${DOCS_API_URL}/bundle/${product.bundleId}/toc`;
241
+ const tocData = await fetchJson(tocUrl);
242
+ return parseTocCategories(tocData);
243
+ }
244
+ catch (error) {
245
+ console.error(`[METADATA] Error fetching TOC categories for ${productId}:`, error);
246
+ return [];
247
+ }
248
+ }
249
+ /**
250
+ * Add or update a topic in the map
251
+ */
252
+ function upsertTopic(topicsMap, category) {
253
+ const topicId = categoryToTopicId(category.title);
254
+ if (!topicsMap.has(topicId)) {
255
+ // Add new topic from TOC
256
+ topicsMap.set(topicId, {
257
+ id: topicId,
258
+ name: category.title,
259
+ source: 'toc',
260
+ articleCount: category.articleCount
261
+ });
262
+ }
263
+ else {
264
+ // Update existing topic with article count (accumulate across products)
265
+ const existing = topicsMap.get(topicId);
266
+ if (existing !== undefined) {
267
+ existing.articleCount = (existing.articleCount ?? 0) + category.articleCount;
268
+ }
269
+ }
270
+ }
271
+ /**
272
+ * Get all topics, combining TOC-derived from all products and manual topics
273
+ */
274
+ export async function getTopicsMetadata() {
275
+ const cacheKey = 'metadata:topics';
276
+ // Check cache
277
+ const cached = await cache.get(cacheKey);
278
+ if (cached !== null) {
279
+ return cached;
280
+ }
281
+ const topicsMap = new Map();
282
+ // Start with manual topics as fallback
283
+ for (const [id, topic] of Object.entries(JAMF_TOPICS)) {
284
+ topicsMap.set(id, {
285
+ id,
286
+ name: topic.name,
287
+ source: 'manual'
288
+ });
289
+ }
290
+ // Fetch TOC categories from ALL products
291
+ const productIds = Object.keys(JAMF_PRODUCTS);
292
+ for (const productId of productIds) {
293
+ try {
294
+ const categories = await fetchTopicCategories(productId);
295
+ for (const category of categories) {
296
+ upsertTopic(topicsMap, category);
297
+ }
298
+ }
299
+ catch (error) {
300
+ console.error(`[METADATA] Error fetching TOC for ${productId}:`, error);
301
+ // Continue with other products
302
+ }
303
+ }
304
+ const topics = Array.from(topicsMap.values());
305
+ // Cache for 24 hours
306
+ await cache.set(cacheKey, topics, CACHE_TTL.ARTICLE_CONTENT);
307
+ return topics;
308
+ }
309
+ // ============================================================================
310
+ // Convenience functions for Resources
311
+ // ============================================================================
312
+ /**
313
+ * Get products data formatted for resource response
314
+ */
315
+ export async function getProductsResourceData() {
316
+ const products = await getProductsMetadata();
317
+ return {
318
+ description: 'Available Jamf products for documentation search',
319
+ products: products.map(p => ({
320
+ id: p.id,
321
+ name: p.name,
322
+ description: p.description,
323
+ latestVersion: p.latestVersion,
324
+ availableVersions: p.availableVersions,
325
+ bundleId: p.bundleId
326
+ })),
327
+ lastUpdated: new Date().toISOString(),
328
+ usage: 'Use product ID (e.g., "jamf-pro") with jamf_docs_search or jamf_docs_get_toc tools. Use version parameter to query specific versions.'
329
+ };
330
+ }
331
+ /**
332
+ * Get topics data formatted for resource response
333
+ */
334
+ export async function getTopicsResourceData() {
335
+ const topics = await getTopicsMetadata();
336
+ return {
337
+ description: 'Topic categories for filtering Jamf documentation searches',
338
+ totalTopics: topics.length,
339
+ topics: topics.map(t => ({
340
+ id: t.id,
341
+ name: t.name,
342
+ source: t.source,
343
+ ...(t.articleCount !== undefined ? { articleCount: t.articleCount } : {})
344
+ })),
345
+ lastUpdated: new Date().toISOString(),
346
+ usage: 'Use topic ID (e.g., "enrollment") with jamf_docs_search tool to filter results'
347
+ };
348
+ }
349
+ //# sourceMappingURL=metadata.js.map