npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@neural-trader/mcp-protocol

v2.0.0

Published

Model Context Protocol (MCP) JSON-RPC 2.0 protocol types for Neural Trader

Readme

@neural-trader/mcp-protocol

CI Status codecov License npm version

Type-safe JSON-RPC 2.0 implementation for Model Context Protocol (MCP) - The foundation for AI-first trading tools

Introduction

@neural-trader/mcp-protocol provides a complete, type-safe implementation of JSON-RPC 2.0 protocol types specifically designed for the Model Context Protocol (MCP). It serves as the communication layer between AI assistants like Claude and Neural Trader's trading capabilities.

This package is the foundation for @neural-trader/mcp, providing all protocol-level types, request/response structures, and error handling for bidirectional communication between AI assistants and trading systems.

Built with zero dependencies (except @neural-trader/core), it ensures lightweight, predictable, and standards-compliant protocol communication for AI-driven trading workflows.

Features

  • JSON-RPC 2.0 Compliant: Fully implements JSON-RPC 2.0 specification
  • Type-Safe Protocol: Complete TypeScript definitions for requests, responses, and errors
  • MCP Specification: Follows Anthropic's Model Context Protocol standards
  • Zero Dependencies: Only depends on @neural-trader/core for shared types
  • Error Codes: Standard JSON-RPC 2.0 error codes with type safety
  • Request/Response Helpers: Utility functions for creating protocol messages
  • Lightweight: ~10 KB package size with no runtime overhead
  • AI-First Design: Built specifically for LLM-to-system communication
  • Bidirectional: Supports both client and server message patterns
  • Validation-Ready: Type structure supports runtime validation

Installation

Via npm (Node.js)

# Protocol package
npm install @neural-trader/mcp-protocol

# With core types
npm install @neural-trader/mcp-protocol @neural-trader/core

# With MCP server
npm install @neural-trader/mcp-protocol @neural-trader/mcp

Via Cargo (Rust)

# Add to Cargo.toml
[dependencies]
neural-trader-mcp-protocol = "1.0.0"
neural-trader-core = "1.0.0"

Package Size: ~10 KB (minimal dependencies)

See main packages documentation for all available packages.

Quick Start

30-second example showing basic protocol usage:

const {
  createRequest,
  createSuccessResponse,
  createErrorResponse,
  ErrorCode
} = require('@neural-trader/mcp-protocol');

// Create a JSON-RPC 2.0 request
const request = createRequest('list_strategies', { category: 'momentum' }, 'req-001');

console.log(request);
// {
//   jsonrpc: '2.0',
//   method: 'list_strategies',
//   params: { category: 'momentum' },
//   id: 'req-001'
// }

// Create a success response
const response = createSuccessResponse(
  { strategies: ['momentum-v1', 'momentum-v2'] },
  'req-001'
);

console.log(response);
// {
//   jsonrpc: '2.0',
//   result: { strategies: ['momentum-v1', 'momentum-v2'] },
//   id: 'req-001'
// }

// Create an error response
const error = createErrorResponse(
  ErrorCode.METHOD_NOT_FOUND,
  'Method not found',
  'req-002'
);

console.log(error);
// {
//   jsonrpc: '2.0',
//   error: { code: -32601, message: 'Method not found' },
//   id: 'req-002'
// }

Expected Output:

{ jsonrpc: '2.0', method: 'list_strategies', params: { category: 'momentum' }, id: 'req-001' }
{ jsonrpc: '2.0', result: { strategies: ['momentum-v1', 'momentum-v2'] }, id: 'req-001' }
{ jsonrpc: '2.0', error: { code: -32601, message: 'Method not found' }, id: 'req-002' }

Core Concepts

JSON-RPC 2.0 Protocol

JSON-RPC 2.0 is a stateless, light-weight remote procedure call (RPC) protocol.

const { createRequest } = require('@neural-trader/mcp-protocol');

// Request with ID (expects response)
const requestWithId = createRequest('method_name', { param: 'value' }, 'unique-id');

// Notification (no ID, no response expected)
const notification = createRequest('notify_event', { data: 'value' });

