+43
-9
lines changedFilter options
+43
-9
lines changed Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ import (
4
4
"context"
5
5
"flag"
6
6
"fmt"
7
-
"log"
7
+
"log/slog"
8
8
"os"
9
9
10
10
"github.com/mark3labs/mcp-go/server"
@@ -29,19 +29,21 @@ func newServer() *server.MCPServer {
29
29
return s
30
30
}
31
31
32
-
func run(transport, addr string) error {
32
+
func run(transport, addr string, logLevel slog.Level) error {
33
+
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: logLevel})))
33
34
s := newServer()
34
35
35
36
switch transport {
36
37
case "stdio":
37
38
srv := server.NewStdioServer(s)
38
39
srv.SetContextFunc(mcpgrafana.ComposedStdioContextFunc)
40
+
slog.Info("Starting Grafana MCP server using stdio transport")
39
41
return srv.Listen(context.Background(), os.Stdin, os.Stdout)
40
42
case "sse":
41
43
srv := server.NewSSEServer(s,
42
44
server.WithSSEContextFunc(mcpgrafana.ComposedSSEContextFunc),
43
45
)
44
-
log.Printf("SSE server listening on %s", addr)
46
+
slog.Info("Starting Grafana MCP server using SSE transport", "address", addr)
45
47
if err := srv.Start(addr); err != nil {
46
48
return fmt.Errorf("Server error: %v", err)
47
49
}
@@ -64,9 +66,18 @@ func main() {
64
66
"Transport type (stdio or sse)",
65
67
)
66
68
addr := flag.String("sse-address", "localhost:8000", "The host and port to start the sse server on")
69
+
logLevel := flag.String("log-level", "info", "Log level (debug, info, warn, error)")
67
70
flag.Parse()
68
71
69
-
if err := run(transport, *addr); err != nil {
72
+
if err := run(transport, *addr, parseLevel(*logLevel)); err != nil {
70
73
panic(err)
71
74
}
72
75
}
76
+
77
+
func parseLevel(level string) slog.Level {
78
+
var l slog.Level
79
+
if err := l.UnmarshalText([]byte(level)); err != nil {
80
+
return slog.LevelInfo
81
+
}
82
+
return l
83
+
}
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package mcpgrafana
3
3
import (
4
4
"context"
5
5
"fmt"
6
+
"log/slog"
6
7
"net/http"
7
8
"net/url"
8
9
"os"
@@ -47,6 +48,11 @@ var ExtractGrafanaInfoFromEnv server.StdioContextFunc = func(ctx context.Context
47
48
if u == "" {
48
49
u = defaultGrafanaURL
49
50
}
51
+
parsedURL, err := url.Parse(u)
52
+
if err != nil {
53
+
panic(fmt.Errorf("invalid Grafana URL %s: %w", u, err))
54
+
}
55
+
slog.Info("Using Grafana configuration", "url", parsedURL.Redacted(), "api_key_set", apiKey != "")
50
56
return WithGrafanaURL(WithGrafanaAPIKey(ctx, apiKey), u)
51
57
}
52
58
@@ -100,22 +106,31 @@ type grafanaClientKey struct{}
100
106
var ExtractGrafanaClientFromEnv server.StdioContextFunc = func(ctx context.Context) context.Context {
101
107
cfg := client.DefaultTransportConfig()
102
108
// Extract transport config from env vars, and set it on the context.
103
-
if u, ok := os.LookupEnv(grafanaURLEnvVar); ok {
104
-
url, err := url.Parse(u)
109
+
var grafanaURL string
110
+
var parsedURL *url.URL
111
+
var ok bool
112
+
var err error
113
+
if grafanaURL, ok = os.LookupEnv(grafanaURLEnvVar); ok {
114
+
parsedURL, err = url.Parse(grafanaURL)
105
115
if err != nil {
106
116
panic(fmt.Errorf("invalid %s: %w", grafanaURLEnvVar, err))
107
117
}
108
-
cfg.Host = url.Host
118
+
cfg.Host = parsedURL.Host
109
119
// The Grafana client will always prefer HTTPS even if the URL is HTTP,
110
120
// so we need to limit the schemes to HTTP if the URL is HTTP.
111
-
if url.Scheme == "http" {
121
+
if parsedURL.Scheme == "http" {
112
122
cfg.Schemes = []string{"http"}
113
123
}
124
+
} else {
125
+
parsedURL, _ = url.Parse(defaultGrafanaURL)
114
126
}
115
-
if apiKey := os.Getenv(grafanaAPIEnvVar); apiKey != "" {
127
+
128
+
apiKey := os.Getenv(grafanaAPIEnvVar)
129
+
if apiKey != "" {
116
130
cfg.APIKey = apiKey
117
131
}
118
132
133
+
slog.Debug("Creating Grafana client", "url", parsedURL.Redacted(), "api_key_set", apiKey != "")
119
134
client := client.NewHTTPClientWithConfig(strfmt.Default, cfg)
120
135
return context.WithValue(ctx, grafanaClientKey{}, client)
121
136
}
@@ -161,7 +176,15 @@ type incidentClientKey struct{}
161
176
162
177
var ExtractIncidentClientFromEnv server.StdioContextFunc = func(ctx context.Context) context.Context {
163
178
grafanaURL, apiKey := urlAndAPIKeyFromEnv()
179
+
if grafanaURL == "" {
180
+
grafanaURL = defaultGrafanaURL
181
+
}
164
182
incidentURL := fmt.Sprintf("%s/api/plugins/grafana-incident-app/resources/api/v1/", grafanaURL)
183
+
parsedURL, err := url.Parse(incidentURL)
184
+
if err != nil {
185
+
panic(fmt.Errorf("invalid incident URL %s: %w", incidentURL, err))
186
+
}
187
+
slog.Debug("Creating Incident client", "url", parsedURL.Redacted(), "api_key_set", apiKey != "")
165
188
client := incident.NewClient(incidentURL, apiKey)
166
189
return context.WithValue(ctx, incidentClientKey{}, client)
167
190
}
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4