mcp

package
v1.8.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 8, 2025 License: MIT Imports: 12 Imported by: 1

README

Model Context Protocol (MCP) Implementation

Overview

This package implements the Model Context Protocol (MCP) server specification in Go, providing a framework for real-time communication between AI models and clients using Server-Sent Events (SSE). The implementation follows the standardized protocol for building AI-assisted applications with bidirectional communication capabilities.

Core Components

Server-Sent Events (SSE) Communication
  • Real-time Communication: Robust SSE-based communication system that maintains persistent connections with clients
  • Connection Management: Client registration, message broadcasting, and client cleanup mechanisms
  • Event Handling: Event types for tools, prompts, and resources changes
JSON-RPC Implementation
  • Request Processing: Complete JSON-RPC request processor for handling MCP protocol methods
  • Response Formatting: Proper response formatting according to JSON-RPC specifications
  • Error Handling: Comprehensive error handling with appropriate error codes
Tool Management
  • Tool Registration: System to register custom tools with handlers
  • Tool Execution: Mechanism to execute tool functions with proper timeout handling
  • Result Handling: Flexible result handling supporting various return types (string, JSON, images)
Prompt System
  • Prompt Registration: System for registering both static and dynamic prompts
  • Argument Validation: Validation for required arguments and default values for optional ones
  • Message Generation: Handlers that generate properly formatted conversation messages
Resource Management
  • Resource Registration: System for managing and accessing external resources
  • Content Delivery: Handlers for delivering resource content to clients on demand
  • Resource Subscription: Mechanisms for clients to subscribe to resource updates
Protocol Features
  • Initialization Sequence: Proper handshaking with capability negotiation
  • Notification Handling: Support for both standard and client-specific notifications
  • Message Routing: Intelligent routing of requests to appropriate handlers

Technical Highlights

Configuration System
  • Flexible Configuration: Configuration system with sensible defaults and customization options
  • CORS Support: Configurable CORS settings for cross-origin requests
  • Server Information: Proper server identification and versioning
Client Session Management
  • Session Tracking: Client session tracking with unique identifiers
  • Connection Health: Ping/pong mechanism to maintain connection health
  • Initialization State: Client initialization state tracking
Content Handling
  • Multi-format Content: Support for text, code, and binary content
  • MIME Type Support: Proper MIME type identification for various content types
  • Audience Annotations: Content audience annotations for user/assistant targeting

Usage

Setting Up an MCP Server

To create and start an MCP server:

package main

import (
	"github.com/zeromicro/go-zero/core/conf"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/mcp"
)

func main() {
	// Load configuration from YAML file
	var c mcp.McpConf
	conf.MustLoad("config.yaml", &c)

	// Optional: Disable stats logging
	logx.DisableStat()

	// Create MCP server
	server := mcp.NewMcpServer(c)

	// Register tools, prompts, and resources (examples below)

	// Start the server and ensure it's stopped on exit
	defer server.Stop()
	server.Start()
}

Sample configuration file (config.yaml):

name: mcp-server
host: localhost
port: 8080
mcp:
  name: my-mcp-server
  messageTimeout: 30s # Timeout for tool calls
  cors:
    - http://localhost:3000 # Optional CORS configuration
Registering Tools

Tools allow AI models to execute custom code through the MCP protocol.

Basic Tool Example:
// Register a simple echo tool
echoTool := mcp.Tool{
	Name:        "echo",
	Description: "Echoes back the message provided by the user",
	InputSchema: mcp.InputSchema{
		Properties: map[string]any{
			"message": map[string]any{
				"type":        "string",
				"description": "The message to echo back",
			},
			"prefix": map[string]any{
				"type":        "string",
				"description": "Optional prefix to add to the echoed message",
				"default":     "Echo: ",
			},
		},
		Required: []string{"message"},
	},
	Handler: func(ctx context.Context, params map[string]any) (any, error) {
		var req struct {
			Message string `json:"message"`
			Prefix  string `json:"prefix,optional"`
		}

		if err := mcp.ParseArguments(params, &req); err != nil {
			return nil, fmt.Errorf("failed to parse params: %w", err)
		}

		prefix := "Echo: "
		if len(req.Prefix) > 0 {
			prefix = req.Prefix
		}

		return prefix + req.Message, nil
	},
}

