Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Release

on:
workflow_dispatch:
inputs:
bump_type:
description: 'Version bump type'
required: true
default: 'patch'
type: choice
options:
- major
- minor
- patch

permissions:
contents: write

env:
GO_VERSION: "1.25"

jobs:
release:
name: Create Library Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: true

- name: Run Tests
run: go test -v -race ./...

- name: Bump version and create tag
id: tag
uses: anothrNick/github-tag-action@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DEFAULT_BUMP: ${{ github.event.inputs.bump_type }}
TAG_PREFIX: v
VERBOSE: true

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
if: steps.tag.outputs.new_tag != ''
with:
version: latest
distribution: goreleaser
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Request pkg.go.dev indexing
if: steps.tag.outputs.new_tag != ''
run: |
TAG=${{ steps.tag.outputs.new_tag }}
echo "Requesting pkg.go.dev indexing for ${TAG}..."
curl -f "https://proxy.golang.org/github.com/tuannvm/oauth-mcp-proxy/@v/${TAG}.info" || true
echo "Visit https://pkg.go.dev/github.com/tuannvm/oauth-mcp-proxy@${TAG} to view documentation"

- name: Summary
if: steps.tag.outputs.new_tag != ''
run: |
TAG=${{ steps.tag.outputs.new_tag }}
echo "### Release ${TAG} Created! 🚀" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Install:**" >> $GITHUB_STEP_SUMMARY
echo '```bash' >> $GITHUB_STEP_SUMMARY
echo "go get github.com/tuannvm/oauth-mcp-proxy@${TAG}" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Documentation:**" >> $GITHUB_STEP_SUMMARY
echo "- [GitHub Release](https://github.com/tuannvm/oauth-mcp-proxy/releases/tag/${TAG})" >> $GITHUB_STEP_SUMMARY
echo "- [pkg.go.dev](https://pkg.go.dev/github.com/tuannvm/oauth-mcp-proxy@${TAG})" >> $GITHUB_STEP_SUMMARY
63 changes: 63 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Test

