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
"""Module for Jira protocol definitions."""
from abc import abstractmethod
from typing import Any, Protocol, runtime_checkable
from ..models.jira import JiraIssue
from ..models.jira.search import JiraSearchResult
class AttachmentsOperationsProto(Protocol):
"""Protocol defining attachments operations interface."""
@abstractmethod
def upload_attachments(
self, issue_key: str, file_paths: list[str]
) -> dict[str, Any]:
"""
Upload multiple attachments to a Jira issue.
Args:
issue_key: The Jira issue key (e.g., 'PROJ-123')
file_paths: List of paths to files to upload
Returns:
A dictionary with upload results
"""
class IssueOperationsProto(Protocol):
"""Protocol defining issue operations interface."""
@abstractmethod
def get_issue(
self,
issue_key: str,
expand: str | None = None,
comment_limit: int | str | None = 10,
fields: str
| list[str]
| tuple[str, ...]
| set[str]
| None = "summary,description,status,assignee,reporter,labels,priority,created,updated,issuetype",
properties: str | list[str] | None = None,
update_history: bool = True,
) -> JiraIssue:
"""Get a Jira issue by key."""
class SearchOperationsProto(Protocol):
"""Protocol defining search operations interface."""
@abstractmethod
def search_issues(
self,
jql: str,
fields: str
| list[str]
| tuple[str, ...]
| set[str]
| None = "summary,description,status,assignee,reporter,labels,priority,created,updated,issuetype",
start: int = 0,
limit: int = 50,
expand: str | None = None,
projects_filter: str | None = None,
) -> JiraSearchResult:
"""Search for issues using JQL."""
class EpicOperationsProto(Protocol):
"""Protocol defining epic operations interface."""
@abstractmethod
def update_epic_fields(self, issue_key: str, kwargs: dict[str, Any]) -> JiraIssue:
"""
Update Epic-specific fields after Epic creation.
This method implements the second step of the two-step Epic creation process,
applying Epic-specific fields that may be rejected during initial creation
due to screen configuration restrictions.
Args:
issue_key: The key of the created Epic
kwargs: Dictionary containing special keys with Epic field information
Returns:
JiraIssue: The updated Epic
Raises:
Exception: If there is an error updating the Epic fields
"""
@abstractmethod
def prepare_epic_fields(
self,
fields: dict[str, Any],
summary: str,
kwargs: dict[str, Any],
project_key: str = None,
) -> None:
"""
Prepare epic-specific fields for issue creation.
Args:
fields: The fields dictionary to update
summary: The issue summary that can be used as a default epic name
kwargs: Additional fields from the user
"""
@abstractmethod
def _try_discover_fields_from_existing_epic(
self, field_ids: dict[str, str]
) -> None:
"""
Try to discover Epic fields from existing epics in the Jira instance.
This is a fallback method used when standard field discovery doesn't find
all the necessary Epic-related fields. It searches for an existing Epic and
analyzes its field structure to identify Epic fields dynamically.
Args:
field_ids: Dictionary of field IDs to update with discovered fields
"""
class FieldsOperationsProto(Protocol):
"""Protocol defining fields operations interface."""
@abstractmethod
def _generate_field_map(self, force_regenerate: bool = False) -> dict[str, str]:
"""
Generates and caches a map of lowercase field names to field IDs.
Args:
force_regenerate: If True, forces regeneration even if cache exists.
Returns:
A dictionary mapping lowercase field names and field IDs to actual field IDs.
"""
@abstractmethod
def get_field_by_id(
self, field_id: str, refresh: bool = False
) -> dict[str, Any] | None:
"""
Get field definition by ID.
"""
@abstractmethod
def get_field_ids_to_epic(self) -> dict[str, str]:
"""
Dynamically discover Jira field IDs relevant to Epic linking.
This method queries the Jira API to find the correct custom field IDs
for Epic-related fields, which can vary between different Jira instances.
Returns:
Dictionary mapping field names to their IDs
(e.g., {'epic_link': 'customfield_10014', 'epic_name': 'customfield_10011'})
"""
@abstractmethod
def get_required_fields(self, issue_type: str, project_key: str) -> dict[str, Any]:
"""
Get required fields for creating an issue of a specific type in a project.
Args:
issue_type: The issue type (e.g., 'Bug', 'Story', 'Epic')
project_key: The project key (e.g., 'PROJ')
Returns:
Dictionary mapping required field names to their definitions
"""
@runtime_checkable
class ProjectsOperationsProto(Protocol):
"""Protocol defining project operations interface."""
@abstractmethod
def get_project_issue_types(self, project_key: str) -> list[dict[str, Any]]:
"""
Get all issue types available for a project.
Args:
project_key: The project key
Returns:
List of issue type data dictionaries
"""
@runtime_checkable
class UsersOperationsProto(Protocol):
"""Protocol defining user operations interface."""
@abstractmethod
def _get_account_id(self, assignee: str) -> str:
"""Get the account ID for a username.
Args:
assignee: Username or account ID
Returns:
Account ID
Raises:
ValueError: If the account ID could not be found
"""