Skip to main content
Glama
registration.py4.88 kB
""" LibreOffice MCP Extension - Registration Module This module handles the registration and lifecycle of the LibreOffice MCP extension. """ import uno import unohelper import logging import threading import traceback import sys import os from com.sun.star.lang import XServiceInfo from com.sun.star.frame import XDispatchProvider, XDispatch from com.sun.star.lang import XInitialization # Add the pythonpath directory to sys.path for imports _this_dir = os.path.dirname(__file__) if _this_dir not in sys.path: sys.path.insert(0, _this_dir) # Set up logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger("MCPExtension") # Implementation name and service name for the extension IMPLEMENTATION_NAME = "org.mcp.libreoffice.MCPExtension" SERVICE_NAMES = ("com.sun.star.frame.ProtocolHandler",) # Global server state (shared across all handler instances) _server_started = False _ai_interface = None _lock = threading.Lock() def _start_server(): """Start the MCP HTTP server""" global _server_started, _ai_interface with _lock: if _server_started: logger.info("Server already started") return try: logger.info("Starting MCP server...") # Import using absolute import (no relative imports in LO Python) import ai_interface _ai_interface = ai_interface.start_ai_interface(port=8765, host="localhost") _server_started = True logger.info("MCP server started successfully on http://localhost:8765") except Exception as e: logger.error(f"Failed to start server: {e}") logger.error(traceback.format_exc()) def _stop_server(): """Stop the MCP HTTP server""" global _server_started, _ai_interface with _lock: if not _server_started: logger.info("Server not running") return try: logger.info("Stopping MCP server...") import ai_interface ai_interface.stop_ai_interface() _ai_interface = None _server_started = False logger.info("MCP server stopped") except Exception as e: logger.error(f"Failed to stop server: {e}") logger.error(traceback.format_exc()) class MCPProtocolHandler(unohelper.Base, XServiceInfo, XDispatchProvider, XDispatch, XInitialization): """Protocol handler for MCP extension menu commands""" def __init__(self, ctx): self.ctx = ctx self.frame = None logger.debug("MCPProtocolHandler created") # XInitialization def initialize(self, args): if args: self.frame = args[0] logger.debug("MCPProtocolHandler initialized with frame") # XServiceInfo def getImplementationName(self): return IMPLEMENTATION_NAME def supportsService(self, name): return name in SERVICE_NAMES def getSupportedServiceNames(self): return SERVICE_NAMES # XDispatchProvider def queryDispatch(self, url, target, flags): logger.debug(f"queryDispatch: {url.Complete}") if url.Protocol == "service:": return self return None def queryDispatches(self, requests): return tuple([self.queryDispatch(r.FeatureURL, r.FrameName, r.SearchFlags) for r in requests]) # XDispatch def dispatch(self, url, args): logger.info(f"dispatch called: {url.Complete}") try: if "?" in url.Complete: command = url.Complete.split("?")[1] logger.info(f"Executing command: {command}") if command == "start_mcp_server": # Run in thread to not block UI threading.Thread(target=_start_server, daemon=True).start() elif command == "stop_mcp_server": threading.Thread(target=_stop_server, daemon=True).start() elif command == "restart_mcp_server": def restart(): _stop_server() _start_server() threading.Thread(target=restart, daemon=True).start() elif command == "get_status": logger.info(f"Server status: started={_server_started}") else: logger.warning(f"Unknown command: {command}") except Exception as e: logger.error(f"Error in dispatch: {e}") logger.error(traceback.format_exc()) def addStatusListener(self, listener, url): pass def removeStatusListener(self, listener, url): pass # Component factory - pass the class directly, not a function g_ImplementationHelper = unohelper.ImplementationHelper() g_ImplementationHelper.addImplementation( MCPProtocolHandler, IMPLEMENTATION_NAME, SERVICE_NAMES )

Latest Blog Posts

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/jwingnut/mcp-libre'

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