mirror of https://github.com/knative/func.git
364 lines
14 KiB
Go
364 lines
14 KiB
Go
package mcp
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/mark3labs/mcp-go/mcp"
|
|
"github.com/mark3labs/mcp-go/server"
|
|
)
|
|
|
|
var TEMPLATE_RESOURCE_URIS = []string{
|
|
"https://github.com/functions-dev/templates",
|
|
}
|
|
|
|
type MCPServer struct {
|
|
server *server.MCPServer
|
|
}
|
|
|
|
func NewServer() *MCPServer {
|
|
mcpServer := server.NewMCPServer(
|
|
"func-mcp",
|
|
"1.0.0",
|
|
server.WithToolCapabilities(true),
|
|
)
|
|
|
|
mcpServer.AddTool(
|
|
mcp.NewTool("healthcheck",
|
|
mcp.WithDescription("Checks if the server is running"),
|
|
),
|
|
handleHealthCheckTool,
|
|
)
|
|
|
|
mcpServer.AddTool(
|
|
mcp.NewTool("create",
|
|
mcp.WithDescription("Creates a Knative function project in the current or specified directory"),
|
|
mcp.WithString("cwd",
|
|
mcp.Required(),
|
|
mcp.Description("Current working directory of the MCP client"),
|
|
),
|
|
mcp.WithString("name",
|
|
mcp.Required(),
|
|
mcp.Description("Name of the function to be created (used as subdirectory)"),
|
|
),
|
|
mcp.WithString("language",
|
|
mcp.Required(),
|
|
mcp.Description("Language runtime to use (e.g., node, go, python)"),
|
|
),
|
|
|
|
// Optional flags
|
|
mcp.WithString("template", mcp.Description("Function template (e.g., http, cloudevents)")),
|
|
mcp.WithString("repository", mcp.Description("URI to Git repo containing the template. Overrides default template selection when provided.")),
|
|
mcp.WithBoolean("confirm", mcp.Description("Prompt to confirm options interactively")),
|
|
mcp.WithBoolean("verbose", mcp.Description("Print verbose logs")),
|
|
),
|
|
handleCreateTool,
|
|
)
|
|
|
|
mcpServer.AddTool(
|
|
mcp.NewTool("deploy",
|
|
mcp.WithDescription("Deploys the function to the cluster"),
|
|
mcp.WithString("registry",
|
|
mcp.Required(),
|
|
mcp.Description("Registry to be used to push the function image"),
|
|
),
|
|
mcp.WithString("cwd",
|
|
mcp.Required(),
|
|
mcp.Description("Full path of the function to be deployed"),
|
|
),
|
|
mcp.WithString("builder",
|
|
mcp.Required(),
|
|
mcp.Description("Builder to be used to build the function image"),
|
|
),
|
|
|
|
// Optional flags
|
|
mcp.WithString("image", mcp.Description("Full image name (overrides registry)")),
|
|
mcp.WithString("namespace", mcp.Description("Namespace to deploy the function into")),
|
|
mcp.WithString("git-url", mcp.Description("Git URL containing the function source")),
|
|
mcp.WithString("git-branch", mcp.Description("Git branch for remote deployment")),
|
|
mcp.WithString("git-dir", mcp.Description("Directory inside the Git repository")),
|
|
mcp.WithString("builder-image", mcp.Description("Custom builder image")),
|
|
mcp.WithString("domain", mcp.Description("Domain for the function route")),
|
|
mcp.WithString("platform", mcp.Description("Target platform to build for (e.g., linux/amd64)")),
|
|
mcp.WithString("path", mcp.Description("Path to the function directory")),
|
|
mcp.WithString("build", mcp.Description(`Build control: "true", "false", or "auto"`)),
|
|
mcp.WithString("pvc-size", mcp.Description("Custom volume size for remote builds")),
|
|
mcp.WithString("service-account", mcp.Description("Kubernetes ServiceAccount to use")),
|
|
mcp.WithString("remote-storage-class", mcp.Description("Storage class for remote volume")),
|
|
|
|
mcp.WithBoolean("confirm", mcp.Description("Prompt for confirmation before deploying")),
|
|
mcp.WithBoolean("push", mcp.Description("Push image to registry before deployment")),
|
|
mcp.WithBoolean("verbose", mcp.Description("Print verbose logs")),
|
|
mcp.WithBoolean("registry-insecure", mcp.Description("Skip TLS verification for registry")),
|
|
mcp.WithBoolean("build-timestamp", mcp.Description("Use actual time in image metadata")),
|
|
mcp.WithBoolean("remote", mcp.Description("Trigger remote deployment")),
|
|
),
|
|
handleDeployTool,
|
|
)
|
|
|
|
mcpServer.AddTool(
|
|
mcp.NewTool("list",
|
|
mcp.WithDescription("Lists all deployed functions in the current or specified namespace"),
|
|
|
|
// Optional flags
|
|
mcp.WithBoolean("all-namespaces", mcp.Description("List functions in all namespaces (overrides --namespace)")),
|
|
mcp.WithString("namespace", mcp.Description("The namespace to list functions in (default is current/active)")),
|
|
mcp.WithString("output", mcp.Description("Output format: human, plain, json, xml, yaml")),
|
|
mcp.WithBoolean("verbose", mcp.Description("Enable verbose output")),
|
|
),
|
|
handleListTool,
|
|
)
|
|
|
|
mcpServer.AddTool(
|
|
mcp.NewTool("build",
|
|
mcp.WithDescription("Builds the function image in the current directory"),
|
|
mcp.WithString("cwd",
|
|
mcp.Required(),
|
|
mcp.Description("Current working directory of the MCP client"),
|
|
),
|
|
mcp.WithString("builder",
|
|
mcp.Required(),
|
|
mcp.Description("Builder to be used to build the function image (pack, s2i, host)"),
|
|
),
|
|
mcp.WithString("registry",
|
|
mcp.Required(),
|
|
mcp.Description("Registry to be used to push the function image (e.g. ghcr.io/user)"),
|
|
),
|
|
|
|
// Optional flags
|
|
mcp.WithString("builder-image", mcp.Description("Custom builder image to use with buildpacks")),
|
|
mcp.WithString("image", mcp.Description("Full image name (overrides registry + function name)")),
|
|
mcp.WithString("path", mcp.Description("Path to the function directory (default is current dir)")),
|
|
mcp.WithString("platform", mcp.Description("Target platform, e.g. linux/amd64 (for s2i builds)")),
|
|
|
|
mcp.WithBoolean("confirm", mcp.Description("Prompt for confirmation before proceeding")),
|
|
mcp.WithBoolean("push", mcp.Description("Push image to registry after building")),
|
|
mcp.WithBoolean("verbose", mcp.Description("Enable verbose logging output")),
|
|
mcp.WithBoolean("registry-insecure", mcp.Description("Skip TLS verification for insecure registries")),
|
|
mcp.WithBoolean("build-timestamp", mcp.Description("Use actual time for image timestamp (buildpacks only)")),
|
|
),
|
|
handleBuildTool,
|
|
)
|
|
|
|
mcpServer.AddTool(
|
|
mcp.NewTool("delete",
|
|
mcp.WithDescription("Deletes a function from the cluster"),
|
|
mcp.WithString("name",
|
|
mcp.Required(),
|
|
mcp.Description("Name of the function to be deleted"),
|
|
),
|
|
|
|
// Optional flags
|
|
mcp.WithString("namespace", mcp.Description("Namespace to delete from (default: current or active)")),
|
|
mcp.WithString("path", mcp.Description("Path to the function project (default is current directory)")),
|
|
mcp.WithString("all", mcp.Description(`Delete all related resources like Pipelines, Secrets ("true"/"false")`)),
|
|
|
|
mcp.WithBoolean("confirm", mcp.Description("Prompt to confirm before deletion")),
|
|
mcp.WithBoolean("verbose", mcp.Description("Enable verbose output")),
|
|
),
|
|
handleDeleteTool,
|
|
)
|
|
|
|
mcpServer.AddTool(
|
|
mcp.NewTool("config_volumes",
|
|
mcp.WithDescription("Lists and manages configured volumes for a function"),
|
|
mcp.WithString("action",
|
|
mcp.Required(),
|
|
mcp.Description("The action to perform: 'add' to add a volume, 'remove' to remove a volume, 'list' to list volumes"),
|
|
),
|
|
mcp.WithString("path",
|
|
mcp.Required(),
|
|
mcp.Description("Path to the function. Default is current directory ($FUNC_PATH)"),
|
|
),
|
|
|
|
// Optional flags
|
|
mcp.WithString("type", mcp.Description("Volume type: configmap, secret, pvc, or emptydir")),
|
|
mcp.WithString("mount_path", mcp.Description("Mount path for the volume in the function container")),
|
|
mcp.WithString("source", mcp.Description("Name of the ConfigMap, Secret, or PVC to mount (not used for emptydir)")),
|
|
mcp.WithString("medium", mcp.Description("Storage medium for EmptyDir volume: 'Memory' or '' (default)")),
|
|
mcp.WithString("size", mcp.Description("Maximum size limit for EmptyDir volume (e.g., 1Gi)")),
|
|
mcp.WithBoolean("read_only", mcp.Description("Mount volume as read-only (only for PVC)")),
|
|
mcp.WithBoolean("verbose", mcp.Description("Print verbose logs ($FUNC_VERBOSE)")),
|
|
),
|
|
handleConfigVolumesTool,
|
|
)
|
|
|
|
mcpServer.AddTool(
|
|
mcp.NewTool("config_labels",
|
|
mcp.WithDescription("Lists and manages labels for a function"),
|
|
mcp.WithString("action",
|
|
mcp.Required(),
|
|
mcp.Description("The action to perform: 'add' to add a label, 'remove' to remove a label, 'list' to list labels"),
|
|
),
|
|
mcp.WithString("path",
|
|
mcp.Required(),
|
|
mcp.Description("Path to the function. Default is current directory ($FUNC_PATH)"),
|
|
),
|
|
|
|
// Optional flags
|
|
mcp.WithString("name", mcp.Description("Name of the label.")),
|
|
mcp.WithString("value", mcp.Description("Value of the label.")),
|
|
mcp.WithBoolean("verbose", mcp.Description("Print verbose logs ($FUNC_VERBOSE)")),
|
|
),
|
|
handleConfigLabelsTool,
|
|
)
|
|
|
|
mcpServer.AddTool(
|
|
mcp.NewTool("config_envs",
|
|
mcp.WithDescription("Lists and manages environment variables for a function"),
|
|
mcp.WithString("action",
|
|
mcp.Required(),
|
|
mcp.Description("The action to perform: 'add' to add an env var, 'remove' to remove, 'list' to list env vars"),
|
|
),
|
|
mcp.WithString("path",
|
|
mcp.Required(),
|
|
mcp.Description("Path to the function. Default is current directory ($FUNC_PATH)"),
|
|
),
|
|
|
|
// Optional flags
|
|
mcp.WithString("name", mcp.Description("Name of the environment variable.")),
|
|
mcp.WithString("value", mcp.Description("Value of the environment variable.")),
|
|
mcp.WithBoolean("verbose", mcp.Description("Print verbose logs ($FUNC_VERBOSE)")),
|
|
),
|
|
handleConfigEnvsTool,
|
|
)
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://docs",
|
|
"Root Help Command",
|
|
mcp.WithResourceDescription("--help output of the func command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), handleRootHelpResource)
|
|
|
|
// Static help resources for each command
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://create/docs",
|
|
"Create Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'create' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"create"}, "func://create/docs")
|
|
})
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://build/docs",
|
|
"Build Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'build' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"build"}, "func://build/docs")
|
|
})
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://deploy/docs",
|
|
"Deploy Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'deploy' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"deploy"}, "func://deploy/docs")
|
|
})
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://list/docs",
|
|
"List Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'list' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"list"}, "func://list/docs")
|
|
})
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://delete/docs",
|
|
"Delete Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'delete' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"delete"}, "func://delete/docs")
|
|
})
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://config/volumes/add/docs",
|
|
"Config Volumes Add Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'config volumes add' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"config", "volumes", "add"}, "func://config/volumes/add/docs")
|
|
})
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://config/volumes/remove/docs",
|
|
"Config Volumes Remove Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'config volumes remove' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"config", "volumes", "remove"}, "func://config/volumes/remove/docs")
|
|
})
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://config/labels/add/docs",
|
|
"Config Labels Add Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'config labels add' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"config", "labels", "add"}, "func://config/labels/add/docs")
|
|
})
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://config/labels/remove/docs",
|
|
"Config Labels Remove Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'config labels remove' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"config", "labels", "remove"}, "func://config/labels/remove/docs")
|
|
})
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://config/envs/add/docs",
|
|
"Config Envs Add Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'config envs add' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"config", "envs", "add"}, "func://config/envs/add/docs")
|
|
})
|
|
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://config/envs/remove/docs",
|
|
"Config Envs Remove Command Help",
|
|
mcp.WithResourceDescription("--help output of the 'config envs remove' command"),
|
|
mcp.WithMIMEType("text/plain"),
|
|
), func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
|
return runHelpCommand([]string{"config", "envs", "remove"}, "func://config/envs/remove/docs")
|
|
})
|
|
|
|
// Static resource for listing available templates
|
|
mcpServer.AddResource(mcp.NewResource(
|
|
"func://templates",
|
|
"Available Templates",
|
|
mcp.WithResourceDescription("List of available function templates"),
|
|
mcp.WithMIMEType("plain/text"),
|
|
), handleListTemplatesResource)
|
|
|
|
mcpServer.AddPrompt(mcp.NewPrompt("help",
|
|
mcp.WithPromptDescription("help prompt for the root command"),
|
|
), handleRootHelpPrompt)
|
|
|
|
mcpServer.AddPrompt(mcp.NewPrompt("cmd_help",
|
|
mcp.WithPromptDescription("help prompt for a specific command"),
|
|
mcp.WithArgument("cmd",
|
|
mcp.ArgumentDescription("The command for which help is requested"),
|
|
mcp.RequiredArgument(),
|
|
),
|
|
), handleCmdHelpPrompt)
|
|
|
|
mcpServer.AddPrompt(mcp.NewPrompt("list_templates",
|
|
mcp.WithPromptDescription("prompt to list available function templates"),
|
|
), handleListTemplatesPrompt)
|
|
|
|
return &MCPServer{
|
|
server: mcpServer,
|
|
}
|
|
}
|
|
|
|
func (s *MCPServer) Start() error {
|
|
return server.ServeStdio(s.server)
|
|
}
|