mcp

package module
v0.6.5 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 14 Imported by: 0

README

GoREST-MCP Plugin

CI Go Report Card License

The gorest-mcp plugin integrates the Model Context Protocol (MCP) into GoREST applications, enabling AI agents (like Claude) to interact with GoREST APIs through a standardized protocol.

Features

  • MCP Server Embedded: Full MCP server as a GoREST plugin endpoint
  • SSE Transport: Server-Sent Events for real-time AI agent communication
  • JWT Authentication: Secure access using existing GoREST authentication
  • CRUD Operations: Expose database operations as MCP tools
  • Schema Introspection: Runtime API discovery for AI agents
  • Multi-Database Support: PostgreSQL, MySQL, SQLite

Installation

go get github.com/nicolasbonnici/gorest-mcp@v0.1.0

Quick Start

1. Add MCP Plugin to Your GoREST Application
package main

import (
    "log"

    "github.com/nicolasbonnici/gorest"
    mcp "github.com/nicolasbonnici/gorest-mcp"
)

func main() {
    app, err := gorest.New(&gorest.Config{
        AppName: "My API",
        Port:    8080,
        Plugins: []gorest.PluginConfig{
            {
                Name:    "mcp",
                Enabled: true,
                Config: map[string]interface{}{
                    "enabled": true,
                    "enabled_operations": []string{"crud", "schema"},
                },
            },
        },
    })

    if err != nil {
        log.Fatal(err)
    }

    // Register MCP plugin
    mcpPlugin := &mcp.Plugin{}
    app.RegisterPlugin(mcpPlugin)

    // Start server
    app.Listen(":8080")
}
2. Authenticate and Get JWT Token
# Login to get JWT token
curl -X POST http://localhost:8080/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"password123"}'

# Response: {"token":"eyJhbGc...","user":{...}}
3. Connect AI Agent via SSE

Configure your MCP client (e.g., Claude Desktop):

{
  "mcpServers": {
    "my-api": {
      "url": "http://localhost:8080/mcp",
      "transport": "sse",
      "headers": {
        "Authorization": "Bearer YOUR_JWT_TOKEN"
      }
    }
  }
}
4. Use MCP Tools

Once connected, AI agents can use these tools:

  • gorest_list_resources - List resources with filtering/pagination
  • gorest_get_resource - Get a single resource by ID
  • gorest_create_resource - Create a new resource
  • gorest_update_resource - Update an existing resource
  • gorest_delete_resource - Delete a resource

And access these resources:

  • gorest://resources - List all available API resources
  • gorest://schema/{resource} - Get schema for a specific resource

Configuration

Full Configuration Example
plugins:
  - name: mcp
    enabled: true
    config:
      # Features
      enabled_operations:
        - crud                         # CRUD tools
        - schema                       # Schema introspection

      # Rate limiting (requests per minute)
      rate_limit:
        enabled: true
        requests_per_minute: 60
        burst: 10

      # SSE settings
      sse:
        heartbeat_interval: 30         # Seconds between heartbeat events
        connection_timeout: 300        # Seconds before idle connection closes
        max_connections_per_user: 3    # Max concurrent SSE connections

      # Logging
      log_requests: true
      log_level: "info"                # debug, info, warn, error
Environment Variables
# Required (inherited from GoREST auth)
JWT_SECRET=your-secret-key-min-32-chars

# Optional (plugin-specific)
MCP_ENABLED=true
MCP_RATE_LIMIT=60
MCP_LOG_LEVEL=info

Architecture

