Implement Go MCP server to verify OAuth flow#3
Open
bettercallsaulj wants to merge 37 commits into
Open
Conversation
added 25 commits
March 13, 2026 20:19
Add CGO bindings for gopher-auth library initialization, shutdown, and version functions in a new auth.go file. Functions added: - IsAuthAvailable(): Check if auth functions are available - AuthInit(): Initialize the auth library - AuthShutdown(): Shutdown the auth library and release resources - AuthVersion(): Get the auth library version string The implementation follows the same CGO pattern as the existing library.go and uses the same CFLAGS and LDFLAGS for linking with libgopher-orch.
Extend auth.go with CGO bindings for auth client management functions. These functions enable creating and configuring auth clients for JWT token validation. New types: - AuthClientHandle: Opaque handle to a native auth client New functions: - AuthClientCreate(jwksURI, issuer string): Create auth client with JWKS endpoint and expected issuer for token validation - AuthClientDestroy(client AuthClientHandle): Destroy client and release resources, safe to call with nil - AuthClientSetOption(client AuthClientHandle, key, value string): Configure client options like cache_duration, auto_refresh, and request_timeout All functions properly handle C string allocation and deallocation using defer for memory safety.
Extend auth.go with CGO bindings for JWT token validation. New types: - ValidationResult: Go struct containing validation status with Valid (bool), ErrorCode (int32), and ErrorMessage (string) fields - gopher_auth_validation_result_t: C struct for FFI communication New functions: - AuthValidateToken(client AuthClientHandle, token string): Validates a JWT token using the auth client and returns validation result The function handles nil client gracefully by returning an error result. Error messages from the native library are properly converted to Go strings with nil pointer checking.
Extend auth.go with CGO bindings for JWT payload decoding and claim extraction without requiring token validation. New types: - AuthPayloadHandle: Opaque handle to a decoded JWT payload New functions: - AuthDecodeToken(token string): Decode JWT token without validation, returns payload handle for claim extraction - AuthPayloadDestroy(payload AuthPayloadHandle): Release payload resources, safe to call with nil - AuthPayloadGetSubject(payload AuthPayloadHandle): Get subject (sub) claim - AuthPayloadGetIssuer(payload AuthPayloadHandle): Get issuer (iss) claim - AuthPayloadGetAudience(payload AuthPayloadHandle): Get audience (aud) claim - AuthPayloadGetScope(payload AuthPayloadHandle): Get scope claim as space-separated string - AuthPayloadGetExpiry(payload AuthPayloadHandle): Get expiration time (exp) as Unix timestamp - AuthPayloadGetIssuedAt(payload AuthPayloadHandle): Get issued at (iat) as Unix timestamp All functions handle nil payload gracefully by returning empty values.
Add comprehensive unit tests for all auth FFI functions in auth_test.go. Tests include: - IsAuthAvailable: Verifies availability check works - AuthInit/AuthShutdown: Tests init/shutdown cycles don't panic - AuthVersion: Verifies non-empty version string is returned - AuthClientCreate: Tests client creation with valid parameters - AuthClientDestroy: Tests destroy with valid and nil handles - AuthClientSetOption: Tests setting various client options - AuthValidateToken: Tests validation with invalid/empty tokens and nil client - AuthDecodeToken: Tests decoding invalid token - AuthPayloadDestroy: Tests destroy with nil handle - AuthPayloadGetters: Tests all getters return empty values for nil payload Both auth.go and auth_test.go now use the 'auth' build tag since the native library does not yet export the gopher_auth_* symbols. Build with '-tags auth' once the native library is updated with auth support.
Add the basic directory structure and configuration files for the Go auth example MCP server. This follows the same project layout as the JavaScript and Python auth examples. Directory structure: - examples/auth/config/ - Configuration loading code - examples/auth/middleware/ - OAuth middleware implementation - examples/auth/routes/ - HTTP route handlers - examples/auth/tools/ - MCP tool definitions Files: - go.mod with module definition and replace directive for parent module - main.go placeholder with empty main function - server.config with all documented OAuth/OIDC options matching JS format The server.config includes settings for: - Server binding (host, port, server_url) - OAuth/OIDC provider configuration - JWKS caching options - Auth bypass mode for development
Add the configuration loading functionality for the Go auth MCP server. This provides INI-style config file parsing matching the format used by the JavaScript and Python auth examples. Implementation: - AuthServerConfig struct with all server, OAuth, scope, and cache settings - parseConfigFile() for INI-style file parsing with comment support - LoadConfigFromFile() to load and populate config from file - CreateDefaultConfig() for sensible default values The config loader handles: - Server: host, port, server_url bindings - OAuth: auth_server_url, jwks_uri, issuer, client credentials - OAuth endpoints: authorize and token URLs - Exchange IDPs as comma-separated list - Allowed scopes as space-separated string - JWKS cache settings: duration, auto-refresh, request timeout - Auth bypass mode for development Default values match typical development configuration with 3600 second JWKS cache and 30 second request timeout.
Extend the configuration loader with automatic endpoint derivation for
OAuth/OIDC endpoints. This allows users to specify just the auth_server_url
and have all required endpoints derived automatically (Keycloak pattern).
New features:
- DeriveEndpoints() method on AuthServerConfig
- parseBool() helper for flexible boolean parsing
Endpoint derivation logic (when auth_server_url is set):
- jwks_uri = {auth_server_url}/protocol/openid-connect/certs
- issuer = {auth_server_url}
- oauth_authorize_url = {auth_server_url}/protocol/openid-connect/auth
- oauth_token_url = {auth_server_url}/protocol/openid-connect/token
Endpoints are only derived if not explicitly set in config, allowing
users to override individual endpoints while still using derivation
for others.
Add comprehensive unit tests for the configuration loader module. Tests cover all aspects of config parsing, endpoint derivation, and default value creation. Tests included: - parseConfigFile() with valid INI content - parseConfigFile() handles comments and empty lines - parseConfigFile() returns error for nonexistent file - LoadConfigFromFile() with full config - Endpoint derivation from auth_server_url - Endpoint derivation with trailing slash handling - Explicit endpoint values override derivation - Server URL derivation from host and port - Server URL not derived when explicitly set - parseBool() with true/TRUE/1/yes variants - parseBool() with false/FALSE/0/no/empty variants - Integer parsing for port and durations - CreateDefaultConfig() returns expected defaults - AllowedScopes parsing from space-separated string - ExchangeIDPs parsing from comma-separated string Added testify dependency for assertions.
Add health check endpoint for the auth MCP server. This provides a
standard health monitoring endpoint that returns server status and uptime.
Implementation:
- HealthResponse struct with status, timestamp, version, uptime fields
- HealthHandler(version string) returns http.HandlerFunc
- Tracks server start time in package variable
- Calculates uptime in seconds since server start
- Uses RFC3339 format for timestamp
- Returns Content-Type: application/json header
Response format:
{
"status": "ok",
"timestamp": "2024-01-15T10:30:00Z",
"version": "1.0.0",
"uptime": 123
}
Add OAuth/OIDC discovery endpoints for the auth MCP server following RFC 9728 (Protected Resource) and RFC 8414 (Authorization Server Metadata). Endpoints implemented: - /.well-known/oauth-protected-resource (RFC 9728) - /.well-known/oauth-authorization-server (RFC 8414) ProtectedResourceResponse includes: - resource: Server MCP endpoint URL - authorization_servers: List with auth server URL - scopes_supported: Allowed scopes from config - bearer_methods_supported: header and query - resource_documentation: Server docs URL AuthorizationServerResponse includes: - issuer, authorization_endpoint, token_endpoint, jwks_uri - registration_endpoint pointing to /oauth/register - Standard response_types, grant_types, auth_methods - Code challenge methods: S256 and plain Helper functions: - RegisterOAuthRoutes() to register all OAuth endpoints - writeJSONResponse() for JSON with CORS headers - handleCORS() for OPTIONS preflight requests
Extend OAuth routes with additional endpoints for OIDC discovery, authorization redirect, and dynamic client registration. New endpoints: - /.well-known/openid-configuration (OIDC Discovery) - /oauth/authorize (redirects to IDP with query params forwarded) - /oauth/register (RFC 7591 stateless client registration) OpenIDConfigurationResponse extends RFC 8414 with: - userinfo_endpoint derived from auth_server_url - subject_types_supported: ["public"] - id_token_signing_alg_values_supported: ["RS256"] Authorize endpoint: - HTTP 302 redirect to oauth_authorize_url - All query parameters forwarded to IDP - CORS headers included Register endpoint (RFC 7591 stateless mode): - POST with JSON body containing redirect_uris - Returns client credentials from server config - client_id_issued_at: current Unix timestamp - client_secret_expires_at: 0 (never expires) - Handles OPTIONS preflight for CORS
Add JSON-RPC 2.0 types and helper functions for the MCP handler. This provides the foundation for MCP protocol communication. Types defined: - JSONRPCRequest with jsonrpc, id, method, params fields - JSONRPCResponse with jsonrpc, id, result, error fields - RPCError with code, message, data fields Error code constants: - ParseError (-32700): Invalid JSON - InvalidRequest (-32600): Invalid request object - MethodNotFound (-32601): Method not found - InvalidParams (-32602): Invalid method parameters - InternalError (-32603): Internal server error Helper functions: - sendError(): Send error response with code and message - sendErrorWithData(): Send error with additional data - sendResult(): Send success response with result All responses include: - Content-Type: application/json header - Access-Control-Allow-Origin: * header for CORS
Add the MCP handler with core JSON-RPC method implementations for the auth example server. Tool interface (tools/tool.go): - Tool interface with Name, Description, InputSchema, RequiredScope, Execute - ToolInfo struct for tools/list response metadata MCPHandler struct: - tools map for registered tools - NewMCPHandler() constructor - RegisterTool() to add tools to registry - ServeHTTP() implementing http.Handler interface Request handling: - JSON-RPC 2.0 version validation - Method routing to appropriate handler - ParseError response for invalid JSON - MethodNotFound response for unknown methods - CORS preflight handling via OPTIONS Placeholder for tools/call handler to be implemented in next prompt.
Add the tools/call method handler to the MCP server for executing registered tools with scope-based authorization. Types added: - ToolsCallParams: name and arguments from JSON-RPC params - ToolCallResult: MCP content array with isError flag - ContentItem: type and text fields for content items - AuthContext: user auth info with scopes (used by middleware) - AuthContextKey: context key for storing auth context Handler flow: 1. Parse params to get tool name and arguments 2. Look up tool in registry, return error if not found 3. Get auth context from request context 4. Check if user has required scope for the tool 5. If scope missing, return access denied response 6. Execute tool handler with arguments 7. Return tool result wrapped in content array
Add OAuth authentication middleware with token extraction logic. Uses
build tags to conditionally compile with or without native FFI support.
Files:
- oauth_auth.go (//go:build auth): Full implementation with FFI
- oauth_auth_stub.go (//go:build !auth): Stub for building without auth
OAuthAuthMiddleware struct:
- authClient: FFI handle for token validation
- config: Server configuration
Token extraction (extractToken):
- Checks Authorization header for "Bearer {token}" format
- Falls back to access_token query parameter
- Returns empty string if no token found
Updated go.mod to require gopher-orch-go for FFI package.
Extend OAuth middleware with token validation logic using FFI bindings. Both auth and stub versions now have complete Middleware implementation. Middleware function (auth version): 1. Skip auth for public paths (isPublicPath) 2. Skip auth if config.AuthDisabled is true 3. Extract token from request 4. Return 401 if token missing 5. Validate token using ffi.AuthValidateToken() 6. Return 401 with error if validation fails 7. Decode payload using ffi.AuthDecodeToken() 8. Create AuthContext from payload claims 9. Store AuthContext in request context 10. Call next handler with updated context 11. Cleanup payload handle with defer
Add example MCP tools demonstrating scope-based authorization with
deterministic weather simulation using FNV-1a hashing.
Tools implemented:
1. get-weather (no scope required):
- Input: city (string, required)
- Returns: city, temperature, condition, humidity, windSpeed
- Public access for basic weather queries
2. get-forecast (requires mcp:read):
- Input: city (string, required), days (int, default 5)
- Returns: city, unit, forecast array
- Forecast includes: day, highTemperature, lowTemperature,
condition, precipitationChance
- Limited to 14 days maximum
3. get-weather-alerts (requires mcp:admin):
- Input: region (string, required)
- Returns: region, alerts array, count
- Alerts include: id, type, severity, message, issued, expires
- 0-3 alerts generated per region
Add server entry point with command line parsing, configuration loading, route setup, and graceful shutdown handling. Two versions for different build modes. Startup sequence: 1. Parse command line flags 2. Load configuration from file 3. Apply command line overrides 4. Derive OAuth endpoints if needed 5. Initialize auth library (auth version only) 6. Create auth client with options (auth version only) 7. Create OAuth middleware 8. Create MCP handler 9. Register weather tools 10. Setup HTTP routes 11. Print startup banner 12. Start HTTP server 13. Handle graceful shutdown on SIGINT/SIGTERM
Add convenience script for building and running the auth example server, plus comprehensive documentation covering all features and usage. run_example.sh: - Checks Go version (1.21+ required) - Checks for native library availability - Supports --no-auth flag for development mode - Supports --auth flag for native build - Supports --host, --port, --config flags - Supports --help for usage information - Color-coded output for status messages - Automatic fallback to stub build if native library missing README.md covers: - Overview of the auth example - Prerequisites (Go version, native library) - Quick start instructions (with and without auth) - Configuration file format and all options - Available endpoints with curl examples - Available tools and their scope requirements - Testing with and without authentication - Troubleshooting common issues - Project structure overview
Update build.sh to build the auth example as part of the standard build process. New Step 5 - Build auth example: - Builds stub mode version (auth-server) without native library - Attempts native auth build (auth-server-native) if library exists - Gracefully handles missing auth symbols in native library Updated final output: - Shows auth example binary location - Adds instructions for running auth example Build produces: - examples/auth/auth-server (stub mode, always works) - examples/auth/auth-server-native (native auth, optional)
Remove build tag system and stub files. The auth example now always requires the native library to build and run. Changes: - Remove //go:build auth tags from all files - Delete stub files (main.go stub, oauth_auth_stub.go) - Rename main_auth.go to main.go - Simplify build.sh to always build with CGO flags - Update run_example.sh to require native library Removed files: - examples/auth/main_auth.go (merged into main.go) - examples/auth/middleware/oauth_auth_stub.go Updated files: - src/ffi/auth.go - removed build tag - src/ffi/auth_test.go - removed build tag - examples/auth/main.go - removed build tag - examples/auth/middleware/oauth_auth.go - removed build tag - examples/auth/run_example.sh - requires native library - build.sh - simplified auth example build step
…lity (#2) Update OAuth endpoints and middleware to work correctly with MCP Inspector's OAuth flow, matching the JS implementation behavior. Changes: - Update submodule to br_release branch (v0.1.2) - Add /.well-known/oauth-protected-resource/mcp endpoint - Fix authorization_servers to point to local server URL - Add comprehensive CORS headers with MCP-specific headers - Handle OPTIONS preflight requests in auth middleware - Add 'none' to token_endpoint_auth_methods_supported for PKCE - Use localhost instead of 0.0.0.0 for client-facing URLs - Add -tags auth to run_example.sh build command - Update build.sh to always pull latest from branch in .gitmodules
Add release infrastructure for Go SDK: - dump-version.sh: Prepares releases by updating CHANGELOG.md and creating git tags - install-native.sh: Helper script for users to download native libraries - CHANGELOG.md: Initial changelog with Keep a Changelog format - .github/workflows/release.yml: CI workflow to create GitHub Release with native binaries Release flow: ./dump-version.sh -> git push origin br_release vX.Y.Z
Make the auth example self-contained so it can be used by third-party developers without needing the full gopher-mcp-go repository locally. Changes: - Remove replace directive from go.mod, use SDK via go get - Update imports from gopher-orch-go to gopher-mcp-go - Rewrite run_example.sh to download native libs from GitHub releases - Add SDK_VERSION and NATIVE_LIB_DIR environment variable support - Update README with installation and troubleshooting instructions - Add .gitignore for native/ directory and build artifacts
5f4fb65 to
8877fca
Compare
added 4 commits
March 22, 2026 01:21
Module rename: - Change module path from gopher-orch-go to gopher-mcp-go - Update all imports to use new module path - Add replace directive for local development Linker fixes: - Remove invalid -lfmt from LDFLAGS (library doesn't exist) - Fix in build.sh, run_example.sh, and FFI files
- Remove replace directive (use published SDK from GitHub) - Download native libraries from gopher-mcp-go releases - Default to latest release
Align release.yml with publish.md documentation: - Download native binaries from gopher-orch using same version tag - Simplify download and prepare steps - Remove verbose logging The Go SDK version must match a gopher-orch release version. Use dump-version.sh to ensure version alignment.
Extract base version (X.Y.Z) from extended version (X.Y.Z.E) when downloading native binaries from gopher-orch. Example: Go SDK v0.1.2.1 downloads from gopher-orch v0.1.2
added 8 commits
March 22, 2026 01:36
- Fetch latest SDK version from GitHub releases automatically - Use go get instead of go mod download to trigger proxy.golang.org - Update go.mod with the latest version - Add documentation about pkg.go.dev indexing
Go's semver does not support 4-part versions (X.Y.Z.E). Convert to prerelease format (X.Y.Z-E) which is valid Go semver. - dump-version.sh: Convert 0.1.2.3 -> 0.1.2-3 - release.yml: Extract base version 0.1.2 from 0.1.2-3
X.Y.Z-N (numeric extension like 0.1.2-4) should NOT be marked as prerelease. Only actual prereleases like -rc1, -alpha, -beta should be marked as prerelease.
Drop old SDK dependency before go get to avoid version conflict with cached modules that have incorrect module path.
After fetching the SDK via go get, explicitly trigger pkg.go.dev indexing by fetching module info through proxy.golang.org.
- Rename title from gopher-orch to gopher-mcp-go - Update all import paths from gopher-orch-go to gopher-mcp-go - Fix license from MIT to Apache License 2.0 (matches LICENSE file)
- Add OAuth 2.0 Authentication to features list - Add Auth Example section with usage instructions - Document server endpoints and configuration options
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR must be merge after #1