diff --git a/go/plugins/mcp/README.md b/go/plugins/mcp/README.md index 772876dda4..238509621a 100644 --- a/go/plugins/mcp/README.md +++ b/go/plugins/mcp/README.md @@ -1,6 +1,8 @@ # Genkit MCP Plugin -Model Context Protocol (MCP) integration for Go Genkit - connect to MCP servers and expose Genkit tools as MCP servers. +Model Context Protocol (MCP) integration for Go Genkit + +Connect to MCP servers and expose Genkit tools as MCP servers. ## GenkitMCPClient - Single Server Connection @@ -10,52 +12,40 @@ Connect to and use tools/prompts from a single MCP server: package main import ( - "context" - "log" - - "github.com/firebase/genkit/go/genkit" - "github.com/firebase/genkit/go/plugins/mcp" + "context" + "log" + + "github.com/firebase/genkit/go/genkit" + "github.com/firebase/genkit/go/plugins/mcp" ) func main() { - ctx := context.Background() - g, _ := genkit.Init(ctx) - - // Connect to the MCP everything server - client, err := mcp.NewGenkitMCPClient(mcp.MCPClientOptions{ - Name: "everything-server", - Stdio: &mcp.StdioConfig{ - Command: "npx", - Args: []string{"-y", "@modelcontextprotocol/server-everything"}, - }, - }) - if err != nil { - log.Fatal(err) - } - - // Get specific tools from the everything server - echoTool, err := client.GetTool(ctx, g, "echo") - if err != nil { - log.Fatal(err) - } - - addTool, err := client.GetTool(ctx, g, "add") - if err != nil { - log.Fatal(err) - } - - // Get specific prompts from the everything server - simplePrompt, err := client.GetPrompt(ctx, g, "simple_prompt") - if err != nil { - log.Fatal(err) - } - - // Get all available tools - tools, err := client.GetActiveTools(ctx, g) - if err != nil { - log.Fatal(err) - } - + ctx := context.Background() + g := genkit.Init(ctx) + + // Connect to the MCP everything server + client, err := mcp.NewGenkitMCPClient(mcp.MCPClientOptions{ + Name: "everything-server", + Stdio: &mcp.StdioConfig{ + Command: "npx", + Args: []string{"-y", "@modelcontextprotocol/server-everything"}, + }, + }) + if err != nil { + log.Fatal(err) + } + + // Get specific prompts from the everything server + simplePrompt, err := client.GetPrompt(ctx, g, "simple-prompt", nil) + if err != nil { + log.Fatal(err) + } + + // Get all available tools + tools, err := client.GetActiveTools(ctx, g) + if err != nil { + log.Fatal(err) + } } ``` @@ -69,7 +59,7 @@ package main import ( "context" "log" - + "github.com/firebase/genkit/go/genkit" "github.com/firebase/genkit/go/plugins/mcp" ) @@ -77,7 +67,7 @@ import ( func main() { ctx := context.Background() g, _ := genkit.Init(ctx) - + // Create manager with multiple servers manager, err := mcp.NewMCPManager(mcp.MCPManagerOptions{ Name: "my-app", @@ -101,7 +91,7 @@ func main() { if err != nil { log.Fatal(err) } - + // Connect to new server at runtime err = manager.ConnectServer(ctx, "weather", mcp.MCPClientOptions{ Name: "weather-server", @@ -113,14 +103,14 @@ func main() { if err != nil { log.Fatal(err) } - + // Temporarily disable/enable servers manager.DisableServer("filesystem") manager.EnableServer("filesystem") - + // Disconnect server manager.DisconnectServer("weather") - + // Get tools from all active servers tools, err := manager.GetActiveTools(ctx, g) if err != nil { @@ -137,48 +127,72 @@ Turn your Genkit app into an MCP server: package main import ( - "context" - "log" - - "github.com/firebase/genkit/go/genkit" - "github.com/firebase/genkit/go/plugins/mcp" - "github.com/firebase/genkit/go/ai" + "context" + "log" + + "github.com/firebase/genkit/go/genkit" + "github.com/firebase/genkit/go/plugins/mcp" ) func main() { - ctx := context.Background() - g, _ := genkit.Init(ctx) - - // Define some tools - addTool := genkit.DefineTool(g, "add", "Add two numbers", - func(ctx *ai.ToolContext, input struct{A, B int}) (int, error) { - return input.A + input.B, nil - }) - - multiplyTool := genkit.DefineTool(g, "multiply", "Multiply two numbers", - func(ctx *ai.ToolContext, input struct{X, Y int}) (int, error) { - return input.X * input.Y, nil - }) - - // Option 1: Auto-expose all tools - server := mcp.NewMCPServer(g, mcp.MCPServerOptions{ - Name: "genkit-calculator", - Version: "1.0.0", - }) - - // Option 2: Expose specific tools only - server = mcp.NewMCPServer(g, mcp.MCPServerOptions{ - Name: "genkit-calculator", - Version: "1.0.0", - Tools: []ai.Tool{addTool, multiplyTool}, - }) - - // Start MCP server - log.Println("Starting MCP server...") - if err := server.ServeStdio(ctx); err != nil { - log.Fatal(err) - } + ctx := context.Background() + g := genkit.Init(ctx) + + // Create a host with multiple servers + host, err := mcp.NewMCPHost(g, mcp.MCPHostOptions{ + Name: "my-app", + MCPServers: []mcp.MCPServerConfig{ + { + Name: "everything-server", + Config: mcp.MCPClientOptions{ + Name: "everything-server", + Stdio: &mcp.StdioConfig{ + Command: "npx", + Args: []string{"-y", "@modelcontextprotocol/server-everything"}, + }, + }, + }, + { + Name: "fs-server", + Config: mcp.MCPClientOptions{ + Name: "fs-server", + Stdio: &mcp.StdioConfig{ + Command: "npx", + Args: []string{"@modelcontextprotocol/server-filesystem", "/tmp"}, + }, + }, + }, + }, + }) + if err != nil { + log.Fatal(err) + } + + // Connect to new server at runtime + err = host.Connect(ctx, g, "weather", mcp.MCPClientOptions{ + Name: "weather-server", + Stdio: &mcp.StdioConfig{ + Command: "python", + Args: []string{"weather_server.py"}, + }, + }) + if err != nil { + log.Fatal(err) + } + + // Reconnect server + host.Reconnect(ctx, "fs-server") + + // Disconnect server + host.Disconnect(ctx, "weather") + + // Get tools from all active servers + tools, err := host.GetActiveTools(ctx, g) + if err != nil { + log.Fatal(err) + } } + ``` ## Testing Your Server @@ -194,6 +208,7 @@ npx @modelcontextprotocol/inspector go run main.go ## Transport Options ### Stdio (Standard) + ```go Stdio: &mcp.StdioConfig{ Command: "uvx", @@ -203,6 +218,7 @@ Stdio: &mcp.StdioConfig{ ``` ### SSE (Web clients) + ```go SSE: &mcp.SSEConfig{ BaseURL: "http://localhost:3000/sse",