Skip to content

Commit 723be7c

Browse files
authored
Add plugin get command (#217)
* Add plugin get command Implement 'mcpd config plugins get' command to display top-level plugin config, or config for a specific plugin within a category.
1 parent 81ef131 commit 723be7c

File tree

11 files changed

+1159
-32
lines changed

11 files changed

+1159
-32
lines changed

cmd/config/plugins/get.go

Lines changed: 131 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,143 @@ import (
55

66
"github.com/spf13/cobra"
77

8-
"github.com/mozilla-ai/mcpd/v2/internal/cmd"
9-
"github.com/mozilla-ai/mcpd/v2/internal/cmd/options"
8+
internalcmd "github.com/mozilla-ai/mcpd/v2/internal/cmd"
9+
cmdopts "github.com/mozilla-ai/mcpd/v2/internal/cmd/options"
10+
"github.com/mozilla-ai/mcpd/v2/internal/cmd/output"
11+
"github.com/mozilla-ai/mcpd/v2/internal/config"
12+
"github.com/mozilla-ai/mcpd/v2/internal/printer"
1013
)
1114

15+
const (
16+
flagCategory = "category"
17+
flagName = "name"
18+
flagFormat = "format"
19+
)
20+
21+
// GetCmd represents the get command.
22+
// NOTE: Use NewGetCmd to create a GetCmd.
23+
type GetCmd struct {
24+
*internalcmd.BaseCmd
25+
26+
// cfgLoader is used to load the configuration.
27+
cfgLoader config.Loader
28+
29+
// pluginConfigPrinter is used to output top-level plugin configuration.
30+
pluginConfigPrinter output.Printer[printer.PluginConfigResult]
31+
32+
// pluginEntryPrinter is used to output specific plugin entries.
33+
pluginEntryPrinter output.Printer[printer.PluginEntryResult]
34+
35+
// format stores the format flag when specified.
36+
format internalcmd.OutputFormat
37+
38+
// category is the (optional) category name to look in for the plugin.
39+
category config.Category
40+
41+
// name is the (optional) name of the plugin to return config for.
42+
name string
43+
}
44+
1245
// NewGetCmd creates the get command for plugins.
13-
// TODO: Implement in a future PR.
14-
func NewGetCmd(baseCmd *cmd.BaseCmd, opt ...options.CmdOption) (*cobra.Command, error) {
46+
func NewGetCmd(baseCmd *internalcmd.BaseCmd, opt ...cmdopts.CmdOption) (*cobra.Command, error) {
47+
opts, err := cmdopts.NewOptions(opt...)
48+
if err != nil {
49+
return nil, err
50+
}
51+
52+
c := &GetCmd{
53+
BaseCmd: baseCmd,
54+
cfgLoader: opts.ConfigLoader,
55+
pluginConfigPrinter: &printer.PluginConfigPrinter{},
56+
pluginEntryPrinter: &printer.PluginEntryPrinter{},
57+
format: internalcmd.FormatText, // Default to plain text
58+
}
59+
1560
cobraCmd := &cobra.Command{
1661
Use: "get",
17-
Short: "Get plugin-level config or specific plugin entry",
18-
Long: "Get plugin-level configuration (when no flags provided) or specific plugin entry (when --category and --name provided)",
19-
RunE: func(cmd *cobra.Command, args []string) error {
20-
return fmt.Errorf("not yet implemented")
21-
},
62+
Short: "Get top level configuration for the plugin subsystem or for a specific plugin entry in a category",
63+
Long: `Get top level configuration for the plugin subsystem or for a specific plugin entry in a category.
64+
65+
When called without flags, shows plugin-level configuration (e.g. plugin directory).
66+
When called with --category and --name, shows the specific plugin entry.
67+
Both --category and --name must be provided together.`,
68+
Example: ` # Get plugin-level configuration
69+
mcpd config plugins get
70+
71+
# Get specific plugin entry
72+
mcpd config plugins get --category authentication --name jwt-auth`,
73+
RunE: c.run,
74+
Args: cobra.NoArgs,
2275
}
2376

77+
allowedCategories := config.OrderedCategories()
78+
cobraCmd.Flags().Var(
79+
&c.category,
80+
flagCategory,
81+
fmt.Sprintf("Specify the category (one of: %s)", allowedCategories.String()),
82+
)
83+
84+
cobraCmd.Flags().StringVar(
85+
&c.name,
86+
flagName,
87+
"",
88+
"Plugin name",
89+
)
90+
91+
allowedOutputFormats := internalcmd.AllowedOutputFormats()
92+
cobraCmd.Flags().Var(
93+
&c.format,
94+
flagFormat,
95+
fmt.Sprintf("Specify the output format (one of: %s)", allowedOutputFormats.String()),
96+
)
97+
2498
return cobraCmd, nil
2599
}
100+
101+
func (c *GetCmd) run(cmd *cobra.Command, _ []string) error {
102+
// Validate optional flags.
103+
if err := c.RequireTogether(cmd, flagCategory, flagName); err != nil {
104+
return err
105+
}
106+
107+
cfg, err := c.LoadConfig(c.cfgLoader)
108+
if err != nil {
109+
return err
110+
}
111+
112+
// Show top-level plugin config settings.
113+
if !cmd.Flags().Changed(flagCategory) {
114+
var dir string
115+
if cfg.Plugins != nil {
116+
dir = cfg.Plugins.Dir
117+
}
118+
119+
result := printer.PluginConfigResult{
120+
Dir: dir,
121+
}
122+
123+
handler, err := internalcmd.FormatHandler(cmd.OutOrStdout(), c.format, c.pluginConfigPrinter)
124+
if err != nil {
125+
return err
126+
}
127+
128+
return handler.HandleResult(result)
129+
}
130+
131+
// Show a single plugin item for category/name if we can find it.
132+
if entry, found := cfg.Plugin(c.category, c.name); found {
133+
result := printer.PluginEntryResult{
134+
PluginEntry: entry,
135+
Category: c.category,
136+
}
137+
138+
handler, err := internalcmd.FormatHandler(cmd.OutOrStdout(), c.format, c.pluginEntryPrinter)
139+
if err != nil {
140+
return err
141+
}
142+
143+
return handler.HandleResult(result)
144+
}
145+
146+
return fmt.Errorf("plugin '%s' not found in category '%s'", c.name, c.category)
147+
}

0 commit comments

Comments
 (0)