romcputils
v0.2.3
Published
Utilities for working with the Model Context Protocol in TypeScript
Maintainers
Readme
ROMCPUtils
A utility package for working with the Model Context Protocol (MCP) in TypeScript/JavaScript applications. This library provides builder patterns for creating MCP tools and resources, along with SDK-compatible transports and a comprehensive testing harness.
Installation
npm install romcputilsFeatures
- Tool Adder System: A builder pattern for defining MCP tools with a fluent, chainable API
- Resource Adder System: A builder pattern for defining MCP resources
- Testing Harness: A comprehensive testing framework for MCP components with:
- SDK-Compatible Transport: Direct implementation of the MCP SDK Transport interface for in-process communication
- Schema Validation: Automatic validation of tool parameters using Zod schemas
- Configuration Validation: Comprehensive validation of test harness configuration
- Runtime Context Injection: Override context values at tool invocation time
- Debug Hooks: Customizable hooks for monitoring tool execution
- Error Recovery: Built-in retry mechanisms and timeout handling
Quick Start Examples
Creating an MCP Tool
import { createTool } from 'romcputils';
import { z } from 'zod';
// Create a tool using the builder pattern
const myTool = createTool('echo')
.withDescription('Echo back the input text')
.withParam('text', z.string(), 'Text to echo')
.withHandler(async ({ text }) => ({
content: [{ type: 'text', text: `Echo: ${text}` }]
}));
// Register with MCP server
myTool.build()((name, schema, handler) => {
mcpServer.tool(name, schema, handler);
});Testing an MCP Tool
import { createTool, Testing } from 'romcputils';
import { z } from 'zod';
// Testing components are in the Testing namespace to avoid naming conflicts
const {
createMcpTestHarness,
createTestHarnessConfig,
LogLevel,
ContextInjectionStrategy
} = Testing;
// Create test harness with configuration
const config = createTestHarnessConfig('test-server', '1.0.0')
.withLogLevel(LogLevel.INFO)
.withDefaultContext({ user: 'test-user' })
.withContextInjectionStrategy(ContextInjectionStrategy.MERGE)
.withValidateToolInputs(true) // Enable schema validation
.build();
const harness = await createMcpTestHarness(config);
// Register the tool BEFORE initialization
harness.registerToolBuilder(myTool);
// Initialize harness
await harness.initialize();
// Call the tool (with automatic schema validation)
const result = await harness.callTool('echo', { text: 'Hello world!' });
console.log(result.content[0].text); // Output: Echo: Hello world!
// Call with runtime context override
const contextResult = await harness.callTool(
'echo',
{ text: 'Hello' },
{ user: 'alice' } // Runtime context override
);
// Clean up
await harness.shutdown();New Features
Schema Validation
Tools automatically validate input parameters against their Zod schemas:
import { createTool } from 'romcputils';
import { z } from 'zod';
const tool = createTool('email-sender')
.withParam('email', z.string().email(), 'Email address')
.withParam('subject', z.string().min(1), 'Email subject')
.withHandler(async ({ email, subject }) => ({
content: [{ type: 'text', text: `Sent to ${email}: ${subject}` }]
}));
// This will throw a validation error
await harness.callTool('email-sender', {
email: 'invalid-email',
subject: ''
});
// Error: Tool input validation failed for "email-sender":
// - email: Invalid email
// - subject: String must contain at least 1 character(s)Configuration Validation
Test harness configuration is validated to catch errors early:
import { Testing } from 'romcputils';
const { createTestHarnessConfig } = Testing;
// This will throw a validation error
const config = createTestHarnessConfig('', 'invalid-version')
.withOperationTimeout(-1000)
.build();
// Error: Configuration validation failed:
// - name: Server name must not be empty
// - version: Version must be in semver format
// - operationTimeout: Number must be greater than 0Runtime Context Injection
Override context values when calling tools:
import { createTool } from 'romcputils';
import { z } from 'zod';
const tool = createTool('greeter')
.withParam('message', z.string())
.withHandler(async ({ message }, context) => ({
content: [{
type: 'text',
text: `${context?.user}: ${message}`
}]
}));
// Default context from configuration
const result1 = await harness.callTool('greeter', { message: 'Hello' });
// Output: "test-user: Hello"
// Runtime context override
const result2 = await harness.callTool(
'greeter',
{ message: 'Hello' },
{ user: 'alice' }
);
// Output: "alice: Hello"Documentation
For comprehensive documentation of all features and APIs, please see API_DOCUMENTATION.md.
License
MIT
