diff --git a/src/handlers.ts b/src/handlers.ts index dd0f088..3b6175f 100644 --- a/src/handlers.ts +++ b/src/handlers.ts @@ -4,15 +4,18 @@ import { FEATURE_REF_REGEX, REQUIREMENT_REF_REGEX, NOTE_REF_REGEX, + EPIC_REF_REGEX, Record, FeatureResponse, RequirementResponse, + EpicResponse, PageResponse, SearchResponse, } from "./types.js"; import { getFeatureQuery, getRequirementQuery, + getEpicQuery, getPageQuery, searchDocumentsQuery, } from "./queries.js"; @@ -36,9 +39,7 @@ export class Handlers { if (FEATURE_REF_REGEX.test(reference)) { const data = await this.client.request( getFeatureQuery, - { - id: reference, - } + { id: reference } ); result = data.feature; } else if (REQUIREMENT_REF_REGEX.test(reference)) { @@ -47,10 +48,16 @@ export class Handlers { { id: reference } ); result = data.requirement; + } else if (EPIC_REF_REGEX.test(reference)) { + const data = await this.client.request( + getEpicQuery, + { id: reference } + ); + result = data.epic; } else { throw new McpError( ErrorCode.InvalidParams, - "Invalid reference number format. Expected DEVELOP-123 or ADT-123-1" + "Invalid reference number format. Expected DEVELOP-123, ADT-123-1, or DCOMMS-E-157" ); } @@ -77,7 +84,6 @@ export class Handlers { if (error instanceof McpError) { throw error; } - const errorMessage = error instanceof Error ? error.message : String(error); console.error("API Error:", errorMessage); @@ -137,7 +143,6 @@ export class Handlers { if (error instanceof McpError) { throw error; } - const errorMessage = error instanceof Error ? error.message : String(error); console.error("API Error:", errorMessage); @@ -179,7 +184,6 @@ export class Handlers { if (error instanceof McpError) { throw error; } - const errorMessage = error instanceof Error ? error.message : String(error); console.error("API Error:", errorMessage); @@ -189,4 +193,4 @@ export class Handlers { ); } } -} +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 0a4795e..3ef9cbc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ #!/usr/bin/env node + import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { @@ -62,14 +63,15 @@ class AhaMcp { tools: [ { name: "get_record", - description: "Get an Aha! feature or requirement by reference number", + description: + "Get an Aha! feature, requirement, or epic by reference number", inputSchema: { type: "object", properties: { reference: { type: "string", description: - "Reference number (e.g., DEVELOP-123 or ADT-123-1)", + "Reference number (e.g., DEVELOP-123, ADT-123-1, or DCOMMS-E-157)", }, }, required: ["reference"], @@ -107,7 +109,8 @@ class AhaMcp { }, searchableType: { type: "string", - description: "Type of document to search for (e.g., Page)", + description: + "Type of document to search for (e.g., Page, Epic, Feature)", default: "Page", }, }, @@ -141,4 +144,4 @@ class AhaMcp { } const server = new AhaMcp(); -server.run().catch(console.error); +server.run().catch(console.error); \ No newline at end of file diff --git a/src/queries.ts b/src/queries.ts index 974fc0d..cace5cc 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -1,57 +1,68 @@ export const getPageQuery = ` - query GetPage($id: ID!, $includeParent: Boolean!) { - page(id: $id) { +query GetPage($id: ID!, $includeParent: Boolean!) { + page(id: $id) { + name + description { + markdownBody + } + children { + name + referenceNum + } + parent @include(if: $includeParent) { name - description { - markdownBody - } - children { - name - referenceNum - } - parent @include(if: $includeParent) { - name - referenceNum - } + referenceNum } } +} `; export const getFeatureQuery = ` - query GetFeature($id: ID!) { - feature(id: $id) { - name - description { - markdownBody - } +query GetFeature($id: ID!) { + feature(id: $id) { + name + description { + markdownBody } } +} `; export const getRequirementQuery = ` - query GetRequirement($id: ID!) { - requirement(id: $id) { - name - description { - markdownBody - } +query GetRequirement($id: ID!) { + requirement(id: $id) { + name + description { + markdownBody } } +} `; -export const searchDocumentsQuery = ` - query SearchDocuments($query: String!, $searchableType: [String!]!) { - searchDocuments(filters: {query: $query, searchableType: $searchableType}) { - nodes { - name - url - searchableId - searchableType - } - currentPage - totalCount - totalPages - isLastPage +export const getEpicQuery = ` +query GetEpic($id: ID!) { + epic(id: $id) { + name + description { + markdownBody } } +} `; + +export const searchDocumentsQuery = ` +query SearchDocuments($query: String!, $searchableType: [String!]!) { + searchDocuments(filters: {query: $query, searchableType: $searchableType}) { + nodes { + name + url + searchableId + searchableType + } + currentPage + totalCount + totalPages + isLastPage + } +} +`; \ No newline at end of file diff --git a/src/types.ts b/src/types.ts index c7dca9c..ba5ae77 100644 --- a/src/types.ts +++ b/src/types.ts @@ -15,6 +15,10 @@ export interface RequirementResponse { requirement: Record; } +export interface EpicResponse { + epic: Record; +} + export interface PageResponse { page: { name: string; @@ -34,6 +38,7 @@ export interface PageResponse { export const FEATURE_REF_REGEX = /^([A-Z][A-Z0-9]*)-(\d+)$/; export const REQUIREMENT_REF_REGEX = /^([A-Z][A-Z0-9]*)-(\d+)-(\d+)$/; export const NOTE_REF_REGEX = /^([A-Z][A-Z0-9]*)-N-(\d+)$/; +export const EPIC_REF_REGEX = /^([A-Z][A-Z0-9]*)-E-(\d+)$/; export interface SearchNode { name: string | null; @@ -50,4 +55,4 @@ export interface SearchResponse { totalPages: number; isLastPage: boolean; }; -} +} \ No newline at end of file