// Request with complex parameters
const complexRequest = createRequest(
  'execute_trade',
  {
    symbol: 'AAPL',
    side: 'BUY',
    quantity: 100,
    orderType: 'LIMIT',
    limitPrice: 175.50
  },
  'trade-001'
);

Request/Response Correlation

Every request with an ID must receive a response with the same ID.

const {
  createRequest,
  createSuccessResponse,
  createErrorResponse,
  ErrorCode
} = require('@neural-trader/mcp-protocol');

// Client creates request
const request = createRequest('get_portfolio', { detailed: true }, 'port-001');

// Server processes and responds
try {
  const portfolioData = { /* ... portfolio data ... */ };
  const response = createSuccessResponse(portfolioData, request.id);
  // Send response back to client
} catch (error) {
  const errorResponse = createErrorResponse(
    ErrorCode.INTERNAL_ERROR,
    error.message,
    request.id
  );
  // Send error response back to client
}

Standard Error Codes

JSON-RPC 2.0 defines standard error codes for common failure scenarios.

const { ErrorCode } = require('@neural-trader/mcp-protocol');

// Standard error codes
console.log(ErrorCode.PARSE_ERROR);        // -32700: Invalid JSON
console.log(ErrorCode.INVALID_REQUEST);    // -32600: Invalid request object
console.log(ErrorCode.METHOD_NOT_FOUND);   // -32601: Method does not exist
console.log(ErrorCode.INVALID_PARAMS);     // -32602: Invalid method parameters
console.log(ErrorCode.INTERNAL_ERROR);     // -32603: Internal JSON-RPC error

// Server-defined error range
console.log(ErrorCode.SERVER_ERROR_START); // -32099
console.log(ErrorCode.SERVER_ERROR_END);   // -32000

Key Terminology

  • Request: A call to a remote method with optional parameters and ID
  • Response: Result or error returned for a request with matching ID
  • Notification: A request without an ID that expects no response
  • Error Object: Structured error with code, message, and optional data
  • Request ID: Unique identifier for correlating requests with responses

Architecture Overview

┌────────────────────────────────────────────────┐
│     @neural-trader/mcp-protocol (Protocol)      │
│                                                 │
│  ┌──────────────┐        ┌──────────────┐     │
│  │   JSON-RPC   │        │    Error     │     │
│  │   Requests   │        │    Codes     │     │
│  └──────────────┘        └──────────────┘     │
│          │                       │             │
│          ▼                       ▼             │
│  ┌──────────────┐        ┌──────────────┐     │
│  │   JSON-RPC   │        │   Utility    │     │
│  │  Responses   │        │  Functions   │     │
│  └──────────────┘        └──────────────┘     │
└────────────────────────────────────────────────┘
                    │
                    ▼
        ┌───────────────────────┐
        │  @neural-trader/mcp   │
        │   (MCP Server with    │
        │    102+ AI Tools)     │
        └───────────────────────┘

API Reference

JsonRpcRequest

JSON-RPC 2.0 request structure.

interface JsonRpcRequest {
  jsonrpc: '2.0';
  method: string;
  params?: any;
  id?: RequestId;  // string | number
}

Example:

const request = {
  jsonrpc: '2.0',
  method: 'run_backtest',
  params: {
    strategy: 'momentum',
    symbol: 'AAPL',
    startDate: '2024-01-01',
    endDate: '2024-12-31'
  },
  id: 'backtest-001'
};

JsonRpcResponse

JSON-RPC 2.0 response structure.

interface JsonRpcResponse {
  jsonrpc: '2.0';
  result?: any;
  error?: JsonRpcError;
  id: RequestId;
}

Example:

// Success response
const successResponse = {
  jsonrpc: '2.0',
  result: {
    sharpeRatio: 1.85,
    totalReturn: 0.342,
    maxDrawdown: -0.125
  },
  id: 'backtest-001'
};

// Error response
const errorResponse = {
  jsonrpc: '2.0',
  error: {
    code: -32602,
    message: 'Invalid params: startDate must be before endDate'
  },
  id: 'backtest-001'
};

JsonRpcError

Error object for JSON-RPC 2.0 responses.

interface JsonRpcError {
  code: number;
  message: string;
  data?: any;
}

Example:

