Development Guide
January 29, 2026 · View on GitHub
This guide covers setting up a development environment for Universal Crypto MCP.
Prerequisites
- Node.js 18+ (LTS recommended)
- pnpm 8+ (package manager)
- Git 2.30+
- VS Code (recommended editor)
Setup
1. Clone the Repository
git clone https://github.com/nirholas/universal-crypto-mcp.git
cd universal-crypto-mcp
2. Install Dependencies
pnpm install
3. Build All Packages
pnpm build
4. Run Tests
pnpm test
Project Structure
universal-crypto-mcp/
├── packages/ # Monorepo packages
│ ├── core/ # Shared types and utilities
│ ├── trading/ # Exchange integrations
│ ├── market-data/ # Price and analytics
│ ├── wallets/ # Wallet management
│ ├── defi/ # DeFi protocols
│ └── payments/ # Payment infrastructure
├── x402-deploy/ # x402 deployment toolkit
├── src/ # Main MCP server source
├── docs/ # Documentation
├── examples/ # Example projects
└── tests/ # Test infrastructure
Development Workflow
Running in Development Mode
# Run the main server in dev mode
pnpm dev
# Run a specific package in dev mode
pnpm --filter @universal-crypto-mcp/trading-binance dev
Building
# Build all packages
pnpm build
# Build a specific package
pnpm --filter @universal-crypto-mcp/core build
# Build with watch mode
pnpm build:watch
Testing
# Run all tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Run tests with coverage
pnpm test:coverage
# Run e2e tests
pnpm test:e2e
# Run tests for a specific package
pnpm --filter @universal-crypto-mcp/core test
Linting and Formatting
# Check linting
pnpm lint
# Fix linting issues
pnpm lint:fix
# Check formatting
pnpm format:check
# Fix formatting
pnpm format
Creating a New Package
1. Create Package Directory
mkdir -p packages/my-package/src
2. Create package.json
{
"name": "@universal-crypto-mcp/my-package",
"version": "1.0.0",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"test": "vitest"
},
"dependencies": {
"@universal-crypto-mcp/core": "workspace:*"
}
}
3. Create tsup.config.ts
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
format: ["cjs", "esm"],
dts: true,
clean: true,
});
4. Create Source Files
// src/index.ts
export * from "./tools";
export * from "./types";
Adding New Tools
1. Create Tool File
// src/tools/my-tool.ts
import { BaseTool, ToolResult } from "@universal-crypto-mcp/core";
export class MyTool extends BaseTool {
name = "my_tool";
description = "Does something useful";
inputSchema = {
type: "object",
properties: {
param1: { type: "string", description: "First parameter" },
},
required: ["param1"],
};
async execute(params: { param1: string }): Promise<ToolResult> {
// Implementation
return {
success: true,
data: { result: "..." },
};
}
}
2. Register Tool
// src/register.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { MyTool } from "./tools/my-tool";
export function registerMyTools(server: McpServer) {
const myTool = new MyTool();
server.registerTool(myTool.name, myTool.inputSchema, myTool.execute);
}
3. Add Tests
// src/tools/my-tool.test.ts
import { describe, it, expect } from "vitest";
import { MyTool } from "./my-tool";
describe("MyTool", () => {
it("should return expected result", async () => {
const tool = new MyTool();
const result = await tool.execute({ param1: "test" });
expect(result.success).toBe(true);
});
});
Environment Variables
Create a .env file for local development:
# API Keys (for testing)
COINGECKO_API_KEY=your-key
BINANCE_API_KEY=your-key
BINANCE_API_SECRET=your-secret
# Wallet (for testing - use testnet!)
PRIVATE_KEY=0x...
# x402 (for testing)
X402_PRIVATE_KEY=0x...
X402_CHAIN=arbitrum
# Logging
LOG_LEVEL=DEBUG
Debugging
VS Code Launch Configuration
Create .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug MCP Server",
"program": "${workspaceFolder}/src/index.ts",
"runtimeArgs": ["-r", "tsx/cjs"],
"console": "integratedTerminal"
},
{
"type": "node",
"request": "launch",
"name": "Debug Tests",
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
"args": ["run", "--reporter=verbose"],
"console": "integratedTerminal"
}
]
}
Console Logging
import { createLogger } from "@universal-crypto-mcp/core";
const logger = createLogger("my-module");
logger.debug("Debug info", { data: someData });
logger.info("Operation complete");
logger.error("Error occurred", { error });
Code Style
TypeScript Guidelines
- Use strict TypeScript settings
- Prefer interfaces over types for objects
- Use explicit return types for public functions
- Document public APIs with JSDoc
Naming Conventions
- Files:
kebab-case.ts - Classes:
PascalCase - Functions/methods:
camelCase - Constants:
UPPER_SNAKE_CASE - Tool names:
snake_case
Example
/**
* Gets the current price of a cryptocurrency.
* @param symbol - The token symbol (e.g., "BTC", "ETH")
* @returns The current price data
*/
export async function getPrice(symbol: string): Promise<PriceData> {
// Implementation
}
Next Steps
- Testing Guide - Writing and running tests
- Release Process - How to release new versions