freshcrate
Skin:/
Home > MCP Servers > mcp-go

mcp-go

A Go implementation of the Model Context Protocol (MCP), enabling seamless integration between LLM applications and external data sources and tools.

Why this rank:Strong adoptionRecent releaseHealthy release cadence

Description

A Go implementation of the Model Context Protocol (MCP), enabling seamless integration between LLM applications and external data sources and tools.

README

MCP Go Logo

Build Go Report Card GoDoc

AgentRank A Go implementation of the Model Context Protocol (MCP), enabling seamless integration between LLM applications and external data sources and tools.


Tutorial


Discuss the SDK on Discord

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(
        "Demo ๐Ÿš€",
        "1.0.0",
        server.WithToolCapabilities(false),
    )

    // Add 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) {
    name, err := request.RequireString("name")
    if err != nil {
        return mcp.NewToolResultError(err.Error()), nil
    }

    return mcp.NewToolResultText(fmt.Sprintf("Hello, %s!", name)), nil
}

That's it!

MCP Go handles all the complex protocol details and server management, so you can focus on building great tools. It aims to be high-level and easy to use.

Key features:

  • Fast: High-level interface means less code and faster development
  • Simple: Build MCP servers with minimal boilerplate
  • Complete*: MCP Go aims to provide a full implementation of the core MCP specification

(*emphasis on aims)

๐Ÿšจ ๐Ÿšง ๐Ÿ—๏ธ MCP Go is under active development, as is the MCP specification itself. Core features are working but some advanced capabilities are still in progress.

Table of Contents

Installation

go get github.com/mark3labs/mcp-go

Quickstart

Let's create a simple MCP server that exposes a calculator tool and some data:

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(
        "Calculator Demo",
        "1.0.0",
        server.WithToolCapabilities(false),
        server.WithRecovery(),
    )

    // Add a calculator tool
    calculatorTool := mcp.NewTool("calculate",
        mcp.WithDescription("Perform basic arithmetic operations"),
        mcp.WithString("operation",
            mcp.Required(),
            mcp.Description("The operation to perform (add, subtract, multiply, divide)"),
            mcp.Enum("add", "subtract", "multiply", "divide"),
        ),
        mcp.WithNumber("x",
            mcp.Required(),
            mcp.Description("First number"),
        ),
        mcp.WithNumber("y",
            mcp.Required(),
            mcp.Description("Second number"),
        ),
    )

    // Add the calculator handler
    s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
        // Using helper functions for type-safe argument access
        op, err := request.RequireString("operation")
        if err != nil {
            return mcp.NewToolResultError(err.Error()), nil
        }
        
        x, err := request.RequireFloat("x")
        if err != nil {
            return mcp.NewToolResultError(err.Error()), nil
        }
        
        y, err := request.RequireFloat("y")
        if err != nil {
            return mcp.NewToolResultError(err.Error()), nil
        }

        var result float64
        switch op {
        case "add":
            result = x + y
        case "subtract":
            result = x - y
        case "multiply":
            result = x * y
        case "divide":
            if y == 0 {
                return mcp.NewToolResultError("cannot divide by zero"), nil
            }
            result = x / y
        }

        return mcp.NewToolResultText(fmt.Sprintf("%.2f", result)), nil
    })

    // Start the server
    if err := server.ServeStdio(s); err != nil {
        fmt.Printf("Server error: %v\n", err)
    }
}

What is MCP?

The Model Context Protocol (MCP) lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. Think of it like a web API, but specifically designed for LLM interactions.

MCP servers can:

  • Expose data through Resources (think of these sort of like GET endpoints; they are used to load information into the LLM's context)
  • Provide functionality through Tools (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
  • Define interaction patterns through Prompts (reusable templates for LLM interactions)
  • And more!

mcp-go implements the Model Context Protocol specification version 2025-11-25, with backward compatibility for versions 2025-06-18, 2025-03-26, and 2024-11-05.

Core Concepts

Server

Show Server Examples

The server is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:

// Create a basic server
s := server.NewMCPServer(
    "My Server",  // Server name
    "1.0.0",     // Version
)

// Start the server using stdio
if err := server.ServeStdio(s); err != nil {
    log.Fatalf("Server error: %v", err)
}

Resources

Show Resource Examples Resources are how you expose data to LLMs. They can be anything - files, API responses, database queries, system information, etc. Resources can be:
  • Static (fixed URI)
  • Dynamic (using URI templates)

Here's a simple example of a static resource:

// Static resource example - exposing a README file
resource := mcp.NewResource(
    "docs://readme",
    "Project README",
    mcp.WithResourceDescription("The project's README file"), 
    mcp.WithMIMEType("text/markdown"),
)

// Add resource with its handler
s.AddResource(resource, func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
    content, err := os.ReadFile("README.md")
    if err != nil {
        return nil, err
    }
    
    return []mcp.ResourceContents{
        mcp.TextResourceContents{
            URI:      "docs://readme",
            MIMEType: "text/markdown",
            Text:     string(content),
        },
    }, nil
})

And here's an example of a dynamic resource using a template:

// Dynamic resource example - user profiles by ID
template := mcp.NewResourceTemplate(
    "users://{id}/profile",
    "User Profile",
    mcp.WithTemplateDescription("Returns user profile information"),
    mcp.WithTemplateMIMEType("application/json"),
)

// Add template with its handler
s.AddResourceTemplate(template, func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
    // Extract ID from the URI using regex matching
    // The server automatically matches URIs to templates
    userID := extractIDFromURI(request.Params.URI)
    
    profile, err := getUserProfile(userID)  // Your DB/API call here
    if err != nil {
        return nil, err
    }
    
    return []mcp.ResourceContents{
        mcp.TextResourceContents{
            URI:      request.Params.URI,
            MIMEType: "application/json",
            Text:     profile,
        },
    }, nil
})

The examples are simple but demonstrate the core concepts. Resources can be much more sophisticated - serving multiple contents, integrating with databases or external APIs, etc.

Tools

Show Tool Examples

Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects. They're similar to POST endpoints in a REST API.

Task-Augmented Tools

Task-augmented tools execute asynchronously and return results via polling. This is useful for long-running operations that would otherwise block or time out. Task tools support three modes:

  • TaskSupportForbidden (default): The tool cannot be invoked as a task
  • TaskSupportOptional: The tool can be invoked as a task or synchronously
  • TaskSupportRequired: The tool must be invoked as a task
