We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/sooperset/mcp-atlassian'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""Models for Jira SLA calculations."""
from typing import Any
from pydantic import BaseModel
class WorkingHoursConfig(BaseModel):
"""Configuration for working hours."""
start: str # Start time in HH:MM format
end: str # End time in HH:MM format
days: list[int] # Working days (1=Mon, 7=Sun)
timezone: str # IANA timezone
class CycleTimeMetric(BaseModel):
"""Cycle time metric (created to resolved)."""
value_minutes: int | None = None
formatted: str | None = None
calculated: bool = False
reason: str | None = None
def to_simplified_dict(self) -> dict[str, Any]:
"""Convert to simplified dictionary."""
result: dict[str, Any] = {"calculated": self.calculated}
if self.calculated and self.value_minutes is not None:
result["value_minutes"] = self.value_minutes
result["formatted"] = self.formatted
if self.reason:
result["reason"] = self.reason
return result
class LeadTimeMetric(BaseModel):
"""Lead time metric (created to now or resolved)."""
value_minutes: int
formatted: str
is_resolved: bool = False
def to_simplified_dict(self) -> dict[str, Any]:
"""Convert to simplified dictionary."""
return {
"value_minutes": self.value_minutes,
"formatted": self.formatted,
"is_resolved": self.is_resolved,
}
class TimeInStatusEntry(BaseModel):
"""Time spent in a single status."""
status: str
value_minutes: int
formatted: str
percentage: float
visit_count: int
def to_simplified_dict(self) -> dict[str, Any]:
"""Convert to simplified dictionary."""
return {
"status": self.status,
"value_minutes": self.value_minutes,
"formatted": self.formatted,
"percentage": round(self.percentage, 2),
"visit_count": self.visit_count,
}
class TimeInStatusMetric(BaseModel):
"""Time in status breakdown."""
statuses: list[TimeInStatusEntry]
total_minutes: int
def to_simplified_dict(self) -> dict[str, Any]:
"""Convert to simplified dictionary."""
return {
"statuses": [s.to_simplified_dict() for s in self.statuses],
"total_minutes": self.total_minutes,
}
class DueDateComplianceMetric(BaseModel):
"""Due date compliance metric."""
status: str # "met", "missed", "no_due_date", "not_resolved"
margin_minutes: int | None = None
formatted_margin: str | None = None
def to_simplified_dict(self) -> dict[str, Any]:
"""Convert to simplified dictionary."""
result: dict[str, Any] = {"status": self.status}
if self.margin_minutes is not None:
result["margin_minutes"] = self.margin_minutes
result["formatted_margin"] = self.formatted_margin
return result
class ResolutionTimeMetric(BaseModel):
"""Resolution time metric (first in progress to resolved)."""
value_minutes: int | None = None
formatted: str | None = None
calculated: bool = False
reason: str | None = None
def to_simplified_dict(self) -> dict[str, Any]:
"""Convert to simplified dictionary."""
result: dict[str, Any] = {"calculated": self.calculated}
if self.calculated and self.value_minutes is not None:
result["value_minutes"] = self.value_minutes
result["formatted"] = self.formatted
if self.reason:
result["reason"] = self.reason
return result
class FirstResponseTimeMetric(BaseModel):
"""First response time metric."""
value_minutes: int | None = None
formatted: str | None = None
calculated: bool = False
response_type: str | None = None # "transition", "comment", etc.
def to_simplified_dict(self) -> dict[str, Any]:
"""Convert to simplified dictionary."""
result: dict[str, Any] = {"calculated": self.calculated}
if self.calculated and self.value_minutes is not None:
result["value_minutes"] = self.value_minutes
result["formatted"] = self.formatted
if self.response_type:
result["response_type"] = self.response_type
return result
class IssueSLAMetrics(BaseModel):
"""Container for all SLA metrics."""
cycle_time: CycleTimeMetric | None = None
lead_time: LeadTimeMetric | None = None
time_in_status: TimeInStatusMetric | None = None
due_date_compliance: DueDateComplianceMetric | None = None
resolution_time: ResolutionTimeMetric | None = None
first_response_time: FirstResponseTimeMetric | None = None
def to_simplified_dict(self) -> dict[str, Any]:
"""Convert to simplified dictionary."""
result: dict[str, Any] = {}
if self.cycle_time:
result["cycle_time"] = self.cycle_time.to_simplified_dict()
if self.lead_time:
result["lead_time"] = self.lead_time.to_simplified_dict()
if self.time_in_status:
result["time_in_status"] = self.time_in_status.to_simplified_dict()
if self.due_date_compliance:
result["due_date_compliance"] = (
self.due_date_compliance.to_simplified_dict()
)
if self.resolution_time:
result["resolution_time"] = self.resolution_time.to_simplified_dict()
if self.first_response_time:
result["first_response_time"] = (
self.first_response_time.to_simplified_dict()
)
return result
class IssueSLAResponse(BaseModel):
"""Response containing SLA metrics for a single issue."""
issue_key: str
metrics: IssueSLAMetrics
raw_dates: dict[str, Any] | None = None
def to_simplified_dict(self) -> dict[str, Any]:
"""Convert to simplified dictionary."""
result: dict[str, Any] = {
"issue_key": self.issue_key,
"metrics": self.metrics.to_simplified_dict(),
}
if self.raw_dates:
result["raw_dates"] = self.raw_dates
return result
class IssueSLABatchResponse(BaseModel):
"""Response containing SLA metrics for multiple issues."""
issues: list[IssueSLAResponse]
total_count: int
success_count: int
error_count: int
errors: list[dict[str, str]]
metrics_calculated: list[str]
working_hours_applied: bool
working_hours_config: WorkingHoursConfig | None = None
def to_simplified_dict(self) -> dict[str, Any]:
"""Convert to simplified dictionary."""
result: dict[str, Any] = {
"issues": [i.to_simplified_dict() for i in self.issues],
"total_count": self.total_count,
"success_count": self.success_count,
"error_count": self.error_count,
"metrics_calculated": self.metrics_calculated,
"working_hours_applied": self.working_hours_applied,
}
if self.errors:
result["errors"] = self.errors
if self.working_hours_config:
result["working_hours_config"] = {
"start": self.working_hours_config.start,
"end": self.working_hours_config.end,
"days": self.working_hours_config.days,
"timezone": self.working_hours_config.timezone,
}
return result