Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c14966a
fix(mcp): fix support for streamable http
remyleone May 5, 2026
e7f572d
Fix
remyleone May 6, 2026
1dbd533
Fix
remyleone May 7, 2026
8eefa5f
Fix lint
remyleone May 7, 2026
4d09016
fix from copilot
remyleone May 7, 2026
a45473a
Fix issues
remyleone May 7, 2026
6aa6189
add checks
remyleone May 7, 2026
5fbccfd
Use localhost
remyleone May 7, 2026
de3248c
remove disable localhost protection
remyleone May 7, 2026
f358991
Fix
remyleone May 7, 2026
f0417ef
fix remove mention of sse
remyleone May 7, 2026
5be5685
wip
remyleone May 7, 2026
c2c252f
Fix
remyleone May 11, 2026
510f8e9
Merge branch 'main' into fix_streamable_http
remyleone May 11, 2026
48b2415
Fix
remyleone May 11, 2026
e81cadf
Fix
remyleone May 11, 2026
7b8cbfd
fix potential panic
remyleone May 12, 2026
a98ced4
Fix
remyleone May 12, 2026
8864fb2
Fix lint
remyleone May 12, 2026
9fd9158
Merge branch 'main' into fix_streamable_http
remyleone May 12, 2026
e3a6bbc
Fix
remyleone May 12, 2026
26244d3
fix ci
remyleone May 12, 2026
93d63e8
Update internal/namespaces/mcp/server/list_tools.go
remyleone May 13, 2026
7790eb5
Update internal/namespaces/mcp/server/list_tools.go
remyleone May 13, 2026
670aa34
Fix
remyleone May 15, 2026
fa3d903
Fix
remyleone May 15, 2026
340dc66
Merge branch 'main' into fix_streamable_http
remyleone May 15, 2026
4817c61
fix: pass the buildinfo to extract the version
remyleone May 18, 2026
a249ae0
Fix tests
remyleone May 18, 2026
a49a4f8
add ensure MetaInContext
remyleone May 18, 2026
b2478eb
Fix
remyleone May 18, 2026
6aff44d
Merge branch 'main' into fix_streamable_http
remyleone May 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ EXAMPLES:
scw mcp server list-resources

List resources for a specific namespace
scw mcp server list-resources namespace=instance
scw mcp server list-resources namespaces=instance

List resources for a specific resource type
scw mcp server list-resources resource=server
scw mcp server list-resources resources=server

List only read-only resources
scw mcp server list-resources read-only=true

ARGS:
[namespace] Filter by namespace (e.g., instance, iam, object)
[resource] Filter by resource (e.g., server, volume, bucket)
[namespaces] Filter by namespaces (e.g., instance, iam, object)
[resources] Filter by resources (e.g., server, volume, bucket)
[read-only=false] Only list read-only resources

FLAGS:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,22 @@ EXAMPLES:
List all available MCP tools
scw mcp server list-tools

List tools for a specific namespace
scw mcp server list-tools namespace=instance
List tools for specific namespaces (comma-separated)
scw mcp server list-tools namespaces=instance

List tools for a specific resource
scw mcp server list-tools resource=server
List tools for specific resources (comma-separated)
scw mcp server list-tools resources=server

List only read-only tools (get/list operations)
scw mcp server list-tools read-only=true

List tools with a specific verb
scw mcp server list-tools verb=get
List tools with specific verbs (comma-separated)
scw mcp server list-tools verbs=get,list

ARGS:
[namespace] Filter by namespace (e.g., instance, iam, object)
[resource] Filter by resource (e.g., server, volume, bucket)
[verb] Filter by verb (e.g., get, list, create)
[namespaces] Filter by namespaces (e.g., instance, iam, object)
[resources] Filter by resources (e.g., server, volume, bucket)
[verbs] Filter by verbs (e.g., get, list, create)
[read-only=false] Only list read-only tools (get, list operations)

FLAGS:
Expand Down
25 changes: 11 additions & 14 deletions cmd/scw/testdata/test-all-usage-mcp-server-serve-usage.golden
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲
🟩🟩🟩 STDOUT️ 🟩🟩🟩️
Runs the MCP server, exposing all CLI commands as MCP tools for AI assistants. Supports stdio (default), SSE, and streamable HTTP transports.
Runs the MCP server, exposing all CLI commands as MCP tools for AI assistants. Supports stdio (default) and streamable HTTP transports.

USAGE:
scw mcp server serve [arg=value ...]
Expand All @@ -13,27 +13,24 @@ EXAMPLES:
scw mcp server serve --read-only

Only serve commands from specific namespaces
scw mcp server serve --enable-namespaces instance,iam,object
scw mcp server serve namespaces=instance,iam,object

Only serve commands from specific resources
scw mcp server serve --enable-resources server,volume,bucket
scw mcp server serve resources=server,volume,bucket

Only serve commands with specific verbs
scw mcp server serve --enable-verbs get,list,create
scw mcp server serve verbs=get,list,create