server.RegisterTool(echoTool)
Tool with Different Response Types:
// Tool returning JSON data
dataTool := mcp.Tool{
	Name:        "data.generate",
	Description: "Generates sample data in various formats",
	InputSchema: mcp.InputSchema{
		Properties: map[string]any{
			"format": map[string]any{
				"type":        "string",
				"description": "Format of data (json, text)",
				"enum":        []string{"json", "text"},
			},
		},
	},
	Handler: func(ctx context.Context, params map[string]any) (any, error) {
		var req struct {
			Format string `json:"format"`
		}

		if err := mcp.ParseArguments(params, &req); err != nil {
			return nil, fmt.Errorf("failed to parse params: %w", err)
		}

		if req.Format == "json" {
			// Return structured data
			return map[string]any{
				"items": []map[string]any{
					{"id": 1, "name": "Item 1"},
					{"id": 2, "name": "Item 2"},
				},
				"count": 2,
			}, nil
		}

		// Default to text
		return "Sample text data", nil
	},
}

server.RegisterTool(dataTool)
Image Generation Tool Example:
// Tool returning image content
imageTool := mcp.Tool{
	Name:        "image.generate",
	Description: "Generates a simple image",
	InputSchema: mcp.InputSchema{
		Properties: map[string]any{
			"type": map[string]any{
				"type":        "string",
				"description": "Type of image to generate",
				"default":     "placeholder",
			},
		},
	},
	Handler: func(ctx context.Context, params map[string]any) (any, error) {
		// Return image content directly
		return mcp.ImageContent{
			Data:     "base64EncodedImageData...", // Base64 encoded image data
			MimeType: "image/png",
		}, nil
	},
}

server.RegisterTool(imageTool)
Using ToolResult for Custom Outputs:
// Tool that returns a custom ToolResult type
customResultTool := mcp.Tool{
	Name:        "custom.result",
	Description: "Returns a custom formatted result",
	InputSchema: mcp.InputSchema{
		Properties: map[string]any{
			"resultType": map[string]any{
				"type": "string",
				"enum": []string{"text", "image"},
			},
		},
	},
	Handler: func(ctx context.Context, params map[string]any) (any, error) {
		var req struct {
			ResultType string `json:"resultType"`
		}

		if err := mcp.ParseArguments(params, &req); err != nil {
			return nil, fmt.Errorf("failed to parse params: %w", err)
		}

		if req.ResultType == "image" {
			return mcp.ToolResult{
				Type: mcp.ContentTypeImage,
				Content: map[string]any{
					"data":     "base64EncodedImageData...",
					"mimeType": "image/jpeg",
				},
			}, nil
		}

		// Default to text
		return mcp.ToolResult{
			Type:    mcp.ContentTypeText,
			Content: "This is a text result from ToolResult",
		}, nil
	},
}

server.RegisterTool(customResultTool)
Registering Prompts

Prompts are reusable conversation templates for AI models.