const error = {
  code: -32603,
  message: 'Internal error: Database connection failed',
  data: {
    timestamp: '2024-01-15T14:30:00Z',
    retryable: true,
    details: 'Connection timeout after 30s'
  }
};

createRequest()

Create a JSON-RPC 2.0 request.

function createRequest(
  method: string,
  params?: any,
  id?: RequestId
): JsonRpcRequest

Parameters:

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | method | string | Yes | Method name to invoke | | params | any | No | Method parameters (object or array) | | id | string | number | No | Request ID (omit for notifications) |

Returns: JsonRpcRequest object

Example:

const { createRequest } = require('@neural-trader/mcp-protocol');

// Simple request
const simpleRequest = createRequest('list_tools');

// Request with parameters
const paramRequest = createRequest('get_strategy_info', {
  strategyId: 'momentum-v1'
});

// Request with ID for response tracking
const trackedRequest = createRequest(
  'execute_trade',
  {
    symbol: 'AAPL',
    side: 'BUY',
    quantity: 100
  },
  'trade-12345'
);

// Notification (no ID, no response)
const notification = createRequest('price_update', {
  symbol: 'AAPL',
  price: 175.50
});

createSuccessResponse()

Create a successful JSON-RPC 2.0 response.

function createSuccessResponse(
  result: any,
  id: RequestId
): JsonRpcResponse

Parameters:

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | result | any | Yes | Result data to return | | id | string | number | Yes | Request ID to match |

Returns: JsonRpcResponse object with result

Example:

const { createSuccessResponse } = require('@neural-trader/mcp-protocol');

// Simple success response
const response1 = createSuccessResponse({ status: 'ok' }, 'req-001');

// Response with complex data
const response2 = createSuccessResponse(
  {
    portfolio: {
      cash: 50000,
      equity: 125000,
      positions: [
        { symbol: 'AAPL', quantity: 100, value: 17550 },
        { symbol: 'NVDA', quantity: 50, value: 24790 }
      ]
    }
  },
  'portfolio-001'
);

// Response with array data
const response3 = createSuccessResponse(
  ['momentum-v1', 'mean-reversion-v2', 'pairs-trading-v1'],
  'list-strategies-001'
);

createErrorResponse()

Create an error JSON-RPC 2.0 response.

function createErrorResponse(
  code: number,
  message: string,
  id: RequestId,
  data?: any
): JsonRpcResponse

Parameters:

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | code | number | Yes | Error code (use ErrorCode constants) | | message | string | Yes | Human-readable error message | | id | string | number | Yes | Request ID to match | | data | any | No | Additional error details |

Returns: JsonRpcResponse object with error

Example:

const { createErrorResponse, ErrorCode } = require('@neural-trader/mcp-protocol');

// Method not found error
const error1 = createErrorResponse(
  ErrorCode.METHOD_NOT_FOUND,
  'Method "invalid_method" does not exist',
  'req-001'
);

// Invalid parameters error with details
const error2 = createErrorResponse(
  ErrorCode.INVALID_PARAMS,
  'Invalid trade parameters',
  'trade-001',
  {
    missing: ['symbol', 'quantity'],
    invalid: { side: 'INVALID_SIDE' }
  }
);

// Internal error with stack trace
const error3 = createErrorResponse(
  ErrorCode.INTERNAL_ERROR,
  'Database query failed',
  'db-query-001',
  {
    query: 'SELECT * FROM trades WHERE ...',
    error: 'Connection timeout',
    timestamp: new Date().toISOString()
  }
);

ErrorCode Constants

Standard JSON-RPC 2.0 error codes.

const ErrorCode = {
  PARSE_ERROR: -32700,
  INVALID_REQUEST: -32600,
  METHOD_NOT_FOUND: -32601,
  INVALID_PARAMS: -32602,
  INTERNAL_ERROR: -32603,
  SERVER_ERROR_START: -32099,
  SERVER_ERROR_END: -32000
};

Usage:

const { ErrorCode } = require('@neural-trader/mcp-protocol');

// Use constants instead of magic numbers
if (error.code === ErrorCode.METHOD_NOT_FOUND) {
  console.log('Method does not exist');
}

