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