Skip to main content
Glama
README.md
# Gitea MCP Server

A production-ready Model Context Protocol (MCP) server for seamless integration with self-hosted Gitea platforms. This server provides tools for creating repositories and uploading files while preserving directory structure.

## Installation and Setup Guide

This guide provides step-by-step instructions for installing and configuring the Gitea MCP server, including troubleshooting common issues.

## Features

- **Repository Creation**: Create new repositories on any configured Gitea instance
- **File Upload**: Upload files and folders while preserving directory structure
- **Project Sync**: Automatically sync entire projects for initial commits (new files only)
- **Advanced File Updates**: Smart update tool with conflict resolution for modifying existing files
- **Multi-Instance Support**: Connect to multiple Gitea instances simultaneously
- **Rate Limiting**: Respect API rate limits per instance
- **Batch Processing**: Efficient file upload with configurable batch sizes
- **Comprehensive Logging**: Structured logging with security-safe output
- **Error Handling**: Robust error handling with retry logic
- **TypeScript**: Full type safety and modern JavaScript features

## Quick Start

### Prerequisites

- Node.js 18.0.0 or higher
- Access to one or more Gitea instances
- Personal access tokens for authentication

### Installation

1. Clone the repository:
```bash
git clone <repository-url>
cd gitea-mcp
```

2. Install dependencies:
```bash
npm install
```

3. Configure environment variables:
```bash
cp .env.example .env
# Edit .env with your Gitea instance details
```

4. Build the project:
```bash
npm run build
```

5. Start the server:
```bash
npm run start:mcp
```

### Troubleshooting Common Issues

#### Windows Compatibility

If you're running on Windows, you might encounter issues with the build script. The default build script uses the `chmod` command, which is not available on Windows. The package.json has been updated to use a Windows-compatible build script.

#### Logging Configuration

If you encounter issues with the logging configuration, make sure you have the `pino-pretty` package installed:

```bash
npm install --save-dev pino-pretty
```

#### Environment Variables

The `.env` file should contain the following configuration:

```
# Server Configuration
NODE_ENV=development
LOG_LEVEL=debug

# Gitea Configuration
# Replace with your Gitea instance URL and token
GITEA_INSTANCES=[{"id":"main","name":"Main Gitea Instance","baseUrl":"https://your-gitea-instance.com","token":"your-personal-access-token","timeout":30000,"rateLimit":{"requests":100,"windowMs":60000}}]

# Upload Configuration
MAX_FILE_SIZE=10485760
MAX_FILES=100
BATCH_SIZE=10

# Gitea API Configuration
GITEA_TIMEOUT=30000
GITEA_MAX_RETRIES=3
```

Make sure to replace `"https://your-gitea-instance.com"` with your actual Gitea instance URL and `"your-personal-access-token"` with your Gitea personal access token.

#### Running with Debug Logging

To run the server with debug logging enabled, use the `start:mcp` script:

```bash
npm run start:mcp
```

This script sets the `NODE_ENV` to `development` and `LOG_LEVEL` to `debug` before starting the server.

### Development Setup

For development with hot reloading:

```bash
npm run dev
```

## Configuration

### Environment Variables

Create a `.env` file based on `.env.example`:

```bash
# Server Configuration
NODE_ENV=development
LOG_LEVEL=info

# Gitea Configuration
GITEA_INSTANCES='[
  {
    "id": "main",
    "name": "Main Gitea Instance", 
    "baseUrl": "https://gitea.example.com",
    "token": "your-personal-access-token",
    "timeout": 30000,
    "rateLimit": {
      "requests": 100,
      "windowMs": 60000
    }
  }
]'

# Upload Configuration
MAX_FILE_SIZE=10485760  # 10MB
MAX_FILES=100
BATCH_SIZE=10

# API Configuration
GITEA_TIMEOUT=30000
GITEA_MAX_RETRIES=3
```

### Gitea Instance Configuration