// Custom server errors (between SERVER_ERROR_END and SERVER_ERROR_START)
const CUSTOM_ERROR_CODE = -32050;
const customError = createErrorResponse(
  CUSTOM_ERROR_CODE,
  'Strategy execution failed',
  'strategy-001'
);

Detailed Tutorials

Tutorial 1: Building a Request/Response Handler

Goal: Create a type-safe request/response handler for trading operations.

Prerequisites:

  • Node.js 18+
  • Basic understanding of JSON-RPC 2.0

Step 1: Create Request Handler

const {
  createRequest,
  createSuccessResponse,
  createErrorResponse,
  ErrorCode
} = require('@neural-trader/mcp-protocol');

class TradingRequestHandler {
  constructor() {
    this.requestCounter = 0;
  }

  // Generate unique request ID
  generateRequestId() {
    return `req-${Date.now()}-${++this.requestCounter}`;
  }

  // Create a trading request
  createTradeRequest(symbol, side, quantity, orderType) {
    return createRequest(
      'execute_trade',
      {
        symbol,
        side,
        quantity,
        orderType,
        timestamp: new Date().toISOString()
      },
      this.generateRequestId()
    );
  }

  // Create a backtest request
  createBacktestRequest(strategy, config) {
    return createRequest(
      'run_backtest',
      {
        strategy,
        config,
        timestamp: new Date().toISOString()
      },
      this.generateRequestId()
    );
  }

  // Create a query request
  createQueryRequest(method, params) {
    return createRequest(method, params, this.generateRequestId());
  }
}

// Usage
const handler = new TradingRequestHandler();
const tradeRequest = handler.createTradeRequest('AAPL', 'BUY', 100, 'MARKET');
console.log(tradeRequest);

Step 2: Create Response Handler

class TradingResponseHandler {
  // Handle successful trade execution
  handleTradeSuccess(orderId, fillPrice, requestId) {
    return createSuccessResponse(
      {
        orderId,
        status: 'FILLED',
        fillPrice,
        timestamp: new Date().toISOString()
      },
      requestId
    );
  }

  // Handle backtest results
  handleBacktestSuccess(results, requestId) {
    return createSuccessResponse(
      {
        metrics: results.metrics,
        trades: results.trades,
        equityCurve: results.equityCurve
      },
      requestId
    );
  }

  // Handle errors
  handleError(code, message, requestId, details) {
    return createErrorResponse(code, message, requestId, details);
  }

  // Validate and route response
  routeResponse(response) {
    if (response.error) {
      console.error(`Error ${response.error.code}: ${response.error.message}`);
      return { success: false, error: response.error };
    } else {
      console.log('Success:', response.result);
      return { success: true, result: response.result };
    }
  }
}

// Usage
const responseHandler = new TradingResponseHandler();
const successResponse = responseHandler.handleTradeSuccess(
  'order-12345',
  175.50,
  'req-001'
);
console.log(successResponse);

Step 3: Complete Request/Response Cycle

async function completeTradingCycle() {
  const requestHandler = new TradingRequestHandler();
  const responseHandler = new TradingResponseHandler();

  // Create request
  const request = requestHandler.createTradeRequest('AAPL', 'BUY', 100, 'MARKET');
  console.log('Request:', request);

  // Simulate processing (in real app, this would be network call)
  try {
    // Simulate successful trade
    const orderId = 'order-' + Date.now();
    const fillPrice = 175.50;

    const response = responseHandler.handleTradeSuccess(
      orderId,
      fillPrice,
      request.id
    );

    console.log('Response:', response);

    // Route and handle response
    const result = responseHandler.routeResponse(response);
    if (result.success) {
      console.log('Trade executed successfully:', result.result);
    }
  } catch (error) {
    const errorResponse = responseHandler.handleError(
      ErrorCode.INTERNAL_ERROR,
      error.message,
      request.id,
      { error: error.toString() }
    );

    console.log('Error Response:', errorResponse);
  }
}

completeTradingCycle();

Tutorial 2: Error Handling Patterns

Goal: Implement comprehensive error handling with proper error codes.

Complete Implementation:

const {
  createErrorResponse,
  ErrorCode
} = require('@neural-trader/mcp-protocol');

