mcptest

package
v0.1.4 Latest Latest
Warning

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

Go to latest
Published: Feb 12, 2026 License: MIT Imports: 8 Imported by: 0

README

MCP Gateway Test Harness

This document describes the test harness infrastructure for validating the MCP gateway integration.

Overview

The test harness provides three main components:

  1. Configurable MCP Test Server - A test server that can be configured with custom tools and resources
  2. Test Driver - Manages multiple test servers and provides transport creation
  3. Validator Client - A client that can explore and assert about MCP server capabilities

Components

1. Configurable MCP Test Server

Located in internal/testutil/mcptest/server.go and config.go.

Features:

  • Configure server name and version
  • Add custom tools with handlers
  • Add resources with content
  • Support for stdio transport via in-memory connections

Example Usage:

// Create a test server with tools
config := mcptest.DefaultServerConfig().
    WithTool(mcptest.SimpleEchoTool("echo")).
    WithResource(mcptest.ResourceConfig{
        URI:         "test://doc1",
        Name:        "Document 1",
        Description: "A test document",
        MimeType:    "text/plain",
        Content:     "Test content",
    })

server := mcptest.NewServer(config)
server.Start()
defer server.Stop()
2. Test Driver

Located in internal/testutil/mcptest/driver.go.

Features:

  • Spawn multiple test servers
  • Create in-memory transports for testing
  • Manage lifecycle (start/stop) of test infrastructure

Example Usage:

driver := mcptest.NewTestDriver()
defer driver.Stop()

// Add test servers
driver.AddTestServer("backend1", config1)
driver.AddTestServer("backend2", config2)

// Create transport to connect to a test server
transport, err := driver.CreateStdioTransport("backend1")
3. Validator Client

Located in internal/testutil/mcptest/validator.go.

Features:

  • Connect to any MCP server via a transport
  • List available tools and resources
  • Call tools with arguments
  • Read resources
  • Validate server information

Example Usage:

validator, err := mcptest.NewValidatorClient(ctx, transport)
defer validator.Close()

// List and validate tools
tools, err := validator.ListTools()
assert.Equal(t, 2, len(tools))

// Call a tool
result, err := validator.CallTool("test_tool", map[string]interface{}{
    "input": "test",
})

Test Examples

Basic Server Test

Test a simple MCP server with one tool:

func TestBasicServerWithOneTool(t *testing.T) {
    config := mcptest.DefaultServerConfig().
        WithTool(mcptest.SimpleEchoTool("test_echo"))
    
    driver := mcptest.NewTestDriver()
    defer driver.Stop()
    
    driver.AddTestServer("test", config)
    transport, _ := driver.CreateStdioTransport("test")
    
    validator, _ := mcptest.NewValidatorClient(ctx, transport)
    defer validator.Close()
    
    tools, _ := validator.ListTools()
    assert.Equal(t, 1, len(tools))
}
Gateway Integration Test

Test the AWMG gateway with multiple backends:

func TestGatewayRoutedMode(t *testing.T) {
    // Create gateway config
    gatewayCfg := &config.Config{
        Servers: map[string]*config.ServerConfig{
            "backend1": {Command: "echo", Args: []string{}},
            "backend2": {Command: "echo", Args: []string{}},
        },
    }
    
    us, _ := server.NewUnified(ctx, gatewayCfg)
    defer us.Close()
    
    // Inject test tools
    us.RegisterTestTool("backend1___tool1", &server.ToolInfo{...})
    us.RegisterTestTool("backend2___tool2", &server.ToolInfo{...})
    
    // Create HTTP server in routed mode
    httpServer := server.CreateHTTPServerForRoutedMode("127.0.0.1:0", us)
    ts := httptest.NewServer(httpServer.Handler)
    defer ts.Close()
    
    // Verify backend isolation
    assert.Equal(t, 1, len(us.GetToolsForBackend("backend1")))
    assert.Equal(t, 1, len(us.GetToolsForBackend("backend2")))
}

Custom Tools

You can create custom tools for testing specific scenarios:

customTool := mcptest.ToolConfig{
    Name:        "calculator",
    Description: "Adds two numbers",
    InputSchema: map[string]interface{}{
        "type": "object",
        "properties": map[string]interface{}{
            "a": map[string]interface{}{"type": "number"},
            "b": map[string]interface{}{"type": "number"},
        },
    },
    Handler: func(args map[string]interface{}) ([]sdk.Content, error) {
        a := args["a"].(float64)
        b := args["b"].(float64)
        return []sdk.Content{
            &sdk.TextContent{Text: fmt.Sprintf("%g", a+b)},
        }, nil
    },
}

Running Tests

Run all test harness tests:

go test -v ./internal/testutil/mcptest/...

Run specific test categories:

# Basic harness tests
go test -v ./internal/testutil/mcptest/... -run TestBasic

# Gateway integration tests
go test -v ./internal/testutil/mcptest/... -run TestGateway

Architecture

┌─────────────────────────────────────────────────────┐
│                 Validator Client                     │
│  (Lists tools, calls tools, reads resources)        │
└──────────────────┬──────────────────────────────────┘
                   │ Transport (in-memory)
┌──────────────────┴──────────────────────────────────┐
│              MCP Test Server                         │
│  - Configured tools                                  │
│  - Configured resources                              │
│  - Custom handlers                                   │
└─────────────────────────────────────────────────────┘

Or for gateway testing:

┌─────────────────────────────────────────────────────┐
│                 HTTP Client                          │
│                                                      │
└──────────────────┬──────────────────────────────────┘
                   │ HTTP