┌─────────────────────────────────────────┐
│       GoREST Application                │
├─────────────────────────────────────────┤
│  Core Middleware                         │
│  ├── Security, CORS, Logger              │
│  └── Content Negotiation                 │
├─────────────────────────────────────────┤
│  Plugin Middleware                       │
│  ├── Auth Plugin (JWT validation)        │
│  └── MCP Plugin                          │
├─────────────────────────────────────────┤
│  Routes                                  │
│  ├── /api/v1/resources (standard CRUD)   │
│  ├── /auth/* (login, register)           │
│  └── /mcp (SSE endpoint) ─────┐          │
└────────────────────────────────┼──────────┘
                                 │
                                 ▼
                    ┌────────────────────┐
                    │   MCP Protocol     │
                    │   ├── SSE Transport│
                    │   ├── Tool Registry│
                    │   └── Resources    │
                    └────────────────────┘
                                 │
                                 ▼
                        ┌────────────┐
                        │ AI Agent   │
                        │ (Claude)   │
                        └────────────┘

MCP Tools Reference

gorest_list_resources

List all resources with pagination and filtering.

Parameters:

{
  "resource": "posts",       // Required: resource name
  "limit": 20,               // Optional: items per page (default: 20)
  "offset": 0,               // Optional: offset (default: 0)
  "filters": {               // Optional: filter conditions
    "status": "published"
  },
  "order_by": "created_at",  // Optional: sort field
  "order": "desc"            // Optional: asc/desc
}
gorest_get_resource

Get a single resource by ID.

Parameters:

{
  "resource": "posts",       // Required: resource name
  "id": "uuid-or-id"         // Required: resource ID
}
gorest_create_resource

Create a new resource.

Parameters:

{
  "resource": "posts",       // Required: resource name
  "data": {                  // Required: resource data
    "title": "New Post",
    "content": "..."
  }
}
gorest_update_resource

Update an existing resource.

Parameters:

{
  "resource": "posts",       // Required: resource name
  "id": "uuid-here",         // Required: resource ID
  "data": {                  // Required: update data
    "title": "Updated Title"
  }
}
gorest_delete_resource

Delete a resource.

Parameters:

{
  "resource": "posts",       // Required: resource name
  "id": "uuid-here"          // Required: resource ID
}

MCP Resources Reference

gorest://resources

List all available resources in the API.

Response:

{
  "resources": [
    {
      "name": "posts",
      "table": "posts",
      "description": "Blog posts",
      "endpoints": ["GET /api/posts", "POST /api/posts", ...]
    }
  ]
}
gorest://schema/{resource}

Get schema definition for a resource.

Response:

{
  "resource": "posts",
  "table": "posts",
  "fields": [
    {
      "name": "id",
      "type": "uuid",
      "nullable": false,
      "primary_key": true
    }
  ]
}

Security

Authentication Flow
  1. Login: Get JWT token from /auth/login
  2. Connect: Pass token via Authorization: Bearer <token> header
  3. Validate: MCP plugin validates JWT on every request
  4. Authorize: RBAC enforced via GoREST hooks
Best Practices
  • Use HTTPS in production for SSE connections
  • Rotate JWT secrets regularly (minimum 32 characters)
  • Set short token expiry (default: 1 hour, configurable)
  • Enable rate limiting to prevent abuse
  • Monitor connections using logs and metrics

Development

Build
make build
Test
make test
Run Example
cd examples/basic
go run main.go
Run with Docker
docker build -t gorest-mcp .
docker run -p 8080:8080 -e JWT_SECRET=your-secret gorest-mcp

Version 0.1.0 Notes

This is the initial release with core functionality:

  • ✅ Plugin interface implementation
  • ✅ SSE transport with JWT authentication
  • ✅ MCP server initialization with mark3labs/mcp-go
  • ✅ Tool registration (CRUD placeholders)
  • ✅ Resource registration (schema placeholders)
  • ✅ Configuration system
  • ✅ Rate limiting
  • ✅ Connection management

Coming in v0.2.0:

  • Full CRUD operations with database integration
  • Complete schema introspection
  • Enhanced error handling
  • Comprehensive tests
  • Performance optimizations

Examples

See the examples/ directory for:

  • basic/ - Basic GoREST app with MCP plugin
  • claude-desktop/ - Claude Desktop configuration

Documentation

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

MIT License - see LICENSE for details

Support

Acknowledgments

Built with:

Documentation

Index

Constants

View Source
const (
	CodeParseError     = -32700
	CodeInvalidRequest = -32600
	CodeMethodNotFound = -32601
	CodeInvalidParams  = -32602
	CodeInternalError  = -32603

	// Custom error codes (application-specific)
	CodeUnauthorized           = -32000
	CodeForbidden              = -32001
	CodeRateLimitExceeded      = -32002
	CodeResourceNotFound       = -32003
	CodeOperationDisabled      = -32004
	CodeMaxConnectionsExceeded = -32005
	CodeConnectionTimeout      = -32006
)

Error code constants following JSON-RPC 2.0 spec

View Source
const (
	// Version is the current version of the gorest-mcp plugin
	Version = "0.1.0"

	// VersionMajor is the major version number
	VersionMajor = 0

	// VersionMinor is the minor version number
	VersionMinor = 1

	// VersionPatch is the patch version number
	VersionPatch = 0
)

Version information

Variables

View Source
var (
	// ErrUnauthorized indicates missing or invalid authentication
	ErrUnauthorized = errors.New("unauthorized: invalid or missing JWT token")

	// ErrForbidden indicates insufficient permissions
	ErrForbidden = errors.New("forbidden: insufficient permissions")

	// ErrRateLimitExceeded indicates rate limit has been exceeded
	ErrRateLimitExceeded = errors.New("rate limit exceeded")

	// ErrInvalidRequest indicates malformed request
	ErrInvalidRequest = errors.New("invalid request")

	// ErrResourceNotFound indicates requested resource doesn't exist
	ErrResourceNotFound = errors.New("resource not found")

	// ErrOperationDisabled indicates the requested operation is disabled
	ErrOperationDisabled = errors.New("operation disabled")

	// ErrMaxConnectionsExceeded indicates user has too many active connections
	ErrMaxConnectionsExceeded = errors.New("maximum connections exceeded")

	// ErrConnectionTimeout indicates connection idle timeout
	ErrConnectionTimeout = errors.New("connection timeout")
)

Functions

func Contains

func Contains(slice []string, value string) bool

Contains checks if a slice contains a value

func FromJSON

func FromJSON(data string, v interface{}) error

FromJSON parses JSON string into a value

func GetUserEmailFromContext

func GetUserEmailFromContext(ctx context.Context) (string, error)

GetUserEmailFromContext extracts the user email from context

func GetUserIDFromContext

func GetUserIDFromContext(ctx context.Context) (string, error)

GetUserIDFromContext extracts the user ID from context

func GetUserRolesFromContext

func GetUserRolesFromContext(ctx context.Context) ([]string, error)

GetUserRolesFromContext extracts the user roles from context

func GetVersion

func GetVersion() string

GetVersion returns the full version string

func HandleSSE

func HandleSSE(c fiber.Ctx, mcpServer *MCPServer, config *Config, log *slog.Logger) error

func NewPlugin added in v0.1.3

func NewPlugin() plugin.Plugin

NewPlugin creates a new MCP plugin instance

func Ptr

func Ptr[T any](v T) *T

Ptr returns a pointer to a value

func ToJSON

func ToJSON(v interface{}) (string, error)

ToJSON converts a value to JSON string

Types

type Config

type Config struct {
	Enabled           bool            `json:"enabled" yaml:"enabled"`
	EnabledOperations []string        `json:"enabled_operations" yaml:"enabled_operations"`
	RateLimit         RateLimitConfig `json:"rate_limit" yaml:"rate_limit"`
	SSE               SSEConfig       `json:"sse" yaml:"sse"`
	LogRequests       bool            `json:"log_requests" yaml:"log_requests"`
	LogLevel          string          `json:"log_level" yaml:"log_level"`
}

Config holds the MCP plugin configuration

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns the default MCP plugin configuration

func ParseConfig

func ParseConfig(cfg interface{}) (*Config, error)

ParseConfig parses configuration from various formats

func (*Config) GetConnectionTimeout

func (c *Config) GetConnectionTimeout() time.Duration

GetConnectionTimeout returns the connection timeout as time.Duration

func (*Config) GetHeartbeatInterval

func (c *Config) GetHeartbeatInterval() time.Duration

GetHeartbeatInterval returns the heartbeat interval as time.Duration

func (*Config) IsOperationEnabled

func (c *Config) IsOperationEnabled(operation string) bool

IsOperationEnabled checks if a specific operation is enabled

func (*Config) Validate

func (c *Config) Validate() error

Validate checks if the configuration is valid

type ConnectionPool

type ConnectionPool struct {
	// contains filtered or unexported fields
}

ConnectionPool tracks active SSE connections per user

func (*ConnectionPool) AddConnection

func (cp *ConnectionPool) AddConnection(userID string) error

AddConnection adds a new connection for a user

func (*ConnectionPool) RemoveConnection

func (cp *ConnectionPool) RemoveConnection(userID string)

RemoveConnection removes a connection for a user

type ContextKey

type ContextKey string

ContextKey is a custom type for context keys to avoid collisions

const (
	// ContextKeyUserID stores the authenticated user ID in context
	ContextKeyUserID ContextKey = "user_id"

	// ContextKeyUserEmail stores the authenticated user email in context
	ContextKeyUserEmail ContextKey = "user_email"

	// ContextKeyUserRoles stores the authenticated user roles in context
	ContextKeyUserRoles ContextKey = "user_roles"
)

type MCPError

type MCPError struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Data    any    `json:"data,omitempty"`
	Err     error  `json:"-"`
}

MCPError wraps an error with additional context for MCP protocol

func NewMCPError

func NewMCPError(code int, message string, err error) *MCPError

NewMCPError creates a new MCP error

func WrapError

func WrapError(err error) *MCPError

WrapError wraps a standard error into an MCPError

func (*MCPError) Error

func (e *MCPError) Error() string

Error implements the error interface

func (*MCPError) Unwrap

func (e *MCPError) Unwrap() error

Unwrap allows errors.Is and errors.As to work

type MCPServer

type MCPServer struct {
	// contains filtered or unexported fields
}

func NewMCPServer

func NewMCPServer(config *Config, db database.Database, log *slog.Logger) (*MCPServer, error)

func (*MCPServer) GetServer

func (s *MCPServer) GetServer() *server.MCPServer

GetServer returns the underlying MCP server for SSE transport

func (*MCPServer) HandleRequest

func (s *MCPServer) HandleRequest(ctx context.Context, request interface{}) (interface{}, error)

HandleRequest processes an MCP request with user context

type Plugin

type Plugin struct {
	// contains filtered or unexported fields
}

func (*Plugin) Handler

func (p *Plugin) Handler() fiber.Handler

func (*Plugin) Initialize

func (p *Plugin) Initialize(cfg map[string]any) error

func (*Plugin) Name

func (p *Plugin) Name() string

func (*Plugin) SetupEndpoints

func (p *Plugin) SetupEndpoints(router fiber.Router) error

type RateLimitConfig

type RateLimitConfig struct {
	Enabled           bool `json:"enabled" yaml:"enabled"`
	RequestsPerMinute int  `json:"requests_per_minute" yaml:"requests_per_minute"`
	Burst             int  `json:"burst" yaml:"burst"`
}

RateLimitConfig configures rate limiting for MCP requests

type SSEConfig

type SSEConfig struct {
	HeartbeatInterval     int `json:"heartbeat_interval" yaml:"heartbeat_interval"` // Seconds
	ConnectionTimeout     int `json:"connection_timeout" yaml:"connection_timeout"` // Seconds
	MaxConnectionsPerUser int `json:"max_connections_per_user" yaml:"max_connections_per_user"`
}

SSEConfig configures Server-Sent Events behavior

Directories

Path Synopsis
examples
basic command

Jump to

Keyboard shortcuts

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