Skip to main content
Glama
jira-fields.ts5.27 kB
/** * Consolidated Jira Fields Tool. * Provides field discovery and custom field management. * @module tools/consolidated/jira-fields */ import { z } from 'zod'; import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { getAllFields, getCustomFields, searchFields, getFieldId, getCommonCustomFieldIds, getFieldSuggestions, clearFieldsCache, } from '../../jira/endpoints/fields.js'; import { encodeToon } from '../../formatters/toon.js'; import { createLogger } from '../../utils/logger.js'; const logger = createLogger('tool-jira-fields'); /** * Schema for the jira_fields tool. */ const jiraFieldsSchema = z.object({ action: z .enum([ 'list', 'list_custom', 'search', 'get_id', 'get_common', 'suggest', 'clear_cache', ]) .describe('The action to perform'), // Search options query: z .string() .optional() .describe('Search query for search/suggest actions'), // Field name fieldName: z.string().optional().describe('Field name for get_id action'), // Get options full: z .boolean() .optional() .default(false) .describe('Return full data instead of minimal fields'), // Suggestion limit limit: z .number() .optional() .default(10) .describe('Maximum suggestions for suggest action'), }); type JiraFieldsInput = z.infer<typeof jiraFieldsSchema>; /** * Handler for the jira_fields tool. */ async function handleJiraFields(input: JiraFieldsInput): Promise<string> { const { action } = input; switch (action) { case 'list': { const fields = await getAllFields(); if (input.full) { return JSON.stringify(fields, null, 2); } const simplified = fields.map((f) => ({ id: f.id, name: f.name, custom: f.custom, searchable: f.searchable, })); return encodeToon({ fields: simplified, count: fields.length, }); } case 'list_custom': { const fields = await getCustomFields(); if (input.full) { return JSON.stringify(fields, null, 2); } const simplified = fields.map((f) => ({ id: f.id, name: f.name, type: f.schema?.custom, })); return encodeToon({ customFields: simplified, count: fields.length, }); } case 'search': { if (!input.query) { throw new Error('query is required for search action'); } const fields = await searchFields(input.query); if (input.full) { return JSON.stringify(fields, null, 2); } const simplified = fields.map((f) => ({ id: f.id, name: f.name, custom: f.custom, clauseNames: f.clauseNames, })); return encodeToon({ fields: simplified, count: fields.length, }); } case 'get_id': { if (!input.fieldName) { throw new Error('fieldName is required for get_id action'); } const fieldId = await getFieldId(input.fieldName); if (!fieldId) { return encodeToon({ found: false, message: `Field "${input.fieldName}" not found`, }); } return encodeToon({ found: true, fieldName: input.fieldName, fieldId, }); } case 'get_common': { const commonFields = await getCommonCustomFieldIds(); return encodeToon({ commonFields, note: 'Use these field IDs in customFields parameter', }); } case 'suggest': { if (!input.query) { throw new Error('query is required for suggest action'); } const suggestions = await getFieldSuggestions( input.query, input.limit ?? 10 ); return encodeToon({ suggestions, count: suggestions.length, }); } case 'clear_cache': { clearFieldsCache(); return encodeToon({ success: true, message: 'Fields cache cleared', }); } default: throw new Error(`Unknown action: ${action}`); } } /** * Registers the jira_fields tool with the MCP server. */ export function registerJiraFieldsTool(server: McpServer): void { server.tool( 'jira_fields', `Discover and manage Jira fields. Actions: - list: List all available fields - list_custom: List only custom fields - search: Search fields by name - get_id: Get field ID by name (useful for custom fields) - get_common: Get IDs of common custom fields (Story Points, Sprint, etc.) - suggest: Get field name suggestions for autocomplete - clear_cache: Clear the fields cache`, jiraFieldsSchema.shape, async (params) => { try { const input = jiraFieldsSchema.parse(params); const result = await handleJiraFields(input); return { content: [{ type: 'text', text: result }] }; } catch (err) { logger.error( 'jira_fields error', err instanceof Error ? err : new Error(String(err)) ); const message = err instanceof Error ? err.message : 'Unknown error'; return { content: [{ type: 'text', text: `Error: ${message}` }], isError: true, }; } } ); }

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/icy-r/jira-mcp'

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