mcp

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Nov 24, 2025 License: Apache-2.0 Imports: 18 Imported by: 0

README

MCP Plugin for AuthSome

The MCP (Model Context Protocol) plugin exposes AuthSome's data and operations to AI assistants through Anthropic's standardized protocol.

What is MCP?

Model Context Protocol (MCP) is an open protocol developed by Anthropic that standardizes how AI assistants interact with external systems. It provides:

  • Resources: Read-only context (configuration, schemas, data)
  • Tools: Interactive operations (queries, checks, modifications)
  • Security: Built-in authorization and sanitization
  • Transport-agnostic: Works over stdio, HTTP, or SSE

Benefits for AuthSome

1. Developer Experience
  • Natural language queries: "Show me users created in the last week"
  • Debug authentication flows: "Why did user@example.com's login fail?"
  • Schema exploration: "What fields does the User model have?"
  • API documentation: Generates integration code from actual configuration
2. Security & Auditing
  • AI-assisted analysis: "Find suspicious login patterns from IP 203.0.113.45"
  • RBAC verification: "Does user X have permission to delete organization Y?"
  • Audit log search: Semantic search across security events
3. Administrative Tasks
  • User management: "Create a test user in organization XYZ"
  • Session control: "Show all active sessions for user@example.com"
  • Multi-tenant operations: "List organizations with failed payment status"

Architecture

┌─────────────────┐
│  AI Assistant   │
│  (Claude, etc)  │
└────────┬────────┘
         │ MCP Protocol (JSON-RPC)
         │
┌────────▼────────┐
│   MCP Server    │
│  (this plugin)  │
├─────────────────┤
│  Resources      │  ← Read-only context
│  - config       │
│  - schema       │
│  - routes       │
│  - users        │
│  - sessions     │
│  - audit logs   │
├─────────────────┤
│  Tools          │  ← Interactive operations
│  - query_user   │
│  - check_perm   │
│  - search_audit │
├─────────────────┤
│  Security       │
│  - Sanitization │
│  - RBAC         │
│  - Rate limit   │
└────────┬────────┘
         │
┌────────▼────────┐
│   AuthSome      │
│   Core Services │
└─────────────────┘

Configuration

Standalone Mode (Development)
mode: standalone

plugins:
  mcp:
    enabled: true
    mode: development  # Allow test data creation
    transport: stdio
    authorization:
      require_api_key: false  # Trust local process
SaaS Mode (Production)
mode: saas

plugins:
  mcp:
    enabled: true
    mode: readonly  # Strict read-only
    transport: http
    http_port: 9090
    authorization:
      require_api_key: true
      allowed_operations:
        - query_user
        - search_audit_logs
        - check_permission
    rate_limit:
      requests_per_minute: 30

Operation Modes

1. readonly (Default, Safest)
  • Only read operations and read-only tools
  • No data modification
  • Recommended for production

Allowed:

  • query_user - Find users
  • list_sessions - View sessions
  • check_permission - Verify RBAC
  • search_audit_logs - Search audit trail
  • explain_route - Get API documentation
  • validate_policy - Check RBAC syntax
2. admin (Controlled Write)
  • Read operations + administrative writes
  • Requires API key with admin role
  • For authorized administrators

Additional:

  • revoke_session - Terminate sessions
  • rotate_api_key - Rotate keys
3. development (Full Access)
  • All operations including dangerous ones
  • Create test data
  • NEVER use in production

Additional:

  • create_test_user - Generate test users
  • create_test_org - Generate test organizations
  • seed_data - Populate test database

Transport Options

Stdio (Default)
  • Uses stdin/stdout for communication
  • Perfect for local development
  • Inherits process permissions
  • No network exposure
# Start MCP server with stdio
authsome mcp serve --config=config.yaml

# AI assistant connects via stdio
claude-desktop mcp://authsome-mcp-serve
HTTP
  • REST API over HTTPS
  • For remote AI assistants
  • Requires API key authentication
  • Can be rate-limited
# Start HTTP MCP server
authsome mcp serve --config=config.yaml --transport=http --port=9090

# AI assistant connects via HTTP
curl -X POST http://localhost:9090/api/mcp \
  -H "X-API-Key: your-api-key" \
  -d '{"method": "resources/list"}'

CLI Usage

Start MCP Server
# Read-only mode (default)
authsome mcp serve --config=config.yaml

# Admin mode
authsome mcp serve --config=config.yaml --mode=admin