class TradingErrorHandler {
  // Parse error - invalid JSON received
  handleParseError(requestId, rawData) {
    return createErrorResponse(
      ErrorCode.PARSE_ERROR,
      'Parse error: Invalid JSON',
      requestId || null,
      {
        receivedData: rawData.substring(0, 100), // First 100 chars
        timestamp: new Date().toISOString()
      }
    );
  }

  // Invalid request - missing required fields
  handleInvalidRequest(requestId, missingFields) {
    return createErrorResponse(
      ErrorCode.INVALID_REQUEST,
      'Invalid Request: Missing required fields',
      requestId || null,
      {
        missing: missingFields,
        requiredFields: ['jsonrpc', 'method'],
        timestamp: new Date().toISOString()
      }
    );
  }

  // Method not found
  handleMethodNotFound(method, requestId) {
    return createErrorResponse(
      ErrorCode.METHOD_NOT_FOUND,
      `Method not found: ${method}`,
      requestId,
      {
        method,
        availableMethods: [
          'execute_trade',
          'run_backtest',
          'get_portfolio',
          'list_strategies'
        ],
        timestamp: new Date().toISOString()
      }
    );
  }

  // Invalid parameters
  handleInvalidParams(method, requestId, validationErrors) {
    return createErrorResponse(
      ErrorCode.INVALID_PARAMS,
      `Invalid params for method: ${method}`,
      requestId,
      {
        method,
        errors: validationErrors,
        timestamp: new Date().toISOString()
      }
    );
  }

  // Internal error
  handleInternalError(requestId, error) {
    return createErrorResponse(
      ErrorCode.INTERNAL_ERROR,
      'Internal error occurred',
      requestId,
      {
        error: error.message,
        stack: process.env.NODE_ENV === 'development' ? error.stack : undefined,
        timestamp: new Date().toISOString()
      }
    );
  }

  // Custom server error
  handleCustomError(code, message, requestId, details) {
    // Ensure code is in server error range
    if (code > ErrorCode.SERVER_ERROR_END || code < ErrorCode.SERVER_ERROR_START) {
      code = ErrorCode.SERVER_ERROR_END - 1; // Default custom error code
    }

    return createErrorResponse(code, message, requestId, details);
  }

  // Validation helper
  validateTradeParams(params) {
    const errors = [];

    if (!params.symbol || typeof params.symbol !== 'string') {
      errors.push({ field: 'symbol', message: 'Required string field' });
    }

    if (!params.side || !['BUY', 'SELL'].includes(params.side)) {
      errors.push({ field: 'side', message: 'Must be BUY or SELL' });
    }

    if (!params.quantity || typeof params.quantity !== 'number' || params.quantity <= 0) {
      errors.push({ field: 'quantity', message: 'Must be positive number' });
    }

    return errors;
  }

  // Process request with error handling
  async processRequest(request) {
    try {
      // Validate request structure
      if (!request.jsonrpc || request.jsonrpc !== '2.0') {
        return this.handleInvalidRequest(request.id, ['jsonrpc']);
      }

      if (!request.method) {
        return this.handleInvalidRequest(request.id, ['method']);
      }

      // Check method exists
      const validMethods = ['execute_trade', 'run_backtest', 'get_portfolio'];
      if (!validMethods.includes(request.method)) {
        return this.handleMethodNotFound(request.method, request.id);
      }

      // Validate parameters
      if (request.method === 'execute_trade') {
        const validationErrors = this.validateTradeParams(request.params || {});
        if (validationErrors.length > 0) {
          return this.handleInvalidParams(request.method, request.id, validationErrors);
        }
      }

      // Process valid request (would call actual implementation)
      // ... processing logic ...

      return null; // No error
    } catch (error) {
      return this.handleInternalError(request.id, error);
    }
  }
}

// Usage example
const errorHandler = new TradingErrorHandler();

// Test various error scenarios
const requests = [
  // Invalid JSON structure
  { invalidData: 'not json' },

  // Missing method
  { jsonrpc: '2.0', id: 'req-001' },

  // Method not found
  { jsonrpc: '2.0', method: 'invalid_method', id: 'req-002' },

  // Invalid parameters
  { jsonrpc: '2.0', method: 'execute_trade', params: { side: 'BUY' }, id: 'req-003' },

  // Valid request
  {
    jsonrpc: '2.0',
    method: 'execute_trade',
    params: { symbol: 'AAPL', side: 'BUY', quantity: 100 },
    id: 'req-004'
  }
];

