Skip to main content
Glama
ibm-ecm

IBM Core Content Services MCP Server

Official
by ibm-ecm

repository_object_search

Search for repository objects in IBM FileNet Content Manager by specifying a class and property filters to locate specific documents or folders.

Instructions

PREREQUISITES IN ORDER: To use this tool, you MUST call two other tools first in a specific sequence.

  1. determine_class tool to get the class_name for search_class.

  2. get_searchable_property_descriptions to get a list of valid property_name for search_properties

Description: This tool will execute a request to search for a repository object(s).

:param search_parameters (SearchParameters): parameters for the searching including the object being searched for and any search conditions.

:returns: A the repository object details, including: - repositoryObjects (dict): a dictionary containing independentObjects: - independentObjects (list): A list of independent objects, each containing: - properties (list): A list of properties, each containing: - label (str): The name of the property. - value (str): The value of the property.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
search_parametersYes

Implementation Reference

  • Main handler function for the repository_object_search tool. Retrieves class metadata, processes search properties to build SQL-like conditions, constructs and executes a GraphQL query to fetch matching repository objects.
    @mcp.tool(
        name="repository_object_search",
    )
    async def get_repository_object_main(
        search_parameters: SearchParameters,
    ) -> dict | ToolError:
        """
        **PREREQUISITES IN ORDER**: To use this tool, you MUST call two other tools first in a specific sequence.
        1. determine_class tool to get the class_name for search_class.
        2. get_searchable_property_descriptions to get a list of valid property_name for search_properties
    
        Description:
        This tool will execute a request to search for a repository object(s).
    
        :param search_parameters (SearchParameters): parameters for the searching including the object being searched for and any search conditions.
    
        :returns: A the repository object details, including:
            - repositoryObjects (dict): a dictionary containing independentObjects:
                - independentObjects (list): A list of independent objects, each containing:
                - properties (list): A list of properties, each containing:
                    - label (str): The name of the property.
                    - value (str): The value of the property.
        """
        # First, get the class metadata from the cache
        class_data = get_class_metadata_tool(
            graphql_client, search_parameters.search_class, metadata_cache
        )
    
        # Check if we got an error instead of class data
        if isinstance(class_data, ToolError):
            return class_data
    
        # Extract property information from the class data
        return_properties = []
        property_types = {}
    
        for prop in class_data.property_descriptions:
            # Skip properties with LIST cardinality or OBJECT data type
            if (
                prop.cardinality == CARDINALITY_LIST
                or prop.data_type == DATA_TYPE_OBJECT
            ):
                continue
    
            property_name = prop.symbolic_name
            return_properties.append(property_name)
            property_types[property_name] = prop.data_type
    
        return_properties_string = ", ".join(
            [f'"{item}"' for item in return_properties]
        )
        return_properties_string = f"[{return_properties_string}]"
    
        # Process search conditions
        query_conditions = []
        for item in search_parameters.search_properties:
            try:
                prop_name = item.property_name
            except AttributeError:
                return {"ERROR": "search_properties missing 'property_name' key"}
            try:
                prop_value = item.property_value.replace("*", "")
            except AttributeError:
                return {"ERROR": "search_properties missing 'property_value' key"}
            try:
                operator = item.operator.value
            except AttributeError:
                return {"ERROR": "search_properties missing 'operator' key"}
    
            if not all([prop_name, prop_value, operator]):
                print(f"Skipping invalid filter item: {item}")
                continue
    
            # Get the data type of the property
            data_type = property_types.get(
                prop_name, DATA_TYPE_STRING
            )  # Default to STRING if not found
    
            # Format the value according to its data type
            formatted_value = format_value_by_type(prop_value, data_type)
    
            # Get the appropriate SQL operator
    
            # Handle string operations
            if data_type == DATA_TYPE_STRING:
                if operator.upper() == OPERATOR_CONTAINS:
                    operator = SQL_LIKE_OPERATOR
                    formatted_value = f"'%{prop_value}%'"
                elif operator.upper() == OPERATOR_STARTS:
                    operator = SQL_LIKE_OPERATOR
                    formatted_value = f"'{prop_value}%'"
                elif operator.upper() == OPERATOR_ENDS:
                    operator = SQL_LIKE_OPERATOR
                    formatted_value = f"'%{prop_value}'"
    
            condition_string = f"{prop_name} {operator} {formatted_value}"
            query_conditions.append(condition_string)
    
        search_properties_string = " AND ".join(query_conditions)
    
        query = """
        query repositoryObjectsSearch($object_store_name: String!,
            $class_name: String!, $where_statement: String!, $return_props: [String!]){
            repositoryObjects(
            repositoryIdentifier: $object_store_name,
            from: $class_name,
            where: $where_statement
            ) {
            independentObjects {
                properties (includes: $return_props){
                label
                value
                }
            }
            }
        }
        """
        var = {
            "object_store_name": graphql_client.object_store,
            "where_statement": search_properties_string,
            "class_name": search_parameters.search_class,
            "return_props": return_properties,
        }
    
        try:
            response = await graphql_client.execute_async(query=query, variables=var)
            return response  # Return response only if no exception occurs
        except Exception as e:
            return ToolError(
                message=f"Error executing search: {str(e)}",
                suggestions=[
                    "Check that all property names are valid for the class",
                    "Ensure property values match the expected data types",
                    "Verify that the operators are appropriate for the property data types",
                ],
            )
  • Pydantic model defining the input schema for the repository_object_search tool, consisting of search_class and a list of SearchProperty conditions.
    class SearchParameters(BaseModel):
        """
        Complete set of parameters for executing a repository search.
        """
    
        search_class: str = Field(
            ...,
            description="The class to search for. Must be a valid class in the repository.",
        )
        search_properties: List[SearchProperty] = Field(
            ...,
            description="List of filter conditions to apply to the search. All conditions are combined with AND logic. If no conditions exist, we return all objects of the given class",
        )
  • Pydantic model for individual search property conditions used within SearchParameters.
    class SearchProperty(BaseModel):
        """
        Defines a single search condition/filter to be applied during repository searches.
        """
    
        property_name: str = Field(
            ...,
            description="The name of the property to filter on. Must be a valid property for the specified class as obtained from the get_searchable_class_properties_tool .",
        )
        property_value: str = Field(
            ...,
            description="The value to filter by. Format should match the property's data type.",
        )
        operator: SearchOperator = Field(
            ...,
            description="The comparison operator that defines how property_name and property_value are compared. "
            "Use CONTAINS for substring matching, STARTS/ENDS for prefix/suffix matching. "
            "Use standard SQL operators: =, >, <, >=, <=, != for other properties.",
        )
  • The @mcp.tool decorator that registers the repository_object_search tool with the MCP server.
    @mcp.tool(
        name="repository_object_search",
    )
    async def get_repository_object_main(
        search_parameters: SearchParameters,
    ) -> dict | ToolError:
        """
        **PREREQUISITES IN ORDER**: To use this tool, you MUST call two other tools first in a specific sequence.
        1. determine_class tool to get the class_name for search_class.
        2. get_searchable_property_descriptions to get a list of valid property_name for search_properties
    
        Description:
        This tool will execute a request to search for a repository object(s).
    
        :param search_parameters (SearchParameters): parameters for the searching including the object being searched for and any search conditions.
    
        :returns: A the repository object details, including:
            - repositoryObjects (dict): a dictionary containing independentObjects:
                - independentObjects (list): A list of independent objects, each containing:
                - properties (list): A list of properties, each containing:
                    - label (str): The name of the property.
                    - value (str): The value of the property.
        """
        # First, get the class metadata from the cache
        class_data = get_class_metadata_tool(
            graphql_client, search_parameters.search_class, metadata_cache
        )
    
        # Check if we got an error instead of class data
        if isinstance(class_data, ToolError):
            return class_data
    
        # Extract property information from the class data
        return_properties = []
        property_types = {}
    
        for prop in class_data.property_descriptions:
            # Skip properties with LIST cardinality or OBJECT data type
            if (
                prop.cardinality == CARDINALITY_LIST
                or prop.data_type == DATA_TYPE_OBJECT
            ):
                continue
    
            property_name = prop.symbolic_name
            return_properties.append(property_name)
            property_types[property_name] = prop.data_type
    
        return_properties_string = ", ".join(
            [f'"{item}"' for item in return_properties]
        )
        return_properties_string = f"[{return_properties_string}]"
    
        # Process search conditions
        query_conditions = []
        for item in search_parameters.search_properties:
            try:
                prop_name = item.property_name
            except AttributeError:
                return {"ERROR": "search_properties missing 'property_name' key"}
            try:
                prop_value = item.property_value.replace("*", "")
            except AttributeError:
                return {"ERROR": "search_properties missing 'property_value' key"}
            try:
                operator = item.operator.value
            except AttributeError:
                return {"ERROR": "search_properties missing 'operator' key"}
    
            if not all([prop_name, prop_value, operator]):
                print(f"Skipping invalid filter item: {item}")
                continue
    
            # Get the data type of the property
            data_type = property_types.get(
                prop_name, DATA_TYPE_STRING
            )  # Default to STRING if not found
    
            # Format the value according to its data type
            formatted_value = format_value_by_type(prop_value, data_type)
    
            # Get the appropriate SQL operator
    
            # Handle string operations
            if data_type == DATA_TYPE_STRING:
                if operator.upper() == OPERATOR_CONTAINS:
                    operator = SQL_LIKE_OPERATOR
                    formatted_value = f"'%{prop_value}%'"
                elif operator.upper() == OPERATOR_STARTS:
                    operator = SQL_LIKE_OPERATOR
                    formatted_value = f"'{prop_value}%'"
                elif operator.upper() == OPERATOR_ENDS:
                    operator = SQL_LIKE_OPERATOR
                    formatted_value = f"'%{prop_value}'"
    
            condition_string = f"{prop_name} {operator} {formatted_value}"
            query_conditions.append(condition_string)
    
        search_properties_string = " AND ".join(query_conditions)
    
        query = """
        query repositoryObjectsSearch($object_store_name: String!,
            $class_name: String!, $where_statement: String!, $return_props: [String!]){
            repositoryObjects(
            repositoryIdentifier: $object_store_name,
            from: $class_name,
            where: $where_statement
            ) {
            independentObjects {
                properties (includes: $return_props){
                label
                value
                }
            }
            }
        }
        """
        var = {
            "object_store_name": graphql_client.object_store,
            "where_statement": search_properties_string,
            "class_name": search_parameters.search_class,
            "return_props": return_properties,
        }
    
        try:
            response = await graphql_client.execute_async(query=query, variables=var)
            return response  # Return response only if no exception occurs
        except Exception as e:
            return ToolError(
                message=f"Error executing search: {str(e)}",
                suggestions=[
                    "Check that all property names are valid for the class",
                    "Ensure property values match the expected data types",
                    "Verify that the operators are appropriate for the property data types",
                ],
            )
  • Invocation of register_search_tools within register_server_tools for CORE server type, which defines and registers the tool.
    register_search_tools(mcp, graphql_client, metadata_cache)

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/ibm-ecm/ibm-content-services-mcp-server'

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