# Development mode (INSECURE)
authsome mcp serve --config=config.yaml --mode=development --no-auth

# HTTP transport
authsome mcp serve --config=config.yaml --transport=http --port=9090
Flags
  • --config=PATH - Configuration file (required)
  • --mode=MODE - Operation mode: readonly, admin, development
  • --transport=TYPE - Transport: stdio, http
  • --port=PORT - HTTP port (default: 9090)
  • --no-auth - Disable API key requirement (INSECURE)

Available Resources

Resources provide read-only context to AI assistants.

authsome://config

Sanitized configuration (secrets removed)

{
  "mode": "saas",
  "base_path": "/api/auth",
  "plugins": ["multitenancy", "twofa", "sso"]
}
authsome://schema/[entity]

Database schema documentation

{
  "user": {
    "fields": {
      "id": {"type": "string", "description": "User UUID"},
      "email": {"type": "string", "description": "Email address"},
      "name": {"type": "string", "description": "Display name"}
    }
  }
}
authsome://routes

Registered API routes

{
  "routes": [
    {
      "method": "POST",
      "path": "/api/auth/signup",
      "description": "User registration",
      "auth": "none"
    }
  ]
}
authsome://users?org_id=X&limit=50

User list (sanitized, respects RBAC)

authsome://sessions?user_id=X&active=true

Active/recent sessions

authsome://audit?action=login&limit=100

Audit log entries

authsome://rbac/policies

RBAC policies and roles

Available Tools

Tools allow AI to perform operations.

Read-Only Tools
query_user

Find user by email/ID/username

{
  "name": "query_user",
  "arguments": {
    "email": "test@example.com"
  }
}

Returns sanitized user data (no password hashes).

check_permission

Verify if user has permission

{
  "name": "check_permission",
  "arguments": {
    "user_id": "user-123",
    "action": "delete",
    "resource": "organization:org-456"
  }
}

Returns boolean + explanation.

search_audit_logs

Search audit logs

{
  "name": "search_audit_logs",
  "arguments": {
    "query": "failed login attempts from suspicious IP",
    "limit": 50
  }
}
Admin Tools (Require Admin Mode)
revoke_session

Revoke specific session

{
  "name": "revoke_session",
  "arguments": {
    "session_id": "session-789"
  }
}
rotate_api_key

Rotate API key

{
  "name": "rotate_api_key",
  "arguments": {
    "key_id": "key-101"
  }
}
Development Tools (Require Development Mode)
create_test_user

Create test user

{
  "name": "create_test_user",
  "arguments": {
    "email": "test@example.com",
    "organization_id": "org-123"
  }
}

Security

Data Sanitization

Always Removed:

  • password_hash
  • twofa_secret
  • backup_codes
  • oauth_tokens
  • API key secrets

Conditionally Masked (readonly mode):

  • Email addresses (partial)
  • Phone numbers (partial)
  • IP addresses (partial)
Authorization Layers
  1. Transport Security

    • Stdio: Process isolation
    • HTTP: API key + HTTPS
  2. Operation Authorization

    • Mode-based operation filtering
    • Role-based access (admin operations)
  3. RBAC Integration

    • Resource queries respect AuthSome's RBAC
    • Multi-tenant isolation enforced
  4. Rate Limiting

    • Configurable requests per minute
    • Uses AuthSome's rate limiter
  5. Audit Logging

    • All tool invocations logged
    • Includes user context and outcome

Usage Examples

Example 1: Developer Debugging

Scenario: User can't log in

AI: "Show me the user with email test@example.com"
→ Tool: query_user(email="test@example.com")
→ Result: User found, emailVerified=false

AI: "That explains it - email not verified. Check recent verification emails."
→ Resource: authsome://audit?user_id=X&action=email.sent
Example 2: Security Analysis

Scenario: Suspicious activity detected

AI: "Show login attempts from IP 203.0.113.45 in last 24h"
→ Resource: authsome://audit?ip=203.0.113.45&action=login.attempt
→ Analysis: 47 failed attempts, different user accounts
→ AI: "Credential stuffing attack detected. Recommend blocking IP."
Example 3: API Integration Help

Scenario: Developer needs to integrate

AI: "How do I create a user with 2FA enabled?"
→ Resource: authsome://routes (find user creation endpoint)
→ Resource: authsome://schema/user (get required fields)
→ AI generates:
   POST /api/auth/signup
   {
     "email": "user@example.com",
     "password": "...",
     "twoFactorEnabled": true
   }

