11 Commits

Author SHA1 Message Date
silverwind 2e67d5ebf3 Trim tool schemas, add param aliases, new PR methods (#191)
- Tool list size reduced by 26.6% (43,032 → 31,599 bytes on the `tools/list` JSON-RPC response).
- Trim redundant tool/param descriptions; shared description constants for `owner`/`repo`/`page`/`per_page`.
- Schemas now use github-mcp-server param names directly: `issue_number` (was `index` on issue tools), `pull_number` (was `index` on PR tools), `path` (was `filePath`), `query` (was `keyword` on user/repo search), `per_page` (was `perPage`).
- New PR read methods `get_files` and `get_status`; new PR write method `update_branch` (update PR branch from base).
- `list_org_repos` now uses `per_page` (was `pageSize`).
- `milestone_write` accepts `update` and `edit`.
- `create_branch` `old_branch` is optional; Gitea defaults to the repo default branch.
- Fix `list_commits` handler to honour optional `page`/`per_page` schema (was erroring out when callers omitted them).

---
This PR was written with the help of Claude Opus 4.7

Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/191
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-05-14 06:24:51 +00:00
unpossible 329a97d5d2 Add tool annotations and PR close/reopen support (#174)
Add MCP `ToolAnnotation` metadata (Title, ReadOnlyHint, DestructiveHint)
to all registered tools so MCP hosts (VS Code, Claude, Cursor) get
accurate per-tool hints. A shared `pkg/annotation` package exposes
`ReadOnly`, `Write`, and `Destructive` helpers for consistency.

Add `close` and `reopen` methods to `pull_request_write` so PR state
can be toggled without going through the generic `update` path.

Co-Authored-By: silverwind <me@silverwind.io>
Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
2026-05-10 11:25:22 +02:00
silverwind baf792b061 Use golangci-lint fmt to format code (#178)
Use `golangci-lint fmt` to format code, replacing the previous gofumpt-based formatter. https://github.com/daixiang0/gci is used to order the imports.

Mirrors https://github.com/go-gitea/gitea/pull/37194.

---
This PR was written with the help of Claude Opus 4.7

Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/178
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-04-17 22:38:13 +00:00
silverwind 05682e2afa Document server-side pagination limit in README (#166)
The maximum effective page size for paginated tools is determined by the Gitea server's [`[api].MAX_RESPONSE_ITEMS`](https://github.com/go-gitea/gitea/blob/ffa626b585225d62718f39e1b5fcc00416b0b7e4/custom/conf/app.example.ini#L2471-L2472) setting (default: 50). Requesting a `perPage` value higher than this limit will be silently capped by the server.

Fixes https://gitea.com/gitea/gitea-mcp/issues/165

Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/166
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-03-26 17:15:33 +00:00
silverwind bba612d238 Consolidate tools from 110 to 45 using method dispatch (#143)
Consolidate 110 individual MCP tools down to 45 using a method dispatch pattern, aligning tool names with the GitHub MCP server conventions.

**Motivation:** LLMs work better with fewer, well-organized tools. The method dispatch pattern (used by GitHub's MCP server) groups related operations under read/write tools with a `method` parameter.

**Changes:**
- Group related tools into `_read`/`_write` pairs with method dispatch (e.g. `issue_read`, `issue_write`, `pull_request_read`, `pull_request_write`)
- Rename tools to match GitHub MCP naming (`get_file_contents`, `create_or_update_file`, `list_issues`, `list_pull_requests`, etc.)
- Rename `pageSize` to `perPage` for GitHub MCP compat
- Move issue label ops (`add_labels`, `remove_label`, etc.) into `issue_write`
- Merge `create_file`/`update_file` into `create_or_update_file` with optional `sha`
- Make `delete_file` require `sha`
- Add `get_labels` method to `issue_read`
- Add shared helpers: `GetInt64Slice`, `GetStringSlice`, `GetPagination` in params package
- Unexport all dispatch handler functions
- Fix: pass assignees/milestone in `CreateIssue`, bounds check in `GetFileContent`

Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/143
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-03-06 19:12:15 +00:00
silverwind c3db4fb65f feat: slim tool responses (#141)
Reduce token usage by slimming tool responses. Instead of returning full Gitea SDK objects (with nested user/repo objects, avatars, permissions, etc.), each operation now has a colocated `slim.go` that extracts only the fields an LLM needs. List endpoints return even fewer fields than single-item endpoints.

Other changes:
- Add `params` helpers to DRY parameter extraction across 40+ handlers
- Remove `{"Result": ...}` wrapper for flatter responses
- Reduce default pageSize from 100 to 30

Fixes: https://gitea.com/gitea/gitea-mcp/issues/128

*Created by Claude on behalf of @silverwind*

Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/141
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-03-05 05:56:23 +00:00
silverwind 67a1e1e7fe feat: accept string values for all numeric input parameters (#138)
## Summary

- MCP clients may send numbers as strings. This adds `ToInt64` and `GetOptionalInt` helpers to `pkg/params` and replaces all raw `.(float64)` type assertions across operation handlers to accept both `float64` and string inputs.

## Test plan

- [x] Verify `go test ./...` passes
- [x] Test with an MCP client that sends numeric parameters as strings

*Created by Claude on behalf of @silverwind*

Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/138
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-02-25 23:28:14 +00:00
silverwind 723a30ae23 fix: replace deprecated SDK calls in timetracking (#136)
## Summary
- Replace `client.GetMyStopwatches()` with `client.ListMyStopwatches(ListStopwatchesOptions{})`
- Replace `client.GetMyTrackedTimes()` with `client.ListMyTrackedTimes(ListTrackedTimesOptions{})`
- Fixes staticcheck SA1019 lint errors for deprecated API usage

## Test plan
- [x] `make lint` passes with 0 issues
- [x] `go test ./...` passes

*Created by Claude on behalf of @silverwind*

Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/136
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-02-25 03:28:59 +00:00
silverwind 8728c04748 chore: add golangci-lint, bump Go to 1.26, fix all lint issues (#133)
## Summary
- Add `.golangci.yml` with linter configuration matching the main gitea repo
- Add `lint`, `lint-fix`, `lint-go`, `lint-go-fix`, and `security-check` Makefile targets
- Add `tidy` Makefile target (extracts min Go version from `go.mod` for `-compat` flag)
- Bump minimum Go version to 1.26
- Update golangci-lint to v2.10.1
- Replace `golang/govulncheck-action` with `make security-check` in CI
- Add `make lint` step to CI
- Fix all lint issues across the codebase (formatting, `errors.New` vs `fmt.Errorf`, `any` vs `interface{}`, unused returns, stuttering names, Go 1.26 `new(expr)`, etc.)
- Remove unused `pkg/ptr` package (inlined by Go 1.26 `new(expr)`)
- Remove dead linter exclusions (staticcheck, gocritic, testifylint, dupl)

## Test plan
- [x] `make lint` passes
- [x] `go test ./...` passes
- [x] `make build` succeeds

Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/133
Reviewed-by: techknowlogick <techknowlogick@noreply.gitea.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-02-22 17:10:04 +00:00
silverwind 4d5fa3ab2c feat: accept string or number for index parameters (#131)
This change makes index parameters more flexible by accepting both numeric and string values. LLM agents often pass issue/PR indices as strings (e.g., "123") since they appear as string identifiers in URLs and CLI contexts. The implementation:

- Created `pkg/params` package with `GetIndex()` helper function
- Updated 25+ tool functions across issue, pull, label, and timetracking operations
- Improved error messages to say "must be a valid integer" instead of misleading "is required"
- Added comprehensive tests for both numeric and string inputs

Based on #122 by @jamespharaoh with review feedback applied (replaced custom `contains()` test helper with `strings.Contains`). Verified working in Claude Code.

Fixes: https://gitea.com/gitea/gitea-mcp/issues/121
Fixes: https://gitea.com/gitea/gitea-mcp/issues/122
---------

Co-authored-by: James Pharaoh <james@pharaoh.uk>
Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/131
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-committed-by: silverwind <me@silverwind.io>
2026-02-20 23:47:22 +00:00
tylermitchell b8f2377f47 feat: add time tracking tools (stopwatch and tracked times) (#113)
## Summary
Implements 9 new MCP tools for Gitea time tracking functionality, enabling AI assistants to help users track time spent on issues.

## New Tools

### Stopwatch Tools
| Tool | Type | Description |
|------|------|-------------|
| `start_stopwatch` | Write | Start timing work on an issue |
| `stop_stopwatch` | Write | Stop stopwatch and record tracked time |
| `delete_stopwatch` | Write | Cancel stopwatch without recording |
| `get_my_stopwatches` | Read | List all active stopwatches for current user |

### Tracked Time Tools
| Tool | Type | Description |
|------|------|-------------|
| `list_tracked_times` | Read | Get tracked times for a specific issue |
| `add_tracked_time` | Write | Manually add time entry to an issue |
| `delete_tracked_time` | Write | Remove a tracked time entry |
| `list_repo_times` | Read | Get all tracked times for a repository |
| `get_my_times` | Read | Get all tracked times for current user |

## Implementation
- Added new `operation/timetracking/timetracking.go` module
- Follows existing patterns from milestone.go
- Uses Gitea SDK v0.22.1 time tracking methods
- Registered in `operation/operation.go`

Fixes #112

Co-authored-by: Tyler Potts <tyler@adhdafterdiagnosis.com>
Reviewed-on: https://gitea.com/gitea/gitea-mcp/pulls/113
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: hiifong <f@f.style>
Co-authored-by: tylermitchell <tylermitchell@noreply.gitea.com>
Co-committed-by: tylermitchell <tylermitchell@noreply.gitea.com>
2026-01-01 14:28:50 +00:00