Documentation
¶
Overview ¶
Package helpers provides test utilities for vMCP integration tests.
Index ¶
- func AssertTextContains(tb testing.TB, text string, expected ...string)
- func AssertTextNotContains(tb testing.TB, text string, forbidden ...string)
- func AssertToolCallSuccess(tb testing.TB, result *mcp.CallToolResult) string
- func CreateBackendServer(tb testing.TB, tools []BackendTool, opts ...BackendServerOption) *httptest.Server
- func GetHTTPHeadersFromContext(ctx context.Context) http.Header
- func GetToolNames(result *mcp.ListToolsResult) []string
- func NewBackend(id string, opts ...func(*vmcptypes.Backend)) vmcptypes.Backend
- func NewVMCPServer(ctx context.Context, tb testing.TB, backends []vmcptypes.Backend, ...) *vmcpserver.Server
- func WithAuth(strategy string, metadata map[string]any) func(*vmcptypes.Backend)
- func WithMetadata(key, value string) func(*vmcptypes.Backend)
- func WithURL(url string) func(*vmcptypes.Backend)
- type BackendServerOption
- type BackendTool
- type MCPClient
- type MCPClientOption
- type VMCPServerOption
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AssertTextContains ¶
AssertTextContains asserts that text contains all expected substrings. This is a variadic helper for checking multiple content expectations in tool results.
The function uses assert (not require), so multiple failures can be reported together.
Example:
text := helpers.AssertToolCallSuccess(t, result) helpers.AssertTextContains(t, text, "user_id", "username", "email")
func AssertTextNotContains ¶
AssertTextNotContains asserts that text does not contain any of the forbidden substrings. This is a variadic helper for checking that certain content is absent from tool results.
The function uses assert (not require), so multiple failures can be reported together.
Example:
text := helpers.AssertToolCallSuccess(t, result) helpers.AssertTextNotContains(t, text, "password", "secret", "api_key")
func AssertToolCallSuccess ¶
func AssertToolCallSuccess(tb testing.TB, result *mcp.CallToolResult) string
AssertToolCallSuccess asserts that a tool call succeeded (IsError=false) and returns the concatenated text content from all content items.
The function uses require assertions, so it will fail the test immediately if the tool call was an error.
Example:
result := client.CallTool(ctx, "get_user", map[string]any{"id": 123})
text := helpers.AssertToolCallSuccess(t, result)
assert.Contains(t, text, "username")
func CreateBackendServer ¶
func CreateBackendServer(tb testing.TB, tools []BackendTool, opts ...BackendServerOption) *httptest.Server
CreateBackendServer creates an MCP backend server using the mark3labs/mcp-go SDK. It returns an *httptest.Server ready to accept streamable-HTTP connections.
The server automatically registers all provided tools with proper closure handling to avoid common Go loop variable capture bugs. Each tool's handler is invoked when the tool is called via the MCP protocol.
The server uses the streamable-HTTP transport, which is compatible with ToolHive's vMCP server and supports both streaming and non-streaming requests.
The returned httptest.Server should be closed after use with defer server.Close().
Example:
// Create a simple echo tool
echoTool := testkit.NewBackendTool(
"echo",
"Echo back the input message",
func(ctx context.Context, args map[string]any) string {
msg := args["message"].(string)
return fmt.Sprintf(`{"echoed": %q}`, msg)
},
)
// Start backend server
backend := testkit.CreateBackendServer(t, []BackendTool{echoTool},
testkit.WithBackendName("echo-server"),
testkit.WithBackendEndpoint("/mcp"),
)
defer backend.Close()
// Use backend URL to connect MCP client
client := testkit.NewMCPClient(ctx, t, backend.URL+"/mcp")
defer client.Close()
func GetHTTPHeadersFromContext ¶
GetHTTPHeadersFromContext retrieves HTTP headers from the context. Returns nil if headers are not present in the context.
func GetToolNames ¶
func GetToolNames(result *mcp.ListToolsResult) []string
GetToolNames extracts tool names from a ListToolsResult. This is a convenience function for common test assertions.
Example:
tools := client.ListTools(ctx)
names := helpers.GetToolNames(tools)
assert.ElementsMatch(t, []string{"tool1", "tool2"}, names)
func NewBackend ¶
NewBackend creates a test backend with sensible defaults. Use functional options to customize.
func NewVMCPServer ¶
func NewVMCPServer( ctx context.Context, tb testing.TB, backends []vmcptypes.Backend, opts ...VMCPServerOption, ) *vmcpserver.Server
NewVMCPServer creates a vMCP server for testing with sensible defaults. The server is automatically started and will be ready when this function returns. Use functional options to customize behavior.
Example:
server := testkit.NewVMCPServer(ctx, t, backends,
testkit.WithPrefixConflictResolution("{workload}_"),
)
defer server.Shutdown(ctx)
func WithMetadata ¶
WithMetadata adds a metadata key-value pair.
Types ¶
type BackendServerOption ¶
type BackendServerOption func(*backendServerConfig)
BackendServerOption is a functional option for configuring a backend server.
func WithBackendName ¶
func WithBackendName(name string) BackendServerOption
WithBackendName sets the backend server name. This name is reported in the server's initialize response.
Default: "test-backend"
func WithCaptureHeaders ¶
func WithCaptureHeaders() BackendServerOption
WithCaptureHeaders enables capturing HTTP request headers in the context. When enabled, tool handlers can access request headers via GetHTTPHeadersFromContext(ctx). This is useful for testing authentication header injection.
Default: false
type BackendTool ¶
type BackendTool struct {
// Name is the unique identifier for the tool
Name string
// Description explains what the tool does
Description string
// InputSchema defines the expected input structure using JSON Schema.
// The schema validates the arguments passed to the tool.
InputSchema mcp.ToolInputSchema
// Handler processes tool calls and returns results.
// The handler receives the tool arguments as a map and should return
// a string representation of the result (typically JSON).
Handler func(ctx context.Context, args map[string]any) string
}
BackendTool defines a tool for MCP backend servers. It provides a simplified interface for creating tools with handlers in tests.
The handler function receives a context and arguments map, and returns a string result. The result should typically be valid JSON matching the tool's output schema.
func NewBackendTool ¶
func NewBackendTool(name, description string, handler func(ctx context.Context, args map[string]any) string) BackendTool
NewBackendTool creates a new BackendTool with sensible defaults. The default InputSchema is an empty object schema that accepts any properties.
Example:
tool := testkit.NewBackendTool(
"create_issue",
"Create a GitHub issue",
func(ctx context.Context, args map[string]any) string {
title := args["title"].(string)
return fmt.Sprintf(`{"issue_id": 123, "title": %q}`, title)
},
)
type MCPClient ¶
type MCPClient struct {
// contains filtered or unexported fields
}
MCPClient wraps the mark3labs MCP client with test-friendly methods. It automatically handles initialization and provides semantic assertion helpers that integrate with Go's testing.TB interface.
Example usage:
ctx := context.Background() mcpClient := helpers.NewMCPClient(ctx, t, serverURL) defer mcpClient.Close() tools := mcpClient.ListTools(ctx) toolNames := helpers.GetToolNames(tools) assert.Contains(t, toolNames, "create_issue")
func NewMCPClient ¶
func NewMCPClient(ctx context.Context, tb testing.TB, serverURL string, opts ...MCPClientOption) *MCPClient
NewMCPClient creates and initializes a new MCP client for testing. It automatically starts the transport and performs the MCP handshake.
The client is configured with sensible defaults suitable for testing:
- Protocol version: Latest (mcp.LATEST_PROTOCOL_VERSION)
- Client name: "testkit-client"
- Client version: "1.0.0"
- Transport: streamable-http (vMCP only supports streamable-http)
The function fails the test immediately if initialization fails.
Example:
client := helpers.NewMCPClient(ctx, t, "http://localhost:8080/mcp") defer client.Close() tools := client.ListTools(ctx) assert.NotEmpty(t, helpers.GetToolNames(tools))
func (*MCPClient) CallTool ¶
func (c *MCPClient) CallTool(ctx context.Context, name string, args map[string]any) *mcp.CallToolResult
CallTool calls the specified tool with the given arguments. The method logs the operation and fails the test if the request fails.
Example:
result := client.CallTool(ctx, "create_issue", map[string]any{
"title": "Bug report",
"body": "Description",
})
text := helpers.AssertToolCallSuccess(t, result)
assert.Contains(t, text, "issue_id")
func (*MCPClient) Close ¶
Close closes the MCP client connection. This should typically be deferred immediately after client creation.
func (*MCPClient) ListTools ¶
func (c *MCPClient) ListTools(ctx context.Context) *mcp.ListToolsResult
ListTools lists all available tools from the MCP server. The method logs the operation and fails the test if the request fails.
Example:
tools := client.ListTools(ctx) toolNames := helpers.GetToolNames(tools) assert.Contains(t, toolNames, "expected_tool")
type MCPClientOption ¶
type MCPClientOption func(*mcpClientConfig)
MCPClientOption is a functional option for configuring an MCPClient.
type VMCPServerOption ¶
type VMCPServerOption func(*vmcpServerConfig)
VMCPServerOption is a functional option for configuring a vMCP test server.
func WithPrefixConflictResolution ¶
func WithPrefixConflictResolution(format string) VMCPServerOption
WithPrefixConflictResolution configures prefix-based conflict resolution.