Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,15 @@ The server provides Azure DevOps integration for monitoring and analyzing Azure

### Lean MCP Interface (Context-Optimized)

The server provides an alternative **lean interface** that reduces context consumption by ~97% (from ~30k tokens to ~900 tokens). Instead of exposing all 56 tools upfront, it uses a 3-meta-tool pattern:
The server provides an alternative **lean interface** that reduces context consumption by ~97% (from ~30k tokens to ~900 tokens). Instead of exposing all 63 tools upfront, it uses a 3-meta-tool pattern:

| Meta-Tool | Purpose |
|-----------|---------|
| `discover_tools(pattern)` | List available tools with optional filtering |
| `get_tool_spec(tool_name)` | Get full schema for a specific tool on-demand |
| `execute_tool(tool_name, params)` | Execute any tool dynamically |

**Tool Coverage**: All 55 tools remain accessible (27 git, 25 GitHub, 3 Azure DevOps).
**Tool Coverage**: All 62 tools remain accessible (27 git, 32 GitHub, 3 Azure DevOps).

**Usage Example**:
```python
Expand Down
1 change: 1 addition & 0 deletions src/mcp_server_git/github/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .release_assets import * # noqa: F401,F403
from .releases import * # noqa: F401,F403
from .repos import * # noqa: F401,F403
from .scanning import * # noqa: F401,F403
from .security import * # noqa: F401,F403
from .workflows import * # noqa: F401,F403

Expand Down
83 changes: 82 additions & 1 deletion src/mcp_server_git/github/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import re

from pydantic import BaseModel, field_validator, model_validator
from typing import Literal

from pydantic import BaseModel, Field, field_validator, model_validator

# ============================================================================
# Validation Constants
Expand Down Expand Up @@ -980,3 +982,82 @@ def validate_org_name(cls, v: str | None) -> str | None:
"can only contain alphanumeric characters and hyphens"
)
return v


# ============================================================================
# GHAS Forensics Models (Issue #186)
# ============================================================================


class GitHubListRulesets(BaseModel):
"""Model for listing rulesets defined on a repository."""

repo_owner: str
repo_name: str
per_page: int | None = Field(default=None, ge=1, le=100, description="Results per page (max 100)")
page: int | None = Field(default=None, ge=1, description="Page number")


class GitHubGetRuleset(BaseModel):
"""Model for fetching a specific ruleset by ID.

Returns full ruleset config including required_status_checks,
code_scanning rules, and bypass actors.
"""

repo_owner: str
repo_name: str
ruleset_id: int # Numeric ruleset ID (from github_list_rulesets)


class GitHubGetBranchRules(BaseModel):
"""Model for listing all rules that apply to a branch.

Returns both classic branch-protection rules and ruleset-based rules
active for the given branch ref.
"""

repo_owner: str
repo_name: str
branch: str # Branch name (e.g. 'main') or pattern


class GitHubListCodeScanningAlerts(BaseModel):
"""Model for listing code scanning alerts with optional filters."""

repo_owner: str
repo_name: str
state: Literal["open", "closed", "dismissed", "fixed"] | None = None
severity: Literal["critical", "high", "medium", "low", "warning", "note", "error"] | None = None
tool_name: str | None = None # Code-scanning tool (e.g. 'CodeQL') — free-form
ref: str | None = None # Branch name or refs/pull/N/head
per_page: int | None = Field(default=None, ge=1, le=100, description="Results per page (max 100)")
page: int | None = Field(default=None, ge=1, description="Page number")


class GitHubListCodeScanningAnalyses(BaseModel):
"""Model for listing code scanning analyses for a repository."""

repo_owner: str
repo_name: str
ref: str | None = None # Branch name or refs/pull/N/head
tool_name: str | None = None # Code-scanning tool (e.g. 'CodeQL')
per_page: int | None = Field(default=None, ge=1, le=100, description="Results per page (max 100)")
page: int | None = Field(default=None, ge=1, description="Page number")


class GitHubGetCodeScanningDefaultSetup(BaseModel):
"""Model for fetching the default-setup configuration for code scanning."""

repo_owner: str
repo_name: str


class GitHubListSecretScanningAlerts(BaseModel):
"""Model for listing secret scanning alerts for a repository."""

repo_owner: str
repo_name: str
state: Literal["open", "resolved"] | None = None
per_page: int | None = Field(default=None, ge=1, le=100, description="Results per page (max 100)")
page: int | None = Field(default=None, ge=1, description="Page number")
Loading
Loading