@@ -2,13 +2,75 @@ package mcp
2
2
3
3
import (
4
4
"context"
5
+ "encoding/json"
5
6
"fmt"
7
+ "io"
8
+ "net/http"
6
9
"os/exec"
7
10
"strings"
8
11
9
12
"github.com/mark3labs/mcp-go/mcp"
10
13
)
11
14
15
+ type template struct {
16
+ Repository string `json:"repository"`
17
+ Language string `json:"language"`
18
+ TemplateName string `json:"template"`
19
+ }
20
+
21
+ func fetchTemplates () ([]template , error ) {
22
+ var out []template
23
+ seen := make (map [string ]bool )
24
+
25
+ for _ , repoURL := range TEMPLATE_RESOURCE_URIS {
26
+ owner , repo := parseGitHubURL (repoURL )
27
+ api := fmt .Sprintf ("https://api.github.com/repos/%s/%s/git/trees/main?recursive=1" , owner , repo )
28
+
29
+ resp , err := http .Get (api )
30
+ if err != nil {
31
+ return nil , err
32
+ }
33
+ defer resp .Body .Close ()
34
+
35
+ body , err := io .ReadAll (resp .Body )
36
+ if err != nil {
37
+ return nil , err
38
+ }
39
+
40
+ var tree struct {
41
+ Tree []struct {
42
+ Path string `json:"path"`
43
+ } `json:"tree"`
44
+ }
45
+ if err := json .Unmarshal (body , & tree ); err != nil {
46
+ return nil , err
47
+ }
48
+
49
+ for _ , item := range tree .Tree {
50
+ parts := strings .Split (item .Path , "/" )
51
+ if len (parts ) >= 2 && ! strings .HasPrefix (parts [0 ], "." ) {
52
+ lang , name := parts [0 ], parts [1 ]
53
+ key := lang + "/" + name
54
+ if ! seen [key ] {
55
+ out = append (out , template {
56
+ Language : lang ,
57
+ TemplateName : name ,
58
+ Repository : repoURL ,
59
+ })
60
+ seen [key ] = true
61
+ }
62
+ }
63
+ }
64
+ }
65
+ return out , nil
66
+ }
67
+
68
+ func parseGitHubURL (url string ) (owner , repo string ) {
69
+ trim := strings .TrimPrefix (url , "https://github.com/" )
70
+ parts := strings .Split (trim , "/" )
71
+ return parts [0 ], parts [1 ]
72
+ }
73
+
12
74
func handleRootHelpResource (ctx context.Context , request mcp.ReadResourceRequest ) ([]mcp.ResourceContents , error ) {
13
75
content , err := exec .Command ("func" , "--help" ).Output ()
14
76
if err != nil {
@@ -39,6 +101,25 @@ func runHelpCommand(args []string, uri string) ([]mcp.ResourceContents, error) {
39
101
}, nil
40
102
}
41
103
104
+ func handleListTemplatesResource (ctx context.Context , request mcp.ReadResourceRequest ) ([]mcp.ResourceContents , error ) {
105
+ templates , err := fetchTemplates ()
106
+ if err != nil {
107
+ return nil , err
108
+ }
109
+ content , err := json .MarshalIndent (templates , "" , " " )
110
+ if err != nil {
111
+ return nil , err
112
+ }
113
+
114
+ return []mcp.ResourceContents {
115
+ mcp.TextResourceContents {
116
+ URI : "func://templates" ,
117
+ MIMEType : "text/plain" ,
118
+ Text : string (content ),
119
+ },
120
+ }, nil
121
+ }
122
+
42
123
func handleCmdHelpPrompt (ctx context.Context , request mcp.GetPromptRequest ) (* mcp.GetPromptResult , error ) {
43
124
cmd := request .Params .Arguments ["cmd" ]
44
125
if cmd == "" {
@@ -86,3 +167,22 @@ func handleRootHelpPrompt(ctx context.Context, request mcp.GetPromptRequest) (*m
86
167
},
87
168
), nil
88
169
}
170
+
171
+ func handleListTemplatesPrompt (ctx context.Context , request mcp.GetPromptRequest ) (* mcp.GetPromptResult , error ) {
172
+ return mcp .NewGetPromptResult (
173
+ "List Templates Prompt" ,
174
+ []mcp.PromptMessage {
175
+ mcp .NewPromptMessage (
176
+ mcp .RoleUser ,
177
+ mcp .NewTextContent ("List available function templates" ),
178
+ ),
179
+ mcp .NewPromptMessage (
180
+ mcp .RoleAssistant ,
181
+ mcp .NewEmbeddedResource (mcp.TextResourceContents {
182
+ URI : "func://templates" ,
183
+ MIMEType : "text/plain" ,
184
+ }),
185
+ ),
186
+ },
187
+ ), nil
188
+ }
0 commit comments