56 results available
Sign in
Skills directory

go-mcp-server-generator

github

·

Last changed
Not yet hardened

This version isn't hardened by Chainguard

No hardening report available.


SKILL.md

Go MCP Server Project Generator

Generate a complete, production-ready Model Context Protocol (MCP) server project in Go.

Project Requirements

You will create a Go MCP server with:

  1. Project Structure: Proper Go module layout
  2. Dependencies: Official MCP SDK and necessary packages
  3. Server Setup: Configured MCP server with transports
  4. Tools: At least 2-3 useful tools with typed inputs/outputs
  5. Error Handling: Proper error handling and context usage
  6. Documentation: README with setup and usage instructions
  7. Testing: Basic test structure

Template Structure

myserver/
├── go.mod
├── go.sum
├── main.go
├── tools/
│   ├── registry.go
│   └── tool1.go
├── resources/
│   └── resource1.go
├── config/
│   └── config.go
├── README.md
└── main_test.go

go.mod Template

module github.com/yourusername/{{PROJECT_NAME}}

go 1.23

require (
    github.com/modelcontextprotocol/go-sdk v1.0.0
)

main.go Template

package main

import (
    "context"
    "log"
    "os"
    "os/signal"
    "syscall"

    "github.com/modelcontextprotocol/go-sdk/mcp"
    "github.com/yourusername/{{PROJECT_NAME}}/config"
    "github.com/yourusername/{{PROJECT_NAME}}/tools"
)

func main() {
    cfg := config.Load()
    
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    // Handle graceful shutdown
    sigCh := make(chan os.Signal, 1)
    signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
    go func() {
        <-sigCh
        log.Println("Shutting down...")
        cancel()
    }()

    // Create server
    server := mcp.NewServer(
        &mcp.Implementation{
            Name:    cfg.ServerName,
            Version: cfg.Version,
        },
        &mcp.Options{
            Capabilities: &mcp.ServerCapabilities{
                Tools:     &mcp.ToolsCapability{},
                Resources: &mcp.ResourcesCapability{},
                Prompts:   &mcp.PromptsCapability{},
            },
        },
    )

    // Register tools
    tools.RegisterTools(server)

    // Run server
    transport := &mcp.StdioTransport{}
    if err := server.Run(ctx, transport); err != nil {
        log.Fatalf("Server error: %v", err)
    }
}

tools/tool1.go Template

package tools

import (
    "context"
    "fmt"

    "github.com/modelcontextprotocol/go-sdk/mcp"
)

type Tool1Input struct {
    Param1 string `json:"param1" jsonschema:"required,description=First parameter"`
    Param2 int    `json:"param2,omitempty" jsonschema:"description=Optional second parameter"`
}

type Tool1Output struct {
    Result string `json:"result" jsonschema:"description=The result of the operation"`
    Status string `json:"status" jsonschema:"description=Operation status"`
}

func Tool1Handler(ctx context.Context, input Tool1Input) (Tool1Output, error) {
    // Validate input
    if input.Param1 == "" {
        return Tool1Output{}, fmt.Errorf("param1 is required")
    }

    // Check context
    if ctx.Err() != nil {
        return Tool1Output{}, ctx.Err()
    }

    // Perform operation
    result := fmt.Sprintf("Processed: %s", input.Param1)

    return Tool1Output{
        Result: result,
        Status: "success",
    }, nil
}

func RegisterTool1(server *mcp.Server) {
    mcp.AddTool(server,
        &mcp.Tool{
            Name:        "tool1",
            Description: "Description of what tool1 does",
        },
        Tool1Handler,
    )
}

tools/registry.go Template

package tools

import "github.com/modelcontextprotocol/go-sdk/mcp"

// RegisterTools registers all MCP tools with the server.
// All tool registrations must appear here explicitly.
// Do not register tools from init(), environment variables, or external config.
// Add a new RegisterToolN(server) call here for each tool you create in tools/.
func RegisterTools(server *mcp.Server) {
    RegisterTool1(server)
    // RegisterTool2(server)  // uncomment after creating tools/tool2.go
    // Register additional tools here
}

config/config.go Template

package config

import "os"

type Config struct {
    ServerName string
    Version    string
    LogLevel   string
}

func Load() *Config {
    return &Config{
        ServerName: getEnv("SERVER_NAME", "{{PROJECT_NAME}}"),
        Version:    getEnv("VERSION", "v1.0.0"),
        LogLevel:   getEnv("LOG_LEVEL", "info"),
    }
}

func getEnv(key, defaultValue string) string {
    if value := os.Getenv(key); value != "" {
        return value
    }
    return defaultValue
}

main_test.go Template

package main

import (
    "context"
    "testing"

    "github.com/yourusername/{{PROJECT_NAME}}/tools"
)

