Skip to content

Add a codec for a custom flag type

Bind refuses to start when an exposed command has a flag whose pflag type it cannot encode, naming the command, the flag and the type:

command "deploy": flag --strategy has type "strategy", which has no codec; register one with WithCodec or exclude the command

Every standard pflag kind has a built-in codec (see the codec table). The message means the flag was registered with a custom pflag.Value, whose Type() returns a name the binding has never seen. You have two choices.

Register a text codec

Most custom values are one string on the command line, parsed by the flag's own Set. Register a text codec for the type name:

mcpcli.Command(mcpcli.WithBinding(
    mcpcobra.WithCodec("strategy", mcpcobra.TextCodec(nil)),
))

The client now sends a string and the child's parser validates it as it always did. To tell the client what to send, add schema constraints:

mcpcobra.WithCodec("strategy", mcpcobra.TextCodec(json.RawMessage(`{"enum":["canary","blue-green"]}`)))

The constraints are merged into the published property. They may not redefine type; the codec sets it to string. A value that fails the constraints is refused by the registry before any process starts.

Or exclude the command

If the command should not be an MCP operation at all, exclude it through the exposure policy your host passes to WithExposure. An unsupported flag on an excluded command does not block the bind. In a tool built on go-tool-base that is gtb disable mcp <command>.

Writing a full codec

For a type whose CLI form is not one string (a repeated value, a key=value list), implement Codec yourself:

type Codec interface {
    Schema(Flag) (json.RawMessage, error)
    Encode(Flag, json.RawMessage) ([]string, error)
}

Schema returns the JSON schema property for the flag. Encode turns the client's JSON into the values for that flag, one per token; the binding emits each as --name=value. Return an error for a value the CLI cannot express faithfully rather than approximating it. Never return a command line: the binding owns flag names and the command path, and there is no shell.

The built-in stringSlice codec is the model for the rule: pflag splits its value on commas, so an element containing a comma is refused, because the child would see two values where the client sent one.