Testing

Manual Testing
# Start MCP server
authsome mcp serve --config=test-config.yaml --mode=development

# In another terminal, send MCP requests
echo '{"jsonrpc":"2.0","id":1,"method":"resources/list","params":{}}' | \
  authsome mcp serve --config=test-config.yaml
Integration Testing
func TestMCPPlugin(t *testing.T) {
    // Create test auth instance
    auth := authsome.New(...)
    
    // Register MCP plugin
    mcpPlugin := mcp.NewPlugin(mcp.WithDefaultConfig(mcp.DefaultConfig()))
    auth.RegisterPlugin(mcpPlugin)
    
    // Initialize
    auth.Initialize(context.Background())
    
    // Test resource reading
    server := mcpPlugin.GetServer()
    content, err := server.ReadResource(ctx, "authsome://config")
    assert.NoError(t, err)
    assert.Contains(t, content, "mode")
}

Troubleshooting

"API key required but not provided"
  • Solution: Add --no-auth flag (development only) or provide valid API key
"Operation not allowed"
  • Solution: Change mode (e.g., --mode=admin for admin operations)
"Resource not found"
  • Solution: Check resource URI syntax, ensure plugin initialized
"RBAC service not available"
  • Solution: Ensure AuthSome fully initialized before starting MCP

Performance Considerations

  • Caching: Resource responses can be cached (use ETags in HTTP mode)
  • Pagination: Large result sets are automatically paginated
  • Rate Limiting: Prevents abuse, configurable per deployment
  • Connection Pooling: HTTP mode reuses database connections

Roadmap

v0.2 (Next Release)
  • HTTP transport implementation
  • Streaming resource updates (Server-Sent Events)
  • More tools: list_sessions, search_audit_logs
  • Custom resource filters via query params
v0.3 (Future)
  • WebSocket transport
  • Real-time subscription support
  • Organization-scoped MCP sessions
  • Plugin for custom resources/tools

Contributing

To add new resources or tools:

  1. Create Resource Handler
type MyResource struct{}

func (r *MyResource) Describe() ResourceDescription {
    return ResourceDescription{
        URI: "authsome://myresource",
        Name: "My Resource",
        Description: "...",
    }
}

func (r *MyResource) Read(ctx context.Context, uri string, plugin *Plugin) (string, error) {
    // Implementation
}
  1. Register in server.go
func (s *Server) registerResources() {
    s.resources.Register("authsome://myresource", &MyResource{})
}
  1. Add tests
  2. Update documentation

References

License

Same as AuthSome project

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AuthorizationConfig

type AuthorizationConfig struct {
	// RequireAPIKey enforces API key authentication
	RequireAPIKey bool `json:"require_api_key" yaml:"require_api_key"`

	// AllowedOperations lists permitted read-only operations
	AllowedOperations []string `json:"allowed_operations" yaml:"allowed_operations"`

	// AdminOperations require admin role (only in admin/development mode)
	AdminOperations []string `json:"admin_operations" yaml:"admin_operations"`
}

AuthorizationConfig defines authorization requirements

type CheckPermissionTool

type CheckPermissionTool struct{}

CheckPermissionTool verifies RBAC permissions

func (*CheckPermissionTool) Describe

func (t *CheckPermissionTool) Describe() ToolDescription

func (*CheckPermissionTool) Execute

func (t *CheckPermissionTool) Execute(ctx context.Context, arguments map[string]interface{}, plugin *Plugin) (string, error)

func (*CheckPermissionTool) RequiresAdmin

func (t *CheckPermissionTool) RequiresAdmin() bool

func (*CheckPermissionTool) RequiresAuth

func (t *CheckPermissionTool) RequiresAuth() bool

type Config

type Config struct {
	// Enabled determines if MCP plugin is active
	Enabled bool `json:"enabled" yaml:"enabled"`

	// Mode controls what operations are allowed
	Mode Mode `json:"mode" yaml:"mode"`

	// Transport specifies communication method
	Transport Transport `json:"transport" yaml:"transport"`

	// Port for HTTP transport (default: 9090)
	Port int `json:"port" yaml:"port"`

	// ExposeSecrets determines if secrets are exposed (dev only)
	ExposeSecrets bool `json:"expose_secrets" yaml:"expose_secrets"`

	// Authorization settings
	Authorization AuthorizationConfig `json:"authorization" yaml:"authorization"`

	// RateLimit settings
	RateLimit RateLimitConfig `json:"rate_limit" yaml:"rate_limit"`
}

Config defines the MCP plugin configuration

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns sensible defaults

type ConfigResource

type ConfigResource struct{}

ConfigResource exposes sanitized configuration

func (*ConfigResource) Describe

func (r *ConfigResource) Describe() ResourceDescription

func (*ConfigResource) Read

func (r *ConfigResource) Read(ctx context.Context, uri string, plugin *Plugin) (string, error)

type MCPError

type MCPError struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data,omitempty"`
}

MCPError represents an MCP error

type MCPRequest

type MCPRequest struct {
	JSONRPC string      `json:"jsonrpc"`
	ID      interface{} `json:"id"`
	Method  string      `json:"method"`
	Params  interface{} `json:"params,omitempty"`
}

MCPRequest represents an MCP JSON-RPC request

type MCPResponse

type MCPResponse struct {
	JSONRPC string      `json:"jsonrpc"`
	ID      interface{} `json:"id"`
	Result  interface{} `json:"result,omitempty"`
	Error   *MCPError   `json:"error,omitempty"`
}

MCPResponse represents an MCP JSON-RPC response

type Mode

type Mode string

Mode defines the MCP plugin operation mode

const (
	// ModeReadOnly only allows read operations and read-only tools
	ModeReadOnly Mode = "readonly"
	// ModeAdmin allows read and administrative write operations
	ModeAdmin Mode = "admin"
	// ModeDevelopment allows all operations including test data creation
	ModeDevelopment Mode = "development"
)

type Plugin

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

Plugin implements the MCP (Model Context Protocol) server Exposes AuthSome data and operations to AI assistants

func NewPlugin

func NewPlugin(opts ...PluginOption) *Plugin

NewPlugin creates a new MCP plugin with optional configuration

func (*Plugin) GetServer

func (p *Plugin) GetServer() *Server

GetServer returns the underlying MCP server (for CLI/testing)

func (*Plugin) ID

func (p *Plugin) ID() string

ID returns the plugin identifier

func (*Plugin) Init

func (p *Plugin) Init(auth core.Authsome) error

Init initializes the plugin with auth instance

func (*Plugin) Migrate

func (p *Plugin) Migrate() error

Migrate runs database migrations (none needed for MCP)

func (*Plugin) RegisterHooks

func (p *Plugin) RegisterHooks(hooks *hooks.HookRegistry) error

RegisterHooks registers plugin hooks (none needed for MCP)

func (*Plugin) RegisterRoutes

func (p *Plugin) RegisterRoutes(router forge.Router) error

RegisterRoutes registers HTTP endpoints if HTTP transport is enabled

func (*Plugin) RegisterServiceDecorators

func (p *Plugin) RegisterServiceDecorators(services *registry.ServiceRegistry) error

RegisterServiceDecorators allows service decoration (none needed for MCP)

func (*Plugin) Start

func (p *Plugin) Start(ctx context.Context) error

Start starts the MCP server (call after Initialize)

func (*Plugin) Stop

func (p *Plugin) Stop(ctx context.Context) error

Stop gracefully stops the MCP server

type PluginOption

type PluginOption func(*Plugin)

PluginOption is a functional option for configuring the MCP plugin

func WithDefaultConfig

func WithDefaultConfig(cfg Config) PluginOption

WithDefaultConfig sets the default configuration for the plugin

func WithEnabled

func WithEnabled(enabled bool) PluginOption

WithEnabled sets whether MCP is enabled

func WithExposeSecrets

func WithExposeSecrets(expose bool) PluginOption

WithExposeSecrets sets whether to expose secrets (dev only)

func WithPort

func WithPort(port int) PluginOption

WithPort sets the HTTP port for MCP server

func WithTransport

func WithTransport(transport string) PluginOption

WithTransport sets the MCP transport type

type QueryUserTool

type QueryUserTool struct{}

QueryUserTool finds users by email/ID/username

func (*QueryUserTool) Describe

func (t *QueryUserTool) Describe() ToolDescription

func (*QueryUserTool) Execute

func (t *QueryUserTool) Execute(ctx context.Context, arguments map[string]interface{}, plugin *Plugin) (string, error)

func (*QueryUserTool) RequiresAdmin

func (t *QueryUserTool) RequiresAdmin() bool

func (*QueryUserTool) RequiresAuth

func (t *QueryUserTool) RequiresAuth() bool

type RateLimitConfig

type RateLimitConfig struct {
	// RequestsPerMinute limits MCP requests
	RequestsPerMinute int `json:"requests_per_minute" yaml:"requests_per_minute"`
}

RateLimitConfig defines rate limiting

type Resource

type Resource interface {
	Read(ctx context.Context, uri string, plugin *Plugin) (string, error)
	Describe() ResourceDescription
}

Resource defines the interface for MCP resources

type ResourceDescription

type ResourceDescription struct {
	URI         string `json:"uri"`
	Name        string `json:"name"`
	Description string `json:"description"`
	MimeType    string `json:"mimeType"`
}

ResourceDescription describes a resource for MCP clients

type ResourceRegistry

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

ResourceRegistry manages available resources

func NewResourceRegistry

func NewResourceRegistry() *ResourceRegistry

NewResourceRegistry creates a new resource registry

func (*ResourceRegistry) List

List returns descriptions of all resources

func (*ResourceRegistry) Read

func (r *ResourceRegistry) Read(ctx context.Context, uri string, plugin *Plugin) (string, error)

Read reads a resource by URI

func (*ResourceRegistry) Register

func (r *ResourceRegistry) Register(uri string, resource Resource)

Register registers a resource handler

type RoutesResource

type RoutesResource struct{}

RoutesResource exposes registered API routes

func (*RoutesResource) Describe

func (r *RoutesResource) Describe() ResourceDescription

func (*RoutesResource) Read

func (r *RoutesResource) Read(ctx context.Context, uri string, plugin *Plugin) (string, error)

type SchemaResource

type SchemaResource struct{}

SchemaResource exposes database schema information

func (*SchemaResource) Describe

func (r *SchemaResource) Describe() ResourceDescription

func (*SchemaResource) Read

func (r *SchemaResource) Read(ctx context.Context, uri string, plugin *Plugin) (string, error)

type SecurityLayer

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

SecurityLayer handles authorization and data sanitization for MCP

func NewSecurityLayer

func NewSecurityLayer(config Config, db *bun.DB) *SecurityLayer

NewSecurityLayer creates a new security layer

func (*SecurityLayer) AuthorizeRequest

func (s *SecurityLayer) AuthorizeRequest(ctx context.Context, operation string, apiKey string) error

AuthorizeRequest checks if a request is authorized

func (*SecurityLayer) CheckOperationAllowed

func (s *SecurityLayer) CheckOperationAllowed(operation string) error

CheckOperationAllowed checks if operation is allowed in current mode

func (*SecurityLayer) SanitizeData

func (s *SecurityLayer) SanitizeData(data interface{}, dataType string) interface{}

SanitizeData removes sensitive information from data

type Server

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

Server implements the MCP (Model Context Protocol) server

func NewServer

func NewServer(config Config, plugin *Plugin) (*Server, error)

NewServer creates a new MCP server

func (*Server) Start

func (s *Server) Start(ctx context.Context) error

Start starts the MCP server

func (*Server) Stop

func (s *Server) Stop(ctx context.Context) error

Stop stops the MCP server

type Tool

type Tool interface {
	Execute(ctx context.Context, arguments map[string]interface{}, plugin *Plugin) (string, error)
	Describe() ToolDescription
	RequiresAuth() bool
	RequiresAdmin() bool
}

Tool defines the interface for MCP tools

type ToolDescription

type ToolDescription struct {
	Name        string                 `json:"name"`
	Description string                 `json:"description"`
	InputSchema map[string]interface{} `json:"inputSchema"`
}

ToolDescription describes a tool for MCP clients

type ToolRegistry

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

ToolRegistry manages available tools

func NewToolRegistry

func NewToolRegistry() *ToolRegistry

NewToolRegistry creates a new tool registry

func (*ToolRegistry) Execute

func (r *ToolRegistry) Execute(ctx context.Context, name string, arguments map[string]interface{}, plugin *Plugin) (string, error)

Execute executes a tool by name

func (*ToolRegistry) List

func (r *ToolRegistry) List(mode Mode) []ToolDescription

List returns descriptions of all tools (filtered by mode)

func (*ToolRegistry) Register

func (r *ToolRegistry) Register(name string, tool Tool)

Register registers a tool handler

type Transport

type Transport string

Transport defines how MCP communicates

const (
	// TransportStdio uses stdin/stdout (for local CLI)
	TransportStdio Transport = "stdio"
	// TransportHTTP uses HTTP endpoints (for remote access)
	TransportHTTP Transport = "http"
)

Jump to

Keyboard shortcuts

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