Quick Start
Get up and running with MCP-Go in minutes. This guide walks you through creating your first MCP server and client.
Hello World Server
Let's start with the simplest possible MCP server - a "hello world" tool:
package main
import (
"context"
"fmt"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
func main() {
// Create a new MCP server
s := server.NewMCPServer(
"Hello World Server",
"1.0.0",
server.WithToolCapabilities(true),
)
// Define a simple tool
tool := mcp.NewTool("hello_world",
mcp.WithDescription("Say hello to someone"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the person to greet"),
),
)
// Add tool handler
s.AddTool(tool, helloHandler)
// Start the stdio server
if err := server.ServeStdio(s); err != nil {
fmt.Printf("Server error: %v\n", err)
}
}
func helloHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
arguments := request.GetArguments()
name, ok := arguments["name"].(string)
if !ok {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: "Error: name parameter is required and must be a string",
},
},
IsError: true,
}, nil
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("Hello, %s! 👋", name),
},
},
}, nil
}
Save this as hello-server/main.go
and run:
cd hello-server
go mod init hello-server
go get github.com/mark3labs/mcp-go
go run main.go
Running Your First Server
Testing with Claude Desktop
-
Install Claude Desktop from Anthropic's website
-
Configure your server by editing Claude's config file:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Windows:%APPDATA%\Claude\claude_desktop_config.json
{ "mcpServers": { "hello-world": { "command": "go", "args": ["run", "/path/to/your/hello-server/main.go"] } } }
-
Restart Claude Desktop and look for the 🔌 icon indicating MCP connection
-
Test your tool by asking Claude: "Use the hello_world tool to greet Alice"
Testing with MCP Inspector
For debugging and development, use the MCP Inspector:
# Install the MCP Inspector
npm install -g @modelcontextprotocol/inspector
# Run your server with the inspector
mcp-inspector go run main.go
This opens a web interface where you can test your tools interactively.
Basic Client Example
You can also create MCP clients to connect to other servers:
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/mark3labs/mcp-go/client"
"github.com/mark3labs/mcp-go/client/transport"
"github.com/mark3labs/mcp-go/mcp"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Create stdio transport
stdioTransport := transport.NewStdio("go", nil, "run", "path/to/server/main.go")
// Create client with the transport
c := client.NewClient(stdioTransport)
// Start the client
if err := c.Start(ctx); err != nil {
log.Fatalf("Failed to start client: %v", err)
}
defer c.Close()
// Initialize the client
initRequest := mcp.InitializeRequest{}
initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
initRequest.Params.ClientInfo = mcp.Implementation{
Name: "Hello World Client",
Version: "1.0.0",
}
initRequest.Params.Capabilities = mcp.ClientCapabilities{}
serverInfo, err := c.Initialize(ctx, initRequest)
if err != nil {
log.Fatalf("Failed to initialize: %v", err)
}
fmt.Printf("Connected to server: %s (version %s)\n",
serverInfo.ServerInfo.Name,
serverInfo.ServerInfo.Version)
// List available tools
if serverInfo.Capabilities.Tools != nil {
toolsRequest := mcp.ListToolsRequest{}
toolsResult, err := c.ListTools(ctx, toolsRequest)
if err != nil {
log.Fatalf("Failed to list tools: %v", err)
}
fmt.Printf("Available tools: %d\n", len(toolsResult.Tools))
for _, tool := range toolsResult.Tools {
fmt.Printf("- %s: %s\n", tool.Name, tool.Description)
}
// Call a tool
callRequest := mcp.CallToolRequest{}
callRequest.Params.Name = "hello_world"
callRequest.Params.Arguments = map[string]interface{}{
"name": "World",
}
result, err := c.CallTool(ctx, callRequest)
if err != nil {
log.Fatalf("Failed to call tool: %v", err)
}
// Print the result
for _, content := range result.Content {
if textContent, ok := content.(mcp.TextContent); ok {
fmt.Printf("Result: %s\n", textContent.Text)
}
}
}
}
StreamableHTTP Client Example
For StreamableHTTP-based servers, use the StreamableHTTP client:
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/mark3labs/mcp-go/client"
"github.com/mark3labs/mcp-go/client/transport"
"github.com/mark3labs/mcp-go/mcp"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Create HTTP transport
httpTransport, err := transport.NewStreamableHTTP("http://localhost:8080/mcp")
if err != nil {
log.Fatalf("Failed to create HTTP transport: %v", err)
}
// Create client with the transport
c := client.NewClient(httpTransport)
defer c.Close()
// Initialize the client
initRequest := mcp.InitializeRequest{}
initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
initRequest.Params.ClientInfo = mcp.Implementation{
Name: "StreamableHTTP Client",
Version: "1.0.0",
}
initRequest.Params.Capabilities = mcp.ClientCapabilities{}
serverInfo, err := c.Initialize(ctx, initRequest)
if err != nil {
log.Fatalf("Failed to initialize: %v", err)
}
fmt.Printf("Connected to server: %s (version %s)\n",
serverInfo.ServerInfo.Name,
serverInfo.ServerInfo.Version)
// Call a tool
if serverInfo.Capabilities.Tools != nil {
callRequest := mcp.CallToolRequest{}
callRequest.Params.Name = "hello_world"
callRequest.Params.Arguments = map[string]interface{}{
"name": "StreamableHTTP World",
}
result, err := c.CallTool(ctx, callRequest)
if err != nil {
log.Fatalf("Failed to call tool: %v", err)
}
fmt.Printf("Tool result: %+v\n", result)
}
}
What's Next?
Now that you have a working MCP server and client:
- Learn about Tools - Create powerful tool interfaces
- Add Resources - Expose data sources to LLMs
- Create Prompts - Build reusable prompt templates
- Explore Advanced Features - Production-ready features
Common Issues
Server Won't Start
- Check that the port isn't already in use
- Verify Go module dependencies are installed
- Ensure proper file permissions
Client Connection Failed
- Verify the server is running and accessible
- Check network connectivity for StreamableHTTP clients
- Validate stdio command paths for stdio clients
Tool Calls Failing
- Verify tool parameter types match the schema
- Check error handling in your tool functions
- Use the MCP Inspector for debugging