@@ -13,8 +13,6 @@ import (
13
13
"github.com/mark3labs/mcp-go/server"
14
14
)
15
15
16
- type clientKey struct {}
17
-
18
16
const (
19
17
grafanaURLEnvVar = "GRAFANA_URL"
20
18
grafanaAPIEnvVar = "GRAFANA_API_KEY"
@@ -35,9 +33,48 @@ func urlAndAPIKeyFromHeaders(req *http.Request) (string, string) {
35
33
return u , apiKey
36
34
}
37
35
38
- // ExtractClientFromEnv is a StdioContextFunc that extracts Grafana configuration
36
+ type grafanaURLKey struct {}
37
+ type grafanaAPIKeyKey struct {}
38
+
39
+ // ExtractGrafanaInfoFromEnv is a StdioContextFunc that extracts Grafana configuration
40
+ // from environment variables and injects a configured client into the context.
41
+ var ExtractGrafanaInfoFromEnv server.StdioContextFunc = func (ctx context.Context ) context.Context {
42
+ u , apiKey := urlAndAPIKeyFromEnv ()
43
+ return WithGrafanaURL (WithGrafanaAPIKey (ctx , apiKey ), u )
44
+ }
45
+
46
+ // ExtractGrafanaInfoFromHeaders is a SSEContextFunc that extracts Grafana configuration
47
+ // from request headers and injects a configured client into the context.
48
+ var ExtractGrafanaInfoFromHeaders server.SSEContextFunc = func (ctx context.Context , req * http.Request ) context.Context {
49
+ u , apiKey := urlAndAPIKeyFromHeaders (req )
50
+ return WithGrafanaURL (WithGrafanaAPIKey (ctx , apiKey ), u )
51
+ }
52
+
53
+ // WithGrafanaURL adds the Grafana URL to the context.
54
+ func WithGrafanaURL (ctx context.Context , url string ) context.Context {
55
+ return context .WithValue (ctx , grafanaURLKey {}, url )
56
+ }
57
+
58
+ // WithGrafanaAPIKey adds the Grafana API key to the context.
59
+ func WithGrafanaAPIKey (ctx context.Context , apiKey string ) context.Context {
60
+ return context .WithValue (ctx , grafanaAPIKeyKey {}, apiKey )
61
+ }
62
+
63
+ // GrafanaURLFromContext extracts the Grafana URL from the context.
64
+ func GrafanaURLFromContext (ctx context.Context ) string {
65
+ return ctx .Value (grafanaURLKey {}).(string )
66
+ }
67
+
68
+ // GrafanaAPIKeyFromContext extracts the Grafana API key from the context.
69
+ func GrafanaAPIKeyFromContext (ctx context.Context ) string {
70
+ return ctx .Value (grafanaAPIKeyKey {}).(string )
71
+ }
72
+
73
+ type grafanaClientKey struct {}
74
+
75
+ // ExtractGrafanaClientFromEnv is a StdioContextFunc that extracts Grafana configuration
39
76
// from environment variables and injects a configured client into the context.
40
- var ExtractClientFromEnv server.StdioContextFunc = func (ctx context.Context ) context.Context {
77
+ var ExtractGrafanaClientFromEnv server.StdioContextFunc = func (ctx context.Context ) context.Context {
41
78
cfg := client .DefaultTransportConfig ()
42
79
// Extract transport config from env vars, and set it on the context.
43
80
if u , ok := os .LookupEnv (grafanaURLEnvVar ); ok {
@@ -57,12 +94,12 @@ var ExtractClientFromEnv server.StdioContextFunc = func(ctx context.Context) con
57
94
}
58
95
59
96
client := client .NewHTTPClientWithConfig (strfmt .Default , cfg )
60
- return context .WithValue (ctx , clientKey {}, client )
97
+ return context .WithValue (ctx , grafanaClientKey {}, client )
61
98
}
62
99
63
- // ExtractClientFromHeaders is a SSEContextFunc that extracts Grafana configuration
100
+ // ExtractGrafanaClientFromHeaders is a SSEContextFunc that extracts Grafana configuration
64
101
// from request headers and injects a configured client into the context.
65
- var ExtractClientFromHeaders server.SSEContextFunc = func (ctx context.Context , req * http.Request ) context.Context {
102
+ var ExtractGrafanaClientFromHeaders server.SSEContextFunc = func (ctx context.Context , req * http.Request ) context.Context {
66
103
cfg := client .DefaultTransportConfig ()
67
104
// Extract transport config from request headers, and set it on the context.
68
105
u , apiKey := urlAndAPIKeyFromHeaders (req )
@@ -85,12 +122,12 @@ var ExtractClientFromHeaders server.SSEContextFunc = func(ctx context.Context, r
85
122
//
86
123
// It can be retrieved using GrafanaClientFromContext.
87
124
func WithGrafanaClient (ctx context.Context , client * client.GrafanaHTTPAPI ) context.Context {
88
- return context .WithValue (ctx , clientKey {}, client )
125
+ return context .WithValue (ctx , grafanaClientKey {}, client )
89
126
}
90
127
91
128
// GrafanaClientFromContext retrieves the Grafana client from the context.
92
129
func GrafanaClientFromContext (ctx context.Context ) * client.GrafanaHTTPAPI {
93
- c , ok := ctx .Value (clientKey {}).(* client.GrafanaHTTPAPI )
130
+ c , ok := ctx .Value (grafanaClientKey {}).(* client.GrafanaHTTPAPI )
94
131
if ! ok {
95
132
return nil
96
133
}
@@ -124,3 +161,37 @@ func IncidentClientFromContext(ctx context.Context) *incident.Client {
124
161
}
125
162
return c
126
163
}
164
+
165
+ // ComposeStdioContextFuncs composes multiple StdioContextFuncs into a single one.
166
+ func ComposeStdioContextFuncs (funcs ... server.StdioContextFunc ) server.StdioContextFunc {
167
+ return func (ctx context.Context ) context.Context {
168
+ for _ , f := range funcs {
169
+ ctx = f (ctx )
170
+ }
171
+ return ctx
172
+ }
173
+ }
174
+
175
+ // ComposeSSEContextFuncs composes multiple SSEContextFuncs into a single one.
176
+ func ComposeSSEContextFuncs (funcs ... server.SSEContextFunc ) server.SSEContextFunc {
177
+ return func (ctx context.Context , req * http.Request ) context.Context {
178
+ for _ , f := range funcs {
179
+ ctx = f (ctx , req )
180
+ }
181
+ return ctx
182
+ }
183
+ }
184
+
185
+ // ComposedStdioContextFunc is a StdioContextFunc that comprises all predefined StdioContextFuncs.
186
+ var ComposedStdioContextFunc = ComposeStdioContextFuncs (
187
+ ExtractGrafanaInfoFromEnv ,
188
+ ExtractGrafanaClientFromEnv ,
189
+ ExtractIncidentClientFromEnv ,
190
+ )
191
+
192
+ // ComposedSSEContextFunc is a SSEContextFunc that comprises all predefined SSEContextFuncs.
193
+ var ComposedSSEContextFunc = ComposeSSEContextFuncs (
194
+ ExtractGrafanaInfoFromHeaders ,
195
+ ExtractGrafanaClientFromHeaders ,
196
+ ExtractIncidentClientFromHeaders ,
197
+ )
0 commit comments