Skip to main content
Glama

manage_jira_insight_object

Perform CRUD operations and run AQL queries on Jira Insights objects to manage asset data, streamline object retrieval, and ensure schema-compliant updates for structured insights.

Instructions

Manage Jira Insights objects with CRUD operations and AQL queries

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
aqlNoAQL query string. Required for query operation. IMPORTANT: For comprehensive AQL documentation, refer to the "jira-insights://aql-syntax" resource using the access_mcp_resource tool. This resource contains detailed syntax guides, examples, and best practices. Guide to Constructing Better Jira Insight AQL Queries: Understanding AQL Fundamentals: - Object Type Case Sensitivity: Use exact case matching for object type names (e.g., ObjectType = "Supported laptops" not objectType = "Supported laptops"). - String Values in Quotes: Always enclose string values in double quotes, especially values containing spaces (e.g., Name = "MacBook Pro" not Name = MacBook Pro). - Attribute References: Reference attributes directly by their name, not by a derived field name (e.g., use Name not name). - LIKE Operator Usage: Use the LIKE operator for partial string matching, but be aware it may be case-sensitive. Effective Query Construction: - Start Simple: Begin with the most basic query to validate object existence before adding complex filters: ObjectType = "Supported laptops" - Examine Response Objects: Study the first responses to understand available attribute names and formats before using them in filters. - Keyword Strategy: When searching for specific items, try multiple potential keywords (e.g., "ThinkPad", "Lenovo", "Carbon") rather than just exclusion logic. - Incremental Complexity: Add filter conditions incrementally, testing after each addition rather than constructing complex queries in one step. Managing Complex Queries: - AND/OR Operators: Structure complex conditions carefully with proper parentheses: ObjectType = "Supported laptops" AND (Name LIKE "ThinkPad" OR Name LIKE "Lenovo") - NOT Operators: Use NOT sparingly and with proper syntax: ObjectType = "Supported laptops" AND NOT Name LIKE "MacBook" - Reference Object Queries: For filtering on related objects, use their object key as a reference: ObjectType = "Supported laptops" AND Manufacturer = "PPL-231" - Pagination Awareness: For large result sets, utilize the startAt and maxResults parameters to get complete data.
attributesNoAttributes of the object as key-value pairs. Optional for create/update.
expandNoOptional fields to include in the response
includeAttributesNoShould the objects attributes be included in the response. If this parameter is false only the information on the object will be returned and the object attributes will not be present.
includeAttributesDeepNoHow many levels of attributes should be included. E.g. consider an object A that has a reference to object B that has a reference to object C. If object A is included in the response and includeAttributesDeep=1 object A's reference to object B will be included in the attributes of object A but object B's reference to object C will not be included. However if the includeAttributesDeep=2 then object B's reference to object C will be included in object B's attributes.
includeExtendedInfoNoInclude information about open Jira issues. Should each object have information if open tickets are connected to the object?
includeTypeAttributesNoShould the response include the object type attribute definition for each attribute that is returned with the objects.
maxResultsNoMaximum number of objects to return. Used for list and query operations. Can also use snake_case "max_results".
nameNoName of the object. Required for create operation, optional for update.
objectIdNoThe ID of the object. Required for get, update, and delete operations. Can also use snake_case "object_id".
objectTypeIdNoThe ID of the object type. Required for create operation. Can also use snake_case "object_type_id".
operationYesOperation to perform on the object
resolveAttributeNamesNoReplace attribute IDs (attr_xxx) with actual attribute names in the response. This provides more meaningful attribute names for better readability.
schemaIdNoThe ID of the schema to use for enhanced validation. When provided, the query will be validated against the schema structure, providing better error messages and suggestions.
simplifiedResponseNoReturn a simplified response with only essential key-value pairs, excluding detailed metadata, references, and type definitions. Useful for reducing response size and improving readability.
startAtNoIndex of the first object to return (0-based). Used for list and query operations. Can also use snake_case "start_at".

