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 52 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 55 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 51 tools remain accessible (26 git, 22 GitHub, 3 Azure DevOps).
**Tool Coverage**: All 54 tools remain accessible (26 git, 25 GitHub, 3 Azure DevOps).

**Usage Example**:
```python
Expand Down
24 changes: 24 additions & 0 deletions src/mcp_server_git/github/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,30 @@ class GitHubDisableVulnerabilityAlerts(BaseModel):
repo_name: str


class GitHubGetRequiredSignatures(BaseModel):
"""Model for checking if required signatures are enabled on a protected branch."""

repo_owner: str
repo_name: str
branch: str


class GitHubEnableRequiredSignatures(BaseModel):
"""Model for enabling required signatures on a protected branch."""

repo_owner: str
repo_name: str
branch: str


class GitHubDisableRequiredSignatures(BaseModel):
"""Model for disabling required signatures on a protected branch."""

repo_owner: str
repo_name: str
branch: str


class GitHubGetAutomatedSecurityFixes(BaseModel):
"""Model for checking if automated security fixes are enabled."""

Expand Down
119 changes: 119 additions & 0 deletions src/mcp_server_git/github/security.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""GitHub security operations - vulnerability alerts, security fixes, analysis."""

from __future__ import annotations
import logging
from mcp_server_git.github.client import github_client_context

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -115,6 +117,123 @@ async def github_disable_vulnerability_alerts(
return f"❌ Error disabling vulnerability alerts: {str(e)}"


async def github_get_required_signatures(
repo_owner: str,
repo_name: str,
branch: str,
) -> str:
"""Check if required signatures are enabled on a protected branch."""
logger.debug(
f"🔍 Getting required signatures status for {repo_owner}/{repo_name}#{branch}"
)

try:
async with github_client_context() as client:
response = await client.get(
f"/repos/{repo_owner}/{repo_name}/branches/{branch}/protection/required_signatures"
)

if response.status == 200:
data = await response.json()
enabled = data.get("enabled", False)
return f"{'✅' if enabled else '❌'} Required signatures: {'enabled' if enabled else 'disabled'} on {repo_owner}/{repo_name}#{branch}"
elif response.status == 404:
return f"❌ Branch protection or branch not found: {repo_owner}/{repo_name}#{branch}"
else:
error_text = await response.text()
return f"❌ Failed to check required signatures: {response.status} - {error_text}"

except ValueError as auth_error:
logger.error(f"Authentication error checking required signatures: {auth_error}")
return f"❌ {str(auth_error)}"
except ConnectionError as conn_error:
logger.error(f"Connection error checking required signatures: {conn_error}")
return f"❌ Network connection failed: {str(conn_error)}"
except Exception as e:
logger.error(
f"Unexpected error checking required signatures: {e}", exc_info=True
)
return f"❌ Error checking required signatures: {str(e)}"


async def github_enable_required_signatures(
repo_owner: str,
repo_name: str,
branch: str,
) -> str:
"""Enable required signatures on a protected branch."""
logger.debug(
f"🚀 Enabling required signatures for {repo_owner}/{repo_name}#{branch}"
)

try:
async with github_client_context() as client:
response = await client.put(
f"/repos/{repo_owner}/{repo_name}/branches/{branch}/protection/required_signatures"
)

if response.status == 200:
logger.info(
f"✅ Enabled required signatures for {repo_owner}/{repo_name}#{branch}"
)
return f"✅ Enabled required signatures on {repo_owner}/{repo_name}#{branch}"
else:
error_text = await response.text()
return f"❌ Failed to enable required signatures: {response.status} - {error_text}"

except ValueError as auth_error:
logger.error(f"Authentication error enabling required signatures: {auth_error}")
return f"❌ {str(auth_error)}"
except ConnectionError as conn_error:
logger.error(f"Connection error enabling required signatures: {conn_error}")
return f"❌ Network connection failed: {str(conn_error)}"
except Exception as e:
logger.error(
f"Unexpected error enabling required signatures: {e}", exc_info=True
)
return f"❌ Error enabling required signatures: {str(e)}"


async def github_disable_required_signatures(
repo_owner: str,
repo_name: str,
branch: str,
) -> str:
"""Disable required signatures on a protected branch."""
logger.debug(
f"🚀 Disabling required signatures for {repo_owner}/{repo_name}#{branch}"
)

try:
async with github_client_context() as client:
response = await client.delete(
f"/repos/{repo_owner}/{repo_name}/branches/{branch}/protection/required_signatures"
)

if response.status == 204:
logger.info(
f"✅ Disabled required signatures for {repo_owner}/{repo_name}#{branch}"
)
return f"✅ Disabled required signatures on {repo_owner}/{repo_name}#{branch}"
else:
error_text = await response.text()
return f"❌ Failed to disable required signatures: {response.status} - {error_text}"

except ValueError as auth_error:
logger.error(
f"Authentication error disabling required signatures: {auth_error}"
)
return f"❌ {str(auth_error)}"
except ConnectionError as conn_error:
logger.error(f"Connection error disabling required signatures: {conn_error}")
return f"❌ Network connection failed: {str(conn_error)}"
except Exception as e:
logger.error(
f"Unexpected error disabling required signatures: {e}", exc_info=True
)
return f"❌ Error disabling required signatures: {str(e)}"


async def github_get_automated_security_fixes(
repo_owner: str,
repo_name: str,
Expand Down
27 changes: 27 additions & 0 deletions src/mcp_server_git/lean/registry_github.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
GitHubDeleteRelease,
GitHubDeleteReleaseAsset,
GitHubDisableAutomatedSecurityFixes,
GitHubDisableRequiredSignatures,
GitHubDisableVulnerabilityAlerts,
GitHubEditPRDescription,
GitHubEnableAutomatedSecurityFixes,
GitHubEnableRequiredSignatures,
GitHubEnableVulnerabilityAlerts,
GitHubGetActionsPermissions,
GitHubGetAutomatedSecurityFixes,
Expand All @@ -29,6 +31,7 @@
GitHubGetPRFiles,
GitHubGetPRStatus,
GitHubGetRelease,
GitHubGetRequiredSignatures,
GitHubGetRepoSettings,
GitHubGetSecurityAnalysis,
GitHubGetVulnerabilityAlerts,
Expand Down Expand Up @@ -450,6 +453,30 @@ def _register_github_tools(interface: Any, github_service: Any):
domain="github",
complexity="focused",
),
ToolDefinition(
name="github_get_required_signatures",
implementation=github_ops.github_get_required_signatures,
description="Get required-signatures status for a protected branch",
schema=GitHubGetRequiredSignatures.model_json_schema(),
domain="github",
complexity="core",
),
ToolDefinition(
name="github_enable_required_signatures",
implementation=github_ops.github_enable_required_signatures,
description="Enable required signatures on a protected branch",
schema=GitHubEnableRequiredSignatures.model_json_schema(),
domain="github",
complexity="focused",
),
ToolDefinition(
name="github_disable_required_signatures",
implementation=github_ops.github_disable_required_signatures,
description="Disable required signatures on a protected branch",
schema=GitHubDisableRequiredSignatures.model_json_schema(),
domain="github",
complexity="focused",
),
ToolDefinition(
name="github_get_automated_security_fixes",
implementation=github_ops.github_get_automated_security_fixes,
Expand Down
Loading
Loading