requests.forEach(async (request) => {
  const error = await errorHandler.processRequest(request);
  if (error) {
    console.log('Error Response:', JSON.stringify(error, null, 2));
  } else {
    console.log('Request valid, processing...');
  }
});

Tutorial 3: Client-Server Communication

Goal: Implement bidirectional client-server communication with MCP protocol.

Complete Implementation:

const {
  createRequest,
  createSuccessResponse,
  createErrorResponse,
  ErrorCode
} = require('@neural-trader/mcp-protocol');

class MCPClient {
  constructor() {
    this.pendingRequests = new Map();
    this.requestCounter = 0;
  }

  // Send request and track for response
  async sendRequest(method, params) {
    const id = `client-${Date.now()}-${++this.requestCounter}`;
    const request = createRequest(method, params, id);

    // Create promise that resolves when response received
    return new Promise((resolve, reject) => {
      this.pendingRequests.set(id, { resolve, reject });

      // Send request (in real app, this would be network call)
      this.transport(request);

      // Timeout after 30 seconds
      setTimeout(() => {
        if (this.pendingRequests.has(id)) {
          this.pendingRequests.delete(id);
          reject(new Error('Request timeout'));
        }
      }, 30000);
    });
  }

  // Handle response received
  handleResponse(response) {
    const pending = this.pendingRequests.get(response.id);
    if (!pending) {
      console.warn('Received response for unknown request:', response.id);
      return;
    }

    this.pendingRequests.delete(response.id);

    if (response.error) {
      pending.reject(new Error(response.error.message));
    } else {
      pending.resolve(response.result);
    }
  }

  // Transport layer (placeholder)
  transport(request) {
    // In real implementation, this would send over WebSocket/HTTP
    console.log('Sending request:', request);

    // Simulate response (in real app, response comes from server)
    setTimeout(() => {
      const response = createSuccessResponse(
        { status: 'processed' },
        request.id
      );
      this.handleResponse(response);
    }, 100);
  }
}

class MCPServer {
  constructor() {
    this.methods = new Map();
    this.registerDefaultMethods();
  }

  // Register method handler
  registerMethod(name, handler) {
    this.methods.set(name, handler);
  }

  // Register default trading methods
  registerDefaultMethods() {
    this.registerMethod('execute_trade', async (params) => {
      return {
        orderId: 'order-' + Date.now(),
        status: 'FILLED',
        fillPrice: 175.50
      };
    });

    this.registerMethod('get_portfolio', async (params) => {
      return {
        cash: 50000,
        equity: 125000,
        positions: [
          { symbol: 'AAPL', quantity: 100 }
        ]
      };
    });

    this.registerMethod('list_strategies', async (params) => {
      return {
        strategies: ['momentum-v1', 'mean-reversion-v2']
      };
    });
  }

  // Handle incoming request
  async handleRequest(request) {
    try {
      // Validate request
      if (!request.jsonrpc || request.jsonrpc !== '2.0') {
        return createErrorResponse(
          ErrorCode.INVALID_REQUEST,
          'Invalid JSON-RPC version',
          request.id || null
        );
      }

      // Check if method exists
      if (!this.methods.has(request.method)) {
        return createErrorResponse(
          ErrorCode.METHOD_NOT_FOUND,
          `Method not found: ${request.method}`,
          request.id,
          { availableMethods: Array.from(this.methods.keys()) }
        );
      }

      // Execute method
      const handler = this.methods.get(request.method);
      const result = await handler(request.params || {});

      // Return success response (or null for notifications)
      return request.id ? createSuccessResponse(result, request.id) : null;
    } catch (error) {
      return createErrorResponse(
        ErrorCode.INTERNAL_ERROR,
        error.message,
        request.id || null,
        { error: error.toString() }
      );
    }
  }
}