// Example: A tool that requires task execution
processBatchTool := mcp.NewTool("process_batch",
    mcp.WithDescription("Process a batch of items asynchronously"),
    mcp.WithTaskSupport(mcp.TaskSupportRequired),
    mcp.WithArray("items",
        mcp.Description("Array of items to process"),
        mcp.WithStringItems(),
        mcp.Required(),
    ),
)

// Task tool handler returns CreateTaskResult instead of CallToolResult
s.AddTaskTool(processBatchTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CreateTaskResult, error) {
    items := request.GetStringSlice("items", []string{})
    
    // Long-running work here
    for i, item := range items {
        select {
        case <-ctx.Done():
            // Task was cancelled
            return nil, ctx.Err()
        default:
            // Process item...
            processItem(item)
        }
    }
    
    // Return result - task ID and metadata are managed by the server
    return &mcp.CreateTaskResult{
        Task: mcp.Task{
            // Task fields (ID, status, etc.) are populated by the server
        },
    }, nil
})

// Enable task capabilities when creating the server
s := server.NewMCPServer(
    "Task Server",
    "1.0.0",
    server.WithTaskCapabilities(
        true, // listTasks: allows clients to list all tasks
        true, // cancel: allows clients to cancel running tasks
        true, // toolCallTasks: enables task augmentation for tools
    ),
    server.WithMaxConcurrentTasks(10), // Optional: limit concurrent running tasks
)

Task execution flow:

  1. Client calls tool with task parameter
  2. Server immediately returns task ID
  3. Tool executes asynchronously in the background
  4. Client polls tasks/result to retrieve the result
  5. Server sends task status notifications on completion

For optional task tools, the same tool can be called synchronously (without task parameter) or asynchronously (with task parameter):

// Tool with optional task support
analyzeTool := mcp.NewTool("analyze_data",
    mcp.WithDescription("Analyze data - can run sync or async"),
    mcp.WithTaskSupport(mcp.TaskSupportOptional),
    mcp.WithString("data", mcp.Required()),
)

// Use AddTaskTool for hybrid tools that support both modes
s.AddTaskTool(analyzeTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CreateTaskResult, error) {
    // This handler runs when called as a task
    data := request.GetString("data", "")
    result := analyzeData(data)
    
    return &mcp.CreateTaskResult{
        Task: mcp.Task{},
    }, nil
})

// The server automatically handles both sync and async invocations
// When called without task param: executes handler and returns immediately
// When called with task param: executes handler asynchronously
Limiting Concurrent Tasks

To prevent resource exhaustion, you can limit the number of concurrent running tasks:

s := server.NewMCPServer(
    "Task Server",
    "1.0.0",
    server.WithTaskCapabilities(true, true, true),
    server.WithMaxConcurrentTasks(10), // Allow up to 10 concurrent running tasks
)

When the limit is reached, new task creation requests will fail with an error. Completed, failed, or cancelled tasks don't count toward the limit - only tasks in "working" status. If WithMaxConcurrentTasks is not specified or set to 0, there is no limit on concurrent tasks.

For traditional synchronous tools that execute and return results immediately:

Simple calculation example:

calculatorTool := mcp.NewTool("calculate",
    mcp.WithDescription("Perform basic arithmetic calculations"),
    mcp.WithString("operation",
        mcp.Required(),
        mcp.Description("The arithmetic operation to perform"),
        mcp.Enum("add", "subtract", "multiply", "divide"),
    ),
    mcp.WithNumber("x",
        mcp.Required(),
        mcp.Description("First number"),
    ),
    mcp.WithNumber("y",
        mcp.Required(),
        mcp.Description("Second number"),
    ),
)

s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    args := request.GetArguments()
    op := args["operation"].(string)
    x := args["x"].(float64)
    y := args["y"].(float64)

    var result float64
    switch op {
    case "add":
        result = x + y
    case "subtract":
        result = x - y
    case "multiply":
        result = x * y
    case "divide":
        if y == 0 {
            return mcp.NewToolResultError("cannot divide by zero"), nil
        }
        result = x / y
    }
    
    return mcp.FormatNumberResult(result), nil
})

HTTP request example:

httpTool := mcp.NewTool("http_request",
    mcp.WithDescription("Make HTTP requests to external APIs"),
    mcp.WithString("method",
        mcp.Required(),
        mcp.Description("HTTP method to use"),
        mcp.Enum("GET", "POST", "PUT", "DELETE"),
    ),
    mcp.WithString("url",
        mcp.Required(),
        mcp.Description("URL to send the request to"),
        mcp.Pattern("^https?://.*"),
    ),
    mcp.WithString("body",
        mcp.Description("Request body (for POST/PUT)"),
    ),
)

s.AddTool(httpTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    args := request.GetArguments()
    method := args["method"].(string)
    url := args["url"].(string)
    body := ""
    if b, ok := args["body"].(string); ok {
        body = b
    }

    // Create and send request
    var req *http.Request
    var err error
    if body != "" {
        req, err = http.NewRequest(method, url, strings.NewReader(body))
    } else {
        req, err = http.NewRequest(method, url, nil)
    }
    if err != nil {
        return mcp.NewToolResultErrorFromErr("unable to create request", err), nil
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return mcp.NewToolResultErrorFromErr("unable to execute request", err), nil
    }
    defer resp.Body.Close()

    // Return response
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        return mcp.NewToolResultErrorFromErr("unable to read request response", err), nil
    }

    return mcp.NewToolResultText(fmt.Sprintf("Status: %d\nBody: %s", resp.StatusCode, string(respBody))), nil
})

Tools can be used for any kind of computation or side effect:

  • Database queries
  • File operations
  • External API calls
  • Calculations
  • System operations

Each tool should:

  • Have a clear description
  • Validate inputs
  • Handle errors gracefully
  • Return structured responses
  • Use appropriate result types

Prompts

Show Prompt Examples

Prompts are reusable templates that help LLMs interact with your server effectively. They're like "best practices" encoded into your server. Here are some examples:

