diff --git a/cmd/cmds.go b/cmd/cmds.go index b4f5f78..4c2d649 100644 --- a/cmd/cmds.go +++ b/cmd/cmds.go @@ -2,13 +2,14 @@ package cmd import ( "fmt" - "github.com/alecthomas/kong" - "github.com/netapp/ontap-mcp/config" - "github.com/netapp/ontap-mcp/server" "log/slog" "os" "path/filepath" "strings" + + "github.com/alecthomas/kong" + "github.com/netapp/ontap-mcp/config" + "github.com/netapp/ontap-mcp/server" ) var logger = setupLogger() @@ -29,6 +30,7 @@ type StartCmd struct { Port int `default:"8080" help:"Listening port" env:"ONTAP_MCP_PORT"` InspectTraffic bool `default:"false" help:"Inspect MCP HTTP traffic"` ReadOnly bool `default:"false" help:"Run MCP in read-only mode. This disables all tool calls that modify ONTAP state."` + Stateless bool `default:"false" help:"Run in stateless mode (no mcp-session-id header validation). Required when deploying behind proxies or gateways that don't preserve session headers, e.g. on-premises data gateways."` } func (a *StartCmd) Run(cli *CLI) error { @@ -47,6 +49,7 @@ func (a *StartCmd) Run(cli *CLI) error { Port: cli.Start.Port, InspectTraffic: cli.Start.InspectTraffic, ReadOnly: cli.Start.ReadOnly, + Stateless: cli.Start.Stateless, } app := server.NewApp(cfg, opts, logger) diff --git a/docs/install.md b/docs/install.md index 7352c78..9f30bb7 100644 --- a/docs/install.md +++ b/docs/install.md @@ -129,6 +129,14 @@ docker run --rm ghcr.io/netapp/ontap-mcp:latest start --help This displays all available environment variables with descriptions, authentication options, and advanced settings. +Some commonly used flags: + +| Flag | Description | +|---|---| +| `--read-only` | Disable all mutating operations. Only read-only tools are registered. | +| `--stateless` | Disable mcp-session-id header validation. Required when deploying behind proxies or gateways that do not preserve session headers, e.g. on-premises data gateways. | +| `--inspect-traffic` | Log all MCP HTTP request and response bodies for debugging. | + ## Next Steps - Explore [Prepare ONTAP](prepare-ontap.md) diff --git a/docs/tools.md b/docs/tools.md index 9d032e7..4fc3d0c 100644 --- a/docs/tools.md +++ b/docs/tools.md @@ -6,7 +6,9 @@ ONTAP MCP provides a set of tools that can be used to interact with the ONTAP AP All ONTAP MCP tools are annotated with hint metadata: `readOnlyHint`, `idempotentHint`, and `destructiveHint`. The `readOnlyHint` indicates that the tool does not modify any data and is safe to use for discovery and information retrieval. The `destructiveHint` indicates that the tool performs actions that can modify or delete data, and should be used with caution. -If you want to run the ONTAP MCP server in read-only mode, you can start the server with the `--read-only` flag. In this mode, only tools with the `readOnlyHint` will be available for use, ensuring that no modifications can be made to the ONTAP cluster. See the [configuration documentation](install.md#configuration) for more details on how to start the server in read-only mode. +If you want to run the ONTAP MCP server in read-only mode, you can start the server with the `--read-only` flag. In this mode, only tools with the `readOnlyHint` will be available for use, ensuring that no modifications can be made to the ONTAP cluster. + +To run without mcp-session-id header validation (e.g. behind proxies that strip session headers), use the `--stateless` flag. See the [configuration documentation](install.md#configuration) for more details. ## API Discovery diff --git a/server/server.go b/server/server.go index d94ad7a..b5026ad 100644 --- a/server/server.go +++ b/server/server.go @@ -36,6 +36,7 @@ type Options struct { IsTest bool Port int ReadOnly bool + Stateless bool TestHTTPClient *http.Client // Optional HTTP client for testing } @@ -78,6 +79,9 @@ func (a *App) StartServer() { if a.options.ReadOnly { a.logger.Info("MCP server is running in read-only mode; mutating operations are disabled") } + if a.options.Stateless { + a.logger.Info("MCP server is running in stateless mode; mcp-session-id header validation is disabled") + } server := a.createMCPServer() a.runHTTPServer(server) } @@ -239,7 +243,7 @@ func (a *App) runHTTPServer(server *mcp.Server) { handler = mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server { return server - }, nil) + }, &mcp.StreamableHTTPOptions{Stateless: a.options.Stateless}) if a.options.InspectTraffic { prevHandler := handler