Files
gitea-mcp-remote/src/gitea_mcp/server.py
lmiranda 694406941c feat(tools): implement issue operations - Closes #3
Implement Gitea issue operations tools with the following features:
- gitea_list_issues: List issues with filters (state, labels, milestone)
- gitea_get_issue: Get single issue by number
- gitea_create_issue: Create new issue with title, body, labels, milestone
- gitea_update_issue: Update issue state, title, body, labels, assignees

Files added:
- src/gitea_mcp/tools/issues.py: Issue operation tool handlers

Files modified:
- src/gitea_mcp/server.py: Register issue tools in MCP server
- src/gitea_mcp/tools/__init__.py: Export issue tool functions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 15:17:40 -05:00

153 lines
4.3 KiB
Python

"""MCP server implementation for Gitea API integration."""
import asyncio
import argparse
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
from . import __version__
from .auth import AuthConfig
from .client import GiteaClient, GiteaClientError
from .tools import get_issue_tools, handle_issue_tool
# Global client instance
gitea_client: GiteaClient | None = None
async def serve() -> None:
"""Run the MCP server."""
server = Server("gitea-mcp")
# Initialize authentication config
try:
config = AuthConfig()
except ValueError as e:
print(f"Configuration error: {e}")
raise
# Initialize Gitea client
global gitea_client
gitea_client = GiteaClient(config)
@server.list_tools()
async def list_tools() -> list[Tool]:
"""List available MCP tools.
Returns:
list: Available tools including issue operations.
"""
# Get issue tools
tools = get_issue_tools()
# Placeholder for future tools (PR tools, etc.)
tools.extend([
Tool(
name="list_repositories",
description="List repositories in an organization (coming soon)",
inputSchema={
"type": "object",
"properties": {
"org": {
"type": "string",
"description": "Organization name",
}
},
"required": ["org"],
},
),
Tool(
name="create_pull_request",
description="Create a new pull request (coming soon)",
inputSchema={
"type": "object",
"properties": {
"owner": {
"type": "string",
"description": "Repository owner",
},
"repo": {
"type": "string",
"description": "Repository name",
},
"title": {
"type": "string",
"description": "Pull request title",
},
"head": {
"type": "string",
"description": "Source branch",
},
"base": {
"type": "string",
"description": "Target branch",
},
},
"required": ["owner", "repo", "title", "head", "base"],
},
),
])
return tools
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
"""Handle tool calls.
Args:
name: Tool name.
arguments: Tool arguments.
Returns:
list: Tool response.
"""
# Handle issue tools
if name.startswith("gitea_") and any(
name.endswith(suffix) for suffix in ["_issues", "_issue"]
):
return await handle_issue_tool(name, arguments, gitea_client)
# Placeholder for other tools
return [
TextContent(
type="text",
text=f"Tool '{name}' is not yet implemented.",
)
]
# Run the server using stdio transport
async with stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options(),
)
def main() -> None:
"""Main entry point with CLI argument parsing."""
parser = argparse.ArgumentParser(
description="Gitea MCP Server - MCP server for Gitea API integration"
)
parser.add_argument(
"--version",
action="version",
version=f"gitea-mcp {__version__}",
)
args = parser.parse_args()
# Run the server
try:
asyncio.run(serve())
except KeyboardInterrupt:
print("\nServer stopped by user")
except Exception as e:
print(f"Server error: {e}")
raise
if __name__ == "__main__":
main()