// Simple greeting prompt
s.AddPrompt(mcp.NewPrompt("greeting",
    mcp.WithPromptDescription("A friendly greeting prompt"),
    mcp.WithArgument("name",
        mcp.ArgumentDescription("Name of the person to greet"),
    ),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
    name := request.Params.Arguments["name"]
    if name == "" {
        name = "friend"
    }
    
    return mcp.NewGetPromptResult(
        "A friendly greeting",
        []mcp.PromptMessage{
            mcp.NewPromptMessage(
                mcp.RoleAssistant,
                mcp.NewTextContent(fmt.Sprintf("Hello, %s! How can I help you today?", name)),
            ),
        },
    ), nil
})

// Code review prompt with embedded resource
s.AddPrompt(mcp.NewPrompt("code_review",
    mcp.WithPromptDescription("Code review assistance"),
    mcp.WithArgument("pr_number",
        mcp.ArgumentDescription("Pull request number to review"),
        mcp.RequiredArgument(),
    ),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
    prNumber := request.Params.Arguments["pr_number"]
    if prNumber == "" {
        return nil, fmt.Errorf("pr_number is required")
    }
    
    return mcp.NewGetPromptResult(
        "Code review assistance",
        []mcp.PromptMessage{
            mcp.NewPromptMessage(
                mcp.RoleUser,
                mcp.NewTextContent("Review the changes and provide constructive feedback."),
            ),
            mcp.NewPromptMessage(
                mcp.RoleAssistant,
                mcp.NewEmbeddedResource(mcp.ResourceContents{
                    URI: fmt.Sprintf("git://pulls/%s/diff", prNumber),
                    MIMEType: "text/x-diff",
                }),
            ),
        },
    ), nil
})

// Database query builder prompt
s.AddPrompt(mcp.NewPrompt("query_builder",
    mcp.WithPromptDescription("SQL query builder assistance"),
    mcp.WithArgument("table",
        mcp.ArgumentDescription("Name of the table to query"),
        mcp.RequiredArgument(),
    ),
), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
    tableName := request.Params.Arguments["table"]
    if tableName == "" {
        return nil, fmt.Errorf("table name is required")
    }
    
    return mcp.NewGetPromptResult(
        "SQL query builder assistance",
        []mcp.PromptMessage{
            mcp.NewPromptMessage(
                mcp.RoleUser,
                mcp.NewTextContent("Help construct efficient and safe queries for the provided schema."),
            ),
            mcp.NewPromptMessage(
                mcp.RoleUser,
                mcp.NewEmbeddedResource(mcp.ResourceContents{
                    URI: fmt.Sprintf("db://schema/%s", tableName),
                    MIMEType: "application/json",
                }),
            ),
        },
    ), nil
})

Prompts can include:

  • System instructions
  • Required arguments
  • Embedded resources
  • Multiple messages
  • Different content types (text, images, etc.)
  • Custom URI schemes

Examples

For examples, see the examples/ directory.

Key examples include:

Extras

Transports

MCP-Go supports stdio, SSE and streamable-HTTP transport layers. For SSE transport, you can use SetConnectionLostHandler() to detect and handle disconnections for implementing reconnection logic.

Session Management

MCP-Go provides a robust session management system that allows you to:

  • Maintain separate state for each connected client
  • Register and track client sessions
  • Send notifications to specific clients
  • Provide per-session tool customization
Show Session Management Examples

Basic Session Handling

// Create a server with session capabilities
s := server.NewMCPServer(
    "Session Demo",
    "1.0.0",
    server.WithToolCapabilities(true),
)

// Implement your own ClientSession
type MySession struct {
    id           string
    notifChannel chan mcp.JSONRPCNotification
    isInitialized bool
    // Add custom fields for your application
}

// Implement the ClientSession interface
func (s *MySession) SessionID() string {
    return s.id
}

func (s *MySession) NotificationChannel() chan<- mcp.JSONRPCNotification {
    return s.notifChannel
}

func (s *MySession) Initialize() {
    s.isInitialized = true
}

func (s *MySession) Initialized() bool {
    return s.isInitialized
}

// Register a session
session := &MySession{
    id:           "user-123",
    notifChannel: make(chan mcp.JSONRPCNotification, 10),
}
if err := s.RegisterSession(context.Background(), session); err != nil {
    log.Printf("Failed to register session: %v", err)
}

// Send notification to a specific client
err := s.SendNotificationToSpecificClient(
    session.SessionID(),
    "notification/update",
    map[string]any{"message": "New data available!"},
)
if err != nil {
    log.Printf("Failed to send notification: %v", err)
}

// Unregister session when done
s.UnregisterSession(context.Background(), session.SessionID())

Per-Session Tools

For more advanced use cases, you can implement the SessionWithTools interface to support per-session tool customization:

// Implement SessionWithTools interface for per-session tools
type MyAdvancedSession struct {
    MySession  // Embed the basic session
    sessionTools map[string]server.ServerTool
}

// Implement additional methods for SessionWithTools
func (s *MyAdvancedSession) GetSessionTools() map[string]server.ServerTool {
    return s.sessionTools
}

func (s *MyAdvancedSession) SetSessionTools(tools map[string]server.ServerTool) {
    s.sessionTools = tools
}

// Create and register a session with tools support
advSession := &MyAdvancedSession{
    MySession: MySession{
        id:           "user-456",
        notifChannel: make(chan mcp.JSONRPCNotification, 10),
    },
    sessionTools: make(map[string]server.ServerTool),
}
if err := s.RegisterSession(context.Background(), advSession); err != nil {
    log.Printf("Failed to register session: %v", err)
}

// Add session-specific tools
userSpecificTool := mcp.NewTool(
    "user_data",
    mcp.WithDescription("Access user-specific data"),
)
// You can use AddSessionTool (similar to AddTool)
err := s.AddSessionTool(
    advSession.SessionID(),
    userSpecificTool,
    func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
        // This handler is only available to this specific session
        return mcp.NewToolResultText("User-specific data for " + advSession.SessionID()), nil
    },
)
if err != nil {
    log.Printf("Failed to add session tool: %v", err)
}

// Or use AddSessionTools directly with ServerTool
/*
err := s.AddSessionTools(
    advSession.SessionID(),
    server.ServerTool{
        Tool: userSpecificTool,
        Handler: func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
            // This handler is only available to this specific session
            return mcp.NewToolResultText("User-specific data for " + advSession.SessionID()), nil
        },
    },
)
if err != nil {
    log.Printf("Failed to add session tool: %v", err)
}
*/

// Delete session-specific tools when no longer needed
err = s.DeleteSessionTools(advSession.SessionID(), "user_data")
if err != nil {
    log.Printf("Failed to delete session tool: %v", err)
}

