Skip to main content
Glama
AstroMined

PyGithub MCP Server

by AstroMined

create_issue

Create new issues in GitHub repositories by specifying owner, repo, title, body, assignees, labels, and milestones.

Instructions

Create a new issue in a GitHub repository.

Args:
    params_dict: Parameters for creating an issue including:
        - owner: Repository owner (user or organization)
        - repo: Repository name
        - title: Issue title
        - body: Issue description (optional)
        - assignees: List of usernames to assign
        - labels: List of labels to add
        - milestone: Milestone number (optional)

Returns:
    Created issue details from GitHub API

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
params_dictYes

Implementation Reference

  • MCP tool handler function decorated with @tool(). Validates input parameters using CreateIssueParams, delegates to operations.issues.create_issue, and formats the MCP response.
    @tool()
    def create_issue(params_dict: dict) -> dict:
        """Create a new issue in a GitHub repository.
        
        Args:
            params_dict: Parameters for creating an issue including:
                - owner: Repository owner (user or organization)
                - repo: Repository name
                - title: Issue title
                - body: Issue description (optional)
                - assignees: List of usernames to assign
                - labels: List of labels to add
                - milestone: Milestone number (optional)
        
        Returns:
            Created issue details from GitHub API
        """
        try:
            # First validate the input params
            try:
                params = CreateIssueParams(**params_dict)
                logger.debug(f"create_issue called with validated params: {params}")
            except Exception as e:
                logger.error(f"Failed to convert dict to CreateIssueParams: {e}")
                return {
                    "content": [{"type": "error", "text": f"Validation error: {str(e)}"}],
                    "is_error": True
                }
    
            # Pass the Pydantic model directly to the operation
            result = issues.create_issue(params)
            logger.debug(f"Got result: {result}")
            response = {"content": [{"type": "text", "text": json.dumps(result, indent=2)}]}
            logger.debug(f"Returning response: {response}")
            return response
        except GitHubError as e:
            logger.error(f"GitHub error: {e}")
            return {
                "content": [{"type": "error", "text": format_github_error(e)}],
                "is_error": True
            }
        except Exception as e:
            logger.error(f"Unexpected error: {e}")
            logger.error(traceback.format_exc())
            error_msg = str(e) if str(e) else "An unexpected error occurred"
            return {
                "content": [{"type": "error", "text": f"Internal server error: {error_msg}"}],
                "is_error": True
            }
  • Pydantic model defining input parameters and validation for the create_issue tool.
    class CreateIssueParams(RepositoryRef):
        """Parameters for creating an issue."""
    
        model_config = ConfigDict(strict=True)
        
        title: str = Field(..., description="Issue title", strict=True)
        body: Optional[str] = Field(None, description="Issue description", strict=True)
        assignees: List[str] = Field(default_factory=list, description="Usernames to assign", strict=True)
        labels: List[str] = Field(default_factory=list, description="Labels to add", strict=True)
        milestone: Optional[int] = Field(None, description="Milestone number", strict=True)
        
        @field_validator('title')
        @classmethod
        def validate_title(cls, v):
            """Validate that title is not empty."""
            if not v.strip():
                raise ValueError("title cannot be empty")
            return v
  • Core operation function that performs the actual GitHub API call to create the issue using PyGithub.
    def create_issue(params: CreateIssueParams) -> Dict[str, Any]:
        """Create a new issue in a repository.
    
        Args:
            params: Validated parameters for creating an issue
    
        Returns:
            Created issue details from GitHub API
    
        Raises:
            GitHubError: If the API request fails
        """
        try:
            client = GitHubClient.get_instance()
            repository = client.get_repo(f"{params.owner}/{params.repo}")
    
            # Build kwargs for create_issue using fields from the Pydantic model
            kwargs = {"title": params.title}  # title is required
    
            # Add optional parameters only if provided
            if params.body is not None:
                kwargs["body"] = params.body
            if params.assignees:  # Only add if non-empty list
                kwargs["assignees"] = params.assignees
            if params.labels:  # Only add if non-empty list
                kwargs["labels"] = params.labels
            if params.milestone is not None:
                try:
                    kwargs["milestone"] = repository.get_milestone(params.milestone)
                except Exception as e:
                    logger.error(f"Failed to get milestone {params.milestone}: {e}")
                    raise GitHubError(f"Invalid milestone number: {params.milestone}")
    
            # Create issue using PyGithub
            issue = repository.create_issue(**kwargs)
    
            # Convert to our schema
            return convert_issue(issue)
    
        except GithubException as e:
            raise GitHubClient.get_instance()._handle_github_exception(e)
  • Registration function that registers the create_issue tool (and others) with the MCP server using register_tools.
    def register(mcp: FastMCP) -> None:
        """Register all issue tools with the MCP server.
        
        Args:
            mcp: The MCP server instance
        """
        from pygithub_mcp_server.tools import register_tools
        
        # List of all issue tools to register
        issue_tools = [
            create_issue,
            list_issues,
            get_issue,
            update_issue,
            add_issue_comment,
            list_issue_comments,
            update_issue_comment,
            delete_issue_comment,
            add_issue_labels,
            remove_issue_label,
        ]
        
        register_tools(mcp, issue_tools)
        logger.debug(f"Registered {len(issue_tools)} issue tools")

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/AstroMined/pygithub-mcp-server'

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