mirror of https://github.com/knative/func.git
mcp: adds remote template support
Signed-off-by: kapil <kapilsareen584@gmail.com>
This commit is contained in:
parent
d04ff0a378
commit
f8f36c93f9
100
pkg/mcp/help.go
100
pkg/mcp/help.go
|
@ -2,13 +2,75 @@ package mcp
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/mark3labs/mcp-go/mcp"
|
||||
)
|
||||
|
||||
type template struct {
|
||||
Repository string `json:"repository"`
|
||||
Language string `json:"language"`
|
||||
TemplateName string `json:"template"`
|
||||
}
|
||||
|
||||
func fetchTemplates() ([]template, error) {
|
||||
var out []template
|
||||
seen := make(map[string]bool)
|
||||
|
||||
for _, repoURL := range TEMPLATE_RESOURCE_URIS {
|
||||
owner, repo := parseGitHubURL(repoURL)
|
||||
api := fmt.Sprintf("https://api.github.com/repos/%s/%s/git/trees/main?recursive=1", owner, repo)
|
||||
|
||||
resp, err := http.Get(api)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tree struct {
|
||||
Tree []struct {
|
||||
Path string `json:"path"`
|
||||
} `json:"tree"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &tree); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, item := range tree.Tree {
|
||||
parts := strings.Split(item.Path, "/")
|
||||
if len(parts) >= 2 && !strings.HasPrefix(parts[0], ".") {
|
||||
lang, name := parts[0], parts[1]
|
||||
key := lang + "/" + name
|
||||
if !seen[key] {
|
||||
out = append(out, template{
|
||||
Language: lang,
|
||||
TemplateName: name,
|
||||
Repository: repoURL,
|
||||
})
|
||||
seen[key] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func parseGitHubURL(url string) (owner, repo string) {
|
||||
trim := strings.TrimPrefix(url, "https://github.com/")
|
||||
parts := strings.Split(trim, "/")
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
|
||||
func handleRootHelpResource(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
||||
content, err := exec.Command("func", "--help").Output()
|
||||
if err != nil {
|
||||
|
@ -39,6 +101,25 @@ func runHelpCommand(args []string, uri string) ([]mcp.ResourceContents, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func handleListTemplatesResource(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
|
||||
templates, err := fetchTemplates()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
content, err := json.MarshalIndent(templates, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []mcp.ResourceContents{
|
||||
mcp.TextResourceContents{
|
||||
URI: "func://templates",
|
||||
MIMEType: "text/plain",
|
||||
Text: string(content),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func handleCmdHelpPrompt(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
|
||||
cmd := request.Params.Arguments["cmd"]
|
||||
if cmd == "" {
|
||||
|
@ -86,3 +167,22 @@ func handleRootHelpPrompt(ctx context.Context, request mcp.GetPromptRequest) (*m
|
|||
},
|
||||
), nil
|
||||
}
|
||||
|
||||
func handleListTemplatesPrompt(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
|
||||
return mcp.NewGetPromptResult(
|
||||
"List Templates Prompt",
|
||||
[]mcp.PromptMessage{
|
||||
mcp.NewPromptMessage(
|
||||
mcp.RoleUser,
|
||||
mcp.NewTextContent("List available function templates"),
|
||||
),
|
||||
mcp.NewPromptMessage(
|
||||
mcp.RoleAssistant,
|
||||
mcp.NewEmbeddedResource(mcp.TextResourceContents{
|
||||
URI: "func://templates",
|
||||
MIMEType: "text/plain",
|
||||
}),
|
||||
),
|
||||
},
|
||||
), nil
|
||||
}
|
||||
|
|
|
@ -7,6 +7,10 @@ import (
|
|||
"github.com/mark3labs/mcp-go/server"
|
||||
)
|
||||
|
||||
var TEMPLATE_RESOURCE_URIS = []string{
|
||||
"https://github.com/gauron99/func-templates",
|
||||
}
|
||||
|
||||
type MCPServer struct {
|
||||
server *server.MCPServer
|
||||
}
|
||||
|
@ -43,7 +47,7 @@ func NewServer() *MCPServer {
|
|||
|
||||
// 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")),
|
||||
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")),
|
||||
),
|
||||
|
@ -325,6 +329,14 @@ func NewServer() *MCPServer {
|
|||
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)
|
||||
|
@ -337,6 +349,10 @@ func NewServer() *MCPServer {
|
|||
),
|
||||
), handleCmdHelpPrompt)
|
||||
|
||||
mcpServer.AddPrompt(mcp.NewPrompt("list_templates",
|
||||
mcp.WithPromptDescription("prompt to list available function templates"),
|
||||
), handleListTemplatesPrompt)
|
||||
|
||||
return &MCPServer{
|
||||
server: mcpServer,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue