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
| Name | Required | Description | Default |
|---|---|---|---|
| entityType | Yes | Type of entity to examine (chart or category) |
Implementation Reference
- build/index.js:168-258 (handler)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)}` }] }; }
- build/index.js:167-167 (schema)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)}` }] }; } });
- build/index.js:598-598 (schema)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."),
- build/index.js:765-765 (schema)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."),