// Usage example: Complete client-server cycle
async function demonstrateClientServer() {
  const client = new MCPClient();
  const server = new MCPServer();

  // Override client transport to actually call server
  client.transport = async (request) => {
    console.log('Client → Server:', request);

    const response = await server.handleRequest(request);
    if (response) {
      console.log('Server → Client:', response);
      client.handleResponse(response);
    }
  };

  // Execute requests
  try {
    // Request 1: Execute trade
    const tradeResult = await client.sendRequest('execute_trade', {
      symbol: 'AAPL',
      side: 'BUY',
      quantity: 100
    });
    console.log('Trade Result:', tradeResult);

    // Request 2: Get portfolio
    const portfolio = await client.sendRequest('get_portfolio', {});
    console.log('Portfolio:', portfolio);

    // Request 3: List strategies
    const strategies = await client.sendRequest('list_strategies', {});
    console.log('Strategies:', strategies);

    // Request 4: Invalid method (error)
    try {
      await client.sendRequest('invalid_method', {});
    } catch (error) {
      console.log('Expected error:', error.message);
    }
  } catch (error) {
    console.error('Request failed:', error);
  }
}

demonstrateClientServer();

Tutorial 4: Batch Request Processing

Goal: Process multiple requests efficiently in a single batch.

Implementation:

const {
  createRequest,
  createSuccessResponse,
  createErrorResponse,
  ErrorCode
} = require('@neural-trader/mcp-protocol');

class BatchRequestProcessor {
  // Create batch of requests
  createBatch(requests) {
    return requests.map((req, index) =>
      createRequest(req.method, req.params, `batch-${index}`)
    );
  }

  // Process batch of requests
  async processBatch(requests) {
    const responses = [];

    for (const request of requests) {
      try {
        // Process each request
        const result = await this.processRequest(request);
        responses.push(createSuccessResponse(result, request.id));
      } catch (error) {
        responses.push(
          createErrorResponse(
            ErrorCode.INTERNAL_ERROR,
            error.message,
            request.id
          )
        );
      }
    }

    return responses;
  }

  // Single request processor
  async processRequest(request) {
    // Simulate processing
    switch (request.method) {
      case 'get_price':
        return { symbol: request.params.symbol, price: 175.50 };
      case 'get_portfolio':
        return { cash: 50000, equity: 125000 };
      case 'list_strategies':
        return { strategies: ['momentum-v1', 'mean-reversion-v2'] };
      default:
        throw new Error('Method not found');
    }
  }
}

// Usage
async function demonstrateBatchProcessing() {
  const processor = new BatchRequestProcessor();

  // Create batch of requests
  const batch = processor.createBatch([
    { method: 'get_price', params: { symbol: 'AAPL' } },
    { method: 'get_price', params: { symbol: 'NVDA' } },
    { method: 'get_portfolio', params: {} },
    { method: 'list_strategies', params: {} }
  ]);

  console.log('Batch requests:', batch);

  // Process batch
  const responses = await processor.processBatch(batch);
  console.log('Batch responses:', responses);
}

demonstrateBatchProcessing();

Tutorial 5: Type-Safe Protocol Validation

Goal: Validate JSON-RPC 2.0 messages with TypeScript.

Advanced Example:

import {
  JsonRpcRequest,
  JsonRpcResponse,
  JsonRpcError,
  RequestId
} from '@neural-trader/mcp-protocol';

class ProtocolValidator {
  // Validate request structure
  validateRequest(data: unknown): JsonRpcRequest | null {
    if (!this.isObject(data)) return null;

    const request = data as Partial<JsonRpcRequest>;

    // Required fields
    if (request.jsonrpc !== '2.0') return null;
    if (typeof request.method !== 'string') return null;

    // Optional fields
    if (request.params !== undefined && !this.isValidParams(request.params)) {
      return null;
    }

    if (request.id !== undefined && !this.isValidId(request.id)) {
      return null;
    }

    return request as JsonRpcRequest;
  }

  // Validate response structure
  validateResponse(data: unknown): JsonRpcResponse | null {
    if (!this.isObject(data)) return null;

    const response = data as Partial<JsonRpcResponse>;

    // Required fields
    if (response.jsonrpc !== '2.0') return null;
    if (!this.isValidId(response.id)) return null;

    // Must have either result or error, not both
    const hasResult = response.result !== undefined;
    const hasError = response.error !== undefined;

    if ((hasResult && hasError) || (!hasResult && !hasError)) {
      return null;
    }

    if (hasError && !this.isValidError(response.error)) {
      return null;
    }

    return response as JsonRpcResponse;
  }

