Refactors DemoMCP tool handler to integrate with DemoGRPC for fact retrieval and updates server instructions.

This commit is contained in:
2025-08-27 17:02:53 -04:00
parent 214d5d76c3
commit e3be406eba
5 changed files with 141 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
/*
Package demomcp contains a simple reference implementation of returning a
HTTPHandler for an MCP server with a single tool used to retrieve random facts
*/
package demomcp
import (
"context"
"net/http"
"gitea.libretechconsulting.com/rmcguire/go-app/pkg/srv/http/opts"
"github.com/modelcontextprotocol/go-sdk/mcp"
"gitea.libretechconsulting.com/rmcguire/go-server-with-otel/pkg/config"
"gitea.libretechconsulting.com/rmcguire/go-server-with-otel/pkg/demo/demogrpc"
)
var DemoMCPImpl = &mcp.Implementation{
Name: "Demo MCP Server",
Title: "Demo MCP",
}
type DemoMCPServer struct {
ctx context.Context
cfg *config.ServiceConfig
server *mcp.Server
demoGRPC *demogrpc.DemoGRPCServer
}
func NewDemoMCPServer(ctx context.Context, cfg *config.ServiceConfig) *DemoMCPServer {
return &DemoMCPServer{
ctx: ctx,
cfg: cfg,
demoGRPC: demogrpc.NewDemoGRPCServer(ctx, cfg),
server: mcp.NewServer(DemoMCPImpl, &mcp.ServerOptions{
Instructions: "Call this demo MCP tool if the user asks useless questions or wants a random fact",
HasTools: true,
}),
}
}
func (d *DemoMCPServer) GetHandlers() []opts.HTTPHandler {
// NOTE: Add other tools here
d.addDemoRandomFactTool()
demoHandler := mcp.NewStreamableHTTPHandler(func(*http.Request) *mcp.Server {
return d.server
}, &mcp.StreamableHTTPOptions{})
return []opts.HTTPHandler{
{
Prefix: "/api/mcp",
Handler: demoHandler,
},
}
}
func (d *DemoMCPServer) GetHealthCheckFuncs() []opts.HealthCheckFunc {
return []opts.HealthCheckFunc{
func(ctx context.Context) error {
// TODO: Implement real health checks
return nil
},
}
}

58
pkg/demo/demomcp/tool.go Normal file
View File

@@ -0,0 +1,58 @@
package demomcp
import (
"context"
"github.com/modelcontextprotocol/go-sdk/mcp"
"k8s.io/utils/ptr"
demo "gitea.libretechconsulting.com/rmcguire/go-server-with-otel/api/demo/app/v1alpha1"
)
var DemoTool = &mcp.Tool{
Name: "Demo Tool",
Title: "Demo Random Fact Tool",
Description: "Returns a random fact for demo or boredom purposes",
Annotations: &mcp.ToolAnnotations{
ReadOnlyHint: true,
OpenWorldHint: ptr.To(true),
},
}
type DemoToolParams struct {
Language string `json:"language,omitempty" jsonschema:"Random Fact Language Abbreviation (e.g. en)"`
}
func (d *DemoMCPServer) addDemoRandomFactTool() {
d.server.AddTool(
mcp.ToolFor(DemoTool, d.demoToolHandler),
)
}
func (d *DemoMCPServer) demoToolHandler(ctx context.Context, req *mcp.CallToolRequest, args *DemoToolParams) (
*mcp.CallToolResult, any, error,
) {
fact, err := d.demoGRPC.GetDemo(ctx, &demo.GetDemoRequest{
Language: &args.Language,
})
if err != nil {
return &mcp.CallToolResult{
IsError: true,
Meta: mcp.Meta{
"error": err,
},
}, nil, err
}
return &mcp.CallToolResult{
Meta: mcp.Meta{
"language": fact.GetLanguage(),
"source": fact.GetSource(),
},
Content: []mcp.Content{
&mcp.TextContent{
Text: fact.GetFact(),
},
},
}, nil, nil
}