@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
80 lines (79 loc) • 3.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatSearchResults = formatSearchResults;
const formatter_util_js_1 = require("../utils/formatter.util.js");
/**
* Format search results for display
* @param searchData - Raw search results from the API
* @returns Formatted string with search results in markdown format
*/
function formatSearchResults(searchData) {
if (searchData.length === 0) {
return ('No Confluence content found matching your query.' +
'\n\n' +
(0, formatter_util_js_1.formatSeparator)() +
'\n' +
`*Information retrieved at: ${(0, formatter_util_js_1.formatDate)(new Date())}*`);
}
const lines = [(0, formatter_util_js_1.formatHeading)('Confluence Search Results', 1), ''];
// Use the numbered list formatter for consistent formatting
const formattedList = (0, formatter_util_js_1.formatNumberedList)(searchData, (result) => {
const itemLines = [];
// Handle both v1 and v2 API result formats
// For v1 API, result.title is directly available
// For v2 API, title is in content object
// Get title from either direct property or content object
const title = result.title || result.content?.title || 'Untitled Result';
// Create an object with properties, handling optional fields
const properties = {
// Use optional chaining and fallbacks for all fields
ID: result.content?.id || result.id || 'N/A',
Type: result.content?.type || result.entityType || 'N/A',
Status: result.content?.status || 'N/A',
Space: result.space?.name ||
result.resultGlobalContainer?.title ||
'N/A',
};
// Add Space ID only if available
if (result.space?.id) {
properties['Space ID'] = result.space.id;
}
// Add URL with proper handling of optional fields
const url = result.url ||
result.content?._links?.webui ||
result.resultGlobalContainer?.displayUrl;
if (url) {
properties['URL'] = {
url: url,
title: 'View in Confluence',
};
}
// Add excerpt if available, with proper handling of both API formats
const excerpt = result.excerpt || result.content?.excerpt?.content;
if (excerpt) {
properties['Excerpt'] = excerpt;
}
// Add modification date if available
const modified = result.lastModified ||
result.content?.lastModified ||
result.friendlyLastModified;
if (modified) {
// Attempt to format date, fallback to original string
try {
properties['Modified'] = (0, formatter_util_js_1.formatDate)(new Date(modified));
}
catch {
properties['Modified'] = modified; // Fallback if parsing fails
}
}
// Create the formatted output
itemLines.push((0, formatter_util_js_1.formatHeading)(title, 2));
itemLines.push((0, formatter_util_js_1.formatBulletList)(properties, (key) => key));
return itemLines.join('\n');
});
lines.push(formattedList);
// Add standard footer with timestamp
lines.push('\n\n' + (0, formatter_util_js_1.formatSeparator)());
lines.push(`*Information retrieved at: ${(0, formatter_util_js_1.formatDate)(new Date())}*`);
return lines.join('\n');
}