feat: harden gateway with policy engine, secure tools, and governance docs
This commit is contained in:
@@ -1,255 +1,61 @@
|
||||
# API Reference
|
||||
|
||||
## HTTP Endpoints
|
||||
|
||||
### `GET /`
|
||||
|
||||
Returns basic server information. No authentication required.
|
||||
|
||||
**Response**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "AegisGitea MCP",
|
||||
"version": "0.1.0",
|
||||
"status": "running"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `GET /health`
|
||||
|
||||
Health check endpoint. No authentication required.
|
||||
|
||||
**Response**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"gitea_connected": true
|
||||
}
|
||||
```
|
||||
|
||||
Returns HTTP 200 when healthy. Returns HTTP 503 when Gitea is unreachable.
|
||||
|
||||
---
|
||||
|
||||
### `GET /mcp/tools`
|
||||
|
||||
Returns the list of available MCP tools. No authentication required (needed for ChatGPT tool discovery).
|
||||
|
||||
**Response**
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": [
|
||||
{
|
||||
"name": "list_repositories",
|
||||
"description": "...",
|
||||
"inputSchema": { ... }
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /mcp/tool/call`
|
||||
|
||||
Executes an MCP tool. **Authentication required.**
|
||||
|
||||
**Request headers**
|
||||
|
||||
```
|
||||
Authorization: Bearer <api-key>
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Request body**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "<tool-name>",
|
||||
"arguments": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
**Response**
|
||||
|
||||
```json
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "..."
|
||||
}
|
||||
],
|
||||
"isError": false
|
||||
}
|
||||
```
|
||||
|
||||
On error, `isError` is `true` and `text` contains the error message.
|
||||
|
||||
---
|
||||
|
||||
### `GET /mcp/sse`
|
||||
|
||||
Server-Sent Events stream endpoint. Authentication required. Used for streaming MCP sessions.
|
||||
|
||||
---
|
||||
|
||||
### `POST /mcp/sse`
|
||||
|
||||
Sends a client message over an active SSE session. Authentication required.
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
All authenticated endpoints require a bearer token:
|
||||
|
||||
```
|
||||
Authorization: Bearer <api-key>
|
||||
```
|
||||
|
||||
Alternatively, the key can be passed as a query parameter (useful for tools that do not support custom headers):
|
||||
|
||||
```
|
||||
GET /mcp/tool/call?api_key=<api-key>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MCP Tools
|
||||
|
||||
### `list_repositories`
|
||||
|
||||
Lists all Gitea repositories accessible to the bot user.
|
||||
|
||||
**Arguments:** none
|
||||
|
||||
**Example response text**
|
||||
|
||||
```
|
||||
Found 3 repositories:
|
||||
|
||||
1. myorg/backend - Backend API service [Python] ★ 42
|
||||
2. myorg/frontend - React frontend [TypeScript] ★ 18
|
||||
3. myorg/infra - Infrastructure as code [HCL] ★ 5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `get_repository_info`
|
||||
|
||||
Returns metadata for a single repository.
|
||||
|
||||
**Arguments**
|
||||
|
||||
| Name | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `owner` | string | Yes | Repository owner (user or organisation) |
|
||||
| `repo` | string | Yes | Repository name |
|
||||
|
||||
**Example response text**
|
||||
|
||||
```
|
||||
Repository: myorg/backend
|
||||
Description: Backend API service
|
||||
Language: Python
|
||||
Stars: 42
|
||||
Forks: 3
|
||||
Default branch: main
|
||||
Private: false
|
||||
URL: https://gitea.example.com/myorg/backend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `get_file_tree`
|
||||
|
||||
Returns the file and directory structure of a repository.
|
||||
|
||||
**Arguments**
|
||||
|
||||
| Name | Type | Required | Default | Description |
|
||||
|---|---|---|---|---|
|
||||
| `owner` | string | Yes | — | Repository owner |
|
||||
| `repo` | string | Yes | — | Repository name |
|
||||
| `ref` | string | No | default branch | Branch, tag, or commit SHA |
|
||||
| `recursive` | boolean | No | `false` | Recursively list all subdirectories |
|
||||
|
||||
> **Note:** Recursive mode is disabled by default to limit response size. Enable with care on large repositories.
|
||||
|
||||
**Example response text**
|
||||
|
||||
```
|
||||
File tree for myorg/backend (ref: main):
|
||||
|
||||
src/
|
||||
src/main.py
|
||||
src/config.py
|
||||
tests/
|
||||
tests/test_main.py
|
||||
README.md
|
||||
requirements.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `get_file_contents`
|
||||
|
||||
Returns the contents of a single file.
|
||||
|
||||
**Arguments**
|
||||
|
||||
| Name | Type | Required | Default | Description |
|
||||
|---|---|---|---|---|
|
||||
| `owner` | string | Yes | — | Repository owner |
|
||||
| `repo` | string | Yes | — | Repository name |
|
||||
| `filepath` | string | Yes | — | Path to the file within the repository |
|
||||
| `ref` | string | No | default branch | Branch, tag, or commit SHA |
|
||||
|
||||
**Limits**
|
||||
|
||||
- Files larger than `MAX_FILE_SIZE_BYTES` (default 1 MB) are rejected.
|
||||
- Binary files that cannot be decoded as UTF-8 are returned as raw base64.
|
||||
|
||||
**Example response text**
|
||||
|
||||
```
|
||||
Contents of myorg/backend/src/main.py (ref: main):
|
||||
|
||||
import fastapi
|
||||
...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Error Responses
|
||||
|
||||
All errors follow this structure:
|
||||
|
||||
```json
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "Error: <description>"
|
||||
}
|
||||
],
|
||||
"isError": true
|
||||
}
|
||||
```
|
||||
|
||||
Common error scenarios:
|
||||
|
||||
| Scenario | HTTP Status | `isError` |
|
||||
|---|---|---|
|
||||
| Missing or invalid API key | 401 | — (rejected before tool runs) |
|
||||
| Rate limited IP address | 429 | — |
|
||||
| Tool not found | 404 | — |
|
||||
| Repository not found in Gitea | 200 | `true` |
|
||||
| File too large | 200 | `true` |
|
||||
| Gitea API unavailable | 200 | `true` |
|
||||
## Endpoints
|
||||
|
||||
- `GET /`: server metadata.
|
||||
- `GET /health`: health probe.
|
||||
- `GET /metrics`: Prometheus metrics (when enabled).
|
||||
- `POST /automation/webhook`: ingest policy-controlled webhook events.
|
||||
- `POST /automation/jobs/run`: run policy-controlled automation jobs.
|
||||
- `GET /mcp/tools`: list tool definitions.
|
||||
- `POST /mcp/tool/call`: execute a tool (`Authorization: Bearer <api-key>` required except in explicitly disabled auth mode).
|
||||
- `GET /mcp/sse` and `POST /mcp/sse`: MCP SSE transport.
|
||||
|
||||
## Automation Jobs
|
||||
|
||||
`POST /automation/jobs/run` supports:
|
||||
- `dependency_hygiene_scan` (read-only scaffold).
|
||||
- `stale_issue_detection` (read-only issue age analysis).
|
||||
- `auto_issue_creation` (write-mode + whitelist + policy required).
|
||||
|
||||
## Read Tools
|
||||
|
||||
- `list_repositories`.
|
||||
- `get_repository_info` (`owner`, `repo`).
|
||||
- `get_file_tree` (`owner`, `repo`, optional `ref`, `recursive`).
|
||||
- `get_file_contents` (`owner`, `repo`, `filepath`, optional `ref`).
|
||||
- `search_code` (`owner`, `repo`, `query`, optional `ref`, `page`, `limit`).
|
||||
- `list_commits` (`owner`, `repo`, optional `ref`, `page`, `limit`).
|
||||
- `get_commit_diff` (`owner`, `repo`, `sha`).
|
||||
- `compare_refs` (`owner`, `repo`, `base`, `head`).
|
||||
- `list_issues` (`owner`, `repo`, optional `state`, `page`, `limit`, `labels`).
|
||||
- `get_issue` (`owner`, `repo`, `issue_number`).
|
||||
- `list_pull_requests` (`owner`, `repo`, optional `state`, `page`, `limit`).
|
||||
- `get_pull_request` (`owner`, `repo`, `pull_number`).
|
||||
- `list_labels` (`owner`, `repo`, optional `page`, `limit`).
|
||||
- `list_tags` (`owner`, `repo`, optional `page`, `limit`).
|
||||
- `list_releases` (`owner`, `repo`, optional `page`, `limit`).
|
||||
|
||||
## Write Tools (Write Mode Required)
|
||||
|
||||
- `create_issue` (`owner`, `repo`, `title`, optional `body`, `labels`, `assignees`).
|
||||
- `update_issue` (`owner`, `repo`, `issue_number`, one or more of `title`, `body`, `state`).
|
||||
- `create_issue_comment` (`owner`, `repo`, `issue_number`, `body`).
|
||||
- `create_pr_comment` (`owner`, `repo`, `pull_number`, `body`).
|
||||
- `add_labels` (`owner`, `repo`, `issue_number`, `labels`).
|
||||
- `assign_issue` (`owner`, `repo`, `issue_number`, `assignees`).
|
||||
|
||||
## Validation and Limits
|
||||
|
||||
- All tool argument schemas reject unknown fields.
|
||||
- List responses are capped by `MAX_TOOL_RESPONSE_ITEMS`.
|
||||
- Text payloads are capped by `MAX_TOOL_RESPONSE_CHARS`.
|
||||
- File reads are capped by `MAX_FILE_SIZE_BYTES`.
|
||||
|
||||
## Error Model
|
||||
|
||||
- Policy denial: HTTP `403`.
|
||||
- Validation error: HTTP `400`.
|
||||
- Auth error: HTTP `401`.
|
||||
- Rate limit: HTTP `429`.
|
||||
- Internal errors: HTTP `500` without stack traces in production.
|
||||
|
||||
Reference in New Issue
Block a user