unanet-api-mcp
MCP server powered by Cloudflare Workers
Quick Start
Prerequisites
- Node.js 18+ (LTS recommended)
- npm 9+
Development
# Start development server
npm run devServer runs at http://localhost:8788/sse
Health Check
curl http://localhost:8788/healthExpected: {"status":"ok","service":"unanet-api-mcp","version":"1.0.0"}
Development Scripts
Quick Commands (for AI Agents)
# Scaffold a new tool
npm run tools:add my_tool -- --description "Tool description"
# Add authentication
mcp-server-kit add-auth
# stytch, auth0, or workos
# List all tools
npm run tools:list
# Validate project
npm run validate
# Run quality checks (type-check + lint + unit tests)
npm run check
# Pre-commit checks (format + check + validate)
npm run precommitTesting
# Run all tests
npm run test:all
# Run unit tests only
npm run test:unit
# Run integration tests (requires dev server running)
npm run test:integration
# Generate coverage report
npm run test:coverage
# Watch mode (re-run on changes)
npm run test:watchDeployment
# Deploy to Cloudflare Workers
npm run deployTools
This MCP server provides the following tools:
health- Returns server health statusecho- Echoes back the provided message (useful for testing)
Project Structure
unanet-api-mcp/
├── src/
│ ├── index.ts # MCP server entry point
│ └── tools/ # Tool implementations
│ ├── health.ts
│ └── echo.ts
├── test/
│ ├── unit/ # Unit tests
│ └── integration/ # Integration tests
│ ├── adapters/ # MCP client adapters
│ ├── specs/ # Test specifications (YAML)
│ └── cli.ts # Integration test CLI
├── wrangler.jsonc # Cloudflare Workers config
├── tsconfig.json # TypeScript configuration
└── package.json # Dependencies and scriptsAdding New Tools
Using mcp-server-kit CLI (Recommended for AI Agents)
# Auto-scaffold a new tool with tests
mcp-server-kit add tool weather --description "Get weather information"
# This automatically:
# - Creates src/tools/weather.ts with TODO markers
# - Generates test/unit/tools/weather.test.ts
# - Generates test/integration/specs/weather.yaml
# - Registers tool in src/index.ts
# - Updates .mcp-template.json metadataManual Process
- Create a new file in
src/tools/ - Implement the tool using the MCP SDK
- Register the tool in
src/index.ts - Add unit tests in
test/unit/ - Add integration test spec in
test/integration/specs/
Validation
# Check project structure and configuration
mcp-server-kit validate
# This checks:
# - All tools are registered in index.ts
# - Test files exist for all tools
# - Integration test YAMLs are valid
# - Metadata is in syncFor AI Agents 🤖
This project is optimized for AI agent development. Use the patterns and utilities below to build tools efficiently.
Quick Reference
Example Tools (in src/tools/):
_example-simple.ts- Basic tool pattern_example-validated.ts- Complex Zod validation_example-async.ts- Async operations & error handling
Optional Utilities (in src/utils/):
mcp-helpers.ts- Response formatting helpersvalidation.ts- Reusable Zod schemas
Test Utilities (in test/utils/):
test-utils.ts- Testing helpers for Vitest
Tool Development Workflow
- Scaffold (automates the forgettable):
mcp-server-kit add tool my_tool --description "Tool description"- Implement (focus on logic):
- Define Zod schema for parameters - Implement tool handler - Use utilities if helpful (optional)
- Test (validate correctness):
npm run test:unit # Fast unit tests
npm run test:integration # End-to-end tests- Validate (catch issues):
mcp-server-kit validateCommon Patterns
Simple Tool (No Validation)
export function registerMyTool(server: McpServer): void {
server.tool("my_tool", "Description", {}, async () => {
return {
content: [{ type: "text", text: "result" }],
};
});
}Tool with Parameters
const MyParamsSchema = z.object({
input: z.string().describe("Input parameter"),
limit: z.number().int().positive().default(10).describe("Max results"),
});
export function registerMyTool(server: McpServer): void {
server.tool("my_tool", "Description", MyParamsSchema.shape, async ({ input, limit }) => {
// Implementation
return {
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
};
});
}Error Handling
async (params) => {
try {
const result = await someAsyncOperation(params);
return {
content: [{ type: "text", text: JSON.stringify(result) }],
};
} catch (error) {
// Return error, don't throw
return {
content: [{ type: "text", text: JSON.stringify({ error: true, message: ... }) }],
isError: true,
};
}
}Testing Patterns
import { describe, it, expect } from "vitest";
import { createMockServer, expectToolSuccess, parseToolResponse } from "../../utils/test-utils.js";
import { registerMyTool } from "../../../src/tools/my-tool.js";
describe("My Tool", () => {
it("should handle valid input", async () => {
const server = createMockServer();
registerMyTool(server);
const response = await expectToolSuccess(server, "my_tool", { input: "test" });
const data = parseToolResponse(response);
expect(data).toEqual({ result: "test" });
});
});Validation Helpers
Use reusable schemas from src/utils/validation.ts:
import { urlSchema, paginationParams, dateRangeParams } from "../utils/validation.js";
const MyParamsSchema = z.object({
url: urlSchema.describe("API endpoint"),
...paginationParams(50, 10),
...dateRangeParams(),
});Response Helpers
Optional helpers from src/utils/mcp-helpers.ts:
import { createToolResponse, createErrorResponse } from "../utils/mcp-helpers.js";
// Simple response
return createToolResponse({ status: "ok" });
// Error response
return createErrorResponse(error, "Operation failed");Best Practices for Agents
✅ DO:
- Use
mcp-server-kit add toolfor scaffolding - Implement tool logic (the creative part)
- Write unit tests using test utilities
- Run
mcp-server-kit validatebefore committing - Check
_example-*.tsfiles when stuck
❌ DON'T:
- Manually create/register tool files (use CLI)
- Forget error handling in async operations
- Throw errors in tool handlers (return error responses)
- Skip validation of user inputs (use Zod)
- Forget to update tests when changing tools
Documentation
License
MIT
