Initial commit: Clean DSS implementation
Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
This commit is contained in:
262
demo/tools/dss_mcp/integrations/confluence.py
Normal file
262
demo/tools/dss_mcp/integrations/confluence.py
Normal file
@@ -0,0 +1,262 @@
|
||||
"""
|
||||
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)}
|
||||
Reference in New Issue
Block a user