Skip to main content
Glama
cmis_search.py7.67 kB
""" CMIS search tool for Alfresco MCP Server. Each tool is self-contained with its own validation, business logic, and env handling. """ import logging from typing import Optional from fastmcp import Context from ...utils.connection import ensure_connection from ...utils.json_utils import safe_format_output logger = logging.getLogger(__name__) async def cmis_search_impl( cmis_query: str, max_results: int = 25, ctx: Optional[Context] = None ) -> str: """Search using CMIS SQL syntax. Args: cmis_query: CMIS SQL query string max_results: Maximum number of results to return (default: 25) ctx: MCP context for progress reporting Returns: Formatted search results from CMIS query """ # Parameter validation and extraction try: # Extract parameters with fallback handling if hasattr(cmis_query, 'value'): actual_query = str(cmis_query.value) else: actual_query = str(cmis_query) if hasattr(max_results, 'value'): actual_max_results = int(max_results.value) else: actual_max_results = int(max_results) # Clean and normalize for display (preserve Unicode characters) safe_query_display = str(actual_query) except Exception as e: logger.error(f"Parameter extraction error: {e}") return f"ERROR: Parameter error: {str(e)}" if not actual_query.strip(): return """CMIS Search Tool Usage: Provide a CMIS SQL query to search Alfresco repository. Example CMIS queries: - SELECT * FROM cmis:document WHERE cmis:name LIKE 'test%' - SELECT * FROM cmis:folder WHERE CONTAINS('project') - SELECT * FROM cmis:document WHERE cmis:creationDate > '2024-01-01T00:00:00.000Z' - SELECT * FROM cmis:document WHERE cmis:contentStreamMimeType = 'application/pdf' CMIS provides precise SQL queries for exact matching and filtering. """ if ctx: await ctx.info(safe_format_output(f"CMIS search for: '{safe_query_display}'")) await ctx.report_progress(0.0) try: # Get all clients that ensure_connection() already created master_client = await ensure_connection() # Access the search client that was already created (same as other search tools) search_client = master_client.search logger.info(f"CMIS search for: '{safe_query_display}'") if ctx: await ctx.report_progress(0.3) # Use same pattern as other search tools but with CMIS language try: # Import the SearchRequest model for CMIS queries from python_alfresco_api.raw_clients.alfresco_search_client.search_client.models import SearchRequest, RequestQuery, RequestPagination, RequestQueryLanguage from python_alfresco_api.raw_clients.alfresco_search_client.search_client.types import UNSET # Create CMIS search request (same pattern as search_utils.simple_search but with CMIS language) request_query = RequestQuery( query=actual_query, language=RequestQueryLanguage.CMIS # Use CMIS instead of AFTS ) request_pagination = RequestPagination( max_items=actual_max_results, skip_count=0 ) search_request = SearchRequest( query=request_query, paging=request_pagination, include=UNSET ) # Use same pattern as search_utils.simple_search search_results = search_client.search.search(search_request) if search_results and hasattr(search_results, 'list_'): entries_list = search_results.list_.entries if search_results.list_ else [] logger.info(f"Found {len(entries_list)} CMIS search results") if ctx: await ctx.report_progress(1.0) if not entries_list: return "0" result_text = f"Found {len(entries_list)} item(s) matching the CMIS query:\n\n" for i, entry in enumerate(entries_list, 1): # Debug: Log the entry structure logger.debug(f"Entry {i} type: {type(entry)}, content: {entry}") # Handle different possible entry structures node = None if isinstance(entry, dict): if 'entry' in entry: node = entry['entry'] elif 'name' in entry: # Direct node structure node = entry else: logger.warning(f"Unknown entry structure: {entry}") continue elif hasattr(entry, 'entry'): # ResultSetRowEntry object node = entry.entry else: logger.warning(f"Entry is not a dict or ResultSetRowEntry: {type(entry)}") continue if node: # Handle both dict and ResultNode objects if isinstance(node, dict): name = str(node.get('name', 'Unknown')) node_id = str(node.get('id', 'Unknown')) node_type = str(node.get('nodeType', 'Unknown')) created_at = str(node.get('createdAt', 'Unknown')) else: # ResultNode object - access attributes directly name = str(getattr(node, 'name', 'Unknown')) node_id = str(getattr(node, 'id', 'Unknown')) node_type = str(getattr(node, 'node_type', 'Unknown')) created_at = str(getattr(node, 'created_at', 'Unknown')) # Clean JSON-friendly formatting (no markdown syntax) # Apply safe formatting to individual fields to prevent emoji encoding issues safe_name = safe_format_output(name) safe_node_id = safe_format_output(node_id) safe_node_type = safe_format_output(node_type) safe_created_at = safe_format_output(created_at) result_text += f"{i}. {safe_name}\n" result_text += f" - ID: {safe_node_id}\n" result_text += f" - Type: {safe_node_type}\n" result_text += f" - Created: {safe_created_at}\n\n" return safe_format_output(result_text) else: return safe_format_output(f"ERROR: CMIS search failed - invalid response from Alfresco") except Exception as e: logger.error(f"CMIS search failed: {e}") return safe_format_output(f"ERROR: CMIS search failed: {str(e)}") except Exception as e: # Preserve Unicode characters in error messages error_msg = f"ERROR: CMIS search failed: {str(e)}" if ctx: await ctx.error(safe_format_output(error_msg)) return safe_format_output(error_msg) if ctx: await ctx.info(safe_format_output("CMIS search completed!"))

Implementation Reference

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/stevereiner/python-alfresco-mcp-server'

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