Tool Filtering

You can also apply filters to control which tools are available to certain sessions:

// Add a tool filter that only shows tools with certain prefixes
s := server.NewMCPServer(
    "Tool Filtering Demo",
    "1.0.0",
    server.WithToolCapabilities(true),
    server.WithToolFilter(func(ctx context.Context, tools []mcp.Tool) []mcp.Tool {
        // Get session from context
        session := server.ClientSessionFromContext(ctx)
        if session == nil {
            return tools // Return all tools if no session
        }
        
        // Example: filter tools based on session ID prefix
        if strings.HasPrefix(session.SessionID(), "admin-") {
            // Admin users get all tools
            return tools
        } else {
            // Regular users only get tools with "public-" prefix
            var filteredTools []mcp.Tool
            for _, tool := range tools {
                if strings.HasPrefix(tool.Name, "public-") {
                    filteredTools = append(filteredTools, tool)
                }
            }
            return filteredTools
        }
    }),
)

Working with Context

The session context is automatically passed to tool and resource handlers:

s.AddTool(mcp.NewTool("session_aware"), func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
    // Get the current session from context
    session := server.ClientSessionFromContext(ctx)
    if session == nil {
        return mcp.NewToolResultError("No active session"), nil
    }
    
    return mcp.NewToolResultText("Hello, session " + session.SessionID()), nil
})

// When using handlers in HTTP/SSE servers, you need to pass the context with the session
httpHandler := func(w http.ResponseWriter, r *http.Request) {
    // Get session from somewhere (like a cookie or header)
    session := getSessionFromRequest(r)
    
    // Add session to context
    ctx := s.WithContext(r.Context(), session)
    
    // Use this context when handling requests
    // ...
}

Request Hooks

Hook into the request lifecycle by creating a Hooks object with your selection among the possible callbacks. This enables telemetry across all functionality, and observability of various facts, for example the ability to count improperly-formatted requests, or to log the agent identity during initialization.

Add the Hooks to the server at the time of creation using the server.WithHooks option.

Tool Handler Middleware

Add middleware to tool call handlers using the server.WithToolHandlerMiddleware option. Middlewares can be registered on server creation and are applied on every tool call.

A recovery middleware option is available to recover from panics in a tool call and can be added to the server with the server.WithRecovery option.

Prompt Handler Middleware

Add middleware to prompt handlers using the server.WithPromptHandlerMiddleware option. Middlewares can be registered on server creation and are applied on every prompts/get call.

Prompt Filtering

Filter prompts based on context using the server.WithPromptFilter option. This works the same way as tool filtering but applies to prompts/list results.

Regenerating Server Code

Server hooks and request handlers are generated. Regenerate them by running:

go generate ./...

You need go installed and the goimports tool available. The generator runs goimports automatically to format and fix imports.

Auto-completions

When users are filling in argument values for a specific prompt (identified by name) or resource template (identified by URI), servers can provide contextual suggestions. To enable completion support, use the server.WithCompletions() option when creating your server.

Completion Providers

You can provide completion logic for both prompt arguments and resource template arguments by implementing the respective interfaces and passing them to the server as options.

Show Completion Provider Examples
type MyPromptCompletionProvider struct{}

func (p *MyPromptCompletionProvider) CompletePromptArgument(
    ctx context.Context,
    promptName string,
    argument mcp.CompleteArgument,
    context mcp.CompleteContext,
) (*mcp.Completion, error) {
    // Example: provide style suggestions for a "code_review" prompt
    if promptName == "code_review" && argument.Name == "style" {
        styles := []string{"formal", "casual", "technical", "creative"}
        var suggestions []string
        
        // Filter based on current input
        for _, style := range styles {
            if strings.HasPrefix(style, argument.Value) {
                suggestions = append(suggestions, style)
            }
        }
        
        return &mcp.Completion{
            Values: suggestions,
        }, nil
    }
    
    // Return empty suggestions for unhandled cases
    return &mcp.Completion{Values: []string{}}, nil
}

type MyResourceCompletionProvider struct{}

func (p *MyResourceCompletionProvider) CompleteResourceArgument(
    ctx context.Context,
    uri string,
    argument mcp.CompleteArgument,
    context mcp.CompleteContext,
) (*mcp.Completion, error) {
    // Example: provide file path completions
    if uri == "file:///{path}" && argument.Name == "path" {
        // You can access previously completed arguments from context.Arguments
        // context.Arguments is a map[string]string of already-resolved arguments
        
        paths := getMatchingPaths(argument.Value) // Your custom logic
        
        return &mcp.Completion{
            Values:  paths[:min(len(paths), 100)], // Max 100 items
            Total:   len(paths),                    // Total available matches
            HasMore: len(paths) > 100,              // More results available
        }, nil
    }
    
    return &mcp.Completion{Values: []string{}}, nil
}

// Register the provider
mcpServer := server.NewMCPServer(
    "my-server",
    "1.0.0",
    server.WithCompletions(),
    server.WithPromptCompletionProvider(&MyPromptCompletionProvider{}),
    server.WithResourceCompletionProvider(&MyResourceCompletionProvider{}),
)

Completion Context

For prompts or resource templates with multiple arguments, the CompleteContext parameter provides access to previously completed arguments. This allows you to provide contextual suggestions based on earlier choices.

Show Completion Context Example
func (p *MyProvider) CompleteResourceArgument(
    ctx context.Context,
    uri string,
    argument mcp.CompleteArgument,
    context mcp.CompleteContext,
) (*mcp.Completion, error) {
    // Access previously completed arguments
    if previousValue, ok := context.Arguments["previous_arg"]; ok {
        // Provide suggestions based on previous_arg value
        return getSuggestionsFor(argument.Value, previousValue), nil
    }
    
    return &mcp.Completion{Values: []string{}}, nil
}

Response Constraints

When returning completion results:

  • Maximum 100 items per response
  • Use Total to indicate the total number of available matches
  • Use HasMore to signal if additional results exist beyond the returned values

Release History

