Tencent/WeKnora · error

stdio transport is disabled for security reasons; please use

Error message

stdio transport is disabled for security reasons; please use SSE or HTTP Streamable transport instead

What it means

Hard security guard in NewMCPClient: the stdio transport (spawning a local subprocess) is deliberately disabled because config-controlled command + args would enable command injection / arbitrary process execution. Only SSE and HTTP Streamable remote transports are allowed.

Source

Thrown at internal/mcp/client.go:226

		}
		if useOAuth {
			mcpClient, err = client.NewOAuthStreamableHttpClient(*config.Service.URL, oauthConfig,
				transport.WithHTTPBasicClient(httpClient),
				transport.WithHTTPHeaders(headers),
			)
		} else {
			// For HTTP streamable, we need to use transport options
			mcpClient, err = client.NewStreamableHttpClient(*config.Service.URL,
				transport.WithHTTPBasicClient(httpClient),
				transport.WithHTTPHeaders(headers),
			)
		}
		if err != nil {
			return nil, fmt.Errorf("failed to create HTTP streamable client: %w", err)
		}
	case types.MCPTransportStdio:
		// Stdio transport is disabled for security reasons (potential command injection vulnerabilities)
		return nil, fmt.Errorf("stdio transport is disabled for security reasons; please use SSE or HTTP Streamable transport instead")
	default:
		return nil, ErrUnsupportedTransport
	}

	instance := &mcpGoClient{
		service: config.Service,
		client:  mcpClient,
	}
	if useOAuth {
		instance.oauth = newOAuthRuntime(
			config.OAuthRepo,
			config.TenantID,
			config.Principal,
			config.Service.ID,
			*config.Service.URL,
			oauthConfig,
		)
	}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Change the service TransportType to MCPTransportSSE or MCPTransportHTTPStreamable with a remote URL
  2. Run the local MCP server as a standalone HTTP/SSE endpoint (e.g. mcp server with an sse/streamable-http listener) and point the URL at it
  3. Remove any code path or UI option that allows selecting stdio transport

Example fix

// before
svc := &types.MCPService{TransportType: types.MCPTransportStdio,
    StdioConfig: &types.StdioConfig{Command: "npx", Args: []string{"-y", "@modelcontextprotocol/server"}}}
// after
url := "http://127.0.0.1:8080/mcp"
svc := &types.MCPService{TransportType: types.MCPTransportHTTPStreamable, URL: &url}
Defensive patterns

Strategy: validation

Validate before calling

func ensureRemoteTransport(svc *types.MCPService) error {
    if svc.TransportType == types.MCPTransportStdio {
        return errors.New("stdio transport is disabled; use SSE or HTTP Streamable")
    }
    return nil
}

Type guard

func isStdioService(svc *types.MCPService) bool {
    return svc != nil && svc.TransportType == types.MCPTransportStdio
}

Try / catch

_, err := NewMCPClient(cfg)
if err != nil && strings.Contains(err.Error(), "stdio transport is disabled") {
    return fmt.Errorf("service %s uses the removed stdio transport; migrate to SSE/streamable", cfg.Service.ID)
}

Prevention

When it happens

Trigger: NewMCPClient called with config.Service.TransportType == types.MCPTransportStdio, regardless of StdioConfig contents. Deterministic — always thrown for this transport type.

Common situations: Service imported or migrated from a config that used stdio; developer following older MCP docs/examples that spawn a local server (e.g. npx-based servers); environment variable forcing stdio transport.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/b8fc60c0463c1da2. Report an issue: GitHub.