# Datai FastMCP TypeScript Server - Comprehensive Build Plan
## Project Overview
Building a high-performance FastMCP TypeScript server for Datai endpoints with the best 8 performing endpoints identified from testing.
**š Implementation Tracking**: Follow the detailed checklist in [`datai_fastmcp_checklist.md`](./datai_fastmcp_checklist.md) to track progress through all implementation phases.
## FastMCP TypeScript Rules Reference
This project follows the FastMCP TypeScript framework standards. The following rules are available and should be activated as needed:
- `@fastMCP_ts-cli.mdc` - CLI tools and development commands
- `@fastMCP_ts-content.mdc` - Content handling and response formatting
- `@fastMCP_ts-core.mdc` - Core FastMCP server implementation patterns
- `@fastMCP_ts-errors.mdc` - Error handling and user-friendly error messages
- `@fastMCP_ts-logging.mdc` - Comprehensive logging standards and practices
- `@fastMCP_ts-resources.mdc` - Resource management and templates
- `@fastMCP_ts-session.mdc` - Session management and client connections
- `@fastMCP_ts-testing.mdc` - Testing patterns and validation approaches
- `@fastMCP_ts-tools.mdc` - Tool implementation and parameter validation
## Best 8 Endpoints (From Test Results)
Based on our performance testing, these are the top performing endpoints:
1. **GET_ALL_USER_DEFI_POSITIONS** - `https://api-v1.mymerlin.io/api/merlin/public/userDeFiPositions/all/{wallet}`
2. **GET_USER_DEFI_POSITIONS_BY_CHAIN** - `https://api-v1.mymerlin.io/api/merlin/public/userDeFiPositions/{wallet}?chain={chain}`
3. **GET_USER_DEFI_POSITIONS_BY_MULTIPLE_CHAINS** - `https://api-v1.mymerlin.io/api/merlin/public/userDeFiPositionsByChains/{wallet}?chains={chains}`
4. **GET_USER_DEFI_POSITIONS_BY_PROTOCOL** - `https://api-v1.mymerlin.io/api/merlin/public/userDeFiPositions/{wallet}?protocol={protocol}`
5. **GET_USER_DEFI_PROTOCOL_BALANCES_BY_CHAIN** - `https://api-v1.mymerlin.io/api/merlin/public/balances/defi/{wallet}?chain={chain}`
6. **GET_USER_OVERALL_BALANCE_ALL_CHAINS** - `https://api-v1.mymerlin.io/api/merlin/public/balances/all/{wallet}`
7. **GET_USER_OVERALL_BALANCE_BY_CHAIN** - `https://api-v1.mymerlin.io/api/merlin/public/balances/overall/{wallet}?chain={chain}`
8. **GET_WALLET_BALANCES_BY_CHAIN** - `https://api-v1.mymerlin.io/api/merlin/public/balances/token/{wallet}?chain={chain}`
## Test Curl Commands (Ready to Use)
These are the exact curl commands with working parameters for testing each endpoint:
```bash
# API Key
API_KEY="dbNb54fQUGCuy2xO3RXPRw7bH9nbDSkS"
# Test Wallet Addresses (Known Working)
WALLET1="0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
WALLET2="0x09CF915e195aF33FA7B932C253352Ae9FBdB0106"
WALLET3="0xbdfa4f4492dd7b7cf211209c4791af8d52bf5c50"
# 1. GET_ALL_USER_DEFI_POSITIONS
curl -X GET -H "Authorization: $API_KEY" \
"https://api-v1.mymerlin.io/api/merlin/public/userDeFiPositions/all/$WALLET1" \
--max-time 180
# 2. GET_USER_DEFI_POSITIONS_BY_CHAIN
curl -X GET -H "Authorization: $API_KEY" \
"https://api-v1.mymerlin.io/api/merlin/public/userDeFiPositions/$WALLET2?chain=arb" \
--max-time 180
# 3. GET_USER_DEFI_POSITIONS_BY_MULTIPLE_CHAINS
curl -X GET -H "Authorization: $API_KEY" \
"https://api-v1.mymerlin.io/api/merlin/public/userDeFiPositionsByChains/$WALLET3?chains=avax,arb" \
--max-time 180
# 4. GET_USER_DEFI_POSITIONS_BY_PROTOCOL
curl -X GET -H "Authorization: $API_KEY" \
"https://api-v1.mymerlin.io/api/merlin/public/userDeFiPositions/$WALLET2?protocol=uniswap" \
--max-time 180
# 5. GET_USER_DEFI_PROTOCOL_BALANCES_BY_CHAIN
curl -X GET -H "Authorization: $API_KEY" \
"https://api-v1.mymerlin.io/api/merlin/public/balances/defi/$WALLET2?chain=arb" \
--max-time 180
# 6. GET_USER_OVERALL_BALANCE_ALL_CHAINS
curl -X GET -H "Authorization: $API_KEY" \
"https://api-v1.mymerlin.io/api/merlin/public/balances/all/$WALLET2" \
--max-time 180
# 7. GET_USER_OVERALL_BALANCE_BY_CHAIN
curl -X GET -H "Authorization: $API_KEY" \
"https://api-v1.mymerlin.io/api/merlin/public/balances/overall/$WALLET1?chain=eth" \
--max-time 180
# 8. GET_WALLET_BALANCES_BY_CHAIN
curl -X GET -H "Authorization: $API_KEY" \
"https://api-v1.mymerlin.io/api/merlin/public/balances/token/$WALLET1?chain=base" \
--max-time 180
```
## Project Structure
```
/Users/ilessio/dev-agents/PARTNERS/DATAI/datai-mcp/src/
āāā index.ts # Main server entry point
āāā config/
ā āāā constants.ts # API endpoints and configuration
ā āāā types.ts # TypeScript interfaces and types
āāā tools/
ā āāā get-all-user-defi-positions.ts # Tool 1: Get all DeFi positions
ā āāā get-user-defi-positions-by-chain.ts # Tool 2: DeFi positions by chain
ā āāā get-user-defi-positions-by-multiple-chains.ts # Tool 3: DeFi positions by multiple chains
ā āāā get-user-defi-positions-by-protocol.ts # Tool 4: DeFi positions by protocol
ā āāā get-user-defi-protocol-balances-by-chain.ts # Tool 5: DeFi protocol balances by chain
ā āāā get-user-overall-balance-all-chains.ts # Tool 6: Overall balance all chains
ā āāā get-user-overall-balance-by-chain.ts # Tool 7: Overall balance by chain
ā āāā get-wallet-balances-by-chain.ts # Tool 8: Wallet balances by chain
ā āāā index.ts # Tool exports and registration
āāā utils/
ā āāā api-client.ts # HTTP client with auth
ā āāā validation.ts # Parameter validation
ā āāā error-handler.ts # Error handling utilities
ā āāā logger.ts # FastMCP logging utilities
āāā types/
ā āāā api-responses.ts # API response interfaces
ā āāā tool-params.ts # Tool parameter interfaces
ā āāā index.ts # Type exports
āāā tests/
āāā tools/ # Individual tool tests (8 files)
āāā utils/ # Utility tests
āāā integration/ # Integration tests
```
## Step-by-Step Implementation Plan
### Phase 1: Project Setup and Foundation (30 minutes)
#### Step 1.1: Initialize Project Structure
- Create TypeScript project with FastMCP dependencies
- Set up package.json with proper scripts
- Configure tsconfig.json for optimal TypeScript settings
- Install dependencies: `fastmcp`, `zod`, `axios`, `@types/node`
#### Step 1.2: Core Configuration
- Create constants.ts with all 8 API endpoints
- Set up types.ts with base interfaces
- Configure API client with authentication headers
- Set up FastMCP logging system
### Phase 2: API Client and Utilities (45 minutes)
#### Step 2.1: HTTP Client Setup
```typescript
// utils/api-client.ts
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
import { FastMCPLogger } from "./logger";
export class DataiClient {
private client: AxiosInstance;
private logger: FastMCPLogger;
constructor(apiKey: string, logger: FastMCPLogger) {
this.logger = logger;
this.client = axios.create({
baseURL: "https://api-v1.mymerlin.io",
timeout: 180000, // 3 minutes as tested
headers: {
Authorization: apiKey,
"Content-Type": "application/json",
"User-Agent": "Datai-FastMCP/1.0.0",
},
});
this.setupInterceptors();
}
private setupInterceptors() {
// Request interceptor for logging
this.client.interceptors.request.use(
(config) => {
this.logger.debug("API Request", {
url: config.url,
method: config.method,
params: config.params,
});
return config;
},
(error) => {
this.logger.error("API Request Error", error);
return Promise.reject(error);
}
);
// Response interceptor for logging and error handling
this.client.interceptors.response.use(
(response) => {
this.logger.debug("API Response", {
status: response.status,
url: response.config.url,
dataSize: JSON.stringify(response.data).length,
});
return response;
},
(error) => {
this.logger.error("API Response Error", {
status: error.response?.status,
message: error.message,
url: error.config?.url,
});
return Promise.reject(error);
}
);
}
}
```
#### Step 2.2: Validation and Error Handling
- Create Zod schemas for all tool parameters
- Implement comprehensive error handling
- Set up parameter validation utilities
- Create custom error classes for different scenarios
### Phase 3: Tool Implementation (60 minutes)
Each tool will be implemented in its own separate file for better maintainability, easier testing, and smaller file sizes.
#### Step 3.1: Individual Tool Files (8 separate files)
**Benefits of separate files:**
- Smaller, manageable files (~50-80 lines each)
- Single responsibility per file
- Easy testing of individual tools
- Better git history tracking
- Easier maintenance and debugging
**Example Tool Structure:**
```typescript
// tools/get-all-user-defi-positions.ts
import { z } from "zod";
import { DataiClient } from "../utils/api-client";
import { Logger } from "../utils/logger";
export function createGetAllUserDeFiPositionsTool(client: DataiClient) {
return {
name: "get_all_user_defi_positions",
description:
"Get all DeFi positions for a wallet across all supported chains",
parameters: z.object({
wallet: z
.string()
.regex(/^0x[a-fA-F0-9]{40}$/, "Must be a valid Ethereum address"),
}),
execute: async (args: { wallet: string }, { log }: { log: Logger }) => {
log.info("Fetching all DeFi positions", { wallet: args.wallet });
try {
const response = await client.get(
`/api/merlin/public/userDeFiPositions/all/${args.wallet}`
);
log.info("Successfully fetched DeFi positions", {
wallet: args.wallet,
positionCount: response.data?.length || 0,
});
return {
content: [
{
type: "text" as const,
text: JSON.stringify(response.data, null, 2),
},
],
};
} catch (error: any) {
log.error("Failed to fetch DeFi positions", {
wallet: args.wallet,
error: error.message,
});
throw new Error(`Failed to fetch DeFi positions: ${error.message}`);
}
},
};
}
```
**Each tool file follows the same pattern:**
- Single tool responsibility
- Proper TypeScript typing
- Comprehensive logging
- Error handling
- Zod parameter validation
- Export function that creates the tool definition
#### Step 3.2: Tool Index and Registration
```typescript
// tools/index.ts
import { DataiClient } from "../utils/api-client";
import { createGetAllUserDeFiPositionsTool } from "./get-all-user-defi-positions";
import { createGetUserDeFiPositionsByChainTool } from "./get-user-defi-positions-by-chain";
import { createGetUserDeFiPositionsByMultipleChainsTool } from "./get-user-defi-positions-by-multiple-chains";
import { createGetUserDeFiPositionsByProtocolTool } from "./get-user-defi-positions-by-protocol";
import { createGetUserDeFiProtocolBalancesByChainTool } from "./get-user-defi-protocol-balances-by-chain";
import { createGetUserOverallBalanceAllChainsTool } from "./get-user-overall-balance-all-chains";
import { createGetUserOverallBalanceByChainTool } from "./get-user-overall-balance-by-chain";
import { createGetWalletBalancesByChainTool } from "./get-wallet-balances-by-chain";
export function registerAllTools(server: any, client: DataiClient) {
// Register DeFi Position Tools
server.addTool(createGetAllUserDeFiPositionsTool(client));
server.addTool(createGetUserDeFiPositionsByChainTool(client));
server.addTool(createGetUserDeFiPositionsByMultipleChainsTool(client));
server.addTool(createGetUserDeFiPositionsByProtocolTool(client));
// Register Balance Tools
server.addTool(createGetUserDeFiProtocolBalancesByChainTool(client));
server.addTool(createGetUserOverallBalanceAllChainsTool(client));
server.addTool(createGetUserOverallBalanceByChainTool(client));
server.addTool(createGetWalletBalancesByChainTool(client));
}
// Export individual tool creators for testing
export {
createGetAllUserDeFiPositionsTool,
createGetUserDeFiPositionsByChainTool,
createGetUserDeFiPositionsByMultipleChainsTool,
createGetUserDeFiPositionsByProtocolTool,
createGetUserDeFiProtocolBalancesByChainTool,
createGetUserOverallBalanceAllChainsTool,
createGetUserOverallBalanceByChainTool,
createGetWalletBalancesByChainTool,
};
```
#### Step 3.3: Tool File Breakdown
**DeFi Position Tools (4 files):**
1. `get-all-user-defi-positions.ts` - All DeFi positions across chains
2. `get-user-defi-positions-by-chain.ts` - DeFi positions by specific chain
3. `get-user-defi-positions-by-multiple-chains.ts` - DeFi positions by multiple chains
4. `get-user-defi-positions-by-protocol.ts` - DeFi positions by protocol
**Balance Tools (4 files):** 5. `get-user-defi-protocol-balances-by-chain.ts` - DeFi protocol balances by chain 6. `get-user-overall-balance-all-chains.ts` - Overall balance across all chains 7. `get-user-overall-balance-by-chain.ts` - Overall balance by specific chain 8. `get-wallet-balances-by-chain.ts` - Wallet token balances by chain
### Phase 4: Server Configuration and Transport Setup (30 minutes)
#### Step 4.1: Main Server Setup
```typescript
// index.ts
import { FastMCP } from "fastmcp";
import { DataiClient } from "./utils/api-client";
import { Logger } from "./utils/logger";
import { registerAllTools } from "./tools";
// Get API key from environment or configuration
const API_KEY = process.env.DATAI_API_KEY || "dbNb54fQUGCuy2xO3RXPRw7bH9nbDSkS";
// Create FastMCP server instance
const server = new FastMCP({
name: "Datai MCP Server",
version: "1.0.0",
description:
"High-performance MCP server for Datai blockchain data endpoints",
// FastMCP logging configuration
logging: {
level: "debug",
enableTimestamps: true,
enableColors: true,
},
// Health check configuration
health: {
enabled: true,
message: "Datai MCP Server is healthy",
path: "/health",
},
// Ping configuration for connection health
ping: {
enabled: true,
intervalMs: 30000, // 30 seconds
logLevel: "debug",
},
});
// Initialize logger and API client
const logger = new Logger();
const apiClient = new DataiClient(API_KEY, logger);
// Register all tools
registerAllTools(server, apiClient);
// Server event handlers
server.on("connect", (event) => {
logger.info("Client connected", {
sessionId: event.session.id,
clientCapabilities: event.session.clientCapabilities,
});
});
server.on("disconnect", (event) => {
logger.info("Client disconnected", {
sessionId: event.session.id,
});
});
server.on("error", (event) => {
logger.error("Server error", {
error: event.error.message,
stack: event.error.stack,
});
});
// Start server with both STDIO and SSE support
if (require.main === module) {
const transportType = process.env.TRANSPORT_TYPE || "stdio";
if (transportType === "stdio") {
server.start({
transportType: "stdio",
});
logger.info("Datai MCP Server started with STDIO transport");
} else if (transportType === "sse") {
const port = parseInt(process.env.PORT || "8080");
server.start({
transportType: "sse",
sse: {
port: port,
endpoint: "/sse",
},
});
logger.info("Datai MCP Server started with SSE transport", { port });
} else if (transportType === "httpStream") {
const port = parseInt(process.env.PORT || "8080");
server.start({
transportType: "httpStream",
httpStream: {
port: port,
path: "/mcp",
},
});
logger.info("Datai MCP Server started with HTTP Stream transport", {
port,
});
}
}
export { server, apiClient, logger };
```
### Phase 5: Testing and Validation (45 minutes)
#### Step 5.1: Unit Tests
- Test each tool individually with mock data
- Validate parameter schemas
- Test error handling scenarios
- Test API client functionality
#### Step 5.2: Integration Tests
- Test with real API endpoints using test wallet addresses
- Validate response formats
- Test timeout handling
- Test authentication
#### Step 5.3: FastMCP CLI Testing
```bash
# Test with FastMCP dev tools
npx fastmcp dev src/index.ts
# Inspect with MCP Inspector
npx fastmcp inspect src/index.ts
```
### Phase 6: Documentation and Deployment (30 minutes)
#### Step 6.1: Documentation
- Create comprehensive README.md
- Document all 8 tools with examples
- Create configuration guide
- Add troubleshooting section
#### Step 6.2: Package Configuration
```json
{
"name": "datai-fastmcp-server",
"version": "1.0.0",
"description": "FastMCP TypeScript server for Datai blockchain data",
"main": "dist/index.js",
"bin": {
"datai-mcp": "./dist/index.js"
},
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsx src/index.ts",
"test": "jest",
"test:integration": "jest --config jest.integration.config.js",
"lint": "eslint src/**/*.ts",
"format": "prettier --write src/**/*.ts"
},
"dependencies": {
"fastmcp": "^3.1.1",
"zod": "^3.22.4",
"axios": "^1.6.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0",
"tsx": "^4.0.0",
"jest": "^29.0.0",
"@types/jest": "^29.0.0",
"eslint": "^8.0.0",
"prettier": "^3.0.0"
}
}
```
## Key Implementation Requirements
### FastMCP Standards Compliance
1. **Logging**: Use FastMCP logging system extensively for debugging
2. **Error Handling**: Implement proper error boundaries and user-friendly messages
3. **Type Safety**: Full TypeScript implementation with strict types
4. **Validation**: Zod schemas for all parameters
5. **Performance**: Efficient HTTP client with proper timeout handling
### API Integration Requirements
1. **Authentication**: Use provided API key in Authorization header
2. **Timeout**: 3-minute timeout for all requests (as tested)
3. **Error Handling**: Graceful handling of API failures
4. **Logging**: Comprehensive request/response logging
5. **Rate Limiting**: Respect API rate limits
### Transport Support
1. **STDIO**: Primary transport for local development
2. **SSE**: For remote access and web integration
3. **HTTP Stream**: For high-performance scenarios
### Testing Requirements
1. **Unit Tests**: 100% coverage for utilities and tools
2. **Integration Tests**: Real API testing with known working parameters
3. **Performance Tests**: Validate 3-minute timeout handling
4. **CLI Testing**: FastMCP dev tools validation
## Success Criteria
1. All 8 tools working with real API endpoints
2. Comprehensive logging for debugging
3. Both STDIO and SSE transport working
4. Full TypeScript type safety
5. Proper error handling and validation
6. Ready for NPM publication
7. Complete documentation
## Timeline
- **Total Estimated Time**: 4 hours
- **Phase 1**: 30 minutes (Setup)
- **Phase 2**: 45 minutes (API Client)
- **Phase 3**: 60 minutes (Tools)
- **Phase 4**: 30 minutes (Server)
- **Phase 5**: 45 minutes (Testing)
- **Phase 6**: 30 minutes (Documentation)
This plan ensures we build a production-ready FastMCP TypeScript server that follows all FastMCP standards and successfully integrates with the Datai API endpoints.