"""MCP protocol models and tool registry.""" from __future__ import annotations from typing import Any from pydantic import BaseModel, ConfigDict, Field class MCPTool(BaseModel): """MCP tool definition.""" name: str = Field(..., description="Unique tool identifier") description: str = Field(..., description="Human-readable tool description") input_schema: dict[str, Any] = Field( ..., alias="inputSchema", serialization_alias="inputSchema", description="JSON schema describing input arguments", ) write_operation: bool = Field(default=False, description="Whether tool mutates data") model_config = ConfigDict(populate_by_name=True) class MCPToolCallRequest(BaseModel): """Request to invoke an MCP tool.""" tool: str = Field(..., description="Name of the tool to invoke") arguments: dict[str, Any] = Field(default_factory=dict, description="Tool argument payload") correlation_id: str | None = Field(default=None, description="Request correlation ID") model_config = ConfigDict(extra="forbid") class MCPToolCallResponse(BaseModel): """Response returned from MCP tool invocation.""" success: bool = Field(..., description="Whether invocation succeeded") result: Any | None = Field(default=None, description="Tool result payload") error: str | None = Field(default=None, description="Error message for failed request") correlation_id: str = Field(..., description="Correlation ID for request tracing") class MCPListToolsResponse(BaseModel): """Response listing available tools.""" tools: list[MCPTool] = Field(..., description="Available tool definitions") def _tool( name: str, description: str, schema: dict[str, Any], write_operation: bool = False ) -> MCPTool: """Construct tool metadata entry.""" return MCPTool( name=name, description=description, inputSchema=schema, write_operation=write_operation, ) AVAILABLE_TOOLS: list[MCPTool] = [ _tool( "list_repositories", "List repositories visible to the configured bot account.", {"type": "object", "properties": {}, "required": []}, ), _tool( "get_repository_info", "Get metadata for a repository.", { "type": "object", "properties": {"owner": {"type": "string"}, "repo": {"type": "string"}}, "required": ["owner", "repo"], "additionalProperties": False, }, ), _tool( "get_file_tree", "Get repository tree at a selected ref.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "ref": {"type": "string", "default": "main"}, "recursive": {"type": "boolean", "default": False}, }, "required": ["owner", "repo"], "additionalProperties": False, }, ), _tool( "get_file_contents", "Read a repository file with size-limited content.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "filepath": {"type": "string"}, "ref": {"type": "string", "default": "main"}, }, "required": ["owner", "repo", "filepath"], "additionalProperties": False, }, ), _tool( "search_code", "Search code in a repository.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "query": {"type": "string"}, "ref": {"type": "string", "default": "main"}, "page": {"type": "integer", "minimum": 1, "default": 1}, "limit": {"type": "integer", "minimum": 1, "maximum": 100, "default": 25}, }, "required": ["owner", "repo", "query"], "additionalProperties": False, }, ), _tool( "list_commits", "List commits for a repository ref.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "ref": {"type": "string", "default": "main"}, "page": {"type": "integer", "minimum": 1, "default": 1}, "limit": {"type": "integer", "minimum": 1, "maximum": 100, "default": 25}, }, "required": ["owner", "repo"], "additionalProperties": False, }, ), _tool( "get_commit_diff", "Get commit metadata and file diffs.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "sha": {"type": "string"}, }, "required": ["owner", "repo", "sha"], "additionalProperties": False, }, ), _tool( "compare_refs", "Compare two repository refs.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "base": {"type": "string"}, "head": {"type": "string"}, }, "required": ["owner", "repo", "base", "head"], "additionalProperties": False, }, ), _tool( "list_issues", "List repository issues.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "state": {"type": "string", "enum": ["open", "closed", "all"], "default": "open"}, "page": {"type": "integer", "minimum": 1, "default": 1}, "limit": {"type": "integer", "minimum": 1, "maximum": 100, "default": 25}, "labels": {"type": "array", "items": {"type": "string"}, "default": []}, }, "required": ["owner", "repo"], "additionalProperties": False, }, ), _tool( "get_issue", "Get repository issue details.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "issue_number": {"type": "integer", "minimum": 1}, }, "required": ["owner", "repo", "issue_number"], "additionalProperties": False, }, ), _tool( "list_pull_requests", "List repository pull requests.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "state": {"type": "string", "enum": ["open", "closed", "all"], "default": "open"}, "page": {"type": "integer", "minimum": 1, "default": 1}, "limit": {"type": "integer", "minimum": 1, "maximum": 100, "default": 25}, }, "required": ["owner", "repo"], "additionalProperties": False, }, ), _tool( "get_pull_request", "Get pull request details.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "pull_number": {"type": "integer", "minimum": 1}, }, "required": ["owner", "repo", "pull_number"], "additionalProperties": False, }, ), _tool( "list_labels", "List labels defined on a repository.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "page": {"type": "integer", "minimum": 1, "default": 1}, "limit": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}, }, "required": ["owner", "repo"], "additionalProperties": False, }, ), _tool( "list_tags", "List repository tags.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "page": {"type": "integer", "minimum": 1, "default": 1}, "limit": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}, }, "required": ["owner", "repo"], "additionalProperties": False, }, ), _tool( "list_releases", "List repository releases.", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "page": {"type": "integer", "minimum": 1, "default": 1}, "limit": {"type": "integer", "minimum": 1, "maximum": 100, "default": 25}, }, "required": ["owner", "repo"], "additionalProperties": False, }, ), _tool( "create_issue", "Create a repository issue (write-mode only).", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "title": {"type": "string"}, "body": {"type": "string", "default": ""}, "labels": {"type": "array", "items": {"type": "string"}, "default": []}, "assignees": {"type": "array", "items": {"type": "string"}, "default": []}, }, "required": ["owner", "repo", "title"], "additionalProperties": False, }, write_operation=True, ), _tool( "update_issue", "Update issue title/body/state (write-mode only).", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "issue_number": {"type": "integer", "minimum": 1}, "title": {"type": "string"}, "body": {"type": "string"}, "state": {"type": "string", "enum": ["open", "closed"]}, }, "required": ["owner", "repo", "issue_number"], "additionalProperties": False, }, write_operation=True, ), _tool( "create_issue_comment", "Create issue comment (write-mode only).", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "issue_number": {"type": "integer", "minimum": 1}, "body": {"type": "string"}, }, "required": ["owner", "repo", "issue_number", "body"], "additionalProperties": False, }, write_operation=True, ), _tool( "create_pr_comment", "Create pull request comment (write-mode only).", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "pull_number": {"type": "integer", "minimum": 1}, "body": {"type": "string"}, }, "required": ["owner", "repo", "pull_number", "body"], "additionalProperties": False, }, write_operation=True, ), _tool( "add_labels", "Add labels to an issue or PR (write-mode only).", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "issue_number": {"type": "integer", "minimum": 1}, "labels": {"type": "array", "items": {"type": "string"}, "minItems": 1}, }, "required": ["owner", "repo", "issue_number", "labels"], "additionalProperties": False, }, write_operation=True, ), _tool( "assign_issue", "Assign users to issue or PR (write-mode only).", { "type": "object", "properties": { "owner": {"type": "string"}, "repo": {"type": "string"}, "issue_number": {"type": "integer", "minimum": 1}, "assignees": {"type": "array", "items": {"type": "string"}, "minItems": 1}, }, "required": ["owner", "repo", "issue_number", "assignees"], "additionalProperties": False, }, write_operation=True, ), ] def get_tool_by_name(tool_name: str) -> MCPTool | None: """Get tool definition by name.""" for tool in AVAILABLE_TOOLS: if tool.name == tool_name: return tool return None