feat: implement MCP server core and authentication

Implemented MCP server core infrastructure with authentication and HTTP client:

- Created auth.py for API token management
  - Loads GITEA_API_URL and GITEA_API_TOKEN from environment
  - Uses python-dotenv for .env file support
  - Validates required configuration on initialization
  - Provides authentication headers for API requests

- Created client.py with base HTTP client
  - GiteaClient class using httpx AsyncClient
  - Async HTTP methods: get(), post(), patch(), delete()
  - Comprehensive error handling for HTTP status codes
  - Custom exception hierarchy for different error types
  - Configurable timeout (default 30s)

- Updated server.py with MCP server setup
  - Initialized MCP server with StdioServerTransport
  - Integrated AuthConfig and GiteaClient
  - Registered placeholder tool handlers (list_repositories, create_issue, create_pull_request)
  - Added CLI with --help and --version options
  - Proper error handling for configuration failures

- Updated pyproject.toml
  - Added console script entry point: gitea-mcp

- Created comprehensive unit tests
  - test_auth.py: Tests for AuthConfig validation and headers
  - test_client.py: Tests for GiteaClient initialization and error handling

All acceptance criteria met:
- MCP server initializes with StdioServerTransport
- Authentication loads from environment variables
- Base HTTP client with auth headers implemented
- Error handling for API connection failures
- Server reports available tools (placeholders for future issues)

Closes #2

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 15:05:25 -05:00
parent 95ed3d81cf
commit 1e0d896d87
6 changed files with 583 additions and 5 deletions

56
tests/test_auth.py Normal file
View File

@@ -0,0 +1,56 @@
"""Tests for authentication module."""
import os
import pytest
from gitea_mcp.auth import AuthConfig
def test_auth_config_success(monkeypatch):
"""Test successful authentication configuration."""
monkeypatch.setenv("GITEA_API_URL", "http://gitea.example.com/api/v1")
monkeypatch.setenv("GITEA_API_TOKEN", "test_token_123")
config = AuthConfig()
assert config.api_url == "http://gitea.example.com/api/v1"
assert config.api_token == "test_token_123"
def test_auth_config_removes_trailing_slash(monkeypatch):
"""Test that trailing slash is removed from URL."""
monkeypatch.setenv("GITEA_API_URL", "http://gitea.example.com/api/v1/")
monkeypatch.setenv("GITEA_API_TOKEN", "test_token_123")
config = AuthConfig()
assert config.api_url == "http://gitea.example.com/api/v1"
def test_auth_config_missing_url(monkeypatch):
"""Test error when GITEA_API_URL is missing."""
monkeypatch.delenv("GITEA_API_URL", raising=False)
monkeypatch.setenv("GITEA_API_TOKEN", "test_token_123")
with pytest.raises(ValueError, match="GITEA_API_URL"):
AuthConfig()
def test_auth_config_missing_token(monkeypatch):
"""Test error when GITEA_API_TOKEN is missing."""
monkeypatch.setenv("GITEA_API_URL", "http://gitea.example.com/api/v1")
monkeypatch.delenv("GITEA_API_TOKEN", raising=False)
with pytest.raises(ValueError, match="GITEA_API_TOKEN"):
AuthConfig()
def test_get_auth_headers(monkeypatch):
"""Test authentication headers generation."""
monkeypatch.setenv("GITEA_API_URL", "http://gitea.example.com/api/v1")
monkeypatch.setenv("GITEA_API_TOKEN", "test_token_123")
config = AuthConfig()
headers = config.get_auth_headers()
assert headers["Authorization"] == "token test_token_123"
assert headers["Content-Type"] == "application/json"