CartographAI/atlas-docs-mcp
criticalProvide LLMs hosted, clean markdown documentation of libraries and frameworks
This MCP server provides AI assistants with clean, markdown documentation for various libraries and frameworks. It fetches and serves documentation fr...
51async function fetchApi(path: string) {
52 const response = await fetch(`${ATLAS_API_URL}${path}`);
53 if (!response.ok) {
54 const error = await response.json();
55 throw new Error(error.error || "API request failed");
56 }
57 return response.json();
58}26const GetDocsIndexSchema = z.object({
27 docName: z.string().describe("Name of the documentation set"),
28});
29
30const GetDocsFullSchema = z.object({
31 docName: z.string().describe("Name of the documentation set"),
32});
33
34const GetDocsPageSchema = z.object({
35 docName: z.string().describe("Name of the documentation set"),
36 pagePath: z
37 .string()
38 .describe(
39 "The root-relative path of the specific documentation page (e.g., '/guides/getting-started', '/api/authentication')",
40 ),
41});
42
43const SearchDocsSchema = z.object({
44 docName: z.string().describe("Name of the documentation set"),
45 query: z.string().describe("Search query to find relevant pages within the documentation set"),
46});// Exploitable if MCP is exposed to untrusted prompts (network_exposed).
The Zod schemas only enforce that docName, pagePath, and query are strings. There is no validation that docName is a known documentation set, or that pagePath is a valid relative path without traversal sequences. This allows arbitrary string inputs to be passed to the fetchApi function.
ImpactEnables SSRF and potential access to unintended API endpoints. Also allows injection of special characters in query parameters.
FixAdd validation to ensure docName is from a predefined list, pagePath matches a safe pattern (e.g., starts with '/' and contains only allowed characters), and query is sanitized.
114case "get_docs_index": {
115 const parsedArgs = GetDocsIndexSchema.safeParse(args);
116 if (!parsedArgs.success) {
117 throw new Error(`Invalid arguments: ${parsedArgs.error}`);
118 }
119 const docName = parsedArgs.data.docName;
120 const page = await fetchApi(`/docs/${docName}/pages/%2Fllms.txt`);
121 return {
122 content: [{ type: "text", text: JSON.stringify(page, null, 2) }],
123 };
124}// Exploitable if MCP is exposed to untrusted prompts (network_exposed) or by a compromised LLM (local_only).
The docName parameter is used directly in the API path without any validation. An attacker could provide a docName like '../../admin' to traverse the API path and access unintended endpoints. The same issue exists in get_docs_full, get_docs_page, and search_docs handlers.
ImpactAn attacker could access arbitrary API endpoints, potentially retrieving sensitive information or performing unauthorized actions on the API server.
FixValidate docName against a whitelist of allowed documentation set names. Reject any docName containing path traversal characters like '..' or '/'.
148const { docName, pagePath } = parsedArgs.data;
149// we need to encodeURIComponent as the pagePath is likely to contain slashes
150const page = await fetchApi(`/docs/${docName}/pages/${encodeURIComponent(pagePath)}`);// Exploitable if MCP is exposed to untrusted prompts or if a compromised LLM sends malicious input.
The pagePath parameter is URL-encoded but not validated for path traversal sequences. An attacker could provide a pagePath like '../../etc/passwd' which, after encoding, might still traverse directories on the server hosting the API, potentially accessing unintended files.
ImpactAn attacker could read arbitrary files on the API server if the API endpoint does not properly restrict paths, leading to information disclosure.
FixValidate pagePath to ensure it does not contain path traversal sequences (e.g., '..') and restrict it to a known set of allowed paths or a specific directory.
142case "get_docs_page": {
143 const parsedArgs = GetDocsPageSchema.safeParse(args);
144 if (!parsedArgs.success) {
145 throw new Error(`Invalid arguments: ${parsedArgs.error}`);
146 }
147 const { docName, pagePath } = parsedArgs.data;
148 // we need to encodeURIComponent as the pagePath is likely to contain slashes
149 const page = await fetchApi(`/docs/${docName}/pages/${encodeURIComponent(pagePath)}`);
150 return {
151 content: [{ type: "text", text: JSON.stringify(page, null, 2) }],
152 };
153}// Exploitable if MCP is exposed to untrusted prompts (network_exposed) or by a compromised LLM (local_only).
The pagePath parameter is URL-encoded but not validated for path traversal sequences. An attacker could provide a pagePath like '../../admin' which, after encoding, still results in path traversal when the API server decodes it. This could allow access to arbitrary API endpoints.
ImpactAn attacker could access arbitrary API endpoints, potentially retrieving sensitive information or performing unauthorized actions on the API server.
FixValidate pagePath to ensure it does not contain path traversal sequences (e.g., '../') and restrict it to a known set of allowed paths or a pattern.
163const { docName, query } = parsedArgs.data;
164const searchResults = await fetchApi(`/docs/${docName}/search?q=${encodeURIComponent(query)}`);// Exploitable if MCP is exposed to untrusted prompts or if a compromised LLM sends malicious input.
The query parameter is URL-encoded but not validated for content. While encoding prevents direct injection into the URL, the API backend might interpret the query in a way that allows injection (e.g., SQL injection, NoSQL injection) if not properly sanitized. The MCP server does not perform any validation on the query string.
ImpactAn attacker could potentially perform injection attacks against the backend API, leading to data leakage or manipulation.
FixValidate the query parameter to ensure it matches expected patterns (e.g., alphanumeric and common punctuation) and consider using parameterized queries on the backend.