Each Gitea instance requires:

- **id**: Unique identifier for the instance
- **name**: Human-readable name for logging
- **baseUrl**: Base URL of your Gitea instance
- **token**: Personal access token with appropriate permissions
- **timeout**: Request timeout in milliseconds (optional)
- **rateLimit**: Rate limiting configuration (optional)

### Personal Access Token Setup

1. Log into your Gitea instance
2. Go to Settings → Applications → Personal Access Tokens
3. Create a new token with these permissions:
   - `repo`: Full repository access
   - `write:repository`: Create repositories
   - `read:user`: Read user information

## MCP Client Configuration

### Claude Desktop

Add to your Claude Desktop configuration:

```json
{
  "mcpServers": {
    "gitea-mcp": {
      "command": "node",
      "args": ["./build/index.js"],
      "cwd": "/path/to/gitea-mcp",
      "env": {
        "NODE_ENV": "production",
        "LOG_LEVEL": "info"
      }
    }
  }
}
```

### Other MCP Clients

The server communicates via stdio and follows the MCP protocol specification. Refer to your client's documentation for configuration details.

## Available Tools

### create_repository

Create a new repository on a specified Gitea instance.

**Parameters:**
- `instanceId` (string, required): Gitea instance identifier
- `name` (string, required): Repository name
- `description` (string, optional): Repository description  
- `private` (boolean, default: true): Make repository private
- `autoInit` (boolean, default: true): Initialize with README
- `defaultBranch` (string, default: "main"): Default branch name

**Example:**
```json
{
  "instanceId": "main",
  "name": "my-new-repo",
  "description": "A test repository",
  "private": true,
  "autoInit": true,
  "defaultBranch": "main"
}
```

### upload_files

Upload multiple files to a repository while preserving directory structure.

**Parameters:**
- `instanceId` (string, required): Gitea instance identifier
- `owner` (string, required): Repository owner username
- `repository` (string, required): Repository name
- `files` (array, required): Array of file objects with `path` and `content`
- `message` (string, required): Commit message
- `branch` (string, default: "main"): Target branch
- `batchSize` (number, default: 10): Files per batch

**Example:**
```json
{
  "instanceId": "main",
  "owner": "username",
  "repository": "my-repo",
  "files": [
    {
      "path": "README.md",
      "content": "# My Project\n\nProject description here."
    },
    {
      "path": "src/index.js", 
      "content": "console.log('Hello, World!');"
    }
  ],
  "message": "Initial commit",
  "branch": "main",
  "batchSize": 5
}
```

### sync_project ⚠️ Initial Commits Only

Automatically discover and sync an entire project directory to a Gitea repository while respecting `.gitignore` rules.

> **Important**: This tool is designed for initial project uploads and can only create new files. It cannot update files that already exist in the repository. For updating existing files, use the `sync_update` tool instead.

**Parameters:**
- `instanceId` (string, required): Gitea instance identifier
- `owner` (string, required): Repository owner username
- `repository` (string, required): Repository name
- `message` (string, required): Commit message for the sync
- `branch` (string, default: "main"): Target branch
- `projectPath` (string, default: "."): Path to project directory to sync
- `dryRun` (boolean, default: false): Preview what would be uploaded without actually uploading
- `includeHidden` (boolean, default: false): Include hidden files (starting with .)
- `maxFileSize` (number, default: 1048576): Maximum file size in bytes (1MB)
- `textOnly` (boolean, default: true): Only upload text files (skip binary files)

**Features:**
- Automatically reads and applies `.gitignore` rules
- Includes sensible defaults for common ignore patterns (node_modules/, .git/, etc.)
- Recursively scans project directory for eligible files
- Simple heuristic to detect and optionally skip binary files
- Size filtering for large files
- Dry run mode for previewing changes
- Detailed reporting of discovered, filtered, uploaded, and failed files

**Use Cases:**
- Initial project setup and first commit
- Uploading new projects to empty repositories
- Bulk upload of files to new repositories

