Skip to content

Commit 319b552

Browse files
authored
feat: add support for https when using streamable-http transport (#270)
mcp-go v0.39.0 adds support for https when using the streamable-http transport. This commit adds support for configuring the server to serve https using custom certificates via the CLI. Fixes #244.
1 parent c293cd9 commit 319b552

File tree

4 files changed

+127
-5
lines changed

4 files changed

+127
-5
lines changed

README.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,45 @@ Scopes define the specific resources that permissions apply to. Each action requ
197197
| `get_assertions` | Asserts | Get assertion summary for a given entity | Plugin-specific permissions | Plugin-specific scopes |
198198
| `generate_deeplink` | Navigation | Generate accurate deeplink URLs for Grafana resources | None (read-only URL generation) | N/A |
199199

200+
## CLI Flags Reference
201+
202+
The `mcp-grafana` binary supports various command-line flags for configuration:
203+
204+
**Transport Options:**
205+
- `-t, --transport`: Transport type (`stdio`, `sse`, or `streamable-http`) - default: `stdio`
206+
- `--address`: The host and port for SSE/streamable-http server - default: `localhost:8000`
207+
- `--base-path`: Base path for the SSE/streamable-http server
208+
- `--endpoint-path`: Endpoint path for the streamable-http server - default: `/`
209+
210+
**Debug and Logging:**
211+
- `--debug`: Enable debug mode for detailed HTTP request/response logging
212+
213+
**Tool Configuration:**
214+
- `--enabled-tools`: Comma-separated list of enabled tools - default: all tools enabled
215+
- `--disable-search`: Disable search tools
216+
- `--disable-datasource`: Disable datasource tools
217+
- `--disable-incident`: Disable incident tools
218+
- `--disable-prometheus`: Disable prometheus tools
219+
- `--disable-loki`: Disable loki tools
220+
- `--disable-alerting`: Disable alerting tools
221+
- `--disable-dashboard`: Disable dashboard tools
222+
- `--disable-oncall`: Disable oncall tools
223+
- `--disable-asserts`: Disable asserts tools
224+
- `--disable-sift`: Disable sift tools
225+
- `--disable-admin`: Disable admin tools
226+
- `--disable-pyroscope`: Disable pyroscope tools
227+
- `--disable-navigation`: Disable navigation tools
228+
229+
**Client TLS Configuration (for Grafana connections):**
230+
- `--tls-cert-file`: Path to TLS certificate file for client authentication
231+
- `--tls-key-file`: Path to TLS private key file for client authentication
232+
- `--tls-ca-file`: Path to TLS CA certificate file for server verification
233+
- `--tls-skip-verify`: Skip TLS certificate verification (insecure)
234+
235+
**Server TLS Configuration (streamable-http transport only):**
236+
- `--server.tls-cert-file`: Path to TLS certificate file for server HTTPS
237+
- `--server.tls-key-file`: Path to TLS private key file for server HTTPS
238+
200239
## Usage
201240

202241
This MCP server works with both local Grafana instances and Grafana Cloud. For Grafana Cloud, use your instance URL (e.g., `https://myinstance.grafana.net`) instead of `http://localhost:3000` in the configuration examples below.
@@ -235,6 +274,21 @@ This MCP server works with both local Grafana instances and Grafana Cloud. For G
235274
docker run --rm -p 8000:8000 -e GRAFANA_URL=http://localhost:3000 -e GRAFANA_API_KEY=<your service account token> mcp/grafana -t streamable-http
236275
```
237276

277+
For HTTPS streamable HTTP mode with server TLS certificates:
278+
279+
```bash
280+
docker pull mcp/grafana
281+
docker run --rm -p 8443:8443 \
282+
-v /path/to/certs:/certs:ro \
283+
-e GRAFANA_URL=http://localhost:3000 \
284+
-e GRAFANA_API_KEY=<your service account token> \
285+
mcp/grafana \
286+
-t streamable-http \
287+
-addr :8443 \
288+
--server.tls-cert-file /certs/server.crt \
289+
--server.tls-key-file /certs/server.key
290+
```
291+
238292
- **Download binary**: Download the latest release of `mcp-grafana` from the [releases page](https://github.com/grafana/mcp-grafana/releases) and place it in your `$PATH`.
239293

240294
- **Build from source**: If you have a Go toolchain installed you can also build and install it from source, using the `GOBIN` environment variable
@@ -324,6 +378,19 @@ If you're using VSCode and running the MCP server in SSE mode (which is the defa
324378
}
325379
```
326380
381+
For HTTPS streamable HTTP mode with server TLS certificates:
382+
383+
```json
384+
"mcp": {
385+
"servers": {
386+
"grafana": {
387+
"type": "sse",
388+
"url": "https://localhost:8443/sse"
389+
}
390+
}
391+
}
392+
```
393+
327394
### Debug Mode
328395
329396
You can enable debug mode for the Grafana transport by adding the `-debug` flag to the command. This will provide detailed logging of HTTP requests and responses between the MCP server and the Grafana API, which can be helpful for troubleshooting.
@@ -510,6 +577,43 @@ grafanaConfig := mcpgrafana.GrafanaConfig{
510577
contextFunc := mcpgrafana.ComposedStdioContextFunc(grafanaConfig)
511578
```
512579

580+
### Server TLS Configuration (Streamable HTTP Transport Only)
581+
582+
When using the streamable HTTP transport (`-t streamable-http`), you can configure the MCP server to serve HTTPS instead of HTTP. This is useful when you need to secure the connection between your MCP client and the server itself.
583+
584+
The server supports the following TLS configuration options for the streamable HTTP transport:
585+
586+
- `--server.tls-cert-file`: Path to TLS certificate file for server HTTPS (required for TLS)
587+
- `--server.tls-key-file`: Path to TLS private key file for server HTTPS (required for TLS)
588+
589+
**Note**: These flags are completely separate from the client TLS flags documented above. The client TLS flags configure how the MCP server connects to Grafana, while these server TLS flags configure how clients connect to the MCP server when using streamable HTTP transport.
590+
591+
**Example with HTTPS streamable HTTP server:**
592+
593+
```bash
594+
./mcp-grafana \
595+
-t streamable-http \
596+
--server.tls-cert-file /path/to/server.crt \
597+
--server.tls-key-file /path/to/server.key \
598+
-addr :8443
599+
```
600+
601+
This would start the MCP server on HTTPS port 8443. Clients would then connect to `https://localhost:8443/` instead of `http://localhost:8000/`.
602+
603+
**Docker example with server TLS:**
604+
605+
```bash
606+
docker run --rm -p 8443:8443 \
607+
-v /path/to/certs:/certs:ro \
608+
-e GRAFANA_URL=http://localhost:3000 \
609+
-e GRAFANA_API_KEY=<your service account token> \
610+
mcp/grafana \
611+
-t streamable-http \
612+
-addr :8443 \
613+
--server.tls-cert-file /certs/server.crt \
614+
--server.tls-key-file /certs/server.key
615+
```
616+
513617
## Troubleshooting
514618

515619
### Grafana Version Compatibility

cmd/mcp-grafana/main.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,16 @@ func newServer(dt disabledTools) *server.MCPServer {
115115
return s
116116
}
117117

118-
func run(transport, addr, basePath, endpointPath string, logLevel slog.Level, dt disabledTools, gc mcpgrafana.GrafanaConfig) error {
118+
type tlsConfig struct {
119+
certFile, keyFile string
120+
}
121+
122+
func (tc *tlsConfig) addFlags() {
123+
flag.StringVar(&tc.certFile, "server.tls-cert-file", "", "Path to TLS certificate file for server HTTPS (required for TLS)")
124+
flag.StringVar(&tc.keyFile, "server.tls-key-file", "", "Path to TLS private key file for server HTTPS (required for TLS)")
125+
}
126+
127+
func run(transport, addr, basePath, endpointPath string, logLevel slog.Level, dt disabledTools, gc mcpgrafana.GrafanaConfig, tls tlsConfig) error {
119128
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: logLevel})))
120129
s := newServer(dt)
121130