Implementation Reference

  • The main handler function `setupObjectHandlers` that executes all operations (get, list, create, update, delete, query) for the `manage_jira_insight_object` tool using Jira Assets API.
    export async function setupObjectHandlers( server: Server, jiraClient: JiraClient, request: any ): Promise<ToolResponse> { const { arguments: args } = request.params; const operation = args.operation as ObjectOperation; // Normalize parameter names (support both camelCase and snake_case) const objectId = args.objectId || args.object_id; const objectTypeId = args.objectTypeId || args.object_type_id; const startAt = args.startAt || args.start_at || 0; const maxResults = args.maxResults || args.max_results || 50; // Normalize attribute inclusion parameters with defaults const includeAttributes = args.includeAttributes !== undefined ? args.includeAttributes : true; const includeAttributesDeep = args.includeAttributesDeep !== undefined ? args.includeAttributesDeep : 1; const includeTypeAttributes = args.includeTypeAttributes !== undefined ? args.includeTypeAttributes : false; const includeExtendedInfo = args.includeExtendedInfo !== undefined ? args.includeExtendedInfo : false; const simplifiedResponse = args.simplifiedResponse !== undefined ? args.simplifiedResponse : true; const resolveAttributeNames = args.resolveAttributeNames !== undefined ? args.resolveAttributeNames : true; try { const assetsApi = await jiraClient.getAssetsApi(); switch (operation) { case 'get': { if (!objectId) { throw new McpError(ErrorCode.InvalidParams, 'Object ID is required for get operation'); } const object = await assetsApi.objectFind({ id: objectId }); // Apply simplification if requested const responseData = simplifiedResponse ? await simplifyInsightObject(object, { resolveAttributeNames }, jiraClient) : object; return { content: [ { type: 'text', text: JSON.stringify(responseData, null, 2), }, ], }; } case 'list': { if (!objectTypeId) { throw new McpError(ErrorCode.InvalidParams, 'Object Type ID is required for list operation'); } // Note: There doesn't seem to be a direct replacement for getObjects in the new API // We'll use objectsByAql with a query that filters by objectTypeId const objectsList = await assetsApi.objectsByAql({ requestBody: { qlQuery: `objectType = ${objectTypeId}` // Changed from 'aql' to 'qlQuery' to match API documentation }, startAt, maxResults, includeAttributes, includeAttributesDeep, includeTypeAttributes, includeExtendedInfo }); // Apply simplification if requested const responseData = simplifiedResponse ? await simplifyQueryResults(objectsList, { resolveAttributeNames }, jiraClient) : objectsList; return { content: [ { type: 'text', text: JSON.stringify(responseData, null, 2), }, ], }; } case 'create': { if (!objectTypeId) { throw new McpError(ErrorCode.InvalidParams, 'Object Type ID is required for create operation'); } if (!args.name) { throw new McpError(ErrorCode.InvalidParams, 'Name is required for create operation'); } // Format attributes using the utility const attributeValues = args.attributes ? formatAttributes(args.attributes) : []; const newObject = await assetsApi.objectCreate({ objectIn: { name: args.name, objectTypeId, attributes: attributeValues, }, }); // Apply simplification if requested const responseData = simplifiedResponse ? await simplifyInsightObject(newObject, { resolveAttributeNames }, jiraClient) : newObject; return { content: [ { type: 'text', text: JSON.stringify(responseData, null, 2), }, ], }; } case 'update': { if (!objectId) { throw new McpError(ErrorCode.InvalidParams, 'Object ID is required for update operation'); } // First get the existing object const existingObject = await assetsApi.objectFind({ id: objectId }) as { name: string; objectTypeId: string; }; // Format attributes using the utility const attributeValues = args.attributes ? formatAttributes(args.attributes) : []; // Update with new values const updatedObject = await assetsApi.objectUpdate({ id: objectId, objectIn: { name: args.name || existingObject.name, objectTypeId: existingObject.objectTypeId, attributes: attributeValues.length > 0 ? attributeValues : undefined, }, }); // Apply simplification if requested const responseData = simplifiedResponse ? await simplifyInsightObject(updatedObject, { resolveAttributeNames }, jiraClient) : updatedObject; return { content: [ { type: 'text', text: JSON.stringify(responseData, null, 2), }, ], }; } case 'delete': { if (!objectId) { throw new McpError(ErrorCode.InvalidParams, 'Object ID is required for delete operation'); } await assetsApi.objectDelete({ id: objectId }); return { content: [ { type: 'text', text: JSON.stringify({ success: true, message: `Object ${objectId} deleted successfully` }, null, 2), }, ], }; } case 'query': { if (!args.aql) { throw new McpError(ErrorCode.InvalidParams, 'AQL query is required for query operation'); } // Get schema context if available (for better validation) let schemaContext; if (args.schemaId) { try { schemaContext = await getSchemaForValidation(args.schemaId, jiraClient); } catch (error) { console.warn('Could not load schema context for validation:', error); } } // Enhanced validation with schema context if available const validation = validateAqlQuery(args.aql, schemaContext); // If the query is invalid, return enhanced validation errors with suggestions if (!validation.isValid) { // Get example queries for the schema or object type const examples = args.schemaId ? getExampleQueriesWithContext(args.schemaId, args.objectTypeId) : []; return { content: [ { type: 'text', text: JSON.stringify({ error: 'Invalid AQL query', validation, suggestedFix: validation.fixedQuery, examples, operation, }, null, 2), }, ], isError: true, }; } // Use the fixed query if available, otherwise format the original const queryToUse = validation.fixedQuery || args.aql; const formattedAql = formatAqlForRequest(queryToUse); try { // Execute the query with the formatted AQL const queryResults = await assetsApi.objectsByAql({ requestBody: { qlQuery: formattedAql // Changed from 'aql' to 'qlQuery' to match API documentation }, startAt, maxResults, includeAttributes, includeAttributesDeep, includeTypeAttributes, includeExtendedInfo }); // Add metadata about the query const metadata = { _originalAql: args.aql, _formattedAql: formattedAql, _wasFixed: validation.fixedQuery ? true : false }; // Apply simplification if requested const simplifiedResponse = args.simplifiedResponse !== undefined ? args.simplifiedResponse : true; let responseData; if (simplifiedResponse) { // First simplify the query results responseData = await simplifyQueryResults( queryResults, { resolveAttributeNames: false }, // Don't resolve attribute names yet jiraClient, metadata ); // If resolveAttributeNames is true, replace attribute IDs with attribute names if (resolveAttributeNames && responseData && responseData.values && responseData.values.length > 0) { try { // Get unique object type IDs from all objects const objectTypeIds = new Set<string>(); for (const obj of queryResults.values) { if (obj && obj.objectType && obj.objectType.id) { objectTypeIds.add(obj.objectType.id); } } console.log(`Found ${objectTypeIds.size} unique object types in query results`); // Fetch attribute names for each object type const attributeMaps: Record<string, Record<string, string>> = {}; for (const objectTypeId of objectTypeIds) { console.log(`Fetching attribute names for object type ${objectTypeId}`); attributeMaps[objectTypeId] = await fetchAttributeNames(objectTypeId, jiraClient); } // Replace attribute IDs with attribute names in each object responseData.values = responseData.values.map((obj: any, index: number) => { const originalObj = queryResults.values[index]; if (originalObj && originalObj.objectType && originalObj.objectType.id) { const objectTypeId = originalObj.objectType.id; const attributeMap = attributeMaps[objectTypeId] || {}; return replaceAttributeIds(obj, attributeMap); } return obj; }); } catch (error) { console.error('Error resolving attribute names:', error); // Continue with unresolved attribute names } } } else { responseData = { ...queryResults, ...metadata }; } return { content: [ { type: 'text', text: JSON.stringify(responseData, null, 2), }, ], }; } catch (error) { // Enhanced error handling for AQL execution errors const { message, suggestions } = getContextualErrorMessage(error as Record<string, unknown>, formattedAql); // Get example queries for the schema or object type const examples = args.schemaId ? getExampleQueriesWithContext(args.schemaId, args.objectTypeId) : []; return { content: [ { type: 'text', text: JSON.stringify({ error: 'Error executing AQL query', message, suggestions, examples, originalQuery: args.aql, formattedQuery: formattedAql }, null, 2), }, ], isError: true, }; } } default: throw new McpError(ErrorCode.InvalidParams, `Unsupported operation: ${operation}`); } } catch (error) { console.error('Error in object handler:', error); if (error instanceof McpError) { throw error; } // Use the new error handler with context return handleError(error, operation, { objectId, objectTypeId, name: args.name, attributes: args.attributes, startAt, maxResults, aql: args.aql, expand: args.expand, includeAttributes, includeAttributesDeep, includeTypeAttributes, includeExtendedInfo }); } }
  • JSON schema defining input parameters for the `manage_jira_insight_object` tool, supporting all operations with detailed descriptions and validation.
    manage_jira_insight_object: { name: 'manage_jira_insight_object', description: 'Manage Jira Insights objects with CRUD operations and AQL queries', inputSchema: { type: 'object', properties: { operation: { type: 'string', enum: ['get', 'list', 'create', 'update', 'delete', 'query'], description: 'Operation to perform on the object', }, // Parameters for get, update, delete operations objectId: { type: 'string', description: 'The ID of the object. Required for get, update, and delete operations. Can also use snake_case "object_id".', }, // Parameters for create and update operations objectTypeId: { type: 'string', description: 'The ID of the object type. Required for create operation. Can also use snake_case "object_type_id".', }, name: { type: 'string', description: 'Name of the object. Required for create operation, optional for update.', }, attributes: { type: 'object', description: 'Attributes of the object as key-value pairs. Optional for create/update.', }, // Parameters for list operation startAt: { type: 'integer', description: 'Index of the first object to return (0-based). Used for list and query operations. Can also use snake_case "start_at".', default: 0, }, maxResults: { type: 'integer', description: 'Maximum number of objects to return. Used for list and query operations. Can also use snake_case "max_results".', default: 50, }, // Parameters for query operation aql: { type: 'string', description: `AQL query string. Required for query operation. IMPORTANT: For comprehensive AQL documentation, refer to the "jira-insights://aql-syntax" resource using the access_mcp_resource tool. This resource contains detailed syntax guides, examples, and best practices. Guide to Constructing Better Jira Insight AQL Queries: Understanding AQL Fundamentals: - Object Type Case Sensitivity: Use exact case matching for object type names (e.g., ObjectType = "Supported laptops" not objectType = "Supported laptops"). - String Values in Quotes: Always enclose string values in double quotes, especially values containing spaces (e.g., Name = "MacBook Pro" not Name = MacBook Pro). - Attribute References: Reference attributes directly by their name, not by a derived field name (e.g., use Name not name). - LIKE Operator Usage: Use the LIKE operator for partial string matching, but be aware it may be case-sensitive. Effective Query Construction: - Start Simple: Begin with the most basic query to validate object existence before adding complex filters: ObjectType = "Supported laptops" - Examine Response Objects: Study the first responses to understand available attribute names and formats before using them in filters. - Keyword Strategy: When searching for specific items, try multiple potential keywords (e.g., "ThinkPad", "Lenovo", "Carbon") rather than just exclusion logic. - Incremental Complexity: Add filter conditions incrementally, testing after each addition rather than constructing complex queries in one step. Managing Complex Queries: - AND/OR Operators: Structure complex conditions carefully with proper parentheses: ObjectType = "Supported laptops" AND (Name LIKE "ThinkPad" OR Name LIKE "Lenovo") - NOT Operators: Use NOT sparingly and with proper syntax: ObjectType = "Supported laptops" AND NOT Name LIKE "MacBook" - Reference Object Queries: For filtering on related objects, use their object key as a reference: ObjectType = "Supported laptops" AND Manufacturer = "PPL-231" - Pagination Awareness: For large result sets, utilize the startAt and maxResults parameters to get complete data.`, }, // Schema-aware validation parameters schemaId: { type: 'string', description: 'The ID of the schema to use for enhanced validation. When provided, the query will be validated against the schema structure, providing better error messages and suggestions.', }, // Attribute inclusion options includeAttributes: { type: 'boolean', description: 'Should the objects attributes be included in the response. If this parameter is false only the information on the object will be returned and the object attributes will not be present.', default: true, }, includeAttributesDeep: { type: 'integer', description: 'How many levels of attributes should be included. E.g. consider an object A that has a reference to object B that has a reference to object C. If object A is included in the response and includeAttributesDeep=1 object A\'s reference to object B will be included in the attributes of object A but object B\'s reference to object C will not be included. However if the includeAttributesDeep=2 then object B\'s reference to object C will be included in object B\'s attributes.', default: 1, }, includeTypeAttributes: { type: 'boolean', description: 'Should the response include the object type attribute definition for each attribute that is returned with the objects.', default: false, }, includeExtendedInfo: { type: 'boolean', description: 'Include information about open Jira issues. Should each object have information if open tickets are connected to the object?', default: false, }, // Response format options simplifiedResponse: { type: 'boolean', description: 'Return a simplified response with only essential key-value pairs, excluding detailed metadata, references, and type definitions. Useful for reducing response size and improving readability.', default: true, }, resolveAttributeNames: { type: 'boolean', description: 'Replace attribute IDs (attr_xxx) with actual attribute names in the response. This provides more meaningful attribute names for better readability.', default: true, }, // Common expansion options expand: { type: 'array', items: { type: 'string', enum: ['attributes', 'objectType', 'schema', 'history'], }, description: 'Optional fields to include in the response', }, }, required: ['operation'], }, },
  • src/index.ts:142-188 (registration)
    Registration of the CallToolRequestSchema handler in the MCP server, which dispatches calls to `manage_jira_insight_object` to the `setupObjectHandlers` function.
    this.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => { console.error('Received request:', JSON.stringify(request, null, 2)); const { name } = request.params; console.error(`Handling tool request: ${name}`); try { let response; // Schema-related tools if (['manage_jira_insight_schema'].includes(name)) { response = await setupSchemaHandlers(this.server, this.jiraClient, this.schemaCacheManager, request); } // Object Type-related tools else if (['manage_jira_insight_object_type'].includes(name)) { response = await setupObjectTypeHandlers(this.server, this.jiraClient, this.schemaCacheManager, request); } // Object-related tools else if (['manage_jira_insight_object'].includes(name)) { response = await setupObjectHandlers(this.server, this.jiraClient, request); } else { console.error(`Unknown tool requested: ${name}`); throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`); } // Ensure we always return a valid response if (!response) { throw new McpError(ErrorCode.InternalError, `No response from handler for tool: ${name}`); } // Convert ToolResponse to the expected return type return { content: response.content, ...(response.isError ? { isError: response.isError } : {}) }; } catch (error) { console.error('Error handling request:', error); if (error instanceof McpError) { throw error; } throw new McpError(ErrorCode.InternalError, 'Internal server error'); } });
  • src/index.ts:82-98 (registration)
    Server initialization with capabilities.tools.schemas populated from toolSchemas, registering the `manage_jira_insight_object` tool schema.
    this.server = new Server( { name: serverName, version: '0.1.0', description: 'Jira Insights MCP Server - Provides tools for interacting with Jira Insights (JSM) asset schemas', }, { capabilities: { tools: { schemas: tools, }, resources: { schemas: [], // Resource schemas are handled by the resource handlers }, }, } );

Other Tools

Related Tools

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/aaronsb/jira-insights-mcp'

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