**Example:**
```json
{
  "instanceId": "main",
  "owner": "username",
  "repository": "my-project",
  "message": "Initial project sync",
  "branch": "main",
  "projectPath": "./my-app",
  "dryRun": false,
  "includeHidden": false,
  "maxFileSize": 2097152,
  "textOnly": true
}
```

### sync_update ✨ Advanced File Updates

Advanced tool for updating existing files in Gitea repository with intelligent conflict resolution and change detection.

**Parameters:**
- `instanceId` (string, required): Gitea instance identifier
- `owner` (string, required): Repository owner username
- `repository` (string, required): Repository name
- `files` (array, required): Array of file operation objects
- `files[].path` (string, required): File path in repository (forward slashes)
- `files[].content` (string, conditional): File content (required for add/modify operations)
- `files[].operation` (string, required): Operation type: 'add', 'modify', or 'delete'
- `files[].sha` (string, optional): Current file SHA (auto-detected if not provided)
- `message` (string, required): Commit message for all operations
- `branch` (string, default: "main"): Target branch
- `strategy` (string, default: "auto"): Update strategy: 'auto', 'batch', or 'individual'
- `conflictResolution` (string, default: "fail"): Conflict handling: 'fail', 'overwrite', or 'skip'
- `detectChanges` (boolean, default: true): Compare with remote files to avoid unnecessary updates
- `dryRun` (boolean, default: false): Preview operations without making changes

**Key Features:**
- **Smart API Usage**: Uses PUT for updates, POST for creates, DELETE for removals
- **Change Detection**: Compares local vs remote content to skip unnecessary updates
- **Auto SHA Resolution**: Automatically fetches required SHA values for update operations
- **Multiple Strategies**: Auto, batch (single commit), or individual (separate commits)
- **Conflict Resolution**: Handles cases where remote files have changed since last sync
- **Mixed Operations**: Can handle create, update, and delete operations in a single call
- **Dry Run Mode**: Preview what operations would be performed without making changes

**Operation Types:**
- `add`: Create new files (equivalent to POST API)
- `modify`: Update existing files (uses PUT API with SHA for conflict resolution)
- `delete`: Remove existing files (uses DELETE API with SHA)

**Strategy Options:**
- `auto`: Intelligently chooses the best approach based on file count and operation types
- `batch`: Performs all operations in a single commit using Gitea's batch API
- `individual`: Performs each operation as a separate commit

**Use Cases:**
- Updating existing project files
- Selective file modifications
- Bulk file operations (create, update, delete)
- Incremental project updates
- Automated file maintenance

**Example:**
```json
{
  "instanceId": "main",
  "owner": "username",
  "repository": "my-project",
  "files": [
    {
      "path": "README.md",
      "content": "# Updated Project\n\nThis is an updated version of the project.",
      "operation": "modify"
    },
    {
      "path": "src/new-feature.js",
      "content": "// New feature implementation\nfunction newFeature() {\n  return 'Hello, World!';\n}",
      "operation": "add"
    },
    {
      "path": "old-file.txt",
      "operation": "delete"
    }
  ],
  "message": "Update documentation and add new feature",
  "branch": "main",
  "strategy": "auto",
  "detectChanges": true,
  "dryRun": false
}
```

**Dry Run Example Response:**
```json
{
  "dryRun": true,
  "strategy": "individual",
  "summary": {
    "discovered": 3,
    "analyzed": 3,
    "needsUpdate": 2,
    "processed": 0,
    "succeeded": 0,
    "failed": 0,
    "skipped": 0
  },
  "filesNeedingUpdate": [
    {
      "path": "README.md",
      "operation": "modify",
      "hasRemoteSha": true
    },
    {
      "path": "src/new-feature.js",
      "operation": "add",
      "hasRemoteSha": false
    }
  ]
}
```

## Tool Selection Guide

**When to use each tool:**