@@ -135,10 +144,15 @@ func run(transport, addr, basePath, endpointPath string, logLevel slog.Level, dt
135144
return fmt.Errorf("server error: %v", err)
136145
}
137146
case "streamable-http":
138-
srv := server.NewStreamableHTTPServer(s, server.WithHTTPContextFunc(mcpgrafana.ComposedHTTPContextFunc(gc)),
147+
opts := []server.StreamableHTTPOption{
148+
server.WithHTTPContextFunc(mcpgrafana.ComposedHTTPContextFunc(gc)),
139149
server.WithStateLess(true),
140150
server.WithEndpointPath(endpointPath),
141-
)
151+
}
152+
if tls.certFile != "" || tls.keyFile != "" {
153+
opts = append(opts, server.WithTLSCert(tls.certFile, tls.keyFile))
154+
}
155+
srv := server.NewStreamableHTTPServer(s, opts...)
142156
slog.Info("Starting Grafana MCP server using StreamableHTTP transport", "version", mcpgrafana.Version(), "address", addr, "endpointPath", endpointPath)
143157
if err := srv.Start(addr); err != nil {
144158
return fmt.Errorf("server error: %v", err)
@@ -170,6 +184,8 @@ func main() {
170184
dt.addFlags()
171185
var gc grafanaConfig
172186
gc.addFlags()
187+
var tls tlsConfig
188+
tls.addFlags()
173189
flag.Parse()
174190

175191
if *showVersion {
@@ -188,7 +204,7 @@ func main() {
188204
}
189205
}
190206

191-
if err := run(transport, *addr, *basePath, *endpointPath, parseLevel(*logLevel), dt, grafanaConfig); err != nil {
207+
if err := run(transport, *addr, *basePath, *endpointPath, parseLevel(*logLevel), dt, grafanaConfig, tls); err != nil {
192208
panic(err)
193209
}
194210
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ require (
1515
github.com/grafana/incident-go v0.0.0-20250211094540-dc6a98fdae43
1616
github.com/grafana/pyroscope/api v1.2.0
1717
github.com/invopop/jsonschema v0.13.0
18-
github.com/mark3labs/mcp-go v0.38.0
18+
github.com/mark3labs/mcp-go v0.39.0
1919
github.com/prometheus/client_golang v1.23.0
2020
github.com/prometheus/common v0.65.0
2121
github.com/prometheus/prometheus v0.305.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4
180180
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
181181
github.com/mark3labs/mcp-go v0.38.0 h1:E5tmJiIXkhwlV0pLAwAT0O5ZjUZSISE/2Jxg+6vpq4I=
182182
github.com/mark3labs/mcp-go v0.38.0/go.mod h1:T7tUa2jO6MavG+3P25Oy/jR7iCeJPHImCZHRymCn39g=
183+
github.com/mark3labs/mcp-go v0.39.0 h1:dQwaOADzUJ1ROslEJB8QV+4u/8XQCqH9ylB//x8cCEQ=
184+
github.com/mark3labs/mcp-go v0.39.0/go.mod h1:T7tUa2jO6MavG+3P25Oy/jR7iCeJPHImCZHRymCn39g=
183185
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
184186
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
185187
github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PTjRLM=

0 commit comments

Comments
 (0)