@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
135 lines (134 loc) • 6.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const logger_util_js_1 = require("../utils/logger.util.js");
const error_util_js_1 = require("../utils/error.util.js");
const atlassian_api_controller_js_1 = require("../controllers/atlassian.api.controller.js");
/**
* CLI module for generic Confluence API access.
* Provides commands for making GET, POST, PUT, PATCH, and DELETE requests to any Confluence API endpoint.
*/
// Create a contextualized logger for this file
const cliLogger = logger_util_js_1.Logger.forContext('cli/atlassian.api.cli.ts');
// Log CLI initialization
cliLogger.debug('Confluence API CLI module initialized');
/**
* Parse JSON string with error handling and basic validation
* @param jsonString - JSON string to parse
* @param fieldName - Name of the field for error messages
* @returns Parsed JSON object
*/
function parseJson(jsonString, fieldName) {
let parsed;
try {
parsed = JSON.parse(jsonString);
}
catch {
throw new Error(`Invalid JSON in --${fieldName}. Please provide valid JSON.`);
}
// Validate that the parsed value is an object (not null, array, or primitive)
if (parsed === null ||
typeof parsed !== 'object' ||
Array.isArray(parsed)) {
throw new Error(`Invalid --${fieldName}: expected a JSON object, got ${parsed === null ? 'null' : Array.isArray(parsed) ? 'array' : typeof parsed}.`);
}
return parsed;
}
/**
* Register a read command (GET/DELETE - no body)
* @param program - Commander program instance
* @param name - Command name
* @param description - Command description
* @param handler - Controller handler function
*/
function registerReadCommand(program, name, description, handler) {
program
.command(name)
.description(description)
.requiredOption('-p, --path <path>', 'API endpoint path (e.g., "/wiki/api/v2/spaces", "/wiki/api/v2/pages/{id}").')
.option('-q, --query-params <json>', 'Query parameters as JSON string (e.g., \'{"limit": "25"}\').')
.option('--jq <expression>', 'JMESPath expression to filter/transform the response.')
.option('-o, --output-format <format>', 'Output format: "toon" (default, token-efficient) or "json".', 'toon')
.action(async (options) => {
const actionLogger = cliLogger.forMethod(name);
try {
actionLogger.debug(`CLI ${name} called`, options);
// Parse query params if provided
let queryParams;
if (options.queryParams) {
queryParams = parseJson(options.queryParams, 'query-params');
}
const result = await handler({
path: options.path,
queryParams,
jq: options.jq,
outputFormat: options.outputFormat,
});
console.log(result.content);
}
catch (error) {
(0, error_util_js_1.handleCliError)(error);
}
});
}
/**
* Register a write command (POST/PUT/PATCH - with body)
* @param program - Commander program instance
* @param name - Command name
* @param description - Command description
* @param handler - Controller handler function
*/
function registerWriteCommand(program, name, description, handler) {
program
.command(name)
.description(description)
.requiredOption('-p, --path <path>', 'API endpoint path (e.g., "/wiki/api/v2/pages", "/wiki/api/v2/pages/{id}/labels").')
.requiredOption('-b, --body <json>', 'Request body as JSON string.')
.option('-q, --query-params <json>', 'Query parameters as JSON string.')
.option('--jq <expression>', 'JMESPath expression to filter/transform the response.')
.option('-o, --output-format <format>', 'Output format: "toon" (default, token-efficient) or "json".', 'toon')
.action(async (options) => {
const actionLogger = cliLogger.forMethod(name);
try {
actionLogger.debug(`CLI ${name} called`, options);
// Parse body
const body = parseJson(options.body, 'body');
// Parse query params if provided
let queryParams;
if (options.queryParams) {
queryParams = parseJson(options.queryParams, 'query-params');
}
const result = await handler({
path: options.path,
body,
queryParams,
jq: options.jq,
outputFormat: options.outputFormat,
});
console.log(result.content);
}
catch (error) {
(0, error_util_js_1.handleCliError)(error);
}
});
}
/**
* Register generic Confluence API CLI commands with the Commander program
*
* @param program - The Commander program instance to register commands with
*/
function register(program) {
const methodLogger = logger_util_js_1.Logger.forContext('cli/atlassian.api.cli.ts', 'register');
methodLogger.debug('Registering Confluence API CLI commands...');
// Register GET command
registerReadCommand(program, 'get', 'GET any Confluence endpoint. Returns JSON, optionally filtered with JMESPath.', atlassian_api_controller_js_1.handleGet);
// Register POST command
registerWriteCommand(program, 'post', 'POST to any Confluence endpoint. Returns JSON, optionally filtered with JMESPath.', atlassian_api_controller_js_1.handlePost);
// Register PUT command
registerWriteCommand(program, 'put', 'PUT to any Confluence endpoint. Returns JSON, optionally filtered with JMESPath.', atlassian_api_controller_js_1.handlePut);
// Register PATCH command
registerWriteCommand(program, 'patch', 'PATCH any Confluence endpoint. Returns JSON, optionally filtered with JMESPath.', atlassian_api_controller_js_1.handlePatch);
// Register DELETE command
registerReadCommand(program, 'delete', 'DELETE any Confluence endpoint. Returns JSON (if any), optionally filtered with JMESPath.', atlassian_api_controller_js_1.handleDelete);
methodLogger.debug('CLI commands registered successfully');
}
exports.default = { register };