  // Validate error object
  validateError(data: unknown): JsonRpcError | null {
    if (!this.isObject(data)) return null;

    const error = data as Partial<JsonRpcError>;

    if (typeof error.code !== 'number') return null;
    if (typeof error.message !== 'string') return null;

    return error as JsonRpcError;
  }

  // Helper methods
  private isObject(value: unknown): boolean {
    return typeof value === 'object' && value !== null && !Array.isArray(value);
  }

  private isValidParams(params: unknown): boolean {
    return typeof params === 'object' && params !== null;
  }

  private isValidId(id: unknown): id is RequestId {
    return typeof id === 'string' || typeof id === 'number';
  }

  private isValidError(error: unknown): boolean {
    if (!this.isObject(error)) return false;

    const err = error as Partial<JsonRpcError>;
    return typeof err.code === 'number' && typeof err.message === 'string';
  }
}

// Usage
const validator = new ProtocolValidator();

// Valid request
const validRequest = {
  jsonrpc: '2.0',
  method: 'execute_trade',
  params: { symbol: 'AAPL' },
  id: 'req-001'
};

const request = validator.validateRequest(validRequest);
if (request) {
  console.log('Valid request:', request);
} else {
  console.log('Invalid request');
}

// Valid response
const validResponse = {
  jsonrpc: '2.0',
  result: { orderId: 'order-001' },
  id: 'req-001'
};

const response = validator.validateResponse(validResponse);
if (response) {
  console.log('Valid response:', response);
} else {
  console.log('Invalid response');
}

Integration Examples

Integration with @neural-trader/mcp

The MCP server uses mcp-protocol for all communication.

const { McpServer } = require('@neural-trader/mcp');
const {
  createRequest,
  createSuccessResponse,
  ErrorCode
} = require('@neural-trader/mcp-protocol');

// MCP server automatically handles protocol
const server = new McpServer({ transport: 'stdio' });

// All requests/responses use mcp-protocol types
await server.start();

Integration with @neural-trader/core

Protocol works seamlessly with core trading types.

const {
  createRequest,
  createSuccessResponse
} = require('@neural-trader/mcp-protocol');
const { BacktestConfig } = require('@neural-trader/core');

// Create backtest request with core types
const backtestConfig = {
  initialCapital: 100000,
  startDate: '2024-01-01',
  endDate: '2024-12-31',
  commission: 0.001,
  slippage: 0.0005,
  useMarkToMarket: true
};

const request = createRequest('run_backtest', backtestConfig, 'backtest-001');

// Response also uses core types
const response = createSuccessResponse(
  {
    metrics: { /* BacktestMetrics */ },
    trades: [ /* Trade[] */ ]
  },
  'backtest-001'
);

Custom Transport Layer

Use protocol with any transport (WebSocket, HTTP, stdio).

const {
  createRequest,
  createSuccessResponse
} = require('@neural-trader/mcp-protocol');

class WebSocketTransport {
  constructor(url) {
    this.ws = new WebSocket(url);
    this.ws.onmessage = (event) => this.handleMessage(event.data);
  }

  send(method, params, id) {
    const request = createRequest(method, params, id);
    this.ws.send(JSON.stringify(request));
  }

  handleMessage(data) {
    const response = JSON.parse(data);
    // Process response...
  }
}

Related Packages

Core Packages

Recommended Combinations

For AI Assistant Integration:

npm install @neural-trader/mcp-protocol @neural-trader/mcp

For Custom MCP Server:

npm install @neural-trader/mcp-protocol @neural-trader/core

Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

License

This project is dual-licensed under MIT OR Apache-2.0.

Support

  • GitHub Issues: https://github.com/ruvnet/neural-trader/issues
  • Discord: https://discord.gg/neural-trader
  • Email: [email protected]

Specifications


Disclaimer: This software is for educational and research purposes only. Trading financial instruments carries risk. Use at your own risk.