Static Prompt Example:
// Register a simple static prompt with placeholders
server.RegisterPrompt(mcp.Prompt{
	Name:        "hello",
	Description: "A simple hello prompt",
	Arguments: []mcp.PromptArgument{
		{
			Name:        "name",
			Description: "The name to greet",
			Required:    false,
		},
	},
	Content: "Say hello to {{name}} and introduce yourself as an AI assistant.",
})
Dynamic Prompt with Handler Function:
// Register a prompt with a dynamic handler function
server.RegisterPrompt(mcp.Prompt{
	Name:        "dynamic-prompt",
	Description: "A prompt that uses a handler to generate dynamic content",
	Arguments: []mcp.PromptArgument{
		{
			Name:        "username",
			Description: "User's name for personalized greeting",
			Required:    true,
		},
		{
			Name:        "topic",
			Description: "Topic of expertise",
			Required:    true,
		},
	},
	Handler: func(ctx context.Context, args map[string]string) ([]mcp.PromptMessage, error) {
		var req struct {
			Username string `json:"username"`
			Topic    string `json:"topic"`
		}

		if err := mcp.ParseArguments(args, &req); err != nil {
			return nil, fmt.Errorf("failed to parse args: %w", err)
		}

		// Create a user message
		userMessage := mcp.PromptMessage{
			Role: mcp.RoleUser,
			Content: mcp.TextContent{
				Text: fmt.Sprintf("Hello, I'm %s and I'd like to learn about %s.", req.Username, req.Topic),
			},
		}

		// Create an assistant response with current time
		currentTime := time.Now().Format(time.RFC1123)
		assistantMessage := mcp.PromptMessage{
			Role: mcp.RoleAssistant,
			Content: mcp.TextContent{
				Text: fmt.Sprintf("Hello %s! I'm an AI assistant and I'll help you learn about %s. The current time is %s.",
					req.Username, req.Topic, currentTime),
			},
		}

		// Return both messages as a conversation
		return []mcp.PromptMessage{userMessage, assistantMessage}, nil
	},
})
Multi-Message Prompt with Code Examples:
// Register a prompt that provides code examples in different programming languages
server.RegisterPrompt(mcp.Prompt{
	Name:        "code-example",
	Description: "Provides code examples in different programming languages",
	Arguments: []mcp.PromptArgument{
		{
			Name:        "language",
			Description: "Programming language for the example",
			Required:    true,
		},
		{
			Name:        "complexity",
			Description: "Complexity level (simple, medium, advanced)",
		},
	},
	Handler: func(ctx context.Context, args map[string]string) ([]mcp.PromptMessage, error) {
		var req struct {
			Language   string `json:"language"`
			Complexity string `json:"complexity,optional"`
		}

		if err := mcp.ParseArguments(args, &req); err != nil {
			return nil, fmt.Errorf("failed to parse args: %w", err)
		}

		// Validate language
		supportedLanguages := map[string]bool{"go": true, "python": true, "javascript": true, "rust": true}
		if !supportedLanguages[req.Language] {
			return nil, fmt.Errorf("unsupported language: %s", req.Language)
		}

		// Generate code example based on language and complexity
		var codeExample string

		switch req.Language {
		case "go":
			if req.Complexity == "simple" {
				codeExample = `
package main

import "fmt"

func main() {
	fmt.Println("Hello, World!")
}`
			} else {
				codeExample = `
package main

import (
	"fmt"
	"time"
)

func main() {
	now := time.Now()
	fmt.Printf("Hello, World! Current time is %s\n", now.Format(time.RFC3339))
}`
			}
		case "python":
			// Python example code
			if req.Complexity == "simple" {
				codeExample = `
def greet(name):
    return f"Hello, {name}!"

print(greet("World"))`
			} else {
				codeExample = `
import datetime

def greet(name, include_time=False):
    message = f"Hello, {name}!"
    if include_time:
        message += f" Current time is {datetime.datetime.now().isoformat()}"
    return message

print(greet("World", include_time=True))`
			}
		}

		// Create messages array according to MCP spec
		messages := []mcp.PromptMessage{
			{
				Role: mcp.RoleAssistant,
				Content: mcp.TextContent{
					Text: fmt.Sprintf("You are a helpful coding assistant specialized in %s programming.", req.Language),
				},
			},
			{
				Role: mcp.RoleUser,
				Content: mcp.TextContent{
					Text: fmt.Sprintf("Show me a %s example of a Hello World program in %s.", req.Complexity, req.Language),
				},
			},
			{
				Role: mcp.RoleAssistant,
				Content: mcp.TextContent{
					Text: fmt.Sprintf("Here's a %s example in %s:\n\n```%s%s\n```\n\nHow can I help you implement this?",
						req.Complexity, req.Language, req.Language, codeExample),
				},
			},
		}

		return messages, nil
	},
})
Registering Resources

Resources provide access to external content such as files or generated data.

Basic Resource Example:
// Register a static resource
server.RegisterResource(mcp.Resource{
	Name:        "example-document",
	URI:         "file:///example/document.txt",
	Description: "An example document",
	MimeType:    "text/plain",
	Handler: func(ctx context.Context) (mcp.ResourceContent, error) {
		return mcp.ResourceContent{
			URI:      "file:///example/document.txt",
			MimeType: "text/plain",
			Text:     "This is an example document content.",
		}, nil
	},
})
Dynamic Resource with Code Example:
// Register a Go code resource with dynamic handler
server.RegisterResource(mcp.Resource{
	Name:        "go-example",
	URI:         "file:///project/src/main.go",
	Description: "A simple Go example with multiple files",
	MimeType:    "text/x-go",
	Handler: func(ctx context.Context) (mcp.ResourceContent, error) {
		// Return ResourceContent with all required fields
		return mcp.ResourceContent{
			URI:      "file:///project/src/main.go",
			MimeType: "text/x-go",
			Text:     "package main\n\nimport (\n\t\"fmt\"\n\t\"./greeting\"\n)\n\nfunc main() {\n\tfmt.Println(greeting.Hello(\"world\"))\n}",
		}, nil
	},
})

// Register a companion file for the above example
server.RegisterResource(mcp.Resource{
	Name:        "go-greeting",
	URI:         "file:///project/src/greeting/greeting.go",
	Description: "A greeting package for the Go example",
	MimeType:    "text/x-go",
	Handler: func(ctx context.Context) (mcp.ResourceContent, error) {
		return mcp.ResourceContent{
			URI:      "file:///project/src/greeting/greeting.go",
			MimeType: "text/x-go",
			Text:     "package greeting\n\nfunc Hello(name string) string {\n\treturn \"Hello, \" + name + \"!\"\n}",
		}, nil
	},
})
Binary Resource Example:
// Register a binary resource (like an image)
server.RegisterResource(mcp.Resource{
	Name:        "example-image",
	URI:         "file:///example/image.png",
	Description: "An example image",
	MimeType:    "image/png",
	Handler: func(ctx context.Context) (mcp.ResourceContent, error) {
		// Read image from file or generate it
		imageData := "base64EncodedImageData..." // Base64 encoded image data

		return mcp.ResourceContent{
			URI:      "file:///example/image.png",
			MimeType: "image/png",
			Blob:     imageData, // For binary data
		}, nil
	},
})
Using Resources in Prompts

You can embed resources in prompt responses to create rich interactions with proper MCP-compliant structure:

// Register a prompt that embeds a resource
server.RegisterPrompt(mcp.Prompt{
	Name:        "resource-example",
	Description: "A prompt that embeds a resource",
	Arguments: []mcp.PromptArgument{
		{
			Name:        "file_type",
			Description: "Type of file to show (rust or go)",
			Required:    true,
		},
	},
	Handler: func(ctx context.Context, args map[string]string) ([]mcp.PromptMessage, error) {
		var req struct {
			FileType string `json:"file_type"`
		}

		if err := mcp.ParseArguments(args, &req); err != nil {
			return nil, fmt.Errorf("failed to parse args: %w", err)
		}

		var resourceURI, mimeType, fileContent string
		if req.FileType == "rust" {
			resourceURI = "file:///project/src/main.rs"
			mimeType = "text/x-rust"
			fileContent = "fn main() {\n    println!(\"Hello world!\");\n}"
		} else {
			resourceURI = "file:///project/src/main.go"
			mimeType = "text/x-go"
			fileContent = "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"Hello, world!\")\n}"
		}

		// Create message with embedded resource using proper MCP format
		return []mcp.PromptMessage{
			{
				Role: mcp.RoleUser,
				Content: mcp.TextContent{
					Text: fmt.Sprintf("Can you explain this %s code?", req.FileType),
				},
			},
			{
				Role: mcp.RoleAssistant,
				Content: mcp.EmbeddedResource{
					Type: mcp.ContentTypeResource,
					Resource: struct {
						URI      string `json:"uri"`
						MimeType string `json:"mimeType"`
						Text     string `json:"text,omitempty"`
						Blob     string `json:"blob,omitempty"`
					}{
						URI:      resourceURI,
						MimeType: mimeType,
						Text:     fileContent,
					},
				},
			},
			{
				Role: mcp.RoleAssistant,
				Content: mcp.TextContent{
					Text: fmt.Sprintf("Above is a simple Hello World example in %s. Let me explain how it works.", req.FileType),
				},
			},
		}, nil
	},
})
Multiple File Resources Example
// Register a prompt that demonstrates embedding multiple resource files
server.RegisterPrompt(mcp.Prompt{
	Name:        "go-code-example",
	Description: "A prompt that correctly embeds multiple resource files",
	Arguments: []mcp.PromptArgument{
		{
			Name:        "format",
			Description: "How to format the code display",
		},
	},
	Handler: func(ctx context.Context, args map[string]string) ([]mcp.PromptMessage, error) {
		var req struct {
			Format string `json:"format,optional"`
		}

		if err := mcp.ParseArguments(args, &req); err != nil {
			return nil, fmt.Errorf("failed to parse args: %w", err)
		}

		// Get the Go code for multiple files
		var mainGoText string = "package main\n\nimport (\n\t\"fmt\"\n\t\"./greeting\"\n)\n\nfunc main() {\n\tfmt.Println(greeting.Hello(\"world\"))\n}"
		var greetingGoText string = "package greeting\n\nfunc Hello(name string) string {\n\treturn \"Hello, \" + name + \"!\"\n}"

		// Create message with properly formatted embedded resource per MCP spec
		messages := []mcp.PromptMessage{
			{
				Role: mcp.RoleUser,
				Content: mcp.TextContent{
					Text: "Show me a simple Go example with proper imports.",
				},
			},
			{
				Role: mcp.RoleAssistant,
				Content: mcp.TextContent{
					Text: "Here's a simple Go example project:",
				},
			},
			{
				Role: mcp.RoleAssistant,
				Content: mcp.EmbeddedResource{
					Type: mcp.ContentTypeResource,
					Resource: struct {
						URI      string `json:"uri"`
						MimeType string `json:"mimeType"`
						Text     string `json:"text,omitempty"`
						Blob     string `json:"blob,omitempty"`
					}{
						URI:      "file:///project/src/main.go",
						MimeType: "text/x-go",
						Text:     mainGoText,
					},
				},
			},
		}

		// Add explanation and additional file if requested
		if req.Format == "with_explanation" {
			messages = append(messages, mcp.PromptMessage{
				Role: mcp.RoleAssistant,
				Content: mcp.TextContent{
					Text: "This example demonstrates a simple Go application with modular structure. The main.go file imports from a local 'greeting' package that provides the Hello function.",
				},
			})

			// Also show the greeting.go file with correct resource format
			messages = append(messages, mcp.PromptMessage{
				Role: mcp.RoleAssistant,
				Content: mcp.EmbeddedResource{
					Type: mcp.ContentTypeResource,
					Resource: struct {
						URI      string `json:"uri"`
						MimeType string `json:"mimeType"`
						Text     string `json:"text,omitempty"`
						Blob     string `json:"blob,omitempty"`
					}{
						URI:      "file:///project/src/greeting/greeting.go",
						MimeType: "text/x-go",
						Text:     greetingGoText,
					},
				},
			})
		}

		return messages, nil
	},
})
Complete Application Example