1. **`create_repository`**: Create new repositories
2. **`sync_project`**: Initial project upload to empty/new repositories
3. **`upload_files`**: Upload specific files with full control over the process
4. **`sync_update`**: Update existing files, create new files, or delete files in existing repositories

**Workflow Example:**
```bash
# 1. Create a new repository
create_repository → "my-new-project"

# 2. Initial upload of all project files
sync_project → Upload entire project structure

# 3. Later updates to specific files
sync_update → Modify README.md, add new features, delete old files
```

## Development

### Scripts

- `npm run build` - Build for production
- `npm run dev` - Development with hot reloading
- `npm start` - Start production server
- `npm test` - Run tests
- `npm run lint` - Lint code
- `npm run format` - Format code
- `npm run type-check` - TypeScript type checking

### Project Structure

```
gitea-mcp/
├── src/
│   ├── index.ts              # Main server entry point
│   ├── config/               # Configuration management
│   ├── gitea/                # Gitea API client
│   ├── tools/                # MCP tool implementations
│   ├── services/             # Business logic services
│   ├── utils/                # Utilities (logging, errors, etc.)
│   └── types/                # TypeScript type definitions
├── build/                    # Compiled JavaScript
├── docs/                     # Documentation
└── package.json
```

### Adding New Tools

1. Create tool implementation in `src/tools/`
2. Add schema validation in `src/tools/schemas.ts`
3. Register tool in `src/tools/index.ts`
4. Add tests in `tests/unit/tools/`

## Deployment

### Docker

Build and run with Docker:

```bash
# Build image
docker build -t gitea-mcp .

# Run container
docker run -d \
  --name gitea-mcp \
  --env-file .env \
  gitea-mcp
```

### Production Considerations

- Use environment variables or secrets management for tokens
- Configure appropriate log levels
- Set up monitoring and health checks
- Use process managers like PM2 for Node.js applications
- Consider using Docker or Kubernetes for orchestration

## Security

### Best Practices

- Store tokens securely using environment variables or secrets management
- Use minimal required permissions for access tokens
- Validate all input parameters
- Log security events without exposing sensitive data
- Use HTTPS for all Gitea API communications
- Regularly rotate access tokens

### Rate Limiting

The server implements rate limiting per Gitea instance to respect API limits:

- Default: 100 requests per minute per instance
- Configurable via `rateLimit` in instance configuration
- Automatic retry with exponential backoff

## Troubleshooting

### Common Issues

**Authentication Failed**
- Verify access token is correct and has required permissions
- Check token hasn't expired
- Ensure base URL is correct

**Rate Limited**
- Reduce batch size for file uploads
- Adjust rate limit configuration
- Wait before retrying requests

**File Upload Failures**
- Check file content is valid
- Verify file paths don't contain illegal characters
- Ensure repository exists and you have write permissions

### Logging

Enable debug logging for troubleshooting:

```bash
LOG_LEVEL=debug npm start
```

### Health Checks

Check server status:

```bash
curl -f http://localhost:8080/health || exit 1
```

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make changes with tests
4. Run linting and type checking
5. Submit a pull request

## License

MIT License - see LICENSE file for details.

## Support

- GitHub Issues: Report bugs and feature requests
- Documentation: Check docs/ directory
- Examples: See examples/ directory

---

Built with ❤️ for the Gitea and MCP communities.

## See Also

- [TranscriptionTools-MCP](https://github.com/MushroomFleet/TranscriptionTools-MCP) — Transcript processing
- [DeepLucid3D-MCP](https://github.com/MushroomFleet/DeepLucid3D-MCP) — Cognitive processing
- [UNO-MCP](https://github.com/MushroomFleet/UNO-MCP) — Narrative enhancement
- [gitea-mcp](https://github.com/MushroomFleet/gitea-mcp) — Gitea integration
- [zero-vector-MCP](https://github.com/MushroomFleet/zero-vector-MCP) — Procedural generation