Skip to main content
Glama

get_issue

Retrieve detailed information on a specified Redmine issue by providing the issue ID, with options to include descriptions, notes, and attachments for comprehensive insights.

Instructions

取得指定的 Redmine 議題詳細資訊 Args: issue_id: 議題 ID include_details: 是否包含詳細資訊(描述、備註、附件等) Returns: 議題的詳細資訊,以易讀格式呈現

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
include_detailsNo
issue_idYes

Implementation Reference

  • Main MCP tool handler for 'get_issue'. Fetches raw issue data from RedmineClient and formats it into a readable string response including details like attachments and journals if requested.
    @mcp.tool() def get_issue(issue_id: int, include_details: bool = True) -> str: """ 取得指定的 Redmine 議題詳細資訊 Args: issue_id: 議題 ID include_details: 是否包含詳細資訊(描述、備註、附件等) Returns: 議題的詳細資訊,以易讀格式呈現 """ try: client = get_client() include_params = [] if include_details: include_params = ['attachments', 'changesets', 'children', 'journals', 'relations', 'watchers'] # 使用新的 get_issue_raw 方法取得完整資料 issue_data = client.get_issue_raw(issue_id, include=include_params) # 格式化基本議題資訊 # 處理父議題資訊 parent_info = "無父議題" if 'parent' in issue_data and issue_data['parent']: parent_info = f"#{issue_data['parent']['id']} - {issue_data['parent'].get('subject', 'N/A')}" result = f"""議題 #{issue_data['id']}: {issue_data['subject']} 基本資訊: - 專案: {issue_data['project'].get('name', 'N/A')} (ID: {issue_data['project'].get('id', 'N/A')}) - 追蹤器: {issue_data['tracker'].get('name', 'N/A')} - 狀態: {issue_data['status'].get('name', 'N/A')} - 優先級: {issue_data['priority'].get('name', 'N/A')} - 建立者: {issue_data['author'].get('name', 'N/A')} - 指派給: {issue_data.get('assigned_to', {}).get('name', '未指派') if issue_data.get('assigned_to') else '未指派'} - 父議題: {parent_info} - 完成度: {issue_data.get('done_ratio', 0)}% - 開始日期: {issue_data.get('start_date', '未設定')} - 完成日期: {issue_data.get('due_date', '未設定')} - 預估工時: {issue_data.get('estimated_hours', '未設定')} 小時 - 建立時間: {issue_data.get('created_on', 'N/A')} - 更新時間: {issue_data.get('updated_on', 'N/A')} 描述: {issue_data.get('description', '無描述')}""" # 加入附件資訊 if include_details and 'attachments' in issue_data and issue_data['attachments']: result += f"\n\n附件 ({len(issue_data['attachments'])} 個):" for attachment in issue_data['attachments']: file_size = attachment.get('filesize', 0) file_size_mb = file_size / (1024 * 1024) if file_size > 0 else 0 size_text = f"{file_size_mb:.2f} MB" if file_size_mb >= 1 else f"{file_size} bytes" result += f""" - 檔名: {attachment.get('filename', 'N/A')} 大小: {size_text} 類型: {attachment.get('content_type', 'N/A')} 上傳者: {attachment.get('author', {}).get('name', 'N/A')} 上傳時間: {attachment.get('created_on', 'N/A')} 下載連結: {client.config.redmine_domain}/attachments/download/{attachment.get('id', '')}/{attachment.get('filename', '')}""" # 加入備註/歷史記錄 if include_details and 'journals' in issue_data and issue_data['journals']: # 過濾出有備註內容的記錄 notes_journals = [j for j in issue_data['journals'] if j.get('notes', '').strip()] if notes_journals: result += f"\n\n備註/歷史記錄 ({len(notes_journals)} 筆):" for i, journal in enumerate(notes_journals, 1): author_name = journal.get('user', {}).get('name', 'N/A') created_on = journal.get('created_on', 'N/A') notes = journal.get('notes', '').strip() result += f""" #{i} - {author_name} ({created_on}): {notes}""" return result except RedmineAPIError as e: return f"取得議題失敗: {str(e)}" except Exception as e: return f"系統錯誤: {str(e)}"
  • Core helper method in RedmineClient that performs the actual API request to fetch raw issue data, called by the get_issue tool handler.
    def get_issue_raw(self, issue_id: int, include: Optional[List[str]] = None) -> Dict[str, Any]: """取得單一議題的原始 API 資料(包含 journals 和 attachments)""" params = {} if include: params['include'] = ','.join(include) response = self._make_request('GET', f'/issues/{issue_id}.json', params=params) if 'issue' not in response: raise RedmineAPIError(f"議題 {issue_id} 不存在") return response['issue']
  • Helper method that parses raw API response into structured RedmineIssue object (related but not directly used by get_issue tool).
    def get_issue(self, issue_id: int, include: Optional[List[str]] = None) -> RedmineIssue: """取得單一議題""" params = {} if include: params['include'] = ','.join(include) response = self._make_request('GET', f'/issues/{issue_id}.json', params=params) if 'issue' not in response: raise RedmineAPIError(f"議題 {issue_id} 不存在") issue_data = response['issue'] return RedmineIssue( id=issue_data['id'], subject=issue_data['subject'], description=issue_data.get('description', ''), status=issue_data['status'], priority=issue_data['priority'], project=issue_data['project'], tracker=issue_data['tracker'], author=issue_data['author'], assigned_to=issue_data.get('assigned_to'), created_on=issue_data.get('created_on'), updated_on=issue_data.get('updated_on'), done_ratio=issue_data.get('done_ratio', 0) )
  • MCP tool registration decorator for the get_issue handler.
    @mcp.tool()
  • Dataclass defining the structure/schema for RedmineIssue objects.
    @dataclass class RedmineIssue: """Redmine 議題數據結構""" id: int subject: str description: str status: Dict[str, Any] priority: Dict[str, Any] project: Dict[str, Any] tracker: Dict[str, Any] author: Dict[str, Any] assigned_to: Optional[Dict[str, Any]] = None created_on: Optional[str] = None updated_on: Optional[str] = None done_ratio: int = 0

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/snowild/redmine-mcp'

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