Here's a complete example demonstrating all the components:

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/zeromicro/go-zero/core/conf"
	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/mcp"
)

func main() {
	// Load configuration
	var c mcp.McpConf
	if err := conf.Load("config.yaml", &c); err != nil {
		log.Fatalf("Failed to load config: %v", err)
	}

	// Set up logging
	logx.DisableStat()

	// Create MCP server
	server := mcp.NewMcpServer(c)
	defer server.Stop()

	// Register a simple echo tool
	echoTool := mcp.Tool{
		Name:        "echo",
		Description: "Echoes back the message provided by the user",
		InputSchema: mcp.InputSchema{
			Properties: map[string]any{
				"message": map[string]any{
					"type":        "string",
					"description": "The message to echo back",
				},
				"prefix": map[string]any{
					"type":        "string",
					"description": "Optional prefix to add to the echoed message",
					"default":     "Echo: ",
				},
			},
			Required: []string{"message"},
		},
		Handler: func(ctx context.Context, params map[string]any) (any, error) {
			var req struct {
				Message string `json:"message"`
				Prefix  string `json:"prefix,optional"`
			}

			if err := mcp.ParseArguments(params, &req); err != nil {
				return nil, fmt.Errorf("failed to parse args: %w", err)
			}

			prefix := "Echo: "
			if len(req.Prefix) > 0 {
				prefix = req.Prefix
			}

			return prefix + req.Message, nil
		},
	}
	server.RegisterTool(echoTool)

	// Register a static prompt
	server.RegisterPrompt(mcp.Prompt{
		Name:        "greeting",
		Description: "A simple greeting prompt",
		Arguments: []mcp.PromptArgument{
			{
				Name:        "name",
				Description: "The name to greet",
				Required:    true,
			},
		},
		Content: "Hello {{name}}! How can I assist you today?",
	})

	// Register a dynamic prompt
	server.RegisterPrompt(mcp.Prompt{
		Name:        "dynamic-prompt",
		Description: "A prompt that uses a handler to generate dynamic content",
		Arguments: []mcp.PromptArgument{
			{
				Name:        "username",
				Description: "User's name for personalized greeting",
				Required:    true,
			},
			{
				Name:        "topic",
				Description: "Topic of expertise",
				Required:    true,
			},
		},
		Handler: func(ctx context.Context, args map[string]string) ([]mcp.PromptMessage, error) {
			var req struct {
				Username string `json:"username"`
				Topic    string `json:"topic"`
			}

			if err := mcp.ParseArguments(args, &req); err != nil {
				return nil, fmt.Errorf("failed to parse args: %w", err)
			}

			// Create messages with current time
			currentTime := time.Now().Format(time.RFC1123)
			return []mcp.PromptMessage{
				{
					Role: mcp.RoleUser,
					Content: mcp.TextContent{
						Text: fmt.Sprintf("Hello, I'm %s and I'd like to learn about %s.", req.Username, req.Topic),
					},
				},
				{
					Role: mcp.RoleAssistant,
					Content: mcp.TextContent{
						Text: fmt.Sprintf("Hello %s! I'm an AI assistant and I'll help you learn about %s. The current time is %s.",
							req.Username, req.Topic, currentTime),
					},
				},
			}, nil
		},
	})

	// Register a resource
	server.RegisterResource(mcp.Resource{
		Name:        "example-doc",
		URI:         "file:///example/doc.txt",
		Description: "An example document",
		MimeType:    "text/plain",
		Handler: func(ctx context.Context) (mcp.ResourceContent, error) {
			return mcp.ResourceContent{
				URI:      "file:///example/doc.txt",
				MimeType: "text/plain",
				Text:     "This is the content of the example document.",
			}, nil
		},
	})

	// Start the server
	fmt.Printf("Starting MCP server on %s:%d\n", c.Host, c.Port)
	server.Start()
}

Error Handling

The MCP implementation provides comprehensive error handling:

  • Tool execution errors are properly reported back to clients
  • Missing or invalid parameters are detected and reported with appropriate error codes
  • Resource and prompt lookup failures are handled gracefully
  • Timeout handling for long-running tool executions using context
  • Panic recovery to prevent server crashes

Advanced Features

  • Annotations: Add audience and priority metadata to content
  • Content Types: Support for text, images, audio, and other content formats
  • Embedded Resources: Include file resources directly in prompt responses
  • Context Awareness: All handlers receive context.Context for timeout and cancellation support
  • Progress Tokens: Support for tracking progress of long-running operations
  • Customizable Timeouts: Configure execution timeouts for tools and operations

Performance Considerations

  • Tool execution runs with configurable timeouts to prevent blocking
  • Efficient client tracking and cleanup to prevent resource leaks
  • Proper concurrency handling with mutex protection for shared resources
  • Buffered message channels to prevent blocking on client message delivery

Documentation

Index

Constants

View Source
const (
	// ContentTypeObject is object content type
	ContentTypeObject = "object"

	// ContentTypeText is text content type
	ContentTypeText = "text"

	// ContentTypeImage is image content type
	ContentTypeImage = "image"

	// ContentTypeAudio is audio content type
	ContentTypeAudio = "audio"

	// ContentTypeResource is resource content type
	ContentTypeResource = "resource"
)

Content type identifiers

Variables

This section is empty.

Functions

func ParseArguments

func ParseArguments(args any, req any) error

ParseArguments parses the arguments and populates the request object

Types

type Annotations

type Annotations struct {
	Audience []RoleType `json:"audience,omitempty"` // Who should see this content
	Priority *float64   `json:"priority,omitempty"` // Optional priority (0-1)
}

Annotations provides additional metadata for content

type AudioContent

type AudioContent struct {
	Data     string `json:"data"`     // Base64-encoded audio data
	MimeType string `json:"mimeType"` // MIME type (e.g., "audio/mp3")
}

AudioContent represents audio data in a message

type CallToolResult

type CallToolResult struct {
	Result
	Content []any `json:"content"`           // Content items (text, images, etc.)
	IsError bool  `json:"isError,omitempty"` // True if tool execution failed
}

CallToolResult represents a tool call result that conforms to the MCP schema

type Cursor

type Cursor string

Cursor is an opaque token used for pagination

type EmbeddedResource

type EmbeddedResource struct {
	Type     string          `json:"type"`     // Always "resource"
	Resource ResourceContent `json:"resource"` // The resource data
}

EmbeddedResource represents a resource embedded in a message

type FileContent

type FileContent struct {
	URI      string `json:"uri"`      // URI identifying the file
	MimeType string `json:"mimeType"` // MIME type of the file
	Text     string `json:"text"`     // File content as text
}

FileContent represents file content

type ImageContent

type ImageContent struct {
	Data     string `json:"data"`     // Base64-encoded image data
	MimeType string `json:"mimeType"` // MIME type (e.g., "image/png")
}

ImageContent represents image data in a message

type InputSchema

type InputSchema struct {
	Type       string         `json:"type"`
	Properties map[string]any `json:"properties"`         // Property definitions
	Required   []string       `json:"required,omitempty"` // List of required properties
}

InputSchema represents tool's input schema in JSON Schema format

type ListToolsResult

type ListToolsResult struct {
	PaginatedResult
	Tools []Tool `json:"tools"` // List of available tools
}

ListToolsResult represents the response to a tools/list request

type McpConf

type McpConf struct {
	rest.RestConf
	Mcp struct {
		// Name is the server name reported in initialize responses
		Name string `json:",optional"`

		// Version is the server version reported in initialize responses
		Version string `json:",default=1.0.0"`

		// ProtocolVersion is the MCP protocol version implemented
		ProtocolVersion string `json:",default=2024-11-05"`

		// BaseUrl is the base URL for the server, used in SSE endpoint messages
		// If not set, defaults to http://localhost:{Port}
		BaseUrl string `json:",optional"`

		// SseEndpoint is the path for Server-Sent Events connections
		SseEndpoint string `json:",default=/sse"`

		// MessageEndpoint is the path for JSON-RPC requests
		MessageEndpoint string `json:",default=/message"`

		// Cors contains allowed CORS origins
		Cors []string `json:",optional"`

		// SseTimeout is the maximum time allowed for SSE connections
		SseTimeout time.Duration `json:",default=24h"`

		// MessageTimeout is the maximum time allowed for request execution
		MessageTimeout time.Duration `json:",default=30s"`
	}
}

McpConf defines the configuration for an MCP server. It embeds rest.RestConf for HTTP server settings and adds MCP-specific configuration options.

type McpServer

type McpServer interface {
	Start()
	Stop()
	RegisterTool(tool Tool) error
	RegisterPrompt(prompt Prompt)
	RegisterResource(resource Resource)
}

McpServer defines the interface for Model Context Protocol servers

func NewMcpServer

func NewMcpServer(c McpConf) McpServer

type PaginatedParams

type PaginatedParams struct {
	Cursor string `json:"cursor"`
	Meta   struct {
		ProgressToken any `json:"progressToken"`
	} `json:"_meta"`
}

type PaginatedResult

type PaginatedResult struct {
	Result
	NextCursor Cursor `json:"nextCursor,omitempty"` // Opaque token for fetching next page
}

PaginatedResult is a base for results that support pagination

type Prompt

type Prompt struct {
	Name        string           `json:"name"`                  // Unique identifier for the prompt
	Description string           `json:"description,omitempty"` // Human-readable description
	Arguments   []PromptArgument `json:"arguments,omitempty"`   // Arguments for customization
	Content     string           `json:"-"`                     // Static content (internal use only)
	Handler     PromptHandler    `json:"-"`                     // Handler for dynamic content generation
}

Prompt represents an MCP Prompt definition

type PromptArgument

type PromptArgument struct {
	Name        string `json:"name"`                  // Argument name
	Description string `json:"description,omitempty"` // Human-readable description
	Required    bool   `json:"required,omitempty"`    // Whether this argument is required
}

PromptArgument defines a single argument that can be passed to a prompt

type PromptHandler

type PromptHandler func(ctx context.Context, args map[string]string) ([]PromptMessage, error)

PromptHandler is a function that dynamically generates prompt content

type PromptMessage

type PromptMessage struct {
	Role    RoleType `json:"role"`    // Message sender role
	Content any      `json:"content"` // Message content (TextContent, ImageContent, etc.)
}

PromptMessage represents a message in a conversation

type Request

type Request struct {
	SessionId string          `form:"session_id"` // Session identifier for client tracking
	JsonRpc   string          `json:"jsonrpc"`    // Must be "2.0" per JSON-RPC spec
	ID        any             `json:"id"`         // Request identifier for matching responses
	Method    string          `json:"method"`     // Method name to invoke
	Params    json.RawMessage `json:"params"`     // Parameters for the method
}

Request represents a generic MCP request following JSON-RPC 2.0 specification

type Resource

type Resource struct {
	URI         string          `json:"uri"`                   // Unique resource identifier (RFC3986)
	Name        string          `json:"name"`                  // Human-readable name
	Description string          `json:"description,omitempty"` // Optional description
	MimeType    string          `json:"mimeType,omitempty"`    // Optional MIME type
	Handler     ResourceHandler `json:"-"`                     // Internal handler not sent to clients
}

Resource represents a Model Context Protocol Resource definition

type ResourceContent

type ResourceContent struct {
	URI      string `json:"uri"`                // Resource URI (required)
	MimeType string `json:"mimeType,omitempty"` // MIME type of the resource
	Text     string `json:"text,omitempty"`     // Text content (if available)
	Blob     string `json:"blob,omitempty"`     // Base64 encoded blob data (if available)
}

ResourceContent represents the content of a resource

type ResourceHandler

type ResourceHandler func(ctx context.Context) (ResourceContent, error)

ResourceHandler is a function that handles resource read requests

type ResourceReadParams

type ResourceReadParams struct {
	URI string `json:"uri"` // URI of the resource to read
}

ResourceReadParams contains parameters for a resources/read request

type ResourceReadResult

type ResourceReadResult struct {
	Result
	Contents []ResourceContent `json:"contents"` // Array of resource content
}

ResourceReadResult contains the result of a resources/read request

type ResourceSubscribeParams

type ResourceSubscribeParams struct {
	URI string `json:"uri"` // URI of the resource to subscribe to
}

ResourceSubscribeParams contains parameters for a resources/subscribe request

type ResourceUpdateNotification

type ResourceUpdateNotification struct {
	URI     string          `json:"uri"`     // URI of the updated resource
	Content ResourceContent `json:"content"` // New resource content
}

ResourceUpdateNotification represents a notification about a resource update

type ResourcesListResult

type ResourcesListResult struct {
	PaginatedResult
	Resources []Resource `json:"resources"` // List of available resources
}

ResourcesListResult represents the response to a resources/list request

type Response

type Response struct {
	JsonRpc string    `json:"jsonrpc"`         // Always "2.0"
	ID      any       `json:"id"`              // Same as request ID
	Result  any       `json:"result"`          // Result object (null if error)
	Error   *errorObj `json:"error,omitempty"` // Error object (null if success)
}

Response represents a JSON-RPC response

type Result

type Result struct {
	Meta map[string]any `json:"_meta,omitempty"` // Optional metadata
}

Result is the base interface for all results

type RoleType

type RoleType string

RoleType represents the sender or recipient of messages in a conversation

const (
	// RoleUser is the "user" role - the entity asking questions
	RoleUser RoleType = "user"

	// RoleAssistant is the "assistant" role - the entity providing responses
	RoleAssistant RoleType = "assistant"
)

User and assistant role definitions

type TextContent

type TextContent struct {
	Text        string       `json:"text"`                  // The text content
	Annotations *Annotations `json:"annotations,omitempty"` // Optional annotations
}

TextContent represents text content in a message

type Tool

type Tool struct {
	Name        string      `json:"name"`        // Unique identifier for the tool
	Description string      `json:"description"` // Human-readable description
	InputSchema InputSchema `json:"inputSchema"` // JSON Schema for parameters
	Handler     ToolHandler `json:"-"`           // Not sent to clients
}

Tool represents a Model Context Protocol Tool definition

type ToolCallParams

type ToolCallParams struct {
	Name       string         `json:"name"`       // Tool name
	Parameters map[string]any `json:"parameters"` // Tool parameters
}

ToolCallParams contains the parameters for a tool call

type ToolHandler

type ToolHandler func(ctx context.Context, params map[string]any) (any, error)

ToolHandler is a function that handles tool calls

type ToolResult

type ToolResult struct {
	Type    string `json:"type"`    // Content type (text, image, etc.)
	Content any    `json:"content"` // Result content
}

ToolResult contains the result of a tool execution

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL