# Contributing to Agent Guardrails Template > Guidelines for contributing to the MCP Server and related components **Version:** 2.6.0 **Last Updated:** 2026-02-15 --- ## Quick Start 1. **Fork** the repository 2. **Clone** your fork: `git clone https://github.com/YOUR_USERNAME/agent-guardrails-template.git` 3. **Set up** the development environment (see below) 4. **Create** a feature branch: `git checkout -b feature/your-feature` 5. **Make** your changes 6. **Test** your changes 7. **Commit** with conventional commit messages 8. **Push** to your fork 9. **Open** a Pull Request --- ## Development Environment ### Prerequisites | Tool | Version | Purpose | |------|---------|---------| | Go | 1.23+ | Primary language for MCP server | | Docker | 20.10+ | Container development | | PostgreSQL | 16+ | Database (or use Docker) | | Redis | 7+ | Cache (or use Docker) | | Make | 3.81+ | Build automation | ### Repository Structure ``` agent-guardrails-template/ ├── mcp-server/ # Go MCP Server (Primary) │ ├── cmd/server/ # Entry point │ ├── internal/ # Internal packages │ │ ├── team/ # Team management (Go) │ │ ├── mcp/ # MCP protocol handlers │ │ ├── database/ # Database operations │ │ ├── cache/ # Redis caching │ │ └── ... │ ├── deploy/ # Docker configs │ └── go.mod # Go dependencies ├── scripts/ # Python scripts (DEPRECATED) ├── docs/ # Documentation └── ... ``` --- ## Go Development Guidelines ### Code Style We follow standard Go conventions: ```bash # Format code cd mcp-server go fmt ./... # Run linter golangci-lint run # Run vet go vet ./... ``` ### Project Structure ```go // Package documentation // Package team provides team management functionality for MCP server. // This is a Go port of the Python team_manager.py core functionality. package team // Imports - grouped by: stdlib, third-party, internal import ( "context" "fmt" "github.com/some/lib" "github.com/thearchitectit/guardrail-mcp/internal/models" ) // Exported types start with capital letter type Manager struct { // fields... } // Constructor function func NewManager(projectName string, opts ...ManagerOption) (*Manager, error) { // implementation... } // Methods func (m *Manager) AssignRole(ctx context.Context, teamID int, role, person string) error { // implementation... } ``` ### Naming Conventions | Type | Convention | Example | |------|------------|---------| | **Packages** | lowercase, single word | `team`, `mcp`, `database` | | **Exported** | PascalCase | `Manager`, `AssignRole` | | **Unexported** | camelCase | `internalFunc`, `helper` | | **Constants** | PascalCase or UPPER_SNAKE | `MaxRetries`, `DEFAULT_TIMEOUT` | | **Interfaces** | -er suffix | `Reader`, `Writer`, `Manager` | | **Structs** | PascalCase | `TeamManager`, `ProjectConfig` | ### Error Handling Use wrapped errors with context: ```go // Good if err := validateProjectName(projectName); err != nil { return fmt.Errorf("invalid project name %q: %w", projectName, err) } // Avoid return errors.New("something went wrong") // No context // Custom error types for specific cases type ValidationError struct { Field string Message string } func (e *ValidationError) Error() string { return fmt.Sprintf("validation error on %s: %s", e.Field, e.Message) } ``` ### Context Usage Always accept `context.Context` as first parameter: ```go // Good func (m *Manager) DoOperation(ctx context.Context, arg string) error { // Use ctx for timeouts, cancellation } // Avoid - no context support func (m *Manager) DoOperation(arg string) error { // ... } ``` ### Testing ```go // Test files: *_test.go package team import ( "context" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestManager_AssignRole(t *testing.T) { // Arrange ctx := context.Background() mgr, err := NewManager("test-project") require.NoError(t, err) // Act err = mgr.AssignRole(ctx, 7, "Technical Lead", "Alice") // Assert assert.NoError(t, err) } // Table-driven tests func TestValidateProjectName(t *testing.T) { tests := []struct { name string input string wantErr bool }{ {"valid", "my-project", false}, {"empty", "", true}, {"with space", "my project", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := ValidateProjectName(tt.input) if tt.wantErr { assert.Error(t, err) } else { assert.NoError(t, err) } }) } } ``` Run tests: ```bash cd mcp-server # Run all tests go test ./... # Run with coverage go test -cover ./... # Run specific package go test ./internal/team/... # Run benchmarks go test -bench=. ./internal/team/... ``` --- ## Commit Guidelines ### Conventional Commits ``` ():