@aashari/mcp-server-atlassian-confluence
Version:
Node.js/TypeScript MCP server for Atlassian Confluence. Provides tools enabling AI systems (LLMs) to list/get spaces & pages (content formatted as Markdown) and search via CQL. Connects AI seamlessly to Confluence knowledge bases using the standard MCP in
150 lines (146 loc) • 5.12 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.saveRawResponse = saveRawResponse;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const crypto = __importStar(require("crypto"));
const logger_util_js_1 = require("./logger.util.js");
const constants_util_js_1 = require("./constants.util.js");
// Create a contextualized logger for this file
const responseLogger = logger_util_js_1.Logger.forContext('utils/response.util.ts');
/**
* Get the project name from PACKAGE_NAME, stripping the scope prefix
* e.g., "@aashari/mcp-server-atlassian-confluence" -> "mcp-server-atlassian-confluence"
*/
function getProjectName() {
const name = constants_util_js_1.PACKAGE_NAME.replace(/^@[^/]+\//, '');
return name;
}
/**
* Generate a unique filename with timestamp and random string
* Format: <timestamp>-<random>.txt
*/
function generateFilename() {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const randomStr = crypto.randomBytes(4).toString('hex');
return `${timestamp}-${randomStr}.txt`;
}
/**
* Ensure the directory exists, creating it if necessary
*/
function ensureDirectoryExists(dirPath) {
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath, { recursive: true });
responseLogger.debug(`Created directory: ${dirPath}`);
}
}
/**
* Save raw API response to a file in /tmp/mcp/<project-name>/
*
* @param url The URL that was called
* @param method The HTTP method used
* @param requestBody The request body (if any)
* @param responseData The raw response data
* @param statusCode The HTTP status code
* @param durationMs The request duration in milliseconds
* @returns The path to the saved file, or null if saving failed
*/
function saveRawResponse(url, method, requestBody, responseData, statusCode, durationMs) {
const methodLogger = logger_util_js_1.Logger.forContext('utils/response.util.ts', 'saveRawResponse');
try {
const projectName = getProjectName();
const dirPath = path.join('/tmp', 'mcp', projectName);
const filename = generateFilename();
const filePath = path.join(dirPath, filename);
ensureDirectoryExists(dirPath);
// Build the content
const content = buildResponseContent(url, method, requestBody, responseData, statusCode, durationMs);
// Write to file
fs.writeFileSync(filePath, content, 'utf8');
methodLogger.debug(`Saved raw response to: ${filePath}`);
return filePath;
}
catch (error) {
methodLogger.error('Failed to save raw response', error);
return null;
}
}
/**
* Build the content string for the response file
*/
function buildResponseContent(url, method, requestBody, responseData, statusCode, durationMs) {
const timestamp = new Date().toISOString();
const separator = '='.repeat(80);
let content = `${separator}
RAW API RESPONSE LOG
${separator}
Timestamp: ${timestamp}
URL: ${url}
Method: ${method}
Status Code: ${statusCode}
Duration: ${durationMs.toFixed(2)}ms
${separator}
REQUEST BODY
${separator}
`;
if (requestBody) {
content +=
typeof requestBody === 'string'
? requestBody
: JSON.stringify(requestBody, null, 2);
}
else {
content += '(no request body)';
}
content += `
${separator}
RESPONSE DATA
${separator}
`;
if (responseData !== undefined && responseData !== null) {
content +=
typeof responseData === 'string'
? responseData
: JSON.stringify(responseData, null, 2);
}
else {
content += '(no response data)';
}
content += `
${separator}
`;
return content;
}