on:
push:
branches: [main, feat/*]
pull_request:
branches: [main]

permissions:
contents: read

env:
GO_VERSION: "1.25"

jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: true

- name: Download dependencies
run: go mod download

- name: Verify dependencies
run: go mod verify

- name: Run tests
run: go test -v -race -coverprofile=coverage.out ./...

- name: Check coverage
run: |
COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | sed 's/%//')
echo "Total coverage: ${COVERAGE}%"
if (( $(echo "$COVERAGE < 30" | bc -l) )); then
echo "Warning: Coverage below 30%"
fi

- name: Build all packages
run: go build ./...

- name: Build examples
run: |
cd examples/simple && go build
cd ../embedded && go build

- name: Run go vet
run: go vet ./...

- name: Check formatting
run: |
if [ -n "$(gofmt -s -l .)" ]; then
echo "Go code is not formatted:"
gofmt -s -d .
exit 1
fi
37 changes: 37 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Binaries
*.exe
*.exe~
*.dll
*.so
*.dylib
oauth-mcp-proxy

# Built binaries (from examples and testing)
/embedded
/main
/examples/simple/simple
/examples/embedded/embedded

# Test binary
*.test

# Output of the go coverage tool
*.out

# Go workspace file
go.work

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db

# Environment variables
.env
.env.local
64 changes: 64 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# GoReleaser configuration for Go library
# This project is a library, not a binary, so we skip builds and only generate releases

version: 2

before:
hooks:
- go mod tidy
- go test ./...

# Skip binary builds (this is a library)
builds:
- skip: true

# Generate changelog
changelog:
use: github
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
- "^chore:"
- Merge pull request
- Merge branch
groups:
- title: Features
regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$'
order: 0
- title: Bug Fixes
regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$'
order: 1
- title: Security
regexp: '^.*?sec(\([[:word:]]+\))??!?:.+$'
order: 2
- title: Other Changes
order: 999

# GitHub Release configuration
release:
draft: false
prerelease: auto
mode: append
header: |
## OAuth MCP Proxy {{ .Tag }}

OAuth 2.1 authentication library for Go MCP servers.

### Installation
```bash
go get github.com/tuannvm/oauth-mcp-proxy@{{ .Tag }}
```

### Documentation
- [README](https://github.com/tuannvm/oauth-mcp-proxy#readme)
- [GoDoc](https://pkg.go.dev/github.com/tuannvm/oauth-mcp-proxy@{{ .Tag }})
- [Examples](https://github.com/tuannvm/oauth-mcp-proxy/tree/{{ .Tag }}/examples)

footer: |
**Full Changelog**: https://github.com/tuannvm/oauth-mcp-proxy/compare/{{ .PreviousTag }}...{{ .Tag }}

# Announce to pkg.go.dev (optional)
announce:
skip: false
42 changes: 42 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Changelog

All notable changes to oauth-mcp-proxy will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.0.1] - 2025-10-19

**Preview Release** - Core functionality complete, pending mcp-trino migration validation (Phase 6).

### Added
- Initial extraction from mcp-trino
- OAuth 2.1 authentication for MCP servers
- Support for 4 providers: HMAC, Okta, Google, Azure AD
- Native and proxy OAuth modes
- `WithOAuth()` simple API for easy integration
- Token validation with 5-minute caching
- Pluggable logger interface
- Instance-scoped state (no globals)
- PKCE support (RFC 7636)
- Comprehensive documentation and examples
- Provider setup guides
- Security best practices guide
- Client configuration guide
- Migration guide from mcp-trino

### Fixed
- Global state → Instance-scoped (Phase 1.5)
- Hardcoded logging → Pluggable Logger interface
- Missing configuration validation

### Security
- Defense-in-depth redirect URI validation
- HMAC-signed state for proxy callbacks
- Localhost-only validation for fixed redirect mode
- Token hash logging (never log full tokens)

[Unreleased]: https://github.com/tuannvm/oauth-mcp-proxy/compare/v0.0.1...HEAD
[0.0.1]: https://github.com/tuannvm/oauth-mcp-proxy/releases/tag/v0.0.1
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 Tuan Nguyen

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
65 changes: 65 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
.PHONY: test test-verbose test-coverage lint clean fmt install help

# Variables
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")

# Default target
.DEFAULT_GOAL := help

# Run tests
test:
go test ./...

# Run tests with verbose output
test-verbose:
go test -v ./...

# Run tests with coverage
test-coverage:
go test -v -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
@echo "Coverage report generated: coverage.html"

# Run linting checks (same as CI)
lint:
@echo "Running linters..."
@go mod tidy
@if ! git diff --quiet go.mod go.sum; then echo "go.mod or go.sum is not tidy, run 'go mod tidy'"; git diff go.mod go.sum; exit 1; fi
@if ! command -v golangci-lint &> /dev/null; then echo "Installing golangci-lint..." && go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest; fi
@golangci-lint run --timeout=5m

# Format code
fmt:
go fmt ./...
gofmt -s -w .

# Clean build artifacts
clean:
rm -f coverage.out coverage.html
go clean -cache -testcache

# Install as local module (for testing)
install:
go mod download
go mod tidy

# Check for security vulnerabilities
vuln:
@if ! command -v govulncheck &> /dev/null; then echo "Installing govulncheck..." && go install golang.org/x/vuln/cmd/govulncheck@latest; fi
govulncheck ./...

# Help target
help:
@echo "oauth-mcp-proxy Makefile targets:"
@echo ""
@echo " make test Run tests"
@echo " make test-verbose Run tests with verbose output"
@echo " make test-coverage Run tests with coverage report"
@echo " make lint Run linters (same as CI)"
@echo " make fmt Format code"
@echo " make clean Clean build artifacts"
@echo " make install Download dependencies"
@echo " make vuln Check for security vulnerabilities"
@echo " make help Show this help message"
@echo ""
@echo "Version: $(VERSION)"
Loading