The MCP server implementation enables exposing tools, prompts, and resources to MCP clients, with support for multiple concurrent sessions.
Creates a new MCP server.
import "github.com/modelcontextprotocol/go-sdk/mcp"
func NewServer(impl *Implementation, options *ServerOptions) *ServerParameters:
impl: Implementation information (must not be nil)options: Optional server configurationExample:
server := mcp.NewServer(&mcp.Implementation{
Name: "my-server",
Version: "1.0.0",
}, &mcp.ServerOptions{
Instructions: "This server provides data analysis tools",
})Configures server behavior and capabilities.
type ServerOptions struct {
Instructions string
Logger *slog.Logger
InitializedHandler func(context.Context, *InitializedRequest)
PageSize int
RootsListChangedHandler func(context.Context, *RootsListChangedRequest)
ProgressNotificationHandler func(context.Context, *ProgressNotificationServerRequest)
CompletionHandler func(context.Context, *CompleteRequest) (*CompleteResult, error)
KeepAlive time.Duration
SubscribeHandler func(context.Context, *SubscribeRequest) error
UnsubscribeHandler func(context.Context, *UnsubscribeRequest) error
HasPrompts bool
HasResources bool
HasTools bool
GetSessionID func() string
}Fields:
Instructions: Optional instructions for connected clientsLogger: If non-nil, log server activityInitializedHandler: Called when "notifications/initialized" is receivedPageSize: Maximum items per page in list methods (default: 1000)RootsListChangedHandler: Called when client roots list changesProgressNotificationHandler: Called when client sends progress notificationsCompletionHandler: Called for completion/complete requestsKeepAlive: Interval for automatic ping requests (0 disables)SubscribeHandler: Called when a client subscribes to a resourceUnsubscribeHandler: Called when a client unsubscribes from a resourceHasPrompts: Advertise prompts capability even if no prompts registeredHasResources: Advertise resources capability even if no resources registeredHasTools: Advertise tools capability even if no tools registeredGetSessionID: Provides session ID for incoming requests (default: random)Default maximum items per page for list operations.
const DefaultPageSize = 1000Runs the server on a given transport (blocking).
func (s *Server) Run(ctx context.Context, t Transport) errorParameters:
ctx: Context for the server operationt: Transport to use for communicationExample:
if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
log.Fatal(err)
}Connects the server over a transport and returns a session.
func (s *Server) Connect(
ctx context.Context,
t Transport,
opts *ServerSessionOptions,
) (*ServerSession, error)Parameters:
ctx: Context for the connection operationt: Transport to use for communicationopts: Optional session configurationReturns: A new ServerSession for interacting with the client
Returns an iterator over all current server sessions.
func (s *Server) Sessions() iter.Seq[*ServerSession]Example:
for session := range server.Sessions() {
fmt.Printf("Session ID: %s\n", session.ID())
}Wraps the sending method handler with middleware.
func (s *Server) AddSendingMiddleware(middleware ...Middleware)Wraps the receiving method handler with middleware.
func (s *Server) AddReceivingMiddleware(middleware ...Middleware)Adds a tool with typed input and output to the server.
func AddTool[In, Out any](s *Server, t *Tool, h ToolHandlerFor[In, Out])Type Parameters:
In: Input type for tool arguments (must be JSON-marshalable)Out: Output type for tool results (use any for no output schema)Parameters:
s: Server to add the tool tot: Tool definitionh: Typed tool handler functionBehavior:
In type if not setOut type if not set and Out is not anyExample:
type CalculateInput struct {
X float64 `json:"x" jsonschema:"first number"`
Y float64 `json:"y" jsonschema:"second number"`
}
type CalculateOutput struct {
Result float64 `json:"result"`
}
mcp.AddTool(server, &mcp.Tool{
Name: "add",
Description: "Adds two numbers",
}, func(ctx context.Context, req *mcp.CallToolRequest, in CalculateInput) (*mcp.CallToolResult, CalculateOutput, error) {
return nil, CalculateOutput{Result: in.X + in.Y}, nil
})Adds a tool with a low-level handler to the server.
func (s *Server) AddTool(t *Tool, h ToolHandler)Parameters:
t: Tool definitionh: Tool handler functionExample:
server.AddTool(&mcp.Tool{
Name: "echo",
Description: "Echoes input",
InputSchema: map[string]any{
"type": "object",
"properties": map[string]any{
"message": map[string]any{"type": "string"},
},
},
}, func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
var args struct {
Message string `json:"message"`
}
if err := json.Unmarshal(req.Params.Arguments, &args); err != nil {
return nil, err
}
return &mcp.CallToolResult{
Content: []mcp.Content{
&mcp.TextContent{Text: args.Message},
},
}, nil
})Removes tools by name and notifies connected clients.
func (s *Server) RemoveTools(names ...string)Parameters:
names: Names of tools to removeLow-level tool handler function type.
type ToolHandler func(
context.Context,
*CallToolRequest,
) (*CallToolResult, error)Typed tool handler function type (used with generic AddTool).
type ToolHandlerFor[In, Out any] func(
_ context.Context,
request *CallToolRequest,
input In,
) (result *CallToolResult, output Out, _ error)Parameters:
ctx: Request contextrequest: Tool call request with metadatainput: Validated and unmarshaled inputReturns:
result: Call result (can be nil to use defaults)output: Structured output (automatically populated in result)error: Error if tool execution failedAdds a prompt template to the server.
func (s *Server) AddPrompt(p *Prompt, h PromptHandler)Parameters:
p: Prompt definitionh: Prompt handler functionExample:
server.AddPrompt(&mcp.Prompt{
Name: "greeting",
Description: "Generate a greeting",
Arguments: []*mcp.PromptArgument{
{Name: "name", Description: "Person to greet", Required: true},
{Name: "language", Description: "Language code", Required: false},
},
}, func(ctx context.Context, req *mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
name := req.Params.Arguments["name"]
language := req.Params.Arguments["language"]
greeting := "Hello"
if language == "es" {
greeting = "Hola"
}
return &mcp.GetPromptResult{
Messages: []*mcp.PromptMessage{
{
Role: "user",
Content: &mcp.TextContent{
Text: fmt.Sprintf("%s, %s!", greeting, name),
},
},
},
}, nil
})Removes prompts by name and notifies connected clients.
func (s *Server) RemovePrompts(names ...string)Prompt handler function type.
type PromptHandler func(
context.Context,
*GetPromptRequest,
) (*GetPromptResult, error)Adds a resource to the server.
func (s *Server) AddResource(r *Resource, h ResourceHandler)Parameters:
r: Resource definitionh: Resource handler functionExample:
server.AddResource(&mcp.Resource{
URI: "file:///data/users.json",
Name: "users",
Description: "User database",
MIMEType: "application/json",
}, func(ctx context.Context, req *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
data, err := os.ReadFile("/data/users.json")
if err != nil {
return nil, err
}
return &mcp.ReadResourceResult{
Contents: []*mcp.ResourceContents{
{
URI: req.Params.URI,
MIMEType: "application/json",
Text: string(data),
},
},
}, nil
})Adds a resource template to the server.
func (s *Server) AddResourceTemplate(t *ResourceTemplate, h ResourceHandler)Parameters:
t: Resource template definitionh: Resource handler functionExample:
server.AddResourceTemplate(&mcp.ResourceTemplate{
URITemplate: "file:///data/{filename}",
Name: "data-files",
Description: "Access data files",
MIMEType: "text/plain",
}, func(ctx context.Context, req *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
// Extract filename from URI
u, _ := url.Parse(req.Params.URI)
filename := filepath.Base(u.Path)
data, err := os.ReadFile(filepath.Join("/data", filename))
if err != nil {
return nil, mcp.ResourceNotFoundError(req.Params.URI)
}
return &mcp.ReadResourceResult{
Contents: []*mcp.ResourceContents{
{URI: req.Params.URI, Text: string(data)},
},
}, nil
})Removes resources by URI and notifies connected clients.
func (s *Server) RemoveResources(uris ...string)Removes resource templates by URI template and notifies connected clients.
func (s *Server) RemoveResourceTemplates(uriTemplates ...string)Notifies subscribed clients that a resource has been updated.
func (s *Server) ResourceUpdated(
ctx context.Context,
params *ResourceUpdatedNotificationParams,
) errorParameters:
ctx: Context for the operationparams: Notification parameters with resource URIExample:
err := server.ResourceUpdated(ctx, &mcp.ResourceUpdatedNotificationParams{
URI: "file:///data/users.json",
})Resource handler function type.
type ResourceHandler func(
context.Context,
*ReadResourceRequest,
) (*ReadResourceResult, error)Creates an error for resource not found scenarios.
func ResourceNotFoundError(uri string) errorA ServerSession represents a logical connection from a single MCP client. Its methods send requests or notifications to the client.
Sends a sampling request to the client (asks client to call an LLM).
func (ss *ServerSession) CreateMessage(
ctx context.Context,
params *CreateMessageParams,
) (*CreateMessageResult, error)Example:
result, err := session.CreateMessage(ctx, &mcp.CreateMessageParams{
Messages: []*mcp.SamplingMessage{
{
Role: "user",
Content: &mcp.TextContent{Text: "What is 2+2?"},
},
},
MaxTokens: 100,
})Sends an elicitation request to the client (asks user for information).
func (ss *ServerSession) Elicit(
ctx context.Context,
params *ElicitParams,
) (*ElicitResult, error)Example:
result, err := session.Elicit(ctx, &mcp.ElicitParams{
Message: "Please enter your API key",
RequestedSchema: map[string]any{
"type": "object",
"properties": map[string]any{
"apiKey": map[string]any{"type": "string"},
},
},
})Lists the client's roots.
func (ss *ServerSession) ListRoots(
ctx context.Context,
params *ListRootsParams,
) (*ListRootsResult, error)Sends a log message to the client.
func (ss *ServerSession) Log(
ctx context.Context,
params *LoggingMessageParams,
) errorExample:
err := session.Log(ctx, &mcp.LoggingMessageParams{
Level: mcp.LevelInfo,
Logger: "my-server",
Data: "Processing request",
})Sends a progress notification to the client.
func (ss *ServerSession) NotifyProgress(
ctx context.Context,
params *ProgressNotificationParams,
) errorPerforms a graceful shutdown of the connection.
func (ss *ServerSession) Close() errorWaits for the connection to be closed by the client.
func (ss *ServerSession) Wait() errorPings the client.
func (ss *ServerSession) Ping(ctx context.Context, params *PingParams) errorReturns the session ID.
func (ss *ServerSession) ID() stringReturns the InitializeParams provided during client's connection.
func (ss *ServerSession) InitializeParams() *InitializeParamsDescribes capabilities that a server may support.
type ServerCapabilities struct {
Completions *CompletionCapabilities `json:"completions,omitempty"`
Experimental map[string]any `json:"experimental,omitempty"`
Logging *LoggingCapabilities `json:"logging,omitempty"`
Prompts *PromptCapabilities `json:"prompts,omitempty"`
Resources *ResourceCapabilities `json:"resources,omitempty"`
Tools *ToolCapabilities `json:"tools,omitempty"`
}Fields:
Completions: Present if server supports argument autocompletionExperimental: Non-standard capabilitiesLogging: Present if server supports sending log messagesPrompts: Present if server offers prompt templatesResources: Present if server offers resources to readTools: Present if server offers tools to calltype ToolCapabilities struct {
ListChanged bool `json:"listChanged,omitempty"`
}type PromptCapabilities struct {
ListChanged bool `json:"listChanged,omitempty"`
}type ResourceCapabilities struct {
ListChanged bool `json:"listChanged,omitempty"`
Subscribe bool `json:"subscribe,omitempty"`
}type CompletionCapabilities struct{}type LoggingCapabilities struct{}An slog.Handler implementation that sends logs to MCP clients.
func NewLoggingHandler(
ss *ServerSession,
opts *LoggingHandlerOptions,
) *LoggingHandlerExample:
handler := mcp.NewLoggingHandler(session, &mcp.LoggingHandlerOptions{
LoggerName: "my-server",
MinInterval: 100 * time.Millisecond,
})
logger := slog.New(handler)
logger.Info("Server started")type LoggingHandlerOptions struct {
LoggerName string
MinInterval time.Duration
}Fields:
LoggerName: Value for the "logger" field of logging notificationsMinInterval: Limits the rate at which log messages are sentconst (
LevelDebug = slog.LevelDebug
LevelInfo = slog.LevelInfo
LevelNotice = (slog.LevelInfo + slog.LevelWarn) / 2
LevelWarning = slog.LevelWarn
LevelError = slog.LevelError
LevelCritical = slog.LevelError + 4
LevelAlert = slog.LevelError + 8
LevelEmergency = slog.LevelError + 12
)Configures the server session.
type ServerSessionOptions struct {
State *ServerSessionState
}Represents the state of a session.
type ServerSessionState struct {
InitializeParams *InitializeParams `json:"initializeParams"`
InitializedParams *InitializedParams `json:"initializedParams"`
LogLevel LoggingLevel `json:"logLevel"`
}Fields:
InitializeParams: Parameters from 'initialize' requestInitializedParams: Parameters from 'notifications/initialized'LogLevel: Current logging level for the session