Go Source Documentation Skill
SkillFiles & storageAdd idiomatic, godoc-compliant documentation to Go source and test files. Use when user asks to document Go files, add doc comments, improve Go documentation, or mentions /document-go. Covers file headers, package comments, types, functions, interfaces, constants, variables, tests (with detailed explanations), benchmarks, fuzz tests, and examples.
Available today. Use it from your connected AI after setup.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
Then ask your AI: use the Go Source Documentation Skill skill
What this skill tells your AI
The instructions your AI receives, as published by jmrplens/gitlab-mcp-server in .github/skills/go-source-documentation/SKILL.md and read by ahel’s review.
Activation
Activate this skill when the user:
- Asks to document Go source files or test files
- Asks to add doc comments to Go code
- Asks to improve or fix Go documentation
- Mentions
/document-goor/doc-go - Asks to add file headers to Go files
- Asks to document a Go package
Prerequisites
Before starting, gather context:
- Read the target file(s) completely to understand structure and purpose
- Read related files in the same package to understand the package API surface
- Check existing tests to understand what behavior the code implements
- Identify the package role within the project architecture
- Use Context7 to verify current Go doc comment conventions if uncertain
Documentation Patterns
Pattern 1: Package Comment
Every package needs exactly one Package comment, and it lives in doc.go (the godoc audit reports one anywhere else; go run ./cmd/godoc_tool/ fix --move-package-doc moves it):
// Package tools implements MCP tool handlers for GitLab operations.
//
// Each tool follows a consistent pattern: a typed input struct with jsonschema
// tags defining the parameter schema, a handler function that calls the GitLab
// API, and a typed output struct for the response.
//
// Actions are exposed through [ActionSpecs], which feed catalog-backed meta,
// dynamic, gitlab://tools resources, and individual tool surfaces with
// appropriate annotations.
//
// # Supported Operations
//
// - Branches: create, list, protect, unprotect
// - Issues: create, list, get, update, search
// - Merge Requests: create, list, get, update, merge
// - Files: get content, create, update
// - Commits: list, get details
package tools
Pattern 2: File Header Comment
For multi-file packages, each file gets a header describing its scope. The header goes immediately before the package declaration:
// branches.go implements MCP tool handlers for GitLab branch operations.
//
// It provides the following tools:
// - gitlab_branch_create: Create a new branch from a ref
// - gitlab_branch_list: List branches with optional search
// - gitlab_branch_protect: Protect a branch with access levels
// - gitlab_branch_unprotect: Remove protection from a branch
package branches
Pattern 3: Input Struct Documentation
Input structs define MCP tool parameters. Document the struct purpose and each field's role:
// CreateInput defines parameters for creating a new merge request.
// ProjectID identifies the target project, SourceBranch and TargetBranch
// define the merge direction, and Title becomes the MR title. The package
// name (mergerequests) carries the domain, so the type takes no MR prefix.
type CreateInput struct {
ProjectID toolutil.StringOrInt `json:"project_id" jsonschema:"Project ID or URL-encoded path,required"`
SourceBranch string `json:"source_branch" jsonschema:"Source branch name,required"`
TargetBranch string `json:"target_branch" jsonschema:"Target branch name,required"`
Title string `json:"title" jsonschema:"Title of the merge request,required"`
Description string `json:"description,omitempty" jsonschema:"Detailed description (Markdown supported)"`
}
Pattern 4: Handler Function Documentation
Handler functions follow the pattern func Action(ctx, client, input) (output, error), exported so the domain's ActionSpecs can route to them:
// Create creates a new merge request in the specified GitLab project.
// It sets the title, description, source branch, and target branch from
// the input parameters. Returns the created merge request details or an
// error if the project is not found, the source branch does not exist,
// or the GitLab API call fails.
func Create(ctx context.Context, client *gitlabclient.Client, input CreateInput) (Output, error) {
Pattern 5: Output Struct Documentation
Output structs define the MCP tool response:
// Output represents a merge request as returned by the GitLab Merge
// Requests API. It mirrors the SDK struct field for field (1:1 policy);
// the excerpt below is abridged.
type Output struct {
toolutil.HintableOutput
IID int `json:"iid"`
Title string `json:"title"`
State string `json:"state"`
WebURL string `json:"web_url"`
SourceBranch string `json:"source_branch"`
TargetBranch string `json:"target_branch"`
Author string `json:"author"`
}
Pattern 6: Converter/Helper Functions
Internal helpers that transform data between API and MCP formats:
// ToOutput converts a GitLab API [gl.MergeRequest] to the MCP tool
// output format, mirroring every SDK field and surfacing the author,
// assignees and references as full nested objects.
func ToOutput(mr *gl.MergeRequest) Output {
Pattern 7: ActionSpecs Functions
The function that exposes a domain's handlers to every surface. There are no
package-local RegisterTools functions: the catalog projects these specs into
the meta, dynamic, and individual surfaces.
// ActionSpecs returns canonical specs for branch and protected branch
// actions. The specs feed meta-tools, dynamic discovery, gitlab://tools
// resources, audits, and individual tool projection (ADR-0004); each
// entry names its individual tool and carries its read-only/destructive
// classification.
func ActionSpecs(client *gitlabclient.Client) []toolutil.ActionSpec {
Pattern 8: Test File Documentation
// branches_test.go contains unit tests for the branch MCP tool handlers
// defined in branches.go. Tests use httptest to mock GitLab API responses
// and verify both success paths and error conditions.
//
// Each test function creates a dedicated httptest server with a handler
// that simulates the relevant GitLab API endpoint, then calls the tool
// handler directly and asserts the output or error.
package branches
Pattern 9: Individual Test Function Documentation
Every test MUST have a detailed doc comment explaining:
- What: The specific function, behavior, or scenario being tested
- How: The test setup (mock configuration, inputs, preconditions)
- Expected: The specific assertions and expected outcomes
- Why: The business rule or edge case this test protects
// TestBranchCreate_Success verifies that Create creates a branch
// when the GitLab API returns HTTP 201 Created.
//
// The test mocks POST /projects/:id/repository/branches to return a
// branch object with name "feature/login" and a known commit SHA. It
// asserts that no error is returned, the output branch name matches
// "feature/login", and the web URL is correctly constructed.
func TestBranchCreate_Success(t *testing.T) {
Error scenario:
// TestBranchCreate_ProjectNotFound verifies that Create returns an
// error when the target project does not exist in GitLab.
//
// The mock returns HTTP 404 with a GitLab error body. The test asserts
// that an error is returned and the error message contains "404". This
// protects against silent failures when operating on deleted projects.
func TestBranchCreate_ProjectNotFound(t *testing.T) {
Pattern 10: Table-Driven Test Documentation
Document the overall strategy AND list all covered scenarios:
// TestBranchList_Scenarios uses table-driven subtests to validate branchList
// across multiple conditions:
//
// - "returns branches with pagination": successful listing with 2 branches,
// verifies item count, names, and pagination metadata
// - "returns empty list": HTTP 200 with empty array, verifies non-nil empty
// slice
// - "returns error on 404": HTTP 404, verifies error propagation
// - "returns error on 500": HTTP 500, verifies error propagation
// - "respects search filter": verifies the search query param is forwarded
//
// Each subtest configures a dedicated httptest handler that returns the
// appropriate response for the scenario being tested.
func TestBranchList_Scenarios(t *testing.T) {
Pattern 11: Test Helper Documentation
The shared helpers live in internal/testutil; a domain test file rarely defines
its own. Their doc comments are the model for any local helper:
// NewTestClient creates a [gitlabclient.Client] connected to an
// httptest server using the provided handler. The test server is
// automatically stopped when the test completes via [testing.TB.Cleanup].
func NewTestClient(tb testing.TB, handler http.Handler) *gitlabclient.Client {
tb.Helper()
Pattern 12: Interface Documentation
Document the contract, not the implementation. List the method set and explain the
behavioral expectations (from internal/subscriptions/manager.go):
// Reader reads the current content of a resource URI. Implementations
// return [ErrInaccessible] or [ErrRateLimited] where those apply; any other
// error is treated as transient.
type Reader interface {
// Read returns the current content of uri, or an error describing why
// it could not be read.
Read(ctx context.Context, uri string) ([]byte, error)
}
Pattern 13: Deprecation Notices
Use the standard // Deprecated: directive (Go 1.19+) on its own paragraph:
// FormatResponse formats an API response into a human-readable string.
//
// Deprecated: Use [FormatMarkdown] instead, which produces richer output
// with proper heading levels and code blocks.
func FormatResponse(data any) string {
Pattern 14: Benchmark and Fuzz Test Documentation
Benchmark tests document the operation being measured and any special setup:
// BenchmarkBranchList measures the throughput of branchList with a
// mock returning 100 branches per page. The benchmark uses b.ResetTimer
// after httptest setup to exclude initialization from measurements.
func BenchmarkBranchList(b *testing.B) {
Fuzz tests document the invariant being checked and the seed corpus:
// FuzzParseProjectID verifies that parseProjectID never panics for
// arbitrary string inputs. The seed corpus includes empty strings,
// numeric IDs, namespaced paths, and URL-encoded paths.
func FuzzParseProjectID(f *testing.F) {
Pattern 15: Example Function Documentation
Example functions appear in godoc under the symbol they demonstrate:
// ExampleNewClient demonstrates creating a GitLab client with a
// personal access token and custom base URL.
func ExampleNewClient() {
Pattern 16: BUG and TODO Annotations
Use // BUG(who): at package level for known bugs that appear in godoc.
Use // TODO: with a ticket reference for planned work (does NOT appear in godoc):
// BUG(jmrplens): ListBranches does not handle pagination for projects
// with more than 10,000 branches due to a GitLab API limitation.
// TODO(TICKET-123): Add retry logic for transient 502 errors.
Decision Framework
For each symbol, decide the documentation level:
| Symbol Type | Exported? | Doc Required? | Level of Detail |
|---|---|---|---|
| Package | — | YES (one per package) | Purpose, scope, key types |
| Type/Struct | Yes | YES | What instances represent |
| Type/Struct | No | If non-obvious | Brief purpose |
| Interface | Yes | YES | Contract, behavioral expectations, concurrency |
| Function | Yes | YES | What it does, params, errors |
| Function | No | If non-obvious | Brief purpose |
| Method | Yes | YES | Start with receiver context |
| Const/Var group | Yes | YES | Group purpose |
| Const/Var group | No | If non-obvious | Brief purpose |
| Test function | — | YES | What/How/Expected/Why |
| Test helper | — | YES | What it creates/configures |
| Benchmark | — | YES | Operation measured, setup |
| Fuzz test | — | YES | Invariant, seed corpus |
| Example func | — | YES | What it demonstrates |
| Deprecation | — | YES | Deprecated: + replacement |
Validation Steps
After documenting each file:
- Analysis check:
golangci-lint run --build-tags e2e ./path/to/package/... - Build check:
go build ./path/to/package/... - Test check:
go test ./path/to/package/... - Doc check:
go doc ./path/to/package— verify all exported symbols appear - No logic changes: Confirm only comments were added/modified
Common Mistakes to Avoid
-
Changing code logic — NEVER modify function bodies, signatures, or variable names
-
Blank line between comment and declaration — renders as regular comment, not doc comment:
// WRONG — blank line breaks the association // Package branches handles branch operations. package branches -
Not starting with symbol name —
go docsynopsis will be wrong -
Using block comments for doc comments — use
//line comments (block/* */style is non-idiomatic for doc comments) -
Redundant comments — don't restate what the code already says clearly
-
Missing error documentation — always document when/why errors are returned
-
Forgetting test docs — test functions MUST have detailed documentation
-
Inconsistent tense — use present tense ("creates", "returns", not "will create")
-
Missing package comment — one file per package must have
// Package name ... -
Over-documenting — a clear name like
UserID stringdoesn't need a comment saying "the user's ID" -
Headings without blank line before — Go 1.19+ headings (
# Heading) must have a blank//line before them -
Doc links to unexported symbols —
[unexportedFunc]won't resolve; only link to exported symbols
Project-Specific Notes
This project (gitlab-mcp-server) has specific patterns to recognize:
- MCP tool input structs have
jsonschematags — mention the tool parameters they define - Handler functions follow
func name(ctx, client, input) (output, error)— document the API operation - ActionSpec functions describe canonical route metadata — document which actions and surfaces they feed
- Tests use
httptest— mention the API endpoint being mocked and HTTP method - Constants like endpoint paths — document they are test fixtures for specific API routes
gitlabclient.Clientwraps the GitLab API — reference it as[gitlabclient.Client]toolutilhelpers — reference using doc links:[toolutil.WrapErr],[toolutil.PaginationFromResponse],[toolutil.ApplyListOptions]- Catalog registration — ordinary GitLab actions flow through
ActionSpecsand the canonical action catalog; package-level meta registration is historical compatibility context only
Signals
- GitHub stars
- 39
- Forks
- 5
- Last commit
- Sep 2026
Advanced
- Item type
- skill
- Key
go-source-documentation- Source
- github.com/jmrplens/gitlab-mcp-server