Implements forgejo-mcp-ya6 per docs/plans/issue-time-tracking.md. Ten new MCP tools wrapping forgejo-sdk/v3 tracked-time and stopwatch APIs: Tracked time: - list_issue_tracked_times, list_repo_tracked_times, list_my_tracked_times - add_issue_time (accepts either 'seconds' int or 'duration' string like "15m") - reset_issue_time, delete_issue_time_entry Stopwatches: - start_issue_stopwatch, stop_issue_stopwatch, cancel_issue_stopwatch - list_my_stopwatches Forgejo shares index namespace between issues and PRs, so one tool set covers both — tool descriptions state this explicitly. - New operation/tracking/ package with unit tests using httptest mock - pkg/to/Float64Ok helper to distinguish 'absent' from 'malformed' in the add_issue_time seconds/duration validation - README tool table updated - Two Showboat demos: demos/issue-time-tracking.md, demos/issue-stopwatch.md
5.6 KiB
5.6 KiB
Demo: issue time tracking tools
2026-04-21T22:45:00Z by Showboat 0.6.1
What these tools do
Six MCP tools give agents a full read/write view of Forgejo's tracked-time ledger on issues and pull requests:
list_issue_tracked_times— List entries on one issue or PR (supportssince/beforefilters).list_repo_tracked_times— List entries across a repository (also supports auserfilter).list_my_tracked_times— List your own entries across all repositories.add_issue_time— Log time against an issue or PR. Accepts eithersecondsorduration(e.g."15m","1h30m"), never both.reset_issue_time— Delete all entries on one issue or PR. Destructive; affects entries from other users too.delete_issue_time_entry— Delete a single entry by its numeric ID.
Forgejo unifies the issue and PR index namespace, so the same tools work against a PR just by passing the PR number as index.
Setup
Set FORGEJO_URL and FORGEJO_ACCESS_TOKEN (or use direnv), then:
make build
CLI mode: parameter schemas
./forgejo-mcp --cli add_issue_time --help 2>/dev/null
Tool: add_issue_time
Description: Log time against an issue or pull request. Provide exactly one of 'seconds' or 'duration'.
Parameters:
created_at string optional Optional RFC3339 timestamp for when the work happened (defaults to server time)
duration string optional Time as a duration string, e.g. "15m", "1h30m", "45s". Provide exactly one of seconds or duration.
index number required Issue or pull request index (Forgejo shares index namespace between the two)
owner string required Repository owner
repo string required Repository name
seconds number optional Time in seconds to log (positive integer). Provide exactly one of seconds or duration.
user_name string optional Optional username to log time on behalf of (requires admin; omit for self)
End-to-end workflow
Step 1: Create a scratch issue to demo against
./forgejo-mcp --cli create_issue \
--args '{"owner":"goern","repo":"forgejo-mcp","title":"demo: time tracking","body":"Scratch issue for a Showboat demo."}' 2>/dev/null
Issue #200 created: demo: time tracking
Step 2: Log 15 minutes via duration
./forgejo-mcp --cli add_issue_time \
--args '{"owner":"goern","repo":"forgejo-mcp","index":200,"duration":"15m"}' 2>/dev/null
Tracked time entry created:
id: 41
time: 900 seconds
user: goern
Step 3: Log 30 more minutes via seconds
./forgejo-mcp --cli add_issue_time \
--args '{"owner":"goern","repo":"forgejo-mcp","index":200,"seconds":1800}' 2>/dev/null
Tracked time entry created:
id: 42
time: 1800 seconds
user: goern
Step 4: List entries on the issue
./forgejo-mcp --cli list_issue_tracked_times \
--args '{"owner":"goern","repo":"forgejo-mcp","index":200}' 2>/dev/null
2 tracked time entries on issue #200:
id=41 time=900s user=goern created=2026-04-21T22:45:12Z
id=42 time=1800s user=goern created=2026-04-21T22:45:15Z
Total: 2700 seconds (45 minutes)
Step 5: Delete one entry by ID
./forgejo-mcp --cli delete_issue_time_entry \
--args '{"owner":"goern","repo":"forgejo-mcp","index":200,"time_id":41}' 2>/dev/null
Delete time entry success
./forgejo-mcp --cli list_issue_tracked_times \
--args '{"owner":"goern","repo":"forgejo-mcp","index":200}' 2>/dev/null
1 tracked time entry on issue #200:
id=42 time=1800s user=goern created=2026-04-21T22:45:15Z
Step 6: Nuke the whole ledger with reset_issue_time
./forgejo-mcp --cli reset_issue_time \
--args '{"owner":"goern","repo":"forgejo-mcp","index":200}' 2>/dev/null
Reset tracked time success
./forgejo-mcp --cli list_issue_tracked_times \
--args '{"owner":"goern","repo":"forgejo-mcp","index":200}' 2>/dev/null
0 tracked time entries on issue #200.
Step 7: Validation failure — both seconds and duration rejected
./forgejo-mcp --cli add_issue_time \
--args '{"owner":"goern","repo":"forgejo-mcp","index":200,"seconds":60,"duration":"1m"}' 2>/dev/null
Error: provide exactly one of 'seconds' or 'duration', not both
This check runs client-side before any HTTP call, so the agent sees a structured error instead of a 400 from the API.
Step 8: Repo-wide and user-scoped queries
./forgejo-mcp --cli list_repo_tracked_times \
--args '{"owner":"goern","repo":"forgejo-mcp","user":"goern","since":"2026-04-21T00:00:00Z"}' 2>/dev/null
./forgejo-mcp --cli list_my_tracked_times --args '{}' 2>/dev/null
Each returns a JSON array of TrackedTime objects across scopes larger than a single issue.
Step 9: Clean up
./forgejo-mcp --cli issue_state_change \
--args '{"owner":"goern","repo":"forgejo-mcp","index":200,"state":"closed"}' 2>/dev/null
Notes
- Issues vs PRs: every tool above also accepts a PR index.
add_issue_time --index 101would log time against PR #101 with no change in parameters. reset_issue_timeis destructive: it removes entries from other users too. The tool description flags this explicitly so agents do not reach for it casually.- Stopwatch companion: see
demos/issue-stopwatch.mdfor the live-timer flow that writes tracked-time entries automatically.