mcp-server

module
v0.0.0-...-6ceb34c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 31, 2026 License: MIT

README

MCP-Server

MCP Server Logo

A Model Context Protocol (MCP) server built with Go, supporting both stdio and HTTP transports for integration with MCP-compatible clients.

Features

  • MCP protocol support via go-sdk
  • Dual transport modes: stdio (CLI) and HTTP (Streamable HTTP)
  • API key authentication middleware for HTTP transport
  • Prometheus metrics with path, method, and status labels
  • Structured JSON logging via slog
  • Configuration via environment variables
  • Distroless Docker image for minimal attack surface
  • Comprehensive unit tests with table-driven patterns using only standard library no external test frameworks

Tools

Tool Description
generate_uuid Generate a UUID v4

Want to add your own tool? Check out the Developer Guide for a step-by-step walkthrough.

MCP Design Flowchart: The flowchart can help guide you during a new tool implementation. Flowchart

Requirements

  • Docker and Docker Compose (recommended)
  • Go 1.25+ (for local development only)
  • Make (optional, for convenience targets)

Endpoints (HTTP Transport)

Endpoint Method Auth Required Description
/health GET No Health check
/metrics GET No Prometheus metrics
/mcp POST Yes* MCP HTTP endpoint

*When AUTH_ENABLED=true

Quick Start

# 1. Configure environment
make config

# 2. Edit .env to set your API key (optional but recommended)
#    API_KEYS=your-secret-key

# 3. Start the server
make docker-up

# 4. Verify it's running
curl http://localhost:8080/health

# 5. View logs
make docker-logs

# 6. Check the health endpoint
curl http://localhost:8080/health

For local development without Docker, see the Development section.

Configuration

All configuration is via environment variables.

Variable Default Description
PORT 8080 Server port
MCP_TRANSPORT stdio Transport mode: stdio or http
AUTH_ENABLED false Enable API key authentication (HTTP only)
API_KEYS Comma-separated list of valid API keys
# Example: Run HTTP with authentication
MCP_TRANSPORT=http AUTH_ENABLED=true API_KEYS="key1,key2" make run

Transport Modes

Stdio (default): For use with Claude Desktop and CLI tools. The server communicates via stdin/stdout.

make run

HTTP: For HTTP-based deployments. Exposes the MCP protocol over Streamable HTTP.

MCP_TRANSPORT=http make run

Authentication

For simplicity API key authentication is implemented in the middleware. This can obviously be replaced with a more robust solution as needed.

When AUTH_ENABLED=true, the /mcp endpoint requires a valid API key in the X-API-Key header.

# Generate a secure API key
openssl rand -hex 32

# Request with API key
curl -X POST http://localhost:8080/mcp \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{...}}'

Unauthenticated requests return 401 Unauthorized:

{"error":"missing API key"}

Invalid keys return:

{"error":"invalid API key"}

Claude Code Integration - Example Config

For Claude Code with HTTP transport:

{
  "mcpServers": {
    "mcp-server": {
      "type": "http",
      "url": "http://localhost:8080/mcp",
      "headers": {
        "X-API-Key": "your-api-key"
      }
    }
  }
}

Curl Examples

Health Check:

curl http://localhost:8080/health

Metrics:

curl http://localhost:8080/metrics

MCP Initialize (with auth):

curl -X POST http://localhost:8080/mcp \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

Docker

The Docker image uses a multi-stage build with a distroless runtime image for security.

# Build and run standalone container (HTTP mode)
make docker-run

# Run with auth enabled
AUTH_ENABLED=true API_KEYS="secret-key" make docker-run

# Stop and remove container
make docker-clean
Docker Compose
# Start services
make docker-up

# View logs
make docker-logs

# Restart services
make docker-restart

# Stop services
make docker-down

Project Structure

.
├── cmd/                      # Application entrypoint
│   └── mcp-server.go         # Main server with transport switching
├── internal/
│   ├── config/               # Environment configuration
│   ├── handlers/             # HTTP handlers (health)
│   ├── middleware/           # Auth and metrics middleware
│   └── tools/                # MCP tool implementations
│       └── uuid/             # UUID generation tool
├── example.env               # Example environment file
├── docker-compose.yml        # Docker Compose configuration
├── Dockerfile                # Multi-stage distroless build
├── Makefile                  # Build and run targets
├── DEVELOPER_GUIDE.md        # Guide for adding new tools
└── README.md                 # This file

Development

Requires Go 1.24+ for local development.

# Build and run locally (stdio mode)
make run

# Run with HTTP transport
MCP_TRANSPORT=http make run

# Run tests
make test

# Run tests with verbose output
make test-verbose

# Run tests with coverage
make coverage

# Generate HTML coverage report
make coverage-html

# Run linter
make lint

# Format code
make fmt

Adding Tools

See DEVELOPER_GUIDE.md for a complete walkthrough on adding new tools.

Quick overview:

  1. Create a new package in internal/tools/<toolname>/
  2. Implement the tool with Input/Output structs
  3. Register via init() with tools.Register()
  4. Add blank import in cmd/mcp-server.go

Example:

package mytool

import (
    "context"

    "github.com/modelcontextprotocol/go-sdk/mcp"
    "github.com/lkendrickd/mcp-server/internal/tools"
)

type Input struct {
    Name string `json:"name" jsonschema:"description=The name to greet"`
}

type Output struct {
    Message string `json:"message"`
}

func Greet(_ context.Context, _ *mcp.CallToolRequest, input Input) (*mcp.CallToolResult, Output, error) {
    return nil, Output{Message: "Hello, " + input.Name}, nil
}

func init() {
    tools.Register(func(s *mcp.Server) {
        mcp.AddTool(s, &mcp.Tool{
            Name:        "greet",
            Description: "Greet someone by name",
        }, Greet)
    })
}

Make Targets

make help  # Show all available targets
Target Description
make Show help
make config Create .env from example.env
make build Build the binary
make run Build and run locally
make test Run unit tests
make test-verbose Run tests with verbose output
make coverage Run tests with coverage
make lint Run golangci-lint
make fmt Format code
make docker-build Build Docker image
make docker-run Build and run container
make docker-clean Stop and remove container
make docker-up Start with docker-compose
make docker-down Stop docker-compose
make docker-logs View docker-compose logs
make docker-restart Restart docker-compose

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL