Skip to main content
Glama

Confluence Communication Server

#!/usr/bin/env node import axios, { AxiosRequestConfig } from 'axios'; import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; /** * Configure your Confluence instance credentials and URL. */ const CONFLUENCE_URL = process.env.CONFLUENCE_URL; const CONFLUENCE_API_MAIL = process.env.CONFLUENCE_API_MAIL; const CONFLUENCE_API_KEY = process.env.CONFLUENCE_API_KEY; /** * Create an MCP server to handle CQL queries and page retrieval. */ const server = new Server( { name: 'Confluence communication server', version: '0.1.0', }, { capabilities: { tools: {}, }, }, ); /** * Handler for listing available tools. * Provides tools for querying Confluence with CQL and retrieving page content. */ server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'execute_cql_search', description: 'Execute a CQL query on Confluence to search pages', inputSchema: { type: 'object', properties: { cql: { type: 'string', description: 'CQL query string', }, limit: { type: 'integer', description: 'Number of results to return', default: 10, }, }, required: ['cql'], }, }, { name: 'get_page_content', description: 'Get the content of a Confluence page', inputSchema: { type: 'object', properties: { pageId: { type: 'string', description: 'Confluence Page ID', }, }, required: ['pageId'], }, }, { name: 'update_page_content', description: 'Update the content of a Confluence page', inputSchema: { type: 'object', properties: { pageId: { type: 'string', description: 'Confluence Page ID', }, content: { type: 'string', description: 'HTML content to update the page with', }, title: { type: 'string', description: 'Page title (optional, if you want to change it)', }, }, required: ['pageId', 'content'], }, }, ], }; }); /** * Function to execute a CQL query against Confluence. * @param {string} cql - CQL query string * @param limit * @returns {Promise<any>} */ async function executeCQL(cql: string, limit: number): Promise<any> { try { const params = { cql, limit, }; const response = await axios.get( `${CONFLUENCE_URL}/wiki/rest/api/content/search`, { // Updated URL headers: getAuthHeaders().headers, params, }, ); return response.data; } catch (error: any) { return { error: error.response ? error.response.data : error.message, }; } } /** * Function to retrieve content from a Confluence page by ID. * @param {string} pageId - Confluence Page ID * @returns {Promise<any>} */ async function getPageContent(pageId: string): Promise<any> { try { const response = await axios.get( `${CONFLUENCE_URL}/wiki/rest/api/content/${pageId}?expand=body.storage,version`, { headers: getAuthHeaders().headers, }, ); return response.data; } catch (error: any) { return { error: error.response ? error.response.data : error.message, }; } } /** * Function to update content on a Confluence page by ID. * @param {string} pageId - Confluence Page ID * @param {string} content - HTML content to update * @param {string} title - Optional new title * @returns {Promise<any>} */ async function updatePageContent( pageId: string, content: string, title?: string, ): Promise<any> { try { // First, get the current page to retrieve its version and other details const currentPage = await getPageContent(pageId); if (currentPage.error) { return { error: `Failed to get current page: ${currentPage.error}`, }; } // Create update payload const updatePayload = { id: pageId, type: currentPage.type, title: title || currentPage.title, space: currentPage.space, body: { storage: { value: content, representation: 'storage', }, }, version: { number: currentPage.version.number + 1, }, }; // Update the page const response = await axios.put( `${CONFLUENCE_URL}/wiki/rest/api/content/${pageId}`, updatePayload, { headers: { ...getAuthHeaders().headers, 'Content-Type': 'application/json', }, }, ); return response.data; } catch (error: any) { return { error: error.response ? error.response.data : error.message, }; } } /** * Function to get the authentication headers. * @returns {AxiosRequestConfig} */ function getAuthHeaders(): AxiosRequestConfig<any> { const authHeader = `Basic ${Buffer.from( `${CONFLUENCE_API_MAIL}:${CONFLUENCE_API_KEY}`, ).toString('base64')}`; return { headers: { Authorization: authHeader, 'Content-Type': 'application/json', }, }; } /** * Handler for the execute_cql_search and get_page_content tools. */ server.setRequestHandler(CallToolRequestSchema, async (request) => { switch (request.params.name) { case 'execute_cql_search': { const cql = String(request.params.arguments?.cql); const limit = Number(request.params.arguments?.limit ?? 10); if (!cql) { throw new Error('CQL query is required'); } const response = await executeCQL(cql, limit); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2), }, ], }; } case 'get_page_content': { const pageId = String(request.params.arguments?.pageId); if (!pageId) { throw new Error('Page ID is required'); } const response = await getPageContent(pageId); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2), }, ], }; } case 'update_page_content': { const pageId = String(request.params.arguments?.pageId); const content = String(request.params.arguments?.content); const title = request.params.arguments?.title ? String(request.params.arguments?.title) : undefined; if (!pageId) { throw new Error('Page ID is required'); } if (!content) { throw new Error('Content is required'); } const response = await updatePageContent(pageId, content, title); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2), }, ], }; } default: throw new Error('Unknown tool'); } }); /** * Start the server using stdio transport. */ async function main() { const transport = new StdioServerTransport(); await server.connect(transport); } main().catch((error) => { console.error('Server error:', error); process.exit(1); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/KS-GEN-AI/confluence-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server