@@ -156,6 +156,29 @@ func NewServer() *MCPServer {
156156 handleDeleteTool ,
157157 )
158158
159+ mcpServer .AddTool (
160+ mcp .NewTool ("config_volumes" ,
161+ mcp .WithDescription ("Lists and manages configured volumes for a function" ),
162+ mcp .WithString ("action" ,
163+ mcp .Required (),
164+ mcp .Description ("The action to perform: 'add' to add a volume, 'remove' to remove a volume, 'list' to list volumes" ),
165+ ),
166+ mcp .WithString ("path" ,
167+ mcp .Required (),
168+ mcp .Description ("Path to the function. Default is current directory ($FUNC_PATH)" ),
169+ ),
170+
171+ // Optional flags
172+ mcp .WithString ("type" , mcp .Description ("Volume type: configmap, secret, pvc, or emptydir" )),
173+ mcp .WithString ("mount_path" , mcp .Description ("Mount path for the volume in the function container" )),
174+ mcp .WithString ("source" , mcp .Description ("Name of the ConfigMap, Secret, or PVC to mount (not used for emptydir)" )),
175+ mcp .WithString ("medium" , mcp .Description ("Storage medium for EmptyDir volume: 'Memory' or '' (default)" )),
176+ mcp .WithString ("size" , mcp .Description ("Maximum size limit for EmptyDir volume (e.g., 1Gi)" )),
177+ mcp .WithBoolean ("read_only" , mcp .Description ("Mount volume as read-only (only for PVC)" )),
178+ mcp .WithBoolean ("verbose" , mcp .Description ("Print verbose logs ($FUNC_VERBOSE)" )),
179+ ),
180+ handleConfigVolumesTool ,
181+ )
159182 mcpServer .AddResource (mcp .NewResource (
160183 "func://docs" ,
161184 "Root Help Command" ,
@@ -170,7 +193,7 @@ func NewServer() *MCPServer {
170193 mcp .WithResourceDescription ("--help output of the 'create' command" ),
171194 mcp .WithMIMEType ("text/plain" ),
172195 ), func (ctx context.Context , request mcp.ReadResourceRequest ) ([]mcp.ResourceContents , error ) {
173- return runHelpCommand ("create" , "func://create/docs" )
196+ return runHelpCommand ([] string { "create" } , "func://create/docs" )
174197 })
175198
176199 mcpServer .AddResource (mcp .NewResource (
@@ -179,7 +202,7 @@ func NewServer() *MCPServer {
179202 mcp .WithResourceDescription ("--help output of the 'build' command" ),
180203 mcp .WithMIMEType ("text/plain" ),
181204 ), func (ctx context.Context , request mcp.ReadResourceRequest ) ([]mcp.ResourceContents , error ) {
182- return runHelpCommand ("build" , "func://build/docs" )
205+ return runHelpCommand ([] string { "build" } , "func://build/docs" )
183206 })
184207
185208 mcpServer .AddResource (mcp .NewResource (
@@ -188,7 +211,7 @@ func NewServer() *MCPServer {
188211 mcp .WithResourceDescription ("--help output of the 'deploy' command" ),
189212 mcp .WithMIMEType ("text/plain" ),
190213 ), func (ctx context.Context , request mcp.ReadResourceRequest ) ([]mcp.ResourceContents , error ) {
191- return runHelpCommand ("deploy" , "func://deploy/docs" )
214+ return runHelpCommand ([] string { "deploy" } , "func://deploy/docs" )
192215 })
193216
194217 mcpServer .AddResource (mcp .NewResource (
@@ -197,7 +220,7 @@ func NewServer() *MCPServer {
197220 mcp .WithResourceDescription ("--help output of the 'list' command" ),
198221 mcp .WithMIMEType ("text/plain" ),
199222 ), func (ctx context.Context , request mcp.ReadResourceRequest ) ([]mcp.ResourceContents , error ) {
200- return runHelpCommand ("list" , "func://list/docs" )
223+ return runHelpCommand ([] string { "list" } , "func://list/docs" )
201224 })
202225
203226 mcpServer .AddResource (mcp .NewResource (
@@ -206,7 +229,25 @@ func NewServer() *MCPServer {
206229 mcp .WithResourceDescription ("--help output of the 'delete' command" ),
207230 mcp .WithMIMEType ("text/plain" ),
208231 ), func (ctx context.Context , request mcp.ReadResourceRequest ) ([]mcp.ResourceContents , error ) {
209- return runHelpCommand ("delete" , "func://delete/docs" )
232+ return runHelpCommand ([]string {"delete" }, "func://delete/docs" )
233+ })
234+
235+ mcpServer .AddResource (mcp .NewResource (
236+ "func://config/volumes/add/docs" ,
237+ "Config Volumes Add Command Help" ,
238+ mcp .WithResourceDescription ("--help output of the 'config volumes add' command" ),
239+ mcp .WithMIMEType ("text/plain" ),
240+ ), func (ctx context.Context , request mcp.ReadResourceRequest ) ([]mcp.ResourceContents , error ) {
241+ return runHelpCommand ([]string {"config" , "volumes" , "add" }, "func://config/volumes/add/docs" )
242+ })
243+
244+ mcpServer .AddResource (mcp .NewResource (
245+ "func://config/volumes/remove/docs" ,
246+ "Config Volumes Remove Command Help" ,
247+ mcp .WithResourceDescription ("--help output of the 'config volumes remove' command" ),
248+ mcp .WithMIMEType ("text/plain" ),
249+ ), func (ctx context.Context , request mcp.ReadResourceRequest ) ([]mcp.ResourceContents , error ) {
250+ return runHelpCommand ([]string {"config" , "volumes" , "remove" }, "func://config/volumes/add/docs" )
210251 })
211252
212253 mcpServer .AddPrompt (mcp .NewPrompt ("help" ,
@@ -245,8 +286,9 @@ func handleRootHelpResource(ctx context.Context, request mcp.ReadResourceRequest
245286 }, nil
246287}
247288
248- func runHelpCommand (cmd string , uri string ) ([]mcp.ResourceContents , error ) {
249- content , err := exec .Command ("func" , cmd , "--help" ).Output ()
289+ func runHelpCommand (args []string , uri string ) ([]mcp.ResourceContents , error ) {
290+ args = append (args , "--help" )
291+ content , err := exec .Command ("func" , args ... ).Output ()
250292 if err != nil {
251293 return nil , err
252294 }
@@ -573,3 +615,73 @@ func handleDeleteTool(
573615 body := []byte (fmt .Sprintf (`{"result": "%s"}` , out ))
574616 return mcp .NewToolResultText (string (body )), nil
575617}
618+
619+ func handleConfigVolumesTool (
620+ ctx context.Context ,
621+ request mcp.CallToolRequest ,
622+ ) (* mcp.CallToolResult , error ) {
623+ action , err := request .RequireString ("action" )
624+ if err != nil {
625+ return mcp .NewToolResultError (err .Error ()), nil
626+ }
627+ path , err := request .RequireString ("path" )
628+ if err != nil {
629+ return mcp .NewToolResultError (err .Error ()), nil
630+ }
631+ if action == "list" {
632+ // For 'list' action, we don't need other parameters, only --path
633+ args := []string {"config" , "volumes" , "--path" , path }
634+ if request .GetBool ("verbose" , false ) {
635+ args = append (args , "--verbose" )
636+ }
637+
638+ cmd := exec .Command ("func" , args ... )
639+ out , err := cmd .CombinedOutput ()
640+ if err != nil {
641+ return mcp .NewToolResultError (fmt .Sprintf ("func config volumes list failed: %s" , out )), nil
642+ }
643+ body := []byte (fmt .Sprintf (`{"result": "%s"}` , out ))
644+ return mcp .NewToolResultText (string (body )), nil
645+ }
646+
647+ args := []string {"config" , "volumes" , action }
648+
649+ if action == "add" {
650+ volumeType , err := request .RequireString ("type" )
651+ if err != nil {
652+ return mcp .NewToolResultError (err .Error ()), nil
653+ }
654+ args = append (args , "--type" , volumeType )
655+ }
656+ mountPath , err := request .RequireString ("mount_path" )
657+ if err != nil {
658+ return mcp .NewToolResultError (err .Error ()), nil
659+ }
660+ args = append (args , "--mount-path" , mountPath , "--path" , path )
661+
662+ // Optional flags
663+ if v := request .GetString ("source" , "" ); v != "" {
664+ args = append (args , "--source" , v )
665+ }
666+ if v := request .GetString ("medium" , "" ); v != "" {
667+ args = append (args , "--medium" , v )
668+ }
669+ if v := request .GetString ("size" , "" ); v != "" {
670+ args = append (args , "--size" , v )
671+ }
672+ if request .GetBool ("read_only" , false ) {
673+ args = append (args , "--read-only" )
674+ }
675+ if request .GetBool ("verbose" , false ) {
676+ args = append (args , "--verbose" )
677+ }
678+
679+ cmd := exec .Command ("func" , args ... )
680+ out , err := cmd .CombinedOutput ()
681+ if err != nil {
682+ return mcp .NewToolResultError (fmt .Sprintf ("func config volumes failed: %s" , out )), nil
683+ }
684+
685+ body := []byte (fmt .Sprintf (`{"result": "%s"}` , out ))
686+ return mcp .NewToolResultText (string (body )), nil
687+ }
0 commit comments