""" Confluence Integration for MCP Provides Confluence API tools for documentation and knowledge base. """ from typing import Dict, Any, List, Optional from atlassian import Confluence from mcp import types from .base import BaseIntegration # Confluence MCP Tool Definitions CONFLUENCE_TOOLS = [ types.Tool( name="confluence_create_page", description="Create a new Confluence page", inputSchema={ "type": "object", "properties": { "space_key": { "type": "string", "description": "Confluence space key" }, "title": { "type": "string", "description": "Page title" }, "body": { "type": "string", "description": "Page content (HTML or wiki markup)" }, "parent_id": { "type": "string", "description": "Optional parent page ID" } }, "required": ["space_key", "title", "body"] } ), types.Tool( name="confluence_get_page", description="Get Confluence page by ID or title", inputSchema={ "type": "object", "properties": { "page_id": { "type": "string", "description": "Page ID (use this OR title)" }, "space_key": { "type": "string", "description": "Space key (required if using title)" }, "title": { "type": "string", "description": "Page title (use this OR page_id)" }, "expand": { "type": "string", "description": "Comma-separated list of expansions (body.storage, version, etc.)", "default": "body.storage,version" } } } ), types.Tool( name="confluence_update_page", description="Update an existing Confluence page", inputSchema={ "type": "object", "properties": { "page_id": { "type": "string", "description": "Page ID to update" }, "title": { "type": "string", "description": "New page title" }, "body": { "type": "string", "description": "New page content" } }, "required": ["page_id", "title", "body"] } ), types.Tool( name="confluence_search", description="Search Confluence pages using CQL", inputSchema={ "type": "object", "properties": { "cql": { "type": "string", "description": "CQL query (e.g., 'space=DSS AND type=page')" }, "limit": { "type": "integer", "description": "Maximum number of results", "default": 25 } }, "required": ["cql"] } ), types.Tool( name="confluence_get_space", description="Get Confluence space details", inputSchema={ "type": "object", "properties": { "space_key": { "type": "string", "description": "Space key" } }, "required": ["space_key"] } ) ] class ConfluenceIntegration(BaseIntegration): """Confluence API integration with circuit breaker""" def __init__(self, config: Dict[str, Any]): """ Initialize Confluence integration. Args: config: Must contain 'url', 'username', 'api_token' """ super().__init__("confluence", config) url = config.get("url") username = config.get("username") api_token = config.get("api_token") if not all([url, username, api_token]): raise ValueError("Confluence configuration incomplete: url, username, api_token required") self.confluence = Confluence( url=url, username=username, password=api_token, cloud=True ) async def create_page( self, space_key: str, title: str, body: str, parent_id: Optional[str] = None ) -> Dict[str, Any]: """Create a new page""" def _create(): return self.confluence.create_page( space=space_key, title=title, body=body, parent_id=parent_id, representation="storage" ) return await self.call_api(_create) async def get_page( self, page_id: Optional[str] = None, space_key: Optional[str] = None, title: Optional[str] = None, expand: str = "body.storage,version" ) -> Dict[str, Any]: """Get page by ID or title""" def _get(): if page_id: return self.confluence.get_page_by_id( page_id=page_id, expand=expand ) elif space_key and title: return self.confluence.get_page_by_title( space=space_key, title=title, expand=expand ) else: raise ValueError("Must provide either page_id or (space_key + title)") return await self.call_api(_get) async def update_page( self, page_id: str, title: str, body: str ) -> Dict[str, Any]: """Update an existing page""" def _update(): # Get current version page = self.confluence.get_page_by_id(page_id, expand="version") current_version = page["version"]["number"] return self.confluence.update_page( page_id=page_id, title=title, body=body, parent_id=None, type="page", representation="storage", minor_edit=False, version_comment="Updated via DSS MCP", version_number=current_version + 1 ) return await self.call_api(_update) async def search(self, cql: str, limit: int = 25) -> Dict[str, Any]: """Search pages using CQL""" def _search(): return self.confluence.cql(cql, limit=limit) return await self.call_api(_search) async def get_space(self, space_key: str) -> Dict[str, Any]: """Get space details""" def _get(): return self.confluence.get_space(space_key) return await self.call_api(_get) class ConfluenceTools: """MCP tool executor for Confluence integration""" def __init__(self, config: Dict[str, Any]): self.confluence = ConfluenceIntegration(config) async def execute_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]: """Execute Confluence tool""" handlers = { "confluence_create_page": self.confluence.create_page, "confluence_get_page": self.confluence.get_page, "confluence_update_page": self.confluence.update_page, "confluence_search": self.confluence.search, "confluence_get_space": self.confluence.get_space } handler = handlers.get(tool_name) if not handler: return {"error": f"Unknown Confluence tool: {tool_name}"} try: clean_args = {k: v for k, v in arguments.items() if not k.startswith("_")} result = await handler(**clean_args) return result except Exception as e: return {"error": str(e)}