@get-technology-inc/jamf-docs-mcp-server 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +233 -21
- package/dist/completions.d.ts +13 -0
- package/dist/completions.d.ts.map +1 -0
- package/dist/completions.js +31 -0
- package/dist/completions.js.map +1 -0
- package/dist/constants.d.ts +125 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +187 -14
- package/dist/constants.js.map +1 -1
- package/dist/index.js +43 -7
- package/dist/index.js.map +1 -1
- package/dist/prompts/compare-versions.d.ts +7 -0
- package/dist/prompts/compare-versions.d.ts.map +1 -0
- package/dist/prompts/compare-versions.js +56 -0
- package/dist/prompts/compare-versions.js.map +1 -0
- package/dist/prompts/index.d.ts +6 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +12 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/setup-guide.d.ts +7 -0
- package/dist/prompts/setup-guide.d.ts.map +1 -0
- package/dist/prompts/setup-guide.js +53 -0
- package/dist/prompts/setup-guide.js.map +1 -0
- package/dist/prompts/troubleshoot.d.ts +7 -0
- package/dist/prompts/troubleshoot.d.ts.map +1 -0
- package/dist/prompts/troubleshoot.js +52 -0
- package/dist/prompts/troubleshoot.js.map +1 -0
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +78 -2
- package/dist/resources/index.js.map +1 -1
- package/dist/schemas/index.d.ts +10 -7
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +18 -16
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/output.d.ts +78 -0
- package/dist/schemas/output.d.ts.map +1 -0
- package/dist/schemas/output.js +78 -0
- package/dist/schemas/output.js.map +1 -0
- package/dist/services/cache.d.ts +37 -3
- package/dist/services/cache.d.ts.map +1 -1
- package/dist/services/cache.js +139 -15
- package/dist/services/cache.js.map +1 -1
- package/dist/services/metadata.d.ts +4 -0
- package/dist/services/metadata.d.ts.map +1 -1
- package/dist/services/metadata.js +52 -9
- package/dist/services/metadata.js.map +1 -1
- package/dist/services/scraper.d.ts +9 -1
- package/dist/services/scraper.d.ts.map +1 -1
- package/dist/services/scraper.js +171 -20
- package/dist/services/scraper.js.map +1 -1
- package/dist/services/tokenizer.d.ts +5 -0
- package/dist/services/tokenizer.d.ts.map +1 -1
- package/dist/services/tokenizer.js +20 -5
- package/dist/services/tokenizer.js.map +1 -1
- package/dist/tools/get-article.d.ts.map +1 -1
- package/dist/tools/get-article.js +37 -11
- package/dist/tools/get-article.js.map +1 -1
- package/dist/tools/get-toc.d.ts.map +1 -1
- package/dist/tools/get-toc.js +54 -10
- package/dist/tools/get-toc.js.map +1 -1
- package/dist/tools/list-products.d.ts.map +1 -1
- package/dist/tools/list-products.js +34 -15
- package/dist/tools/list-products.js.map +1 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +83 -22
- package/dist/tools/search.js.map +1 -1
- package/dist/transport/http.d.ts +12 -0
- package/dist/transport/http.d.ts.map +1 -0
- package/dist/transport/http.js +297 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/transport/index.d.ts +13 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +40 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/types.d.ts +30 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/doc-type.d.ts +9 -0
- package/dist/utils/doc-type.d.ts.map +1 -0
- package/dist/utils/doc-type.js +16 -0
- package/dist/utils/doc-type.js.map +1 -0
- package/dist/utils/progress.d.ts +13 -0
- package/dist/utils/progress.d.ts.map +1 -0
- package/dist/utils/progress.js +18 -0
- package/dist/utils/progress.js.map +1 -0
- package/dist/utils/sanitize.d.ts +30 -0
- package/dist/utils/sanitize.d.ts.map +1 -0
- package/dist/utils/sanitize.js +57 -0
- package/dist/utils/sanitize.js.map +1 -0
- package/dist/utils/url.d.ts +11 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/url.js +23 -0
- package/dist/utils/url.js.map +1 -0
- package/package.json +11 -4
package/dist/tools/search.js
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
* Search Jamf documentation for articles matching a query.
|
|
4
4
|
*/
|
|
5
5
|
import { SearchInputSchema } from '../schemas/index.js';
|
|
6
|
+
import { SearchOutputSchema } from '../schemas/output.js';
|
|
6
7
|
import { ResponseFormat, OutputMode, JAMF_PRODUCTS, JAMF_TOPICS, TOKEN_CONFIG } from '../constants.js';
|
|
7
8
|
import { searchDocumentation } from '../services/scraper.js';
|
|
8
9
|
import { generateSearchSuggestions, formatSearchSuggestions } from '../services/search-suggestions.js';
|
|
10
|
+
import { sanitizeMarkdownText, sanitizeMarkdownUrl, getSafeErrorMessage } from '../utils/sanitize.js';
|
|
9
11
|
function formatFiltersLine(filters) {
|
|
10
12
|
const parts = [];
|
|
11
13
|
if (filters.product !== undefined) {
|
|
@@ -20,11 +22,11 @@ function formatFiltersLine(filters) {
|
|
|
20
22
|
return parts.length > 0 ? `\n*Filtered by: ${parts.join(', ')}*` : '';
|
|
21
23
|
}
|
|
22
24
|
function formatSearchResult(result) {
|
|
23
|
-
let output = `### [${result.title}](${result.url})\n\n`;
|
|
24
|
-
output += `> ${result.snippet}\n\n`;
|
|
25
|
-
if (result.product !== '' || result.version !== undefined) {
|
|
25
|
+
let output = `### [${sanitizeMarkdownText(result.title)}](${sanitizeMarkdownUrl(result.url)})\n\n`;
|
|
26
|
+
output += `> ${sanitizeMarkdownText(result.snippet)}\n\n`;
|
|
27
|
+
if ((result.product !== null && result.product !== '') || result.version !== undefined) {
|
|
26
28
|
const meta = [];
|
|
27
|
-
if (result.product !== '') {
|
|
29
|
+
if (result.product !== null && result.product !== '') {
|
|
28
30
|
meta.push(`**Product**: ${result.product}`);
|
|
29
31
|
}
|
|
30
32
|
if (result.version !== undefined) {
|
|
@@ -62,7 +64,7 @@ function formatSearchResultCompact(result, index) {
|
|
|
62
64
|
const snippetPreview = result.snippet.length > 80
|
|
63
65
|
? `${result.snippet.slice(0, 77)}...`
|
|
64
66
|
: result.snippet;
|
|
65
|
-
return `${index}. [${result.title}](${result.url}) - ${snippetPreview}\n`;
|
|
67
|
+
return `${index}. [${sanitizeMarkdownText(result.title)}](${sanitizeMarkdownUrl(result.url)}) - ${sanitizeMarkdownText(snippetPreview)}\n`;
|
|
66
68
|
}
|
|
67
69
|
/**
|
|
68
70
|
* Format search results as compact markdown
|
|
@@ -92,17 +94,18 @@ const TOOL_NAME = 'jamf_docs_search';
|
|
|
92
94
|
const TOOL_DESCRIPTION = `Search Jamf documentation for articles matching your query.
|
|
93
95
|
|
|
94
96
|
This tool searches across all Jamf product documentation including Jamf Pro,
|
|
95
|
-
Jamf School, Jamf Connect,
|
|
96
|
-
snippets, and direct links.
|
|
97
|
+
Jamf School, Jamf Connect, Jamf Protect, Jamf Now, Jamf Safe Internet, and more.
|
|
98
|
+
Results include article titles, snippets, and direct links.
|
|
97
99
|
|
|
98
100
|
Args:
|
|
99
101
|
- query (string, required): Search keywords (2-200 characters)
|
|
100
|
-
- product (string, optional): Filter by product ID (
|
|
102
|
+
- product (string, optional): Filter by product ID (use jamf_docs_list_products to see all)
|
|
101
103
|
- topic (string, optional): Filter by topic (enrollment, profiles, security, inventory, policies, smart-groups, apps, identity, api, network)
|
|
104
|
+
- docType (string, optional): Filter by document type: documentation, release-notes, install-guide, technical-paper, configuration-guide, training
|
|
102
105
|
- version (string, optional): Filter by version (e.g., "11.5.0", "10.x")
|
|
103
106
|
- limit (number, optional): Maximum results per page 1-50 (default: 10)
|
|
104
107
|
- page (number, optional): Page number for pagination 1-100 (default: 1)
|
|
105
|
-
- maxTokens (number, optional): Maximum tokens in response 100-
|
|
108
|
+
- maxTokens (number, optional): Maximum tokens in response 100-50000 (default: 5000)
|
|
106
109
|
- outputMode ('full' | 'compact'): Output detail level (default: 'full'). Use 'compact' for brief, token-efficient output
|
|
107
110
|
- responseFormat ('markdown' | 'json'): Output format (default: 'markdown')
|
|
108
111
|
|
|
@@ -146,6 +149,7 @@ export function registerSearchTool(server) {
|
|
|
146
149
|
title: 'Search Jamf Documentation',
|
|
147
150
|
description: TOOL_DESCRIPTION,
|
|
148
151
|
inputSchema: SearchInputSchema,
|
|
152
|
+
outputSchema: SearchOutputSchema,
|
|
149
153
|
annotations: {
|
|
150
154
|
readOnlyHint: true,
|
|
151
155
|
destructiveHint: false,
|
|
@@ -163,7 +167,6 @@ export function registerSearchTool(server) {
|
|
|
163
167
|
}
|
|
164
168
|
const params = parseResult.data;
|
|
165
169
|
try {
|
|
166
|
-
// Validate product if provided
|
|
167
170
|
if (params.product !== undefined && !(params.product in JAMF_PRODUCTS)) {
|
|
168
171
|
return {
|
|
169
172
|
isError: true,
|
|
@@ -173,7 +176,6 @@ export function registerSearchTool(server) {
|
|
|
173
176
|
}]
|
|
174
177
|
};
|
|
175
178
|
}
|
|
176
|
-
// Validate topic if provided
|
|
177
179
|
if (params.topic !== undefined && !(params.topic in JAMF_TOPICS)) {
|
|
178
180
|
return {
|
|
179
181
|
isError: true,
|
|
@@ -183,17 +185,22 @@ export function registerSearchTool(server) {
|
|
|
183
185
|
}]
|
|
184
186
|
};
|
|
185
187
|
}
|
|
186
|
-
// Perform search
|
|
188
|
+
// Perform search
|
|
187
189
|
const searchResult = await searchDocumentation({
|
|
188
190
|
query: params.query,
|
|
189
191
|
product: params.product,
|
|
190
192
|
topic: params.topic,
|
|
193
|
+
docType: params.docType,
|
|
191
194
|
version: params.version,
|
|
192
195
|
limit: params.limit,
|
|
193
196
|
page: params.page,
|
|
194
197
|
maxTokens: params.maxTokens ?? TOKEN_CONFIG.DEFAULT_MAX_TOKENS
|
|
195
198
|
});
|
|
196
|
-
const { results, pagination, tokenInfo } = searchResult;
|
|
199
|
+
const { results, pagination, tokenInfo, filterRelaxation, truncatedContent } = searchResult;
|
|
200
|
+
// Version transparency
|
|
201
|
+
const versionNote = (params.version !== undefined && params.version !== 'current')
|
|
202
|
+
? 'The Jamf documentation API only provides current version content. Results shown are from the latest version.'
|
|
203
|
+
: undefined;
|
|
197
204
|
// Build response
|
|
198
205
|
const response = {
|
|
199
206
|
total: pagination.totalItems,
|
|
@@ -205,45 +212,99 @@ export function registerSearchTool(server) {
|
|
|
205
212
|
...(params.topic !== undefined ? { topic: params.topic } : {})
|
|
206
213
|
},
|
|
207
214
|
tokenInfo,
|
|
208
|
-
pagination
|
|
215
|
+
pagination,
|
|
216
|
+
...(filterRelaxation !== undefined ? { filterRelaxation } : {}),
|
|
217
|
+
...(versionNote !== undefined ? { versionNote } : {}),
|
|
218
|
+
...(truncatedContent !== undefined ? { truncatedContent } : {})
|
|
209
219
|
};
|
|
210
220
|
// Handle no results with suggestions
|
|
211
221
|
if (results.length === 0 && pagination.totalItems === 0) {
|
|
212
222
|
const suggestions = generateSearchSuggestions(params.query, params.product !== undefined, params.topic !== undefined);
|
|
223
|
+
const suggestionTexts = [
|
|
224
|
+
...(suggestions.simplifiedQuery !== null ? [`Try: ${suggestions.simplifiedQuery}`] : []),
|
|
225
|
+
...suggestions.alternativeKeywords,
|
|
226
|
+
...suggestions.tips
|
|
227
|
+
];
|
|
228
|
+
const structuredContent = {
|
|
229
|
+
query: params.query,
|
|
230
|
+
totalResults: 0,
|
|
231
|
+
page: 1,
|
|
232
|
+
totalPages: 0,
|
|
233
|
+
hasMore: false,
|
|
234
|
+
results: [],
|
|
235
|
+
suggestions: suggestionTexts
|
|
236
|
+
};
|
|
213
237
|
return {
|
|
214
238
|
content: [{
|
|
215
239
|
type: 'text',
|
|
216
240
|
text: formatSearchSuggestions(params.query, suggestions)
|
|
217
|
-
}]
|
|
241
|
+
}],
|
|
242
|
+
structuredContent
|
|
218
243
|
};
|
|
219
244
|
}
|
|
220
|
-
|
|
245
|
+
const structuredContent = {
|
|
246
|
+
query: params.query,
|
|
247
|
+
totalResults: pagination.totalItems,
|
|
248
|
+
page: pagination.page,
|
|
249
|
+
totalPages: pagination.totalPages,
|
|
250
|
+
hasMore: pagination.hasNext,
|
|
251
|
+
results: results.map(r => ({
|
|
252
|
+
title: r.title,
|
|
253
|
+
url: r.url,
|
|
254
|
+
snippet: r.snippet,
|
|
255
|
+
product: r.product ?? '',
|
|
256
|
+
...(r.version !== undefined ? { version: r.version } : {}),
|
|
257
|
+
...(r.docType !== undefined ? { docType: r.docType } : {})
|
|
258
|
+
})),
|
|
259
|
+
...(filterRelaxation !== undefined ? { filterRelaxation } : {}),
|
|
260
|
+
...(versionNote !== undefined ? { versionNote } : {}),
|
|
261
|
+
...(truncatedContent !== undefined ? { truncatedContent } : {})
|
|
262
|
+
};
|
|
221
263
|
if (params.responseFormat === ResponseFormat.JSON) {
|
|
264
|
+
// Add relevance note only in JSON format
|
|
265
|
+
const jsonResponse = {
|
|
266
|
+
...response,
|
|
267
|
+
relevanceNote: 'Relevance scores are provided by the Zoomin Search API based on text matching. Higher values indicate stronger keyword matches.'
|
|
268
|
+
};
|
|
222
269
|
return {
|
|
223
270
|
content: [{
|
|
224
271
|
type: 'text',
|
|
225
|
-
text: JSON.stringify(
|
|
226
|
-
}]
|
|
272
|
+
text: JSON.stringify(jsonResponse, null, 2)
|
|
273
|
+
}],
|
|
274
|
+
structuredContent: {
|
|
275
|
+
...structuredContent,
|
|
276
|
+
relevanceNote: jsonResponse.relevanceNote
|
|
277
|
+
}
|
|
227
278
|
};
|
|
228
279
|
}
|
|
229
280
|
// Markdown format (full or compact)
|
|
230
|
-
|
|
281
|
+
let markdown = params.outputMode === OutputMode.COMPACT
|
|
231
282
|
? formatSearchResultsAsCompact(params.query, results, response.filters ?? {}, pagination, tokenInfo)
|
|
232
283
|
: formatSearchResultsAsMarkdown(params.query, results, response.filters ?? {}, pagination, tokenInfo);
|
|
284
|
+
// Append notices for markdown
|
|
285
|
+
if (filterRelaxation !== undefined) {
|
|
286
|
+
markdown += `\n> **Note:** ${filterRelaxation.message}\n`;
|
|
287
|
+
}
|
|
288
|
+
if (versionNote !== undefined) {
|
|
289
|
+
markdown += `\n> **Version Note:** ${versionNote}\n`;
|
|
290
|
+
}
|
|
291
|
+
if (truncatedContent !== undefined && truncatedContent.omittedCount > 0) {
|
|
292
|
+
markdown += `\n*${truncatedContent.omittedCount} additional result(s) omitted due to token limit.*\n`;
|
|
293
|
+
}
|
|
233
294
|
return {
|
|
234
295
|
content: [{
|
|
235
296
|
type: 'text',
|
|
236
297
|
text: markdown
|
|
237
|
-
}]
|
|
298
|
+
}],
|
|
299
|
+
structuredContent
|
|
238
300
|
};
|
|
239
301
|
}
|
|
240
302
|
catch (error) {
|
|
241
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
242
303
|
return {
|
|
243
304
|
isError: true,
|
|
244
305
|
content: [{
|
|
245
306
|
type: 'text',
|
|
246
|
-
text: `Search error: ${
|
|
307
|
+
text: `Search error: ${getSafeErrorMessage(error)}\n\nPlease try again or use different search terms.`
|
|
247
308
|
}]
|
|
248
309
|
};
|
|
249
310
|
}
|
package/dist/tools/search.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP transport using Web Standard APIs
|
|
3
|
+
*
|
|
4
|
+
* Uses WebStandardStreamableHTTPServerTransport from the SDK,
|
|
5
|
+
* compatible with Node.js, Cloudflare Workers, Deno, and Bun.
|
|
6
|
+
*/
|
|
7
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create and start an HTTP server for the MCP server
|
|
10
|
+
*/
|
|
11
|
+
export declare function startHttpServer(mcpServer: McpServer, port: number, host: string): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA8KzE;;GAEG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAsDf"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP transport using Web Standard APIs
|
|
3
|
+
*
|
|
4
|
+
* Uses WebStandardStreamableHTTPServerTransport from the SDK,
|
|
5
|
+
* compatible with Node.js, Cloudflare Workers, Deno, and Bun.
|
|
6
|
+
*/
|
|
7
|
+
import { createServer } from 'node:http';
|
|
8
|
+
import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
|
|
9
|
+
import { SERVER_VERSION, getEnvNumber } from '../constants.js';
|
|
10
|
+
const SHUTDOWN_TIMEOUT = 10_000;
|
|
11
|
+
const MAX_BODY_SIZE = 1_048_576; // 1MB
|
|
12
|
+
class PayloadTooLargeError extends Error {
|
|
13
|
+
constructor() {
|
|
14
|
+
super('Payload too large');
|
|
15
|
+
this.name = 'PayloadTooLargeError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// CORS configuration
|
|
19
|
+
const CORS_ALLOWED_ORIGINS = (process.env.CORS_ALLOWED_ORIGINS ?? '').split(',').map(s => s.trim()).filter(Boolean);
|
|
20
|
+
/**
|
|
21
|
+
* Token bucket rate limiter (per-IP)
|
|
22
|
+
*/
|
|
23
|
+
class RateLimiter {
|
|
24
|
+
buckets = new Map();
|
|
25
|
+
maxTokens;
|
|
26
|
+
windowMs;
|
|
27
|
+
constructor(maxTokens, windowMs) {
|
|
28
|
+
this.maxTokens = maxTokens;
|
|
29
|
+
this.windowMs = windowMs;
|
|
30
|
+
}
|
|
31
|
+
isAllowed(ip) {
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
let bucket = this.buckets.get(ip);
|
|
34
|
+
if (bucket === undefined) {
|
|
35
|
+
bucket = { tokens: this.maxTokens, lastRefill: now };
|
|
36
|
+
this.buckets.set(ip, bucket);
|
|
37
|
+
}
|
|
38
|
+
// Refill tokens based on elapsed time
|
|
39
|
+
const elapsed = now - bucket.lastRefill;
|
|
40
|
+
const tokensToAdd = (elapsed / this.windowMs) * this.maxTokens;
|
|
41
|
+
bucket.tokens = Math.min(this.maxTokens, bucket.tokens + tokensToAdd);
|
|
42
|
+
bucket.lastRefill = now;
|
|
43
|
+
if (bucket.tokens >= 1) {
|
|
44
|
+
bucket.tokens -= 1;
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
// Periodically clean up old entries to prevent memory leak
|
|
50
|
+
cleanup() {
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
for (const [ip, bucket] of this.buckets.entries()) {
|
|
53
|
+
if (now - bucket.lastRefill > this.windowMs * 2) {
|
|
54
|
+
this.buckets.delete(ip);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get CORS headers for a given origin
|
|
61
|
+
*/
|
|
62
|
+
function getCorsHeaders(origin) {
|
|
63
|
+
const headers = {};
|
|
64
|
+
if (CORS_ALLOWED_ORIGINS.length === 0) {
|
|
65
|
+
// No origins configured — deny cross-origin by not setting Access-Control-Allow-Origin
|
|
66
|
+
return headers;
|
|
67
|
+
}
|
|
68
|
+
const originStr = Array.isArray(origin) ? origin[0] : origin;
|
|
69
|
+
if (originStr !== undefined && CORS_ALLOWED_ORIGINS.includes(originStr)) {
|
|
70
|
+
headers['Access-Control-Allow-Origin'] = originStr;
|
|
71
|
+
headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS';
|
|
72
|
+
headers['Access-Control-Allow-Headers'] = 'Content-Type';
|
|
73
|
+
headers['Access-Control-Max-Age'] = '86400';
|
|
74
|
+
headers.Vary = 'Origin';
|
|
75
|
+
}
|
|
76
|
+
return headers;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get client IP from request
|
|
80
|
+
*/
|
|
81
|
+
function getClientIp(req) {
|
|
82
|
+
const forwarded = req.headers['x-forwarded-for'];
|
|
83
|
+
if (typeof forwarded === 'string') {
|
|
84
|
+
return forwarded.split(',')[0]?.trim() ?? 'unknown';
|
|
85
|
+
}
|
|
86
|
+
// socket may be undefined in test environments
|
|
87
|
+
const socket = req.socket;
|
|
88
|
+
return socket?.remoteAddress ?? 'unknown';
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Convert Node.js IncomingMessage to a Web Standard Request
|
|
92
|
+
*/
|
|
93
|
+
function toWebRequest(req, body, url) {
|
|
94
|
+
const headers = new Headers();
|
|
95
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
96
|
+
if (value !== undefined) {
|
|
97
|
+
if (Array.isArray(value)) {
|
|
98
|
+
for (const v of value) {
|
|
99
|
+
headers.append(key, v);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
headers.set(key, value);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const method = req.method ?? 'GET';
|
|
108
|
+
const init = {
|
|
109
|
+
method,
|
|
110
|
+
headers,
|
|
111
|
+
};
|
|
112
|
+
// Only add body for methods that support it
|
|
113
|
+
if (method !== 'GET' && method !== 'HEAD' && method !== 'DELETE') {
|
|
114
|
+
init.body = body;
|
|
115
|
+
}
|
|
116
|
+
return new Request(url.toString(), init);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Write a Web Standard Response back to Node.js ServerResponse
|
|
120
|
+
*/
|
|
121
|
+
async function writeWebResponse(webRes, res) {
|
|
122
|
+
res.writeHead(webRes.status, Object.fromEntries(webRes.headers.entries()));
|
|
123
|
+
if (webRes.body === null) {
|
|
124
|
+
res.end();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const reader = webRes.body.getReader();
|
|
128
|
+
try {
|
|
129
|
+
for (;;) {
|
|
130
|
+
const result = await reader.read();
|
|
131
|
+
if (result.done) {
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
res.write(result.value);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
reader.releaseLock();
|
|
139
|
+
res.end();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Collect request body from IncomingMessage into a Buffer.
|
|
144
|
+
* Enforces a maximum body size to prevent memory exhaustion.
|
|
145
|
+
*/
|
|
146
|
+
async function collectBody(req) {
|
|
147
|
+
const chunks = [];
|
|
148
|
+
let totalSize = 0;
|
|
149
|
+
for await (const chunk of req) {
|
|
150
|
+
const buf = typeof chunk === 'string' ? Buffer.from(chunk) : chunk;
|
|
151
|
+
totalSize += buf.length;
|
|
152
|
+
if (totalSize > MAX_BODY_SIZE) {
|
|
153
|
+
req.destroy();
|
|
154
|
+
throw new PayloadTooLargeError();
|
|
155
|
+
}
|
|
156
|
+
chunks.push(buf);
|
|
157
|
+
}
|
|
158
|
+
return Buffer.concat(chunks);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Create and start an HTTP server for the MCP server
|
|
162
|
+
*/
|
|
163
|
+
export async function startHttpServer(mcpServer, port, host) {
|
|
164
|
+
const rateLimitRpm = getEnvNumber('RATE_LIMIT_RPM', 60, 1, 10000);
|
|
165
|
+
const rateLimiter = new RateLimiter(rateLimitRpm, 60_000);
|
|
166
|
+
setInterval(() => { rateLimiter.cleanup(); }, 5 * 60_000).unref();
|
|
167
|
+
const httpServer = createServer((req, res) => {
|
|
168
|
+
void handleHttpRequest(req, res, mcpServer, rateLimiter);
|
|
169
|
+
});
|
|
170
|
+
// Graceful shutdown
|
|
171
|
+
let shuttingDown = false;
|
|
172
|
+
function shutdown(signal) {
|
|
173
|
+
if (shuttingDown) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
shuttingDown = true;
|
|
177
|
+
console.error(`\n${signal} received, shutting down...`);
|
|
178
|
+
httpServer.close(() => {
|
|
179
|
+
console.error('HTTP server closed');
|
|
180
|
+
process.exit(0);
|
|
181
|
+
});
|
|
182
|
+
// Force exit after timeout
|
|
183
|
+
setTimeout(() => {
|
|
184
|
+
console.error('Shutdown timeout, forcing exit');
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}, SHUTDOWN_TIMEOUT);
|
|
187
|
+
}
|
|
188
|
+
process.on('SIGINT', () => { shutdown('SIGINT'); });
|
|
189
|
+
process.on('SIGTERM', () => { shutdown('SIGTERM'); });
|
|
190
|
+
// Start listening
|
|
191
|
+
await new Promise((resolve, reject) => {
|
|
192
|
+
httpServer.on('error', (error) => {
|
|
193
|
+
if (error.code === 'EADDRINUSE') {
|
|
194
|
+
console.error(`Port ${port} is already in use`);
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
reject(error);
|
|
198
|
+
});
|
|
199
|
+
httpServer.listen(port, host, () => {
|
|
200
|
+
if (host !== '127.0.0.1' && host !== '::1') {
|
|
201
|
+
console.error(`[SECURITY WARNING] Server is binding to ${host}, which exposes it to the network. Use 127.0.0.1 for local-only access.`);
|
|
202
|
+
}
|
|
203
|
+
console.error(`Jamf Docs MCP Server running on http://${host}:${port}`);
|
|
204
|
+
console.error(`MCP endpoint: http://${host}:${port}/mcp`);
|
|
205
|
+
console.error(`Health check: http://${host}:${port}/health`);
|
|
206
|
+
resolve();
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Handle a single HTTP request
|
|
212
|
+
*/
|
|
213
|
+
async function handleHttpRequest(req, res, mcpServer, rateLimiter) {
|
|
214
|
+
// Use hardcoded base URL to prevent Host header injection (SAST #8)
|
|
215
|
+
const url = new URL(req.url ?? '/', 'http://localhost');
|
|
216
|
+
const { pathname } = url;
|
|
217
|
+
const { origin } = req.headers;
|
|
218
|
+
const corsHeaders = getCorsHeaders(origin);
|
|
219
|
+
// Handle CORS preflight
|
|
220
|
+
if (req.method === 'OPTIONS') {
|
|
221
|
+
res.writeHead(204, { ...corsHeaders, 'Content-Length': '0' });
|
|
222
|
+
res.end();
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
// Rate limiting
|
|
226
|
+
const clientIp = getClientIp(req);
|
|
227
|
+
if (!rateLimiter.isAllowed(clientIp)) {
|
|
228
|
+
res.writeHead(429, { 'Content-Type': 'application/json', ...corsHeaders });
|
|
229
|
+
res.end(JSON.stringify({ error: 'Too many requests' }));
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
// Health check endpoint
|
|
233
|
+
if (pathname === '/health' && req.method === 'GET') {
|
|
234
|
+
res.writeHead(200, { 'Content-Type': 'application/json', ...corsHeaders });
|
|
235
|
+
res.end(JSON.stringify({ status: 'ok', version: SERVER_VERSION }));
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
// MCP endpoint
|
|
239
|
+
if (pathname === '/mcp') {
|
|
240
|
+
let body;
|
|
241
|
+
try {
|
|
242
|
+
body = await collectBody(req);
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
if (err instanceof PayloadTooLargeError) {
|
|
246
|
+
res.writeHead(413, { 'Content-Type': 'application/json', ...corsHeaders });
|
|
247
|
+
res.end(JSON.stringify({ error: 'Payload too large' }));
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
throw err;
|
|
251
|
+
}
|
|
252
|
+
// Create a per-request transport (stateless mode)
|
|
253
|
+
const transport = new WebStandardStreamableHTTPServerTransport({
|
|
254
|
+
enableJsonResponse: true,
|
|
255
|
+
});
|
|
256
|
+
// Connect the MCP server to this transport
|
|
257
|
+
await mcpServer.connect(transport);
|
|
258
|
+
try {
|
|
259
|
+
// Convert Node request to Web Standard Request
|
|
260
|
+
const webReq = toWebRequest(req, body, url);
|
|
261
|
+
// Parse body for the transport if present
|
|
262
|
+
let parsedBody;
|
|
263
|
+
if (body.length > 0) {
|
|
264
|
+
try {
|
|
265
|
+
parsedBody = JSON.parse(body.toString());
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
res.writeHead(400, { 'Content-Type': 'application/json', ...corsHeaders });
|
|
269
|
+
res.end(JSON.stringify({ error: 'Invalid JSON in request body' }));
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Handle the request
|
|
274
|
+
const webRes = await transport.handleRequest(webReq, { parsedBody });
|
|
275
|
+
// Add CORS headers to the web response before writing
|
|
276
|
+
for (const [key, value] of Object.entries(corsHeaders)) {
|
|
277
|
+
webRes.headers.set(key, value);
|
|
278
|
+
}
|
|
279
|
+
// Write the response
|
|
280
|
+
await writeWebResponse(webRes, res);
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
if (!res.headersSent) {
|
|
284
|
+
res.writeHead(500, { 'Content-Type': 'application/json', ...corsHeaders });
|
|
285
|
+
res.end(JSON.stringify({ error: 'Internal server error' }));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
finally {
|
|
289
|
+
await transport.close();
|
|
290
|
+
}
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
// 404 for everything else
|
|
294
|
+
res.writeHead(404, { 'Content-Type': 'application/json', ...corsHeaders });
|
|
295
|
+
res.end(JSON.stringify({ error: 'Not found' }));
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transport/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport configuration and CLI argument parsing
|
|
3
|
+
*/
|
|
4
|
+
export interface TransportArgs {
|
|
5
|
+
transport: 'stdio' | 'http';
|
|
6
|
+
port: number;
|
|
7
|
+
host: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Parse CLI arguments for transport configuration
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseCliArgs(argv: string[]): TransportArgs;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAgC1D"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport configuration and CLI argument parsing
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Parse CLI arguments for transport configuration
|
|
6
|
+
*/
|
|
7
|
+
export function parseCliArgs(argv) {
|
|
8
|
+
const args = {
|
|
9
|
+
transport: 'stdio',
|
|
10
|
+
port: 3000,
|
|
11
|
+
host: '127.0.0.1',
|
|
12
|
+
};
|
|
13
|
+
for (let i = 0; i < argv.length; i++) {
|
|
14
|
+
const arg = argv[i];
|
|
15
|
+
const next = argv[i + 1];
|
|
16
|
+
if (arg === '--transport' && next !== undefined) {
|
|
17
|
+
if (next !== 'stdio' && next !== 'http') {
|
|
18
|
+
console.error(`Invalid transport: "${next}". Must be "stdio" or "http".`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
args.transport = next;
|
|
22
|
+
i++;
|
|
23
|
+
}
|
|
24
|
+
else if (arg === '--port' && next !== undefined) {
|
|
25
|
+
const port = parseInt(next, 10);
|
|
26
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
27
|
+
console.error(`Invalid port: "${next}". Must be 1-65535.`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
args.port = port;
|
|
31
|
+
i++;
|
|
32
|
+
}
|
|
33
|
+
else if (arg === '--host' && next !== undefined) {
|
|
34
|
+
args.host = next;
|
|
35
|
+
i++;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return args;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transport/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,MAAM,IAAI,GAAkB;QAC1B,SAAS,EAAE,OAAO;QAClB,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,WAAW;KAClB,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,IAAI,GAAG,KAAK,aAAa,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAChD,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBACxC,OAAO,CAAC,KAAK,CAAC,uBAAuB,IAAI,+BAA+B,CAAC,CAAC;gBAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAClD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAChC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;gBAC5C,OAAO,CAAC,KAAK,CAAC,kBAAkB,IAAI,qBAAqB,CAAC,CAAC;gBAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;YACjB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAClD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;YACjB,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|