Skip to main content
Glama

get-filterable-attributes

Identify which attributes can filter PI Dashboard charts or categories by analyzing a sample entity type.

Instructions

Get the list of attributes that can be used for filtering by examining a sample entity

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
entityTypeYesType of entity to examine (chart or category)

Implementation Reference

  • Handler function that executes the tool logic: fetches sample entities for the given type ('chart' or 'category'), analyzes the first entity's properties to determine filterable attributes, their types, suitable operators, and generates usage examples.
    }, async ({ entityType }) => {
        try {
            if (!apiUrlSet || !authToken) {
                return {
                    isError: true,
                    content: [{
                            type: "text",
                            text: "Please set API URL and authenticate before using this tool."
                        }]
                };
            }
            let endpoint = "";
            // Get a sample entity
            if (entityType === "chart") {
                endpoint = "/charts";
            }
            else if (entityType === "category") {
                endpoint = "/categories";
            }
            // Get all entities (since pagination may not be supported)
            const listResponse = await authenticatedRequest(endpoint, "GET");
            if (listResponse &&
                typeof listResponse === 'object' &&
                'content' in listResponse &&
                Array.isArray(listResponse.content) &&
                listResponse.content.length > 0) {
                // Just use the first entity as our sample
                const sampleEntity = listResponse.content[0];
                // Extract the attributes from the sample entity
                const attributes = Object.keys(sampleEntity).map(key => {
                    const value = sampleEntity[key];
                    const type = typeof value;
                    // Determine which operators are suitable based on the value type
                    let availableOperators = [];
                    if (type === "string") {
                        // Prioritize 'like' for string fields since it's case-insensitive
                        availableOperators = ["like", "nlike", "eq", "ne"];
                    }
                    else if (type === "number") {
                        availableOperators = ["eq", "ne", "gt", "lt", "ge", "le"];
                    }
                    else if (type === "boolean") {
                        availableOperators = ["eq", "ne"];
                    }
                    return {
                        name: key,
                        type: type,
                        example: value !== null && value !== undefined ? String(value).substring(0, 30) : "null", // Show a sample value (truncated)
                        operators: availableOperators
                    };
                });
                // Find a string field for the example if possible
                const stringField = attributes.find(attr => attr.type === "string" && attr.example && attr.example !== "null");
                let exampleFilter = "";
                if (stringField) {
                    exampleFilter = `${stringField.name}(like)=${stringField.example}`;
                }
                else if (attributes.length > 0) {
                    const firstAttr = attributes[0];
                    exampleFilter = `${firstAttr.name}(${firstAttr.operators[0]})=${firstAttr.example}`;
                }
                let exampleMultipleFilter = "";
                if (attributes.length > 1) {
                    const secondAttr = attributes[1];
                    exampleMultipleFilter = `${exampleFilter}&${secondAttr.name}(${secondAttr.operators[0]})=${secondAttr.example}`;
                }
                return {
                    content: [{
                            type: "text",
                            text: `Filterable attributes for ${entityType}:\n${JSON.stringify(attributes, null, 2)}\n\n` +
                                `Example filter usage: '${exampleFilter}'\n\n` +
                                `Example with multiple filters: '${exampleMultipleFilter || "Not enough attributes for multiple filter example"}'\n\n` +
                                `Note: For text fields, the 'like' operator is recommended as it performs case-insensitive substring matching.`
                        }]
                };
            }
            else {
                return {
                    content: [{
                            type: "text",
                            text: `No ${entityType} entities found to analyze. Please ensure there is at least one ${entityType} in the system.`
                        }]
                };
            }
        }
        catch (error) {
            return {
                isError: true,
                content: [{ type: "text", text: `Error fetching ${entityType} attributes: ${getErrorMessage(error)}` }]
            };
        }
  • Input schema for the tool: requires 'entityType' as either 'chart' or 'category'.
    entityType: z.enum(["chart", "category"]).describe("Type of entity to examine (chart or category)")
  • build/index.js:166-259 (registration)
    Registration of the get-filterable-attributes tool using server.tool(), including description, input schema, and inline handler function.
    server.tool("get-filterable-attributes", "Get the list of attributes that can be used for filtering by examining a sample entity", {
        entityType: z.enum(["chart", "category"]).describe("Type of entity to examine (chart or category)")
    }, async ({ entityType }) => {
        try {
            if (!apiUrlSet || !authToken) {
                return {
                    isError: true,
                    content: [{
                            type: "text",
                            text: "Please set API URL and authenticate before using this tool."
                        }]
                };
            }
            let endpoint = "";
            // Get a sample entity
            if (entityType === "chart") {
                endpoint = "/charts";
            }
            else if (entityType === "category") {
                endpoint = "/categories";
            }
            // Get all entities (since pagination may not be supported)
            const listResponse = await authenticatedRequest(endpoint, "GET");
            if (listResponse &&
                typeof listResponse === 'object' &&
                'content' in listResponse &&
                Array.isArray(listResponse.content) &&
                listResponse.content.length > 0) {
                // Just use the first entity as our sample
                const sampleEntity = listResponse.content[0];
                // Extract the attributes from the sample entity
                const attributes = Object.keys(sampleEntity).map(key => {
                    const value = sampleEntity[key];
                    const type = typeof value;
                    // Determine which operators are suitable based on the value type
                    let availableOperators = [];
                    if (type === "string") {
                        // Prioritize 'like' for string fields since it's case-insensitive
                        availableOperators = ["like", "nlike", "eq", "ne"];
                    }
                    else if (type === "number") {
                        availableOperators = ["eq", "ne", "gt", "lt", "ge", "le"];
                    }
                    else if (type === "boolean") {
                        availableOperators = ["eq", "ne"];
                    }
                    return {
                        name: key,
                        type: type,
                        example: value !== null && value !== undefined ? String(value).substring(0, 30) : "null", // Show a sample value (truncated)
                        operators: availableOperators
                    };
                });
                // Find a string field for the example if possible
                const stringField = attributes.find(attr => attr.type === "string" && attr.example && attr.example !== "null");
                let exampleFilter = "";
                if (stringField) {
                    exampleFilter = `${stringField.name}(like)=${stringField.example}`;
                }
                else if (attributes.length > 0) {
                    const firstAttr = attributes[0];
                    exampleFilter = `${firstAttr.name}(${firstAttr.operators[0]})=${firstAttr.example}`;
                }
                let exampleMultipleFilter = "";
                if (attributes.length > 1) {
                    const secondAttr = attributes[1];
                    exampleMultipleFilter = `${exampleFilter}&${secondAttr.name}(${secondAttr.operators[0]})=${secondAttr.example}`;
                }
                return {
                    content: [{
                            type: "text",
                            text: `Filterable attributes for ${entityType}:\n${JSON.stringify(attributes, null, 2)}\n\n` +
                                `Example filter usage: '${exampleFilter}'\n\n` +
                                `Example with multiple filters: '${exampleMultipleFilter || "Not enough attributes for multiple filter example"}'\n\n` +
                                `Note: For text fields, the 'like' operator is recommended as it performs case-insensitive substring matching.`
                        }]
                };
            }
            else {
                return {
                    content: [{
                            type: "text",
                            text: `No ${entityType} entities found to analyze. Please ensure there is at least one ${entityType} in the system.`
                        }]
                };
            }
        }
        catch (error) {
            return {
                isError: true,
                content: [{ type: "text", text: `Error fetching ${entityType} attributes: ${getErrorMessage(error)}` }]
            };
        }
    });
  • Reference to get-filterable-attributes in the input schema description of list-categories tool.
    filter: z.string().optional().describe("Filter criteria in the format 'fieldName(operator)=value'. Multiple filters can be combined with & (e.g., 'description(like)=dashboard&orgId(eq)=1'). Available operators: eq, ne, gt, lt, ge, le, like, nlike. Use get-filterable-attributes tool to see available fields."),
  • Reference to get-filterable-attributes in the input schema description of list-charts tool.
    filter: z.string().optional().describe("Filter criteria in the format 'fieldName(operator)=value'. Multiple filters can be combined with & (e.g., 'description(like)=revenue&categoryId(eq)=5'). Available operators: eq, ne, gt, lt, ge, le, like, nlike. Use get-filterable-attributes tool to see available fields."),

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/mingzilla/pi-api-mcp-server'

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