PyGithub MCP Server
by AstroMined
- src
- pygithub_mcp_server
- schemas
"""Repository-related schema models.
This module defines Pydantic models for GitHub repository operations
such as creating, searching, and managing repositories.
"""
from typing import List, Optional
from pydantic import BaseModel, Field, field_validator, ConfigDict
from .base import RepositoryRef, FileContent
class CreateOrUpdateFileParams(RepositoryRef):
"""Parameters for creating or updating a single file."""
model_config = ConfigDict(strict=True)
path: str = Field(..., description="Path where to create/update the file")
content: str = Field(..., description="Content of the file")
message: str = Field(..., description="Commit message")
branch: str = Field(..., description="Branch to create/update the file in")
sha: Optional[str] = Field(None, description="SHA of file being replaced (for updates)")
@field_validator('path')
@classmethod
def validate_path(cls, v):
"""Validate that path is not empty."""
if not v.strip():
raise ValueError("path cannot be empty")
return v
@field_validator('content')
@classmethod
def validate_content(cls, v):
"""Validate that content is not empty."""
if not v.strip():
raise ValueError("content cannot be empty")
return v
@field_validator('message')
@classmethod
def validate_message(cls, v):
"""Validate that message is not empty."""
if not v.strip():
raise ValueError("message cannot be empty")
return v
@field_validator('branch')
@classmethod
def validate_branch(cls, v):
"""Validate that branch is not empty."""
if not v.strip():
raise ValueError("branch cannot be empty")
return v
class PushFilesParams(RepositoryRef):
"""Parameters for pushing multiple files in a single commit."""
model_config = ConfigDict(strict=True)
branch: str = Field(..., description="Branch to push to")
files: List[FileContent] = Field(..., description="Files to push")
message: str = Field(..., description="Commit message")
@field_validator('branch')
@classmethod
def validate_branch(cls, v):
"""Validate that branch is not empty."""
if not v.strip():
raise ValueError("branch cannot be empty")
return v
@field_validator('files')
@classmethod
def validate_files(cls, v):
"""Validate that files list is not empty."""
if not v:
raise ValueError("files list cannot be empty")
return v
@field_validator('message')
@classmethod
def validate_message(cls, v):
"""Validate that message is not empty."""
if not v.strip():
raise ValueError("message cannot be empty")
return v
class SearchRepositoriesParams(BaseModel):
"""Parameters for searching repositories."""
model_config = ConfigDict(strict=True)
query: str = Field(..., description="Search query")
page: Optional[int] = Field(None, description="Page number for pagination")
per_page: Optional[int] = Field(
None, description="Number of results per page (default: 30, max: 100)"
)
@field_validator('query')
@classmethod
def validate_query(cls, v):
"""Validate that query is not empty."""
if not v.strip():
raise ValueError("query cannot be empty")
return v
@field_validator('page')
@classmethod
def validate_page(cls, v):
"""Validate that page is a positive integer."""
if v is not None and v < 1:
raise ValueError("page must be a positive integer")
return v
@field_validator('per_page')
@classmethod
def validate_per_page(cls, v):
"""Validate that per_page is within allowed range."""
if v is not None:
if v < 1:
raise ValueError("per_page must be a positive integer")
if v > 100:
raise ValueError("per_page cannot exceed 100")
return v
class CreateRepositoryParams(BaseModel):
"""Parameters for creating a new repository."""
model_config = ConfigDict(strict=True)
name: str = Field(..., description="Repository name")
description: Optional[str] = Field(None, description="Repository description")
private: Optional[bool] = Field(None, description="Whether repo should be private")
auto_init: Optional[bool] = Field(
None, description="Initialize repository with README"
)
@field_validator('name')
@classmethod
def validate_name(cls, v):
"""Validate that name is not empty."""
if not v.strip():
raise ValueError("name cannot be empty")
return v
class GetFileContentsParams(RepositoryRef):
"""Parameters for getting file contents."""
model_config = ConfigDict(strict=True)
path: str = Field(..., description="Path to file/directory")
branch: Optional[str] = Field(None, description="Branch to get contents from")
@field_validator('path')
@classmethod
def validate_path(cls, v):
"""Validate that path is not empty."""
if not v.strip():
raise ValueError("path cannot be empty")
return v
class ForkRepositoryParams(RepositoryRef):
"""Parameters for forking a repository."""
model_config = ConfigDict(strict=True)
organization: Optional[str] = Field(
None, description="Organization to fork to (defaults to user account)"
)
class CreateBranchParams(RepositoryRef):
"""Parameters for creating a branch."""
model_config = ConfigDict(strict=True)
branch: str = Field(..., description="Name for new branch")
from_branch: Optional[str] = Field(
None, description="Source branch (defaults to repo default)"
)
@field_validator('branch')
@classmethod
def validate_branch(cls, v):
"""Validate that branch is not empty."""
if not v.strip():
raise ValueError("branch cannot be empty")
return v
class ListCommitsParams(RepositoryRef):
"""Parameters for listing commits."""
model_config = ConfigDict(strict=True)
page: Optional[int] = Field(None, description="Page number")
per_page: Optional[int] = Field(None, description="Results per page")
sha: Optional[str] = Field(None, description="Branch name or commit SHA")
@field_validator('page')
@classmethod
def validate_page(cls, v):
"""Validate that page is a positive integer."""
if v is not None and v < 1:
raise ValueError("page must be a positive integer")
return v
@field_validator('per_page')
@classmethod
def validate_per_page(cls, v):
"""Validate that per_page is within allowed range."""
if v is not None:
if v < 1:
raise ValueError("per_page must be a positive integer")
if v > 100:
raise ValueError("per_page cannot exceed 100")
return v