Combine filters to serve only instance server get/list commands
scw mcp server serve --enable-namespaces instance --enable-resources server --enable-verbs get,list

Start the MCP server with SSE transport on port 8080
scw mcp server serve --transport sse --address :8080
scw mcp server serve namespaces=instance resources=server verbs=get,list

ARGS:
[transport=stdio] Transport mode: stdio (default), sse, or streamable-http
[address=:8080] Address to bind for SSE and streamable-http transports (e.g., :8080)
[read-only=false] Only register read-only commands (get, list operations)
[enable-namespaces] Only serve commands from specified namespaces (comma-separated)
[enable-resources] Only serve commands from specified resources (comma-separated)
[enable-verbs] Only serve commands with specified verbs (comma-separated)
[transport=stdio] Transport mode: stdio (default) or streamable-http
[address=:8080] Address to bind for streamable-http transports (e.g., :8080)
[read-only=false] Only register read-only commands (get, list operations)
[namespaces] Only serve commands from specified namespaces (comma-separated)
[resources] Only serve commands from specified resources (comma-separated)
[verbs] Only serve commands with specified verbs (comma-separated)

FLAGS:
-h, --help help for serve
Expand Down
2 changes: 1 addition & 1 deletion core/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func CreateAndCloseFile(path string) error {
// runAfterCommandChecks execute checks after a command has been executed
// skipped if command has disabled checks or was executed in the last 24 hours
func runAfterCommandChecks(ctx context.Context, checkFuncs ...AfterCommandCheckFunc) {
cmd := extractMeta(ctx).command
cmd := ExtractMeta(ctx).command
cmdDisableCheck := cmd != nil && cmd.DisableAfterChecks
if cmdDisableCheck {
ExtractLogger(ctx).Debug("skipping after command checks")
Expand Down
2 changes: 1 addition & 1 deletion core/cobra_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func cobraRun(ctx context.Context, cmd *Command) func(*cobra.Command, []string)

rawArgs := args.RawArgs(rawArgsStr)

meta := extractMeta(ctx)
meta := ExtractMeta(ctx)
meta.command = cmd

// Check if --list-sub-commands flag is set
Expand Down
142 changes: 115 additions & 27 deletions core/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package core

import (
"context"
"errors"
"io"
"net/http"
"os"
Expand Down Expand Up @@ -50,71 +51,121 @@ func InjectMeta(ctx context.Context, meta *Meta) context.Context {
return context.WithValue(ctx, metaContextKey, meta)
}

// extractMeta extracts Meta from a given context.
func extractMeta(ctx context.Context) *Meta {
return ctx.Value(metaContextKey).(*Meta)
// ExtractMeta extracts Meta from a given context.
func ExtractMeta(ctx context.Context) *Meta {
if meta, ok := ctx.Value(metaContextKey).(*Meta); ok {
return meta
}

return nil
}

// injectSDKConfig add config to a Meta context
func InjectConfig(ctx context.Context, config *scw.Config) {
extractMeta(ctx).Platform.SetScwConfig(config)
meta := ExtractMeta(ctx)
if meta != nil && meta.Platform != nil {
meta.Platform.SetScwConfig(config)
}
}

func extractConfig(ctx context.Context) *scw.Config {
m := extractMeta(ctx)
if m.Platform != nil {
m := ExtractMeta(ctx)
if m != nil && m.Platform != nil {
return m.Platform.ScwConfig()
}

return nil
}

func ExtractCommands(ctx context.Context) *Commands {
return extractMeta(ctx).Commands
meta := ExtractMeta(ctx)
if meta == nil {
return nil
}

return meta.Commands
}

func ExtractCliConfig(ctx context.Context) *cliConfig.Config {
return extractMeta(ctx).CliConfig
meta := ExtractMeta(ctx)
if meta == nil {
return nil
}

return meta.CliConfig
}

func ExtractAliases(ctx context.Context) *alias.Config {
return ExtractCliConfig(ctx).Alias
cliConfig := ExtractCliConfig(ctx)
if cliConfig == nil {
return nil
}

return cliConfig.Alias
}

func GetOrganizationIDFromContext(ctx context.Context) string {
client := ExtractClient(ctx)
if client == nil {
return ""
}
organizationID, _ := client.GetDefaultOrganizationID()

return organizationID
}

func GetProjectIDFromContext(ctx context.Context) string {
client := ExtractClient(ctx)
if client == nil {
return ""
}
projectID, _ := client.GetDefaultProjectID()

return projectID
}

func ExtractClient(ctx context.Context) *scw.Client {
return extractMeta(ctx).Client
meta := ExtractMeta(ctx)
if meta == nil {
return nil
}

return meta.Client
}

func ExtractLogger(ctx context.Context) *Logger {
return extractMeta(ctx).Logger
meta := ExtractMeta(ctx)
if meta == nil {
return nil
}

return meta.Logger
}

func ExtractBuildInfo(ctx context.Context) *BuildInfo {
return extractMeta(ctx).BuildInfo
meta := ExtractMeta(ctx)
if meta == nil {
return nil
}

return meta.BuildInfo
}

func ExtractBetaMode(ctx context.Context) bool {
return extractMeta(ctx).BetaMode
meta := ExtractMeta(ctx)
if meta == nil {
return false
}

return meta.BetaMode
}

func ExtractEnv(ctx context.Context, envKey string) string {
meta := extractMeta(ctx)
if value, exist := meta.OverrideEnv[envKey]; exist {
return value
meta := ExtractMeta(ctx)
if meta != nil {
if value, exist := meta.OverrideEnv[envKey]; exist {
return value
}
}

if envKey == "HOME" {
Expand All @@ -140,17 +191,28 @@ func ExtractCacheDir(ctx context.Context) string {
}

func ExtractBinaryName(ctx context.Context) string {
return extractMeta(ctx).BinaryName
meta := ExtractMeta(ctx)
if meta == nil {
return ""
}

return meta.BinaryName
}

func ExtractStdin(ctx context.Context) io.Reader {
return extractMeta(ctx).stdin
meta := ExtractMeta(ctx)
if meta == nil {
return nil
}

return meta.stdin
}

func ExtractProfileName(ctx context.Context) string {
meta := ExtractMeta(ctx)
// Handle profile flag -p
if extractMeta(ctx).ProfileFlag != "" {
return extractMeta(ctx).ProfileFlag
if meta != nil && meta.ProfileFlag != "" {
return meta.ProfileFlag
}

// Handle SCW_PROFILE env variable
Expand All @@ -170,13 +232,21 @@ func ExtractProfileName(ctx context.Context) string {
}

func ExtractHTTPClient(ctx context.Context) *http.Client {
return extractMeta(ctx).httpClient
meta := ExtractMeta(ctx)
if meta == nil {
return nil
}

return meta.httpClient
}

func ExtractConfigPath(ctx context.Context) string {
meta := extractMeta(ctx)
meta := ExtractMeta(ctx)
if meta == nil {
return scw.GetConfigPath()
}
if meta.ConfigPathFlag != "" {
return extractMeta(ctx).ConfigPathFlag
return meta.ConfigPathFlag
}
// This is only useful for test when we override home environment variable
if home := meta.OverrideEnv["HOME"]; home != "" {
Expand All @@ -187,7 +257,12 @@ func ExtractConfigPath(ctx context.Context) string {
}

func ExtractCliConfigPath(ctx context.Context) string {
meta := extractMeta(ctx)
meta := ExtractMeta(ctx)
if meta == nil {
configPath, _ := cliConfig.FilePath()

return configPath
}
// This is only useful for test when we override home environment variable
if home := meta.OverrideEnv["HOME"]; home != "" {
return path.Join(home, ".config", "scw", cliConfig.DefaultConfigFileName)
Expand All @@ -198,8 +273,11 @@ func ExtractCliConfigPath(ctx context.Context) string {
}

func ReloadClient(ctx context.Context) error {
meta := ExtractMeta(ctx)
if meta == nil {
return errors.New("cannot reload client: meta not found in context")
}
var err error
meta := extractMeta(ctx)
meta.Client, err = meta.Platform.CreateClient(
meta.httpClient,
ExtractConfigPath(ctx),
Expand All @@ -210,11 +288,21 @@ func ReloadClient(ctx context.Context) error {
}

func ExtractConfigPathFlag(ctx context.Context) string {
return extractMeta(ctx).ConfigPathFlag
meta := ExtractMeta(ctx)
if meta == nil {
return ""
}

return meta.ConfigPathFlag
}

func ExtractProfileFlag(ctx context.Context) string {
return extractMeta(ctx).ProfileFlag
meta := ExtractMeta(ctx)
if meta == nil {
return ""
}

return meta.ProfileFlag
}

// GetDocGenContext returns a minimal context that can be used by scw-doc-gen
Expand Down
2 changes: 1 addition & 1 deletion core/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func defaultOverrideExec(cmd *exec.Cmd) (exitCode int, err error) {
}

func ExecCmd(ctx context.Context, cmd *exec.Cmd) (exitCode int, err error) {
meta := extractMeta(ctx)
meta := ExtractMeta(ctx)

// We do not support override of stdin
if cmd.Stdin == nil {
Expand Down
2 changes: 1 addition & 1 deletion core/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type Completer struct {
func NewShellCompleter(ctx context.Context) *Completer {
return &Completer{
commands: ExtractCommands(ctx),
meta: extractMeta(ctx),
meta: ExtractMeta(ctx),
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func validateDeprecated(

for i := range fieldValues {
if rawArgs.ExistsArgByName(strings.Replace(arg.Name, "{index}", strconv.Itoa(i), 1)) {
helpCmd := cmd.GetCommandLine(extractMeta(ctx).BinaryName) + " --help"
helpCmd := cmd.GetCommandLine(ExtractMeta(ctx).BinaryName) + " --help"
ExtractLogger(
ctx,
).Warningf("The argument '%s' is deprecated, more info with: %s\n", arg.Name, helpCmd)
Expand Down
Loading
Loading