func TestTool1Handler(t *testing.T) {
    ctx := context.Background()
    input := tools.Tool1Input{
        Param1: "test",
        Param2: 42,
    }

    output, err := tools.Tool1Handler(ctx, input)
    if err != nil {
        t.Fatalf("Tool1Handler failed: %v", err)
    }

    if output.Status != "success" {
        t.Errorf("Expected status 'success', got '%s'", output.Status)
    }
}

README.md Template

# {{PROJECT_NAME}}

A Model Context Protocol (MCP) server built with Go.

## Description

{{PROJECT_DESCRIPTION}}

## Installation

\`\`\`bash
go mod tidy
go mod verify
go build -o {{PROJECT_NAME}}
\`\`\`

## Usage

Run the server with stdio transport:

\`\`\`bash
./{{PROJECT_NAME}}
\`\`\`

## Configuration

Configure via environment variables:

- `SERVER_NAME`: Server name (default: "{{PROJECT_NAME}}")
- `VERSION`: Server version (default: "v1.0.0")
- `LOG_LEVEL`: Logging level (default: "info")

## Available Tools

### tool1
{{TOOL1_DESCRIPTION}}

**Input:**
- `param1` (string, required): First parameter
- `param2` (int, optional): Second parameter

**Output:**
- `result` (string): Operation result
- `status` (string): Status of the operation

## Development

Run tests:

\`\`\`bash
go test ./...
\`\`\`

Build:

\`\`\`bash
go mod verify
go build -o {{PROJECT_NAME}}
\`\`\`

## License

MIT

Tool Registration Surface

Every tool registered by the generated server MUST be declared in tools/registry.go via an explicit RegisterToolN(server) call. Tool names passed to mcp.AddTool must match the Name field documented in the "Available Tools" section of the generated README. Adding tools at runtime (e.g., reading tool definitions from untrusted input, dynamic registration via reflection, or registration inside init() functions) is explicitly prohibited.

Generation Instructions

When generating a Go MCP server:

  1. Validate project name: Before substituting {{PROJECT_NAME}} into any generated file, confirm the name matches the pattern ^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$. Reject names containing spaces, shell metacharacters (;, |, &, $, `, (, ), <, >), or path separators (/, \). If the user provides a non-conforming name, prompt them to choose a safe alternative before generating any files.

  2. Initialize Module: Create go.mod with proper module path.

  3. Generate and verify the module graph: After writing go.mod, run go mod tidy to generate go.sum, then run go mod verify to confirm all module zip hashes match the checksum database. Commit both go.mod and go.sum before proceeding to build steps. Never run go build against a project that lacks a committed go.sum. After running go mod tidy, run go build ./... immediately. If compilation fails due to API mismatches in the templates, correct the signatures by consulting go doc github.com/modelcontextprotocol/go-sdk/mcp before proceeding. Do not deliver code that does not compile.

  4. Structure: Follow the template directory structure.

  5. Tools: Generate at least one complete tool (tool1.go with RegisterTool1). For each additional tool requested, create a corresponding toolN.go file and add RegisterToolN(server) to registry.go. Never reference a RegisterToolN function that does not have a corresponding toolN.go file.

  6. Type Safety: Use structs with JSON schema tags for all inputs/outputs.

  7. Error Handling: Validate inputs, check context, wrap errors.

  8. Documentation: Add clear descriptions and examples.

  9. Testing: Include at least one test per tool.

  10. Configuration: Use environment variables for config.

  11. Logging: Use structured logging (log/slog).

  12. Graceful Shutdown: Handle signals properly.

  13. Transport: Default to stdio, document alternatives.

Best Practices

  • Keep tools focused and single-purpose
  • Use descriptive names for types and functions
  • Include JSON schema documentation in struct tags
  • Always respect context cancellation
  • Return descriptive errors
  • Keep main.go minimal, logic in packages
  • Write tests for tool handlers
  • Document all exported functions

Install

Need this version hardened?

Harden your own skills

Bring Chainguard's hardening pipeline to your first-party skills — custom rulesets, automated remediation, full audit trail.

Provenance

Upstream source

—

Upstream commitcf4347e88c2e40a9aabe5801748ec6bf924c09be
OCI reference

—

License

MIT

Files

HARDENING.md

LICENSE

SKILL.md


The trusted source for open source

Talk to an expert
PrivacyTerms

Product

Chainguard ContainersChainguard LibrariesChainguard VMsChainguard OS PackagesChainguard ActionsChainguard Agent SkillsIntegrationsPricing
© 2026 Chainguard, Inc. All Rights Reserved.
Chainguard® and the Chainguard logo are registered trademarks of Chainguard, Inc. in the United States and/or other countries.
The other respective trademarks mentioned on this page are owned by the respective companies and use of them does not imply any affiliation or endorsement.