We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/garimiddisuman/jira-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
// src/services/StoriesService.ts
import { JiraStory } from "../types/JiraTypes";
import { JiraClient } from "../clients/JiraClient";
import { JiraConstants } from "../constants/JiraConstants";
import { Messages } from "../constants/Messages";
import { Logger } from "../utils/logger";
/**
* Stories Service - manages story data and operations
*/
export class StoriesService {
private stories: Map<string, JiraStory>;
private readonly jiraClient: JiraClient;
constructor(jiraClient: JiraClient) {
this.jiraClient = jiraClient;
this.stories = new Map<string, JiraStory>();
}
public async loadStories(): Promise<void> {
Logger.info(Messages.LOADING_STORIES);
this.stories = await this.jiraClient.fetchAllStories();
this.logLoadedCount();
}
public async refreshStories(): Promise<number> {
await this.loadStories();
return this.getStoriesCount();
}
public getAllStories(): JiraStory[] {
return Array.from(this.stories.values());
}
public getStoryByKey(key: string): JiraStory | undefined {
return this.stories.get(key);
}
public async fetchAndGetStoryByKey(key: string): Promise<JiraStory | null> {
return await this.jiraClient.fetchStoryByKey(key);
}
public getStoriesByStatus(status: string): JiraStory[] {
return this.getAllStories().filter((story) =>
this.isStatusMatch(story.status, status)
);
}
public searchStories(keyword: string): JiraStory[] {
const lowerKeyword = keyword.toLowerCase();
return this.getAllStories().filter((story) =>
this.matchesKeyword(story, lowerKeyword)
);
}
public getOpenStories(): JiraStory[] {
return this.getAllStories().filter((story) =>
this.isOpenStatus(story.status)
);
}
/**
* Active stories are those in early or ongoing workflow stages we want to focus on.
* We treat the following (case-insensitive) statuses as active:
* - todo
* - backlog
* - in progress
*/
public getActiveStories(): JiraStory[] {
const active = ["todo", "backlog", "in progress"]; // minimal focused set
return this.getAllStories().filter((story) =>
active.includes(story.status.toLowerCase())
);
}
public getStoriesCount(): number {
return this.stories.size;
}
public getAllStoryKeys(): string[] {
return Array.from(this.stories.keys());
}
public getAvailableStatuses(): string[] {
const statuses = new Set<string>();
this.getAllStories().forEach((story) => statuses.add(story.status));
return Array.from(statuses);
}
private isStatusMatch(storyStatus: string, targetStatus: string): boolean {
return storyStatus.toLowerCase() === targetStatus.toLowerCase();
}
private matchesKeyword(story: JiraStory, keyword: string): boolean {
return (
story.title.toLowerCase().includes(keyword) ||
story.description.toLowerCase().includes(keyword)
);
}
private isOpenStatus(status: string): boolean {
const lowerStatus = status.toLowerCase();
return (
lowerStatus !== JiraConstants.STATUS_DONE &&
lowerStatus !== JiraConstants.STATUS_CLOSED &&
lowerStatus !== JiraConstants.STATUS_RESOLVED
);
}
private logLoadedCount(): void {
Logger.info(`${Messages.STORIES_LOADED} ${this.getStoriesCount()} stories`);
}
}