VersionChangesUrgencyDate
v0.54.1Latest release: v0.54.1High5/25/2026
v0.54.0## What's Changed * fix(server): handle resources/subscribe and resources/unsubscribe (#865) by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/873 * fix(oauth): use LATEST_PROTOCOL_VERSION in metadata discovery (#868) by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/874 * fix(oauth): don't hold metadataMu across HTTP discovery (#871) by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/875 * feat(mcp): add 2025-11-25 sampling-with-tools and capability sub-fields (#867) by @ezHigh5/13/2026
v0.53.0## What's Changed * feat(server): add WithStrictInputSchemaDefault by @QuentinBisson in https://github.com/mark3labs/mcp-go/pull/853 * fix(server): add CloseSessions and prevent double-close panic on SSE sessions by @blackwell-systems in https://github.com/mark3labs/mcp-go/pull/852 * fix(transport): suppress closed-pipe shutdown noise by @Gujiassh in https://github.com/mark3labs/mcp-go/pull/863 * fix: add panic recovery to transport goroutines by @blackwell-systems in https://github.com/markHigh5/12/2026
v0.52.0Latest release: v0.52.0High5/5/2026
v0.50.0Latest release: v0.50.0High4/30/2026
v0.49.0Release v0.49.0High4/21/2026
v0.48.0Latest release: v0.48.0High4/14/2026
v0.47.1## What's Changed * docs(client): add example to NewSSEMCPClient to avoid variable shadowing by @vincent067 in https://github.com/mark3labs/mcp-go/pull/773 * Bound stdio child shutdown in Close() by @jbjardine in https://github.com/mark3labs/mcp-go/pull/784 * fix(client/http_streamable): exit ContinuousListening goroutine on context cancellation by @swedishborgie in https://github.com/mark3labs/mcp-go/pull/790 ## New Contributors * @jbjardine made their first contribution in https://githuHigh4/8/2026
v0.47.0## What's Changed * docs: add missing example references to README by @vincent067 in https://github.com/mark3labs/mcp-go/pull/772 * fix: close done channel on nil response to prevent goroutine leak by @Sim-hu in https://github.com/mark3labs/mcp-go/pull/766 * fix(server): reject sync calls to task-only tools by @Gujiassh in https://github.com/mark3labs/mcp-go/pull/778 * fix(transport): preserve OAuth discovery paths by @Gujiassh in https://github.com/mark3labs/mcp-go/pull/775 * enhancement: Medium4/4/2026
v0.46.0## What's Changed * fix(oauth): Handle token_type case-insensitively per RFC 6749 by @MariaChrysafis in https://github.com/mark3labs/mcp-go/pull/737 * test: add regression tests for tool schema serialization (#671) by @koriyoshi2041 in https://github.com/mark3labs/mcp-go/pull/739 * server: return 202 for empty ping responses by @bjornmp in https://github.com/mark3labs/mcp-go/pull/741 * fix(server): return 202 Accepted for sampling responses by @dugenkui03 in https://github.com/mark3labs/mcp-Medium3/26/2026
v0.45.0## What's Changed * Add RFC 7591 client_uri support in dynamic client registration by @MariaChrysafis in https://github.com/mark3labs/mcp-go/pull/726 * feat(transport): return ErrLegacySSEServer on 4xx initialize for spec-compliant SSE fallback by @MariaChrysafis in https://github.com/mark3labs/mcp-go/pull/731 * feat: add GetHooks() method to MCPServer for hook composability by @naji247 in https://github.com/mark3labs/mcp-go/pull/728 * fix: always include properties field in tool JSON SchemaLow3/6/2026
v0.44.1## What's Changed * fix: add session idle TTL sweeper to prevent transport state leak by @NLipatov in https://github.com/mark3labs/mcp-go/pull/724 ## New Contributors * @NLipatov made their first contribution in https://github.com/mark3labs/mcp-go/pull/724 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.44.0...v0.44.1Low2/27/2026
v0.44.0## What's Changed * feat: defer tool loading to enable Anthropic's "Tool Search" pattern by @wolfeidau in https://github.com/mark3labs/mcp-go/pull/644 * fix: return an error if the responseWriter does not support Flush by @JoelPfaffDD in https://github.com/mark3labs/mcp-go/pull/652 * Add Icons support for MCP spec 2025-11-25 compliance by @dask-58 in https://github.com/mark3labs/mcp-go/pull/660 * fix: add ErrUnauthorized sentinel for static token 401 responses by @ezynda3 in https://github.cLow2/15/2026
v0.44.0-beta.3Release v0.44.0-beta.3Low2/4/2026
v0.44.0-beta.2## What's Changed * Implement Elicitation URL mode for MCP spec 2025-11-25 by @dask-58 in https://github.com/mark3labs/mcp-go/pull/666 * feat: Add Host header override support for manual DNS resolution by @ComingCL in https://github.com/mark3labs/mcp-go/pull/674 * fix: low mcp version been selected by mcp server, mcp server may also raise 'unsupported protocol version 2025-11-25' error by @yuehaii in https://github.com/mark3labs/mcp-go/pull/687 * Add AdditionalProperties to ToolInputSchema bLow1/9/2026
v0.44.0-beta.1## What's Changed * feat: defer tool loading to enable Anthropic's "Tool Search" pattern by @wolfeidau in https://github.com/mark3labs/mcp-go/pull/644 * fix: return an error if the responseWriter does not support Flush by @JoelPfaffDD in https://github.com/mark3labs/mcp-go/pull/652 * Add Icons support for MCP spec 2025-11-25 compliance by @dask-58 in https://github.com/mark3labs/mcp-go/pull/660 * fix: add ErrUnauthorized sentinel for static token 401 responses by @ezynda3 in https://github.cLow12/19/2025
v0.43.2## What's Changed * fix: notification break the client tool call by @yuehaii in https://github.com/mark3labs/mcp-go/pull/642 * fix: handle either $defs or definitions field when unmarshaling ToolArgumentsSchema by @sd2k in https://github.com/mark3labs/mcp-go/pull/645 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.43.1...v0.43.2Low12/4/2025
v0.43.1## What's Changed * fix: create StatelessGeneratingSessionIdManager to fix multi-instance deployments by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/641 * fix: implement SessionWithClientInfo for streamableHttpSession by @Anko59 in https://github.com/mark3labs/mcp-go/pull/640 ## New Contributors * @Anko59 made their first contribution in https://github.com/mark3labs/mcp-go/pull/640 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.43.0...v0.43.1Low11/23/2025
v0.43.0## What's Changed * feat: add support for custom HTTP headers in client requests by @matthisholleville in https://github.com/mark3labs/mcp-go/pull/546 * feat: add SessionWithResourceTemplates for session-specific resource templates by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/624 * feat(mcp): Add SessionIdManagerResolver interface for request-based session management by @aradyaron in https://github.com/mark3labs/mcp-go/pull/626 * feat(mcp): add HTTP and Stdio client `Roots` featurLow11/2/2025
v0.43.0-beta.3## What's Changed * feat(mcp): Add SessionIdManagerResolver interface for request-based session management by @aradyaron in https://github.com/mark3labs/mcp-go/pull/626 * feat(mcp): add HTTP and Stdio client `Roots` feature by @yuehaii in https://github.com/mark3labs/mcp-go/pull/620 ## New Contributors * @aradyaron made their first contribution in https://github.com/mark3labs/mcp-go/pull/626 * @yuehaii made their first contribution in https://github.com/mark3labs/mcp-go/pull/620 **FullLow10/30/2025
v0.43.0-beta.2## What's Changed * feat: add SessionWithResourceTemplates for session-specific resource templates by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/624 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.43.0-beta.1...v0.43.0-beta.2Low10/25/2025
v0.43.0-beta.1## What's Changed * feat: add support for custom HTTP headers in client requests by @matthisholleville in https://github.com/mark3labs/mcp-go/pull/546 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.42.0...v0.43.0-beta.1Low10/21/2025
v0.42.0## What's Changed * HTTP Sampling Improvements by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/601 * feat: update type definition of _meta field to text/blob resources. by @rabbah in https://github.com/mark3labs/mcp-go/pull/591 * fix: documentation typos by @Artmorse in https://github.com/mark3labs/mcp-go/pull/608 * fix: prevent tools invocation without valid session initialization by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/607 * fix: make transport Start() idempotent tLow10/21/2025
v0.42.0-beta.3## What's Changed * Add support for Session-specific resources by @jaredly in https://github.com/mark3labs/mcp-go/pull/610 * feat: Add session resource helper functions by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/617 * [disable-stream] Add WithDisableStreaming option to StreamableHTTP server to allow disabling streaming by @jaredly in https://github.com/mark3labs/mcp-go/pull/613 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.42.0-beta.2...v0.42.0-beta.3Low10/17/2025
v0.42.0-beta.2## What's Changed * fix: documentation typos by @Artmorse in https://github.com/mark3labs/mcp-go/pull/608 * fix: prevent tools invocation without valid session initialization by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/607 * fix: make transport Start() idempotent to resolve issue #583 by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/606 * feat: extend resource middlewares to resource templates by @tjhop in https://github.com/mark3labs/mcp-go/pull/582 * Preserve Tool _metaLow10/14/2025
v0.42.0-beta.1## What's Changed * HTTP Sampling Improvements by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/601 * feat: update type definition of _meta field to text/blob resources. by @rabbah in https://github.com/mark3labs/mcp-go/pull/591 ## New Contributors * @rabbah made their first contribution in https://github.com/mark3labs/mcp-go/pull/591 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.41.1...v0.42.0-beta.1Low9/30/2025
v0.41.1## What's Changed * fix: replace bufio.Scanner with bufio.Reader to support large messageโ€ฆ by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/603 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.41.0...v0.41.1Low9/30/2025
v0.41.0## What's Changed * fix(oauth): use oauth-authorization-server discovery before default endpoints by @trungutt in https://github.com/mark3labs/mcp-go/pull/581 * Improve JSON-RPC error handling with typed errors and response constructors by @peteski22 in https://github.com/mark3labs/mcp-go/pull/595 * fix: Streamable HTTP client ping response handling by @havasik in https://github.com/mark3labs/mcp-go/pull/578 * feat: add support for call tool result annotations by @Crescent617 in https://githLow9/27/2025
v0.40.0## What's Changed * feat(get-server-tools): add GetTools method for retrieve MCPServer.tools by @ValeriiStepanets in https://github.com/mark3labs/mcp-go/pull/437 * fix: don't share mutex between tools/resources by @tjhop in https://github.com/mark3labs/mcp-go/pull/574 * docs(server): Correct custom endpoint example for streamable HTTP transport by @IAmSurajBobade in https://github.com/mark3labs/mcp-go/pull/577 * feat: add NewToolResultJSON by @changkun in https://github.com/mark3labs/mcp-go/Low9/19/2025
v0.39.1## What's Changed * fix(tool): Do not return empty `outputSchema` by @alex210501 in https://github.com/mark3labs/mcp-go/pull/573 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.39.0...v0.39.1Low9/2/2025
v0.39.0## What's Changed * fix: use bufio.Scanner for stdio transport to avoid panic when stdio mcp server outputs a long line by @WingT in https://github.com/mark3labs/mcp-go/pull/464 * fix(tool): Return the OutputSchema from the tool definition by @alex210501 in https://github.com/mark3labs/mcp-go/pull/571 * feat: add resource handler middleware capability by @tjhop in https://github.com/mark3labs/mcp-go/pull/569 * feat: add tls support for streamable-http by @opencow in https://github.com/mark3lLow9/2/2025
v0.38.0## What's Changed * fix: resolve stdio transport race condition for concurrent tool calls by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/529 * fix CallToolResult json marshaling and unmarshaling: need structuredCโ€ฆ by @sunfuze in https://github.com/mark3labs/mcp-go/pull/523 * feat: refactor constants for resource content types by @CocaineCong in https://github.com/mark3labs/mcp-go/pull/489 * feat: add missing SetPrompts, DeleteResources, and SetResources methods by @vasayxtx in httpsLow8/20/2025
v0.37.0## โš ๏ธ Breaking Changes The `Result.Meta` field type has changed from `map[string]any` to `*Meta`. Code that directly accesses or sets this field will need to be updated: ```go // Before (v0.36.0 and earlier): result.Meta = map[string]any{"key": "value"} // After (v0.37.0): result.Meta = &mcp.Meta{AdditionalFields: map[string]any{"key": "value"}} ``` ## What's Changed * Replace Prompts/Resources/Resource Templates by @dgageot in https://github.com/mark3labs/mcp-go/pLow8/5/2025
v0.36.0## What's Changed * Add defs field to ToolsInputSchema by @ostafen in https://github.com/mark3labs/mcp-go/pull/488 * Remove `sampling_server` binary file by @JeffreyCA in https://github.com/mark3labs/mcp-go/pull/512 * chore: remove comments related to JSON-Batching by @cryo-zd in https://github.com/mark3labs/mcp-go/pull/514 * feat: support structured content and output schema by @pottekkat in https://github.com/mark3labs/mcp-go/pull/460 * Hide error log when it's not useful by @dgageot in hLow7/28/2025
v0.35.0## What's Changed * Http headers by @adityamj in https://github.com/mark3labs/mcp-go/pull/480 * fix: check if resp is nil on error for initialize methods by @pottekkat in https://github.com/mark3labs/mcp-go/pull/492 * Fix race condition in stdio.SendRequest with canceled context by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/503 * Embed client capabilities into the Session by @ardaguclu in https://github.com/mark3labs/mcp-go/pull/491 * enhc(server): allow adding multiple resource tLow7/25/2025
v0.34.0## What's Changed * fix(streamable_http): ensure graceful shutdown to prevent close requeโ€ฆ by @sunerpy in https://github.com/mark3labs/mcp-go/pull/477 * fix(streamble_http) SendNotification not work bug by @Robin-ZMH in https://github.com/mark3labs/mcp-go/pull/473 * refactor: replace fmt.Errorf with TransportError wrapper by @AdamShannag in https://github.com/mark3labs/mcp-go/pull/486 * fix `Content-Type: application/json; charset=utf-8` error by @oldweipro in https://github.com/mark3labs/mcLow7/15/2025
v0.33.0## What's Changed * fix(server): Fix the logic of the WithStateLess function by @dcsunny in https://github.com/mark3labs/mcp-go/pull/387 * fix(srv/stream): correct handleGet status code to 200 by @cryo-zd in https://github.com/mark3labs/mcp-go/pull/379 * Add an example of an in process client by @edwardcqian in https://github.com/mark3labs/mcp-go/pull/371 * feat: add type-safe array items helper functions by @davidleitw in https://github.com/mark3labs/mcp-go/pull/396 * Issue 400 fix by @ozzLow7/8/2025
v0.32.0## What's Changed * feat(mcp): add NewToolResultErrorf by @icholy in https://github.com/mark3labs/mcp-go/pull/357 * feat(mcptest): extend test server with prompt and resource support by @vasayxtx in https://github.com/mark3labs/mcp-go/pull/346 * [streamable-http] Add ability to override the http.Client by @tra4less in https://github.com/mark3labs/mcp-go/pull/359 * fixed logo issue in home page by @asaf-shitrit in https://github.com/mark3labs/mcp-go/pull/364 * feat(mcptest): Change `Server.SLow6/11/2025
v0.31.0## What's Changed * [feat] separate request struct by @OswinWu in https://github.com/mark3labs/mcp-go/pull/333 * fix: logo on website is squashed by @corani in https://github.com/mark3labs/mcp-go/pull/349 * fix: panic when streamable HTTP server sends notification by @dugenkui03 in https://github.com/mark3labs/mcp-go/pull/348 * fix: move styles.css to www/docs by @corani in https://github.com/mark3labs/mcp-go/pull/354 * fix(server): resolve stdio server context cancellation bug by @soniricLow5/30/2025
v0.30.1## What's Changed * fix(server): Implement MCP version negotiation. by @octo in https://github.com/mark3labs/mcp-go/pull/341 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.30.0...v0.30.1Low5/28/2025
v0.30.0## What's Changed * Feat: Impl Server-Side Streamable HTTP transport by @leavez in https://github.com/mark3labs/mcp-go/pull/273 * Support customize request header by @dugenkui03 in https://github.com/mark3labs/mcp-go/pull/315 * docs: add regeneration instructions by @pmenglund in https://github.com/mark3labs/mcp-go/pull/309 * docs(examples): correct use of `GetArguments` by @jamietanna in https://github.com/mark3labs/mcp-go/pull/316 * fix: avoid painc caused by writing to closed channel byLow5/25/2025
v0.29.0## What's Changed * refactor: make CallToolRequest.Arguments more flexible (Breaking Change) by @ezynda3 in https://github.com/mark3labs/mcp-go/pull/287 * Drop unused fields from server.sseSession by @ggoodman in https://github.com/mark3labs/mcp-go/pull/303 * chore: remove unused variables and type arguments by @pottekkat in https://github.com/mark3labs/mcp-go/pull/302 * chore(Srv/stdio): duplicated setting of ErrorLogger by @cryo-zd in https://github.com/mark3labs/mcp-go/pull/306 * fix: haLow5/20/2025
v0.28.0## What's Changed * feat(tools): implicitly register capabilities by @david-hamilton-glean in https://github.com/mark3labs/mcp-go/pull/292 * fix: Gate notifications on capabilities by @david-hamilton-glean in https://github.com/mark3labs/mcp-go/pull/290 * feat(protocol): allow additional fields in meta by @anuraaga in https://github.com/mark3labs/mcp-go/pull/293 * fix: type mismatch for request/response ID by @pottekkat in https://github.com/mark3labs/mcp-go/pull/291 * feat(MCPServer): suLow5/16/2025
v0.27.1## What's Changed * docs: add CONTRIBUTING.md by @pottekkat in https://github.com/mark3labs/mcp-go/pull/275 * chore: create CODE_OF_CONDUCT.md by @pottekkat in https://github.com/mark3labs/mcp-go/pull/274 * chore: add issue and pull request templates by @pottekkat in https://github.com/mark3labs/mcp-go/pull/281 * ci: add golangci-lint by @pottekkat in https://github.com/mark3labs/mcp-go/pull/282 * fix: proper deprecation messaging for WithHTTPContextFunc by @aotarola in https://github.com/mLow5/14/2025
v0.27.0## What's Changed * Support audio content type in tools/call and prompts/get by @dugenkui03 in https://github.com/mark3labs/mcp-go/pull/250 * refactor(server): extract common HTTP transport configuration options by @robert-jackson-glean in https://github.com/mark3labs/mcp-go/pull/253 * ci: add check to verify generated code is up-to-date by @robert-jackson-glean in https://github.com/mark3labs/mcp-go/pull/258 * fix(MCPServer): correct notification method in func `RemoveResource()` by @cryo-zLow5/11/2025
v0.26.0## What's Changed * feat(sse): Add `SessionWithTools` support to SSEServer by @robert-jackson-glean in https://github.com/mark3labs/mcp-go/pull/232 * Fix bug with MarshalJSON for NotificationParams by @Gelembjuk in https://github.com/mark3labs/mcp-go/pull/233 * fix: write back error message if the response marshal failed by @ppzqh in https://github.com/mark3labs/mcp-go/pull/235 * fix(server/sse): potential goroutine leak in Heartbeat sender by @cryo-zd in https://github.com/mark3labs/mcp-go/Low5/6/2025
v0.25.0## What's Changed * update doc comments to match Go conventions by @yinebebt in https://github.com/mark3labs/mcp-go/pull/226 * fix: Add Accept Header in StreamableHTTP Client by @hhxiao in https://github.com/mark3labs/mcp-go/pull/230 * fix(SSE): only initialize `http.Server` when not set by @cryo-zd in https://github.com/mark3labs/mcp-go/pull/229 * fix: Prevent panic in parsing functions for null results by @cocovs in https://github.com/mark3labs/mcp-go/pull/218 * [SSEClient] Add ability toLow5/1/2025
v0.24.1## What's Changed * fix: marshal `ToolInputSchema.Properties` to {} when len=0 by @cryo-zd in https://github.com/mark3labs/mcp-go/pull/225 * fix(client/test): verify mock server binary exists after compilation by @robert-jackson-glean in https://github.com/mark3labs/mcp-go/pull/215 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.24.0...v0.24.1Low4/29/2025
v0.24.0## What's Changed * Use correct name in Go documentation by @oschwald in https://github.com/mark3labs/mcp-go/pull/202 * fix(client): resource leak in `SSEClient.SendRequest()` by @cryo-zd in https://github.com/mark3labs/mcp-go/pull/206 * fix(client): risk of resource leak and closing closed channel by @cryo-zd in https://github.com/mark3labs/mcp-go/pull/208 * no need to check empty text by @graydovee in https://github.com/mark3labs/mcp-go/pull/209 * refactor: Pull out `Annotations` structLow4/29/2025
v0.23.1## What's Changed * fix(client): prevent panics by @jkoelker in https://github.com/mark3labs/mcp-go/pull/192 * fix: correct JSON key for client capabilities by @TBXark in https://github.com/mark3labs/mcp-go/pull/197 * fix(client): check stdio started before sending notification by @cryo-zd in https://github.com/mark3labs/mcp-go/pull/199 * fix(client): potential risk of sending on closed channel by @cryo-zd in https://github.com/mark3labs/mcp-go/pull/194 ## New Contributors * @TBXark madLow4/23/2025
v0.23.0## What's Changed * Export SendNotificationToAllClients by @scottfeldman in https://github.com/mark3labs/mcp-go/pull/176 * feat(server): Add hooks.AddOnUnregisterSession functionality by @robert-jackson-glean in https://github.com/mark3labs/mcp-go/pull/175 * Refact: pre-allocate memory for memory-efficiency by @cryo-zd in https://github.com/mark3labs/mcp-go/pull/178 * fix sse shutdown by @karngyan in https://github.com/mark3labs/mcp-go/pull/128 * fix: update spec link by @warjiang in https:Low4/22/2025
v0.22.0## What's Changed * fix: add mutex to SSEServer to avoid data race between Start and Shutdown; fix test error on Windows (#166 #172) by @Wood-Q in https://github.com/mark3labs/mcp-go/pull/170 * feat(server): convert ping messages to be spec compliant by @robert-jackson-glean in https://github.com/mark3labs/mcp-go/pull/169 * feat: Implement Streamable-HTTP Client Basic by @leavez in https://github.com/mark3labs/mcp-go/pull/168 * feat:Added the parameter parsing mode to parse any to the specifLow4/19/2025
v0.21.1## What's Changed * fix: tool annotation by @dugenkui03 in https://github.com/mark3labs/mcp-go/pull/165 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.21.0...v0.21.1Low4/17/2025
v0.21.0## What's Changed * Add DefaultArray by @tiborvass in https://github.com/mark3labs/mcp-go/pull/67 * Unified Client Transport Layer for Streamable HTTP Support by @leavez in https://github.com/mark3labs/mcp-go/pull/114 * fix(tools): add `omitempty` to properties by @jkoelker in https://github.com/mark3labs/mcp-go/pull/116 * new feat: tool annotation by @dugenkui03 in https://github.com/mark3labs/mcp-go/pull/158 * introduce NewToolResultErrorWithErr and update docs by @deviantony in https://gLow4/16/2025
v0.20.1## What's Changed * Dustin/138 deadlock remove global mutex by @StarpTech in https://github.com/mark3labs/mcp-go/pull/139 ## New Contributors * @StarpTech made their first contribution in https://github.com/mark3labs/mcp-go/pull/139 **Full Changelog**: https://github.com/mark3labs/mcp-go/compare/v0.20.0...v0.20.1Low4/14/2025

