Files
gitea-mcp-server/mcp/AGENTS.md
T

7.0 KiB

AGENTS.md

This file provides guidance to AI coding agents when working with code in this repository.

Development Commands

Build: make build - Build the gitea-mcp binary Install: make install - Build and install to GOPATH/bin Clean: make clean - Remove build artifacts Test: go test ./... - Run all tests Hot reload: make dev - Start development server with hot reload (requires air) Dependencies: make vendor - Tidy and verify module dependencies

Architecture Overview

This is a Gitea MCP (Model Context Protocol) Server written in Go that provides MCP tools for interacting with Gitea repositories, issues, pull requests, users, and more.

Core Components:

  • main.go + cmd/cmd.go: CLI entry point and flag parsing
  • operation/operation.go: Main server setup and tool registration
  • pkg/tool/tool.go: Tool registry with read/write categorization
  • operation/*/: Individual tool modules (user, repo, issue, pull, search, wiki, etc.)

Transport Modes:

  • stdio (default): Standard input/output for MCP clients
  • HTTP: HTTP server mode on configurable port (default 8080)

Authentication:

  • Global token via --token flag or GITEA_ACCESS_TOKEN env var
  • HTTP mode supports per-request Bearer token override in Authorization header
  • Token precedence: HTTP Authorization header > CLI flag > environment variable

Tool Organization:

  • Tools are categorized as read-only or write operations
  • --read-only flag exposes only read tools
  • Tool modules register via Tool.RegisterRead() and Tool.RegisterWrite()

Key Configuration:

  • Default Gitea host: https://gitea.com (override with --host or GITEA_HOST)
  • Environment variables can override CLI flags: MCP_MODE, GITEA_READONLY, GITEA_DEBUG, GITEA_INSECURE
  • Logs are written to ~/.gitea-mcp/gitea-mcp.log with rotation

Available Tools

The server provides 40+ MCP tools covering:

  • User: get_my_user_info, get_user_orgs, search_users
  • Repository: create_repo, fork_repo, list_my_repos, search_repos
  • Branches/Tags: create_branch, delete_branch, list_branches, create_tag, list_tags
  • Files: get_file_content, create_file, update_file, delete_file, get_dir_content
  • Issues: create_issue, list_repo_issues, create_issue_comment, edit_issue
  • Pull Requests: create_pull_request, list_repo_pull_requests, get_pull_request_by_index
  • Releases: create_release, list_releases, get_latest_release
  • Wiki: create_wiki_page, update_wiki_page, list_wiki_pages
  • Search: search_repos, search_users, search_org_teams
  • Version: get_gitea_mcp_server_version

Error Handling and Logging

The codebase provides comprehensive error handling and structured logging with context support.

Enhanced Error Handling

The pkg/errors package provides enhanced error handling with context and fluent API:

import "gitea.com/gitea/gitea-mcp/pkg/errors"

// Basic error translation
err := someGiteaOperation()
if err != nil {
    return errors.TranslateError(err, map[string]string{
        "operation": "GetFile",
        "owner":     owner,
        "repo":      repo,
        "path":      path,
    })
}

// Using fluent API for building error context
err := someGiteaOperation()
if err != nil {
    return errors.TranslateError(err, nil).
        WithOperation("GetFile").
        WithParam("owner", owner).
        WithParam("repo", repo).
        WithParam("path", path)
}

// Error includes automatic timestamp
enhanced := err.(*errors.EnhancedError)
fmt.Printf("Error occurred at: %v\n", enhanced.Timestamp)

// Format error for logging (human-readable)
fmt.Println(enhanced.Format())
// Output: Operation: GetFile | Error: File or directory not found | Category: file | Context: owner=gitea, path=README.md | Original: GetContents failed

// Format error for structured logging (JSON-like)
fmt.Println(enhanced.FormatDetailed())
// Output:
// {
//   "error": "File or directory not found",
//   "category": "file",
//   "operation": "GetFile",
//   "timestamp": "2024-01-15T10:30:00Z",
//   "context": {
//     "owner": "gitea",
//     "path": "README.md"
//   },
//   "original": "GetContents failed with status 404"
// }

Error Category Checking

// Check error categories
if errors.IsNotFound(err) {
    // Handle not found (404, "not found" messages)
}

if errors.IsAuthError(err) {
    // Handle auth errors (401, 403)
}

if errors.IsTimeout(err) {
    // Handle timeout errors
}

if errors.IsNetworkError(err) {
    // Handle network connectivity issues
}

// Check specific HTTP status codes
if errors.IsUnauthorized(err) {
    // Handle 401
}

if errors.IsForbidden(err) {
    // Handle 403
}

if errors.IsServerError(err) {
    // Handle 5xx errors
}

Structured Logging with Context

The pkg/log package provides request-scoped structured logging with correlation IDs:

import (
    "context"
    "gitea.com/gitea/gitea-mcp/pkg/log"
    "go.uber.org/zap"
)

// Create context with correlation ID for request tracing
ctx := log.WithCorrelationID(context.Background(), "req-12345")

// Add operation name to context
ctx = log.WithOperation(ctx, "GetFile")

// Create logger with context
logger := log.WithContext(ctx)

// Log messages - correlation_id and operation are automatically included
logger.Info("processing request")
logger.Error("operation failed", zap.Error(err))

// Log with additional fields
logger.Info("file retrieved",
    zap.String("owner", owner),
    zap.String("repo", repo),
    zap.String("path", path),
)

// Operation logging with timing
op := log.StartOperation(ctx, "CreatePullRequest")
op.Start("beginning pull request creation")
// ... do work ...
op.Success("pull request created successfully")
// Or on failure:
op.Failure("failed to create pull request", err)

REST API Logging

The pkg/gitea/rest.go automatically logs all API requests with context:

import (
    "context"
    "gitea.com/gitea/gitea-mcp/pkg/log"
    "gitea.com/gitea/gitea-mcp/pkg/gitea"
)

// Create context with operation name for tracing
ctx := log.WithOperation(context.Background(), "GetRepository")

// All API calls are automatically logged with:
// - operation name
// - HTTP method
// - request path (no sensitive data)
// - response status code
// - duration
// - correlation ID
status, err := gitea.DoJSON(ctx, "GET", fmt.Sprintf("repos/%s/%s", owner, repo), nil, nil, &repo)

// Logs will include:
// - Debug: "sending API request" with operation, method, path, correlation_id
// - Debug: "API request completed" with status_code and duration on success
// - Error: "API request returned error status" with details on failure

Common Development Patterns

Testing: Use go test ./operation -run TestFunctionName for specific tests

Token Context: HTTP requests use pkg/context.TokenContextKey for request-scoped token access

Flag Access: All packages access configuration via global variables in pkg/flag/flag.go

Graceful Shutdown: HTTP mode implements graceful shutdown with 10-second timeout on SIGTERM/SIGINT