-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
104 lines (82 loc) · 2.59 KB
/
main.go
File metadata and controls
104 lines (82 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package main
import (
"context"
"flag"
"log/slog"
"os"
"os/signal"
"syscall"
"time"
"go-mcp-postgres-server/config"
"go-mcp-postgres-server/db"
"go-mcp-postgres-server/tools"
"github.com/mark3labs/mcp-go/server"
)
const serverVersion = "1.0.0"
func main() {
// 1. Parse CLI flags
initSchema := flag.Bool("init-schema", false, "Print schema DDL and exit")
flag.Parse()
// 2. Initialize structured JSON logger
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, nil)))
// 3. Load configuration
cfg := config.Load()
// 4. If --init-schema: print DDL and exit without connecting to DB
if *initSchema {
db.PrintSchema(os.Stdout)
os.Exit(0)
}
// 5. Log startup info
slog.Info("starting server",
"version", serverVersion,
"listen_addr", cfg.ListenAddr,
"db_host", cfg.DBHost,
)
slog.Info("active configuration", "config", cfg.LogSafe())
// 6. Create connection pool
ctx := context.Background()
pool, err := db.NewPool(ctx, cfg.DSN())
if err != nil {
slog.Error("failed to create database connection pool", "error", err)
os.Exit(1)
}
// 7. Run schema initialization
if err := db.InitSchema(ctx, pool); err != nil {
slog.Error("failed to initialize database schema", "error", err)
os.Exit(1)
}
// 8. Create repository
repo := db.NewRepository(pool)
// 9. Create MCP server with panic recovery
mcpServer := server.NewMCPServer("go-mcp-postgres-server", serverVersion,
server.WithRecovery(),
)
// 10. Register all 6 tools
mcpServer.AddTool(tools.NewStoreTool(), tools.StoreHandler(repo))
mcpServer.AddTool(tools.NewQueryTool(), tools.QueryHandler(repo))
mcpServer.AddTool(tools.NewGetTool(), tools.GetHandler(repo))
mcpServer.AddTool(tools.NewListTool(), tools.ListHandler(repo))
mcpServer.AddTool(tools.NewUpdateTool(), tools.UpdateHandler(repo))
mcpServer.AddTool(tools.NewDeleteTool(), tools.DeleteHandler(repo))
// 11. Create and start SSE server
sseServer := server.NewSSEServer(mcpServer)
go func() {
slog.Info("SSE server listening", "addr", cfg.ListenAddr)
if err := sseServer.Start(cfg.ListenAddr); err != nil {
slog.Error("SSE server error", "error", err)
os.Exit(1)
}
}()
// 12. Graceful shutdown on SIGINT/SIGTERM
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
sig := <-sigCh
slog.Info("received shutdown signal", "signal", sig.String())
shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := sseServer.Shutdown(shutdownCtx); err != nil {
slog.Error("SSE server shutdown error", "error", err)
}
pool.Close()
slog.Info("shutdown complete")
}