Dependencies & License Audit

Loading dependencies...

Similar Packages

mcp-tidy๐Ÿงน Simplify your MCP servers with mcp-tidy, clearing server bloat to enhance performance and improve tool selection in Claude Code.main@2026-06-07
Paylink๐ŸŒ Simplify payment processing with PayLink, a unified API for multi-provider checkouts, ensuring reliable transactions and seamless integration.main@2026-06-06
ai-gatewayOne API for 25+ LLMs, OpenAI, Anthropic, Bedrock, Azure. Caching, guardrails & cost controls. Go-native LiteLLM & Kong AI Gateway alternative.v1.1.2
casdoorAn open-source Agent-first Identity and Access Management (IAM) /LLM MCP & agent gateway and auth server with web UI supporting OpenClaw, MCP, OAuth, OIDC, SAML, CAS, LDAP, SCIM, WebAuthn, TOTP, MFA, v3.83.0
ksailAll-in-one Kubernetes SDK: create, manage, and operate clusters across distributions (Kind, K3d, Talos, VCluster) with built-in GitOps, secrets, AI assistant, and MCP server. Only requires Docker.v7.26.0

More in MCP Servers

PlanExeCreate a plan from a description in minutes
agentroveYour own Claude Code UI, sandbox, in-browser VS Code, terminal, multi-provider support (Anthropic, OpenAI, GitHub Copilot, OpenRouter), custom skills, and MCP servers.
ProxmoxMCP-PlusEnhanced Proxmox MCP server with advanced virtualization management and full OpenAPI integration.
node9-proxyThe Execution Security Layer for the Agentic Era. Providing deterministic "Sudo" governance and audit logs for autonomous AI agents.