Implement SEP-973 (#570)
mcp/protocol: Implement SEP-973 - Define Icon structure, which includes source, mimeType and sizes. - sizes is any array of strings. refer https://github.com/modelcontextprotocol/modelcontextprotocol/pull/1531 - Support setting websiteUrl, icons for mcp.Implementation - Support setting icons for mcp.Prompt - Support setting icons for mcp.Tool - Support setting icons for mcp.Resource Fixes #552
This commit is contained in:
parent
35dfcf21c9
commit
faddd764aa
2 changed files with 417 additions and 9 deletions
|
|
@ -7,6 +7,7 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
|
|
@ -50,19 +51,28 @@ func main() {
|
|||
CompletionHandler: complete, // support completions by setting this handler
|
||||
}
|
||||
|
||||
server := mcp.NewServer(&mcp.Implementation{Name: "everything"}, opts)
|
||||
// Optionally add an icon to the server implementation.
|
||||
icons, err := iconToBase64DataURL("./mcp.png")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read icon: %v", err)
|
||||
}
|
||||
|
||||
server := mcp.NewServer(&mcp.Implementation{Name: "everything", WebsiteURL: "https://example.com", Icons: icons}, opts)
|
||||
|
||||
// Add tools that exercise different features of the protocol.
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "greet", Description: "say hi"}, contentTool)
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "greet (structured)"}, structuredTool) // returns structured output
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "ping"}, pingingTool) // performs a ping
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "log"}, loggingTool) // performs a log
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "sample"}, samplingTool) // performs sampling
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "elicit"}, elicitingTool) // performs elicitation
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "roots"}, rootsTool) // lists roots
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "greet (structured)"}, structuredTool) // returns structured output
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "greet (with Icons)", Icons: icons}, structuredTool) // tool with icons
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "greet (content with ResourceLink)"}, resourceLinkContentTool(icons)) // tool that returns content with a resource link
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "ping"}, pingingTool) // performs a ping
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "log"}, loggingTool) // performs a log
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "sample"}, samplingTool) // performs sampling
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "elicit"}, elicitingTool) // performs elicitation
|
||||
mcp.AddTool(server, &mcp.Tool{Name: "roots"}, rootsTool) // lists roots
|
||||
|
||||
// Add a basic prompt.
|
||||
server.AddPrompt(&mcp.Prompt{Name: "greet"}, prompt)
|
||||
server.AddPrompt(&mcp.Prompt{Name: "greet (with Icons)", Icons: icons}, prompt) // greet prompt with icons
|
||||
|
||||
// Add an embedded resource.
|
||||
server.AddResource(&mcp.Resource{
|
||||
|
|
@ -70,6 +80,20 @@ func main() {
|
|||
MIMEType: "text/plain",
|
||||
URI: "embedded:info",
|
||||
}, embeddedResource)
|
||||
server.AddResource(&mcp.Resource{ // text resource with icons
|
||||
Name: "info (with Icons)",
|
||||
MIMEType: "text/plain",
|
||||
URI: "embedded:info",
|
||||
Icons: icons,
|
||||
}, embeddedResource)
|
||||
|
||||
// Add a resource template.
|
||||
server.AddResourceTemplate(&mcp.ResourceTemplate{
|
||||
Name: "Resource template (with Icon)",
|
||||
MIMEType: "text/plain",
|
||||
URITemplate: "http://example.com/~{resource_name}/",
|
||||
Icons: icons,
|
||||
}, embeddedResource)
|
||||
|
||||
// Serve over stdio, or streamable HTTP if -http is set.
|
||||
if *httpAddr != "" {
|
||||
|
|
@ -140,6 +164,23 @@ func contentTool(ctx context.Context, req *mcp.CallToolRequest, args args) (*mcp
|
|||
}, nil, nil
|
||||
}
|
||||
|
||||
// resourceLinkContentTool returns a ResourceLink content with icons.
|
||||
func resourceLinkContentTool(icons []mcp.Icon) func(ctx context.Context, req *mcp.CallToolRequest, args args) (*mcp.CallToolResult, any, error) {
|
||||
return func(ctx context.Context, req *mcp.CallToolRequest, args args) (*mcp.CallToolResult, any, error) {
|
||||
return &mcp.CallToolResult{
|
||||
Content: []mcp.Content{
|
||||
&mcp.ResourceLink{
|
||||
Name: "greeting",
|
||||
Title: "A friendly greeting",
|
||||
MIMEType: "text/plain",
|
||||
URI: "data:text/plain,Hi%20" + url.PathEscape(args.Name),
|
||||
Icons: icons,
|
||||
},
|
||||
},
|
||||
}, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
type result struct {
|
||||
Message string `json:"message" jsonschema:"the message to convey"`
|
||||
}
|
||||
|
|
@ -222,3 +263,16 @@ func complete(ctx context.Context, req *mcp.CompleteRequest) (*mcp.CompleteResul
|
|||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func iconToBase64DataURL(path string) ([]mcp.Icon, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []mcp.Icon{{
|
||||
Source: "data:image/png;base64," + base64.StdEncoding.EncodeToString(data),
|
||||
MIMEType: "image/png",
|
||||
Sizes: []string{"48x48"},
|
||||
Theme: "light", // or "dark" or empty
|
||||
}}, nil
|
||||
}
|
||||
|
|
|
|||
BIN
examples/server/everything/mcp.png
Normal file
BIN
examples/server/everything/mcp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
Loading…
Reference in a new issue