┌──────────────────┴──────────────────────────────────┐
│              AWMG Gateway (Routed)                   │
│  /mcp/backend1 ──> Test Backend 1                   │
│  /mcp/backend2 ──> Test Backend 2                   │
└─────────────────────────────────────────────────────┘

Benefits

  1. Isolated Testing - Test gateway functionality without external dependencies
  2. Fast Execution - In-memory transports provide millisecond test execution
  3. Flexible Configuration - Easy to create complex test scenarios
  4. Comprehensive Validation - Validator client checks all MCP capabilities
  5. Gateway Integration - Test routed and unified modes with multiple backends

Future Enhancements

  • Support for HTTP transport testing (SSE)
  • Built-in assertions for common test patterns
  • Mock resource templates
  • Mock prompts support
  • Performance testing utilities
  • Concurrent client testing

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CreateCommandTransport

func CreateCommandTransport(ctx context.Context, command string, args ...string) sdk.Transport

CreateCommandTransport creates a command-based transport that runs a command This is useful for testing with actual executables

Types

type ResourceConfig

type ResourceConfig struct {
	// URI of the resource
	URI string
	// Name of the resource
	Name string
	// Description of the resource
	Description string
	// MimeType of the resource content
	MimeType string
	// Content is the actual resource data
	Content string
}

ResourceConfig defines a resource for the test server

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is a configurable MCP test server

func NewServer

func NewServer(config *ServerConfig) *Server

NewServer creates a new configurable MCP test server

func (*Server) GetServer

func (s *Server) GetServer() *sdk.Server

GetServer returns the underlying SDK server for transport attachment

func (*Server) Start

func (s *Server) Start() error

Start initializes and starts the MCP server with configured tools and resources

func (*Server) Stop

func (s *Server) Stop()

Stop stops the server

type ServerConfig

type ServerConfig struct {
	// Name is the name of the test server
	Name string
	// Version is the version of the test server
	Version string
	// Tools is the list of tools to expose
	Tools []ToolConfig
	// Resources is the list of resources to expose
	Resources []ResourceConfig
}

ServerConfig defines the configuration for a test MCP server

func DefaultServerConfig

func DefaultServerConfig() *ServerConfig

DefaultServerConfig returns a basic server configuration for testing

func (*ServerConfig) WithResource

func (c *ServerConfig) WithResource(resource ResourceConfig) *ServerConfig

WithResource adds a resource to the server configuration

func (*ServerConfig) WithTool

func (c *ServerConfig) WithTool(tool ToolConfig) *ServerConfig

WithTool adds a tool to the server configuration

type TestDriver

type TestDriver struct {
	// contains filtered or unexported fields
}

TestDriver manages test servers and the gateway for integration testing

func NewTestDriver

func NewTestDriver() *TestDriver

NewTestDriver creates a new test driver

func (*TestDriver) AddTestServer

func (td *TestDriver) AddTestServer(serverID string, config *ServerConfig) error

AddTestServer adds a test server with the given ID and configuration

func (*TestDriver) CreateStdioTransport

func (td *TestDriver) CreateStdioTransport(serverID string) (sdk.Transport, error)

CreateStdioTransport creates an in-memory stdio transport to a test server

func (*TestDriver) GetGatewayServer

func (td *TestDriver) GetGatewayServer() *server.UnifiedServer

GetGatewayServer returns the unified server for testing

func (*TestDriver) StartGateway

func (td *TestDriver) StartGateway() error

StartGateway starts the AWMG gateway on top of the test servers

func (*TestDriver) Stop

func (td *TestDriver) Stop()

Stop stops the test driver and all test servers

type ToolConfig

type ToolConfig struct {
	// Name of the tool
	Name string
	// Description of what the tool does
	Description string
	// InputSchema defines the expected input parameters
	InputSchema map[string]interface{}
	// Handler is the function that executes when the tool is called
	Handler func(arguments map[string]interface{}) ([]sdk.Content, error)
}

ToolConfig defines a tool for the test server

func SimpleEchoTool

func SimpleEchoTool(name string) ToolConfig

SimpleEchoTool creates a basic echo tool for testing

type ValidatorClient

type ValidatorClient struct {
	// contains filtered or unexported fields
}

ValidatorClient is a client for validating MCP servers

func NewValidatorClient

func NewValidatorClient(ctx context.Context, transport sdk.Transport) (*ValidatorClient, error)

NewValidatorClient creates a new validator client connected to the given transport

func (*ValidatorClient) CallTool

func (v *ValidatorClient) CallTool(name string, arguments map[string]interface{}) (*sdk.CallToolResult, error)

CallTool calls a tool on the MCP server

func (*ValidatorClient) Close

func (v *ValidatorClient) Close() error

Close closes the validator client connection

func (*ValidatorClient) GetServerInfo

func (v *ValidatorClient) GetServerInfo() *sdk.Implementation

GetServerInfo returns the server information from the initialize handshake

func (*ValidatorClient) ListResources

func (v *ValidatorClient) ListResources() ([]*sdk.Resource, error)

ListResources retrieves the list of resources from the connected MCP server

func (*ValidatorClient) ListTools

func (v *ValidatorClient) ListTools() ([]*sdk.Tool, error)

ListTools retrieves the list of tools from the connected MCP server

func (*ValidatorClient) ReadResource

func (v *ValidatorClient) ReadResource(uri string) (*sdk.ReadResourceResult, error)

ReadResource reads a resource from the MCP server

Jump to

Keyboard shortcuts

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