|
| 1 | +# StackQL MCP Server Package |
| 2 | + |
| 3 | +This package implements a Model Context Protocol (MCP) server for StackQL, enabling LLMs to consume StackQL as a first-class information source. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The `mcp_server` package provides: |
| 8 | + |
| 9 | +1. **Backend Interface Abstraction**: A clean interface for executing queries that can be implemented for in-memory, TCP, or other communication methods |
| 10 | +2. **Configuration Management**: Comprehensive configuration structures with JSON and YAML support |
| 11 | +3. **MCP Server Implementation**: A complete MCP server supporting multiple transports (stdio, TCP, WebSocket) |
| 12 | + |
| 13 | +## Architecture |
| 14 | + |
| 15 | +The package is designed with zero dependencies on StackQL internals, making it modular and reusable. The key components are: |
| 16 | + |
| 17 | +- `Backend`: Interface for query execution and schema retrieval |
| 18 | +- `Config`: Configuration structures with validation |
| 19 | +- `MCPServer`: Main server implementation supporting MCP protocol |
| 20 | +- `ExampleBackend`: Sample implementation for testing and demonstration |
| 21 | + |
| 22 | +## Usage |
| 23 | + |
| 24 | +### Basic Usage |
| 25 | + |
| 26 | +```go |
| 27 | +package main |
| 28 | + |
| 29 | +import ( |
| 30 | + "context" |
| 31 | + "log" |
| 32 | + |
| 33 | + "github.com/stackql/stackql/pkg/mcp_server" |
| 34 | +) |
| 35 | + |
| 36 | +func main() { |
| 37 | + // Create server with default configuration and example backend |
| 38 | + server, err := mcp_server.NewMCPServerWithExampleBackend(nil) |
| 39 | + if err != nil { |
| 40 | + log.Fatal(err) |
| 41 | + } |
| 42 | + |
| 43 | + // Start the server |
| 44 | + ctx := context.Background() |
| 45 | + if err := server.Start(ctx); err != nil { |
| 46 | + log.Fatal(err) |
| 47 | + } |
| 48 | + |
| 49 | + // Server will run until context is cancelled |
| 50 | + <-ctx.Done() |
| 51 | + |
| 52 | + // Graceful shutdown |
| 53 | + server.Stop(context.Background()) |
| 54 | +} |
| 55 | +``` |
| 56 | + |
| 57 | +### Custom Configuration |
| 58 | + |
| 59 | +```go |
| 60 | +config := &mcp_server.Config{ |
| 61 | + Server: mcp_server.ServerConfig{ |
| 62 | + Name: "My StackQL MCP Server", |
| 63 | + Version: "1.0.0", |
| 64 | + Description: "Custom MCP server for StackQL", |
| 65 | + MaxConcurrentRequests: 50, |
| 66 | + RequestTimeout: mcp_server.Duration(30 * time.Second), |
| 67 | + }, |
| 68 | + Backend: mcp_server.BackendConfig{ |
| 69 | + Type: "stackql", |
| 70 | + ConnectionString: "stackql://localhost:5432", |
| 71 | + MaxConnections: 20, |
| 72 | + ConnectionTimeout: mcp_server.Duration(10 * time.Second), |
| 73 | + QueryTimeout: mcp_server.Duration(60 * time.Second), |
| 74 | + }, |
| 75 | + Transport: mcp_server.TransportConfig{ |
| 76 | + EnabledTransports: []string{"stdio", "tcp"}, |
| 77 | + TCP: mcp_server.TCPTransportConfig{ |
| 78 | + Address: "0.0.0.0", |
| 79 | + Port: 8080, |
| 80 | + }, |
| 81 | + }, |
| 82 | + Logging: mcp_server.LoggingConfig{ |
| 83 | + Level: "info", |
| 84 | + Format: "json", |
| 85 | + Output: "/var/log/mcp-server.log", |
| 86 | + }, |
| 87 | +} |
| 88 | + |
| 89 | +server, err := mcp_server.NewMCPServer(config, backend, logger) |
| 90 | +``` |
| 91 | + |
| 92 | +### Implementing a Custom Backend |
| 93 | + |
| 94 | +```go |
| 95 | +type MyBackend struct { |
| 96 | + // Your backend implementation |
| 97 | +} |
| 98 | + |
| 99 | +func (b *MyBackend) Execute(ctx context.Context, query string, params map[string]interface{}) (*mcp_server.QueryResult, error) { |
| 100 | + // Execute the query using your preferred method |
| 101 | + // Return structured results |
| 102 | +} |
| 103 | + |
| 104 | +func (b *MyBackend) GetSchema(ctx context.Context) (*mcp_server.Schema, error) { |
| 105 | + // Return schema information about available providers and resources |
| 106 | +} |
| 107 | + |
| 108 | +func (b *MyBackend) Ping(ctx context.Context) error { |
| 109 | + // Verify backend connectivity |
| 110 | +} |
| 111 | + |
| 112 | +func (b *MyBackend) Close() error { |
| 113 | + // Clean up resources |
| 114 | +} |
| 115 | +``` |
| 116 | + |
| 117 | +## Configuration |
| 118 | + |
| 119 | +### JSON Configuration Example |
| 120 | + |
| 121 | +```json |
| 122 | +{ |
| 123 | + "server": { |
| 124 | + "name": "StackQL MCP Server", |
| 125 | + "version": "1.0.0", |
| 126 | + "description": "Model Context Protocol server for StackQL", |
| 127 | + "max_concurrent_requests": 100, |
| 128 | + "request_timeout": "30s" |
| 129 | + }, |
| 130 | + "backend": { |
| 131 | + "type": "stackql", |
| 132 | + "connection_string": "stackql://localhost", |
| 133 | + "max_connections": 10, |
| 134 | + "connection_timeout": "10s", |
| 135 | + "query_timeout": "30s", |
| 136 | + "retry": { |
| 137 | + "enabled": true, |
| 138 | + "max_attempts": 3, |
| 139 | + "initial_delay": "100ms", |
| 140 | + "max_delay": "5s", |
| 141 | + "multiplier": 2.0 |
| 142 | + } |
| 143 | + }, |
| 144 | + "transport": { |
| 145 | + "enabled_transports": ["stdio", "tcp"], |
| 146 | + "tcp": { |
| 147 | + "address": "localhost", |
| 148 | + "port": 8080, |
| 149 | + "max_connections": 100, |
| 150 | + "read_timeout": "30s", |
| 151 | + "write_timeout": "30s" |
| 152 | + } |
| 153 | + }, |
| 154 | + "logging": { |
| 155 | + "level": "info", |
| 156 | + "format": "text", |
| 157 | + "output": "stdout", |
| 158 | + "enable_request_logging": false |
| 159 | + } |
| 160 | +} |
| 161 | +``` |
| 162 | + |
| 163 | +### YAML Configuration Example |
| 164 | + |
| 165 | +```yaml |
| 166 | +server: |
| 167 | + name: "StackQL MCP Server" |
| 168 | + version: "1.0.0" |
| 169 | + description: "Model Context Protocol server for StackQL" |
| 170 | + max_concurrent_requests: 100 |
| 171 | + request_timeout: "30s" |
| 172 | + |
| 173 | +backend: |
| 174 | + type: "stackql" |
| 175 | + connection_string: "stackql://localhost" |
| 176 | + max_connections: 10 |
| 177 | + connection_timeout: "10s" |
| 178 | + query_timeout: "30s" |
| 179 | + retry: |
| 180 | + enabled: true |
| 181 | + max_attempts: 3 |
| 182 | + initial_delay: "100ms" |
| 183 | + max_delay: "5s" |
| 184 | + multiplier: 2.0 |
| 185 | + |
| 186 | +transport: |
| 187 | + enabled_transports: ["stdio", "tcp"] |
| 188 | + tcp: |
| 189 | + address: "localhost" |
| 190 | + port: 8080 |
| 191 | + max_connections: 100 |
| 192 | + read_timeout: "30s" |
| 193 | + write_timeout: "30s" |
| 194 | + |
| 195 | +logging: |
| 196 | + level: "info" |
| 197 | + format: "text" |
| 198 | + output: "stdout" |
| 199 | + enable_request_logging: false |
| 200 | +``` |
| 201 | +
|
| 202 | +## MCP Protocol Support |
| 203 | +
|
| 204 | +The server implements the Model Context Protocol specification and supports: |
| 205 | +
|
| 206 | +- **Initialization**: Capability negotiation with MCP clients |
| 207 | +- **Resources**: Listing and reading StackQL resources (providers, services, resources) |
| 208 | +- **Tools**: Query execution tool for running StackQL queries |
| 209 | +- **Multiple Transports**: stdio, TCP, and WebSocket (WebSocket implementation is placeholder) |
| 210 | +
|
| 211 | +### Supported MCP Methods |
| 212 | +
|
| 213 | +- `initialize`: Server initialization and capability negotiation |
| 214 | +- `resources/list`: List available StackQL resources |
| 215 | +- `resources/read`: Read specific resource data |
| 216 | +- `tools/list`: List available tools (StackQL query execution) |
| 217 | +- `tools/call`: Execute StackQL queries |
| 218 | + |
| 219 | +## Transport Support |
| 220 | + |
| 221 | +### Stdio Transport |
| 222 | +- Primary transport for command-line integration |
| 223 | +- JSON-RPC over stdin/stdout |
| 224 | +- Ideal for shell integrations and CLI tools |
| 225 | + |
| 226 | +### TCP Transport |
| 227 | +- HTTP-based JSON-RPC |
| 228 | +- Suitable for network-based integrations |
| 229 | +- Configurable address, port, and connection limits |
| 230 | + |
| 231 | +### WebSocket Transport (Placeholder) |
| 232 | +- Real-time bidirectional communication |
| 233 | +- Suitable for web applications |
| 234 | +- Currently implemented as placeholder |
| 235 | + |
| 236 | +## Development |
| 237 | + |
| 238 | +### Testing |
| 239 | + |
| 240 | +The package includes an example backend for testing: |
| 241 | + |
| 242 | +```bash |
| 243 | +go test ./pkg/mcp_server/... |
| 244 | +``` |
| 245 | + |
| 246 | +### Integration with StackQL |
| 247 | + |
| 248 | +To integrate with actual StackQL: |
| 249 | + |
| 250 | +1. Implement the `Backend` interface using StackQL's query execution engine |
| 251 | +2. Map StackQL's schema information to the `Schema` structure |
| 252 | +3. Handle StackQL-specific error types and convert them to `BackendError` |
| 253 | + |
| 254 | +## Dependencies |
| 255 | + |
| 256 | +The package uses minimal external dependencies: |
| 257 | +- `github.com/gorilla/mux`: HTTP routing (already available in StackQL) |
| 258 | +- `golang.org/x/sync`: Concurrency utilities (already available in StackQL) |
| 259 | +- `gopkg.in/yaml.v2`: YAML configuration support (already available in StackQL) |
| 260 | + |
| 261 | +No MCP SDK dependency is required as the package implements the MCP protocol directly. |
| 262 | + |
| 263 | +## Future Enhancements |
| 264 | + |
| 265 | +1. **Full WebSocket Implementation**: Complete WebSocket transport support |
| 266 | +2. **Stdio Transport**: Complete stdio JSON-RPC implementation |
| 267 | +3. **Authentication**: Add authentication and authorization support |
| 268 | +4. **Streaming**: Support for streaming large query results |
| 269 | +5. **Caching**: Query result caching for improved performance |
| 270 | +6. **Metrics**: Prometheus metrics for monitoring and observability |
0 commit comments