Labsco
hed-standard logo

HED MCP Server

β˜… 2

from hed-standard

An MCP server for Hierarchical Event Descriptors (HED) that automates sidecar creation and annotation for BIDS event files using LLMs.

πŸ”₯πŸ”₯πŸ”₯βœ“ VerifiedFreeQuick setup

HED MCP TypeScript Server

License: ISC TypeScript MCP Maintainability Code Coverage

Introduction

A Model Context Protocol (MCP) server for validating HED (Hierarchical Event Descriptor) data. This server provides comprehensive HED validation tools through the standardized MCP interface, making HED validation accessible to any MCP-compatible client.

What is HED?

HED (Hierarchical Event Descriptor) is:

  • A standardized vocabulary for describing experimental events
  • A hierarchical system that allows for precise event annotation
  • Widely used in BIDS (Brain Imaging Data Structure) datasets
  • Essential for reproducible neuroscience research

What is MCP?

Model Context Protocol (MCP) is:

  • A standardized protocol for tool and resource sharing
  • Enables AI assistants and applications to access external capabilities
  • Provides a consistent interface across different implementations
  • Facilitates integration between diverse software systems

Features

  • HED string validation: Validate individual HED tag strings against schema specifications
  • TSV file validation: Validate entire BIDS TSV files containing HED annotations
  • JSON sidecar validation: Parse and validate HED sidecar JSON files
  • File system access: Read files from local filesystem paths
  • Multi-schema support: Support for standard HED schemas and library schemas
  • Definition processing: Handle HED definitions for enhanced validation
  • Warning detection: Optional warning detection in addition to error reporting
  • Schema caching: Intelligent caching system for optimal performance
  • Multiple interfaces: MCP server (stdio/WebSocket) + HTTP REST API
  • Browser compatibility: Full browser support with multiple integration options

Table of contents

Understanding HED

HED Basics

HED uses a hierarchical tag structure where tags are organized from general to specific:

Event                 # General event type
Event/Sensory-event   # More specific
Sensory-event         # Same as Event/Sensory-event 

The hierarchical structure is used for search generality -- allowing a search for Event to pick up Event/Sensory-event as well as Sensory-event.

Note: All tags in the HED vocabulary are unique. It is recommended that you annotate using just the tag, not the full path.

Tag Structure

  • Path notation: Tags use forward slashes to indicate hierarchy
  • Grouping: Parentheses group related tags: (Red, Large)
  • Definitions: Custom definitions can be used for complex concepts
  • Extension: Custom subtags can be added for specialization

Common HED Patterns

Basic event description

Sensory-event, Red

Grouped Tags

Sensory-event, (Red, Square)

Using Definitions

You can create definitions to represent strings of tags that you frequently use:

(Definition/BlueSquare, ((Background-view, Black), ((Blue, Square), (Center-of, Computer-Screen))))

The annotation:

Def/BlueSquare

can appear anywhere a normal HED tag would. Tools can substitute the full annotation when needed.

Schema Versions

HED schemas evolve over time. Use the latest version whenever possible:

  • Standard HED: 8.4.0 - Basic vocabulary
  • Library schemas:
    • lang_1.1.0 - Language-related tags
    • score_2.1.0 - EEG features based on SCORE standard

Server Architecture

Core Components

HED MCP Server (src)
β”œβ”€β”€ server.ts              # Main MCP server (stdio/WebSocket modes)
β”œβ”€β”€ tools/                 # Validation functions
β”‚   β”œβ”€β”€ validateHedString.ts
β”‚   β”œβ”€β”€ validateHedTsv.ts
β”‚   β”œβ”€β”€ validateHedSidecar.ts
β”‚   └── getFileFromPath.ts
β”œβ”€β”€ resources/             # Schema Information
β”‚   └── hedSchema.ts
β”œβ”€β”€ utils/                 # Utilities
β”‚   β”œβ”€β”€ definitionProcessor.ts
β”‚   β”œβ”€β”€ fileReader.ts
β”‚   β”œβ”€β”€ issueFormatter.ts
β”‚   β”œβ”€β”€ mcpToZod.ts
β”‚   └── schemaCache.ts     # Schema caching system
└── types/                 # TypeScript definitions

Examples (examples/)
β”œβ”€β”€ definition-usage.ts    # Example of HED definition processing
β”œβ”€β”€ hed-demo.html          # Interactive demo and integration guide
β”œβ”€β”€ hed-validator-client.js # Modern browser client for HED validation
β”œβ”€β”€ hed-validator.css      # Styles for the browser interface
β”œβ”€β”€ hed-validator.html     # Full-featured browser validation interface
β”œβ”€β”€ http-server.ts         # HTTP REST API server example
β”œβ”€β”€ mcp-client.js          # Interactive MCP client example
β”œβ”€β”€ README.md              # README for the examples
└── test-server.js         # Automated server testing script

Data Flow

  1. Client request β†’ MCP server
  2. Schema loading β†’ Cache or load from network
  3. Data processing β†’ Parse and validate
  4. Issue formatting β†’ Standardize error/Warning format
  5. Response β†’ Return to client

Caching system

The server implements intelligent caching:

  • Schema caching: Avoids reloading schemas for repeated operations
  • Definition caching: Reuses processed definitions
  • Memory management: Automatic cleanup of unused cache entries

Available tools

ToolDescriptionRequired parametersOptional parameters
validateHedStringValidates HED tag stringshedString, hedVersioncheckForWarnings, definitions
validateHedTsvValidates TSV files with HEDfilePath, hedVersioncheckForWarnings, fileData, jsonData, definitions
validateHedSidecarValidates HED sidecar JSON filesfilePath, hedVersioncheckForWarnings, fileData
getFileFromPathReads files from filesystemfilePath

Tool reference

validateHedString

Purpose: Validates individual HED tag strings

When to use:

  • Testing specific HED constructs
  • Interactive validation during annotation
  • Validating programmatically generated HED strings

Parameters:

  • hedString (required): The HED string to validate
  • hedVersion (required): Schema version (e.g., "8.4.0")
  • checkForWarnings (optional): Include warnings in results
  • definitions (optional): Array of definition strings

Best practices:

  • Use specific schema versions in production
  • Enable warnings during development
  • Group related definitions together

validateHedTsv

Purpose: Validates TSV files containing HED annotations

When to use:

  • Validating BIDS event files
  • Checking TSV files before publication
  • Automated dataset validation

Parameters:

  • filePath (required): Path to TSV file
  • hedVersion (required): Schema version
  • checkForWarnings (optional): Include warnings
  • fileData (optional): Inline TSV data
  • jsonData (optional): Sidecar data as JSON string
  • definitions (optional): Definition strings

Best practices:

  • Use fileData for small datasets to avoid file I/O
  • Include sidecar data via jsonData for complete validation
  • Process files in batches for large datasets

validateHedSidecar

Purpose: Validates HED sidecar JSON files

When to use:

  • Validating BIDS sidecar files
  • Checking JSON structure and HED content
  • Converting between sidecar formats

Parameters:

  • filePath (required): Path to JSON sidecar file
  • hedVersion (required): Schema version
  • checkForWarnings (optional): Include warnings
  • fileData (optional): Inline JSON data

Best practices:

  • Validate sidecar files before TSV files
  • Use parsed output for debugging sidecar structure
  • Check both structure and HED content validity

getFileFromPath

Purpose: Retrieves files from the local filesystem

When to use:

  • Reading configuration files
  • Accessing data files for validation
  • File system operations

Parameters:

  • filePath (required): Absolute path to the file

Best practices:

  • Use absolute file paths
  • Check file permissions and existence
  • Handle file encoding properly (UTF-8 recommended)

Working with HED Data

Validation Workflow

  1. Schema Selection: Choose appropriate HED schema version
  2. Definition Setup: Prepare any custom definitions
  3. Data Validation: Run appropriate validation tool
  4. Issue Resolution: Address errors and warnings
  5. Quality Assurance: Final validation with warnings enabled

Common Validation Scenarios

Scenario 1: New Dataset Validation

// 1. First validate sidecar files
{
  "name": "validateHedSidecar",
  "arguments": {
    "filePath": "/data/task-rest_events.json",
    "hedVersion": "8.4.0",
    "checkForWarnings": true
  }
}

// 2. Then validate TSV files with sidecar data
{
  "name": "validateHedTsv", 
  "arguments": {
    "filePath": "/data/sub-01_task-rest_events.tsv",
    "hedVersion": "8.4.0",
    "jsonData": "{...sidecar content...}",
    "checkForWarnings": true
  }
}

Scenario 2: Interactive Annotation

// Test individual HED strings during annotation
{
  "name": "validateHedString",
  "arguments": {
    "hedString": "Event/Sensory-event, (Red, Large)",
    "hedVersion": "8.4.0",
    "checkForWarnings": true
  }
}

Scenario 3: Definition Development

// Test definitions before using in datasets
{
  "name": "validateHedString",
  "arguments": {
    "hedString": "Def/MyStimulus, Blue",
    "hedVersion": "8.4.0", 
    "definitions": [
      "(Definition/MyStimulus, (Event/Sensory-event, (Onset)))"
    ],
    "checkForWarnings": true
  }
}

Error interpretation

Common error types

  1. TAG_INVALID: Tag not found in schema

    • Check spelling and capitalization
    • Verify tag exists in specified schema version
    • Consider using extension tags if appropriate
  2. DEFINITION_INVALID: Malformed definition

    • Ensure proper parentheses around definition content
    • Check that definition name follows conventions
    • Verify definition content is valid HED
  3. SCHEMA_LOAD_FAILED: Invalid schema version

    • Verify schema version exists
    • Check network connectivity for schema download
    • Use stable, released schema versions
  4. FILE_READ_ERROR: Cannot read specified file

    • Verify file path and permissions
    • Check file exists and is readable
    • Consider using inline data for virtual files

Warning types

  1. TAG_EXTENDED: Extension tag used

    • Consider using more specific standard tags
    • Acceptable for novel experimental paradigms
    • Document extensions for reproducibility
  2. DEFINITION_WARNING: Definition issues

    • Non-critical definition problems
    • May indicate style or convention issues
    • Review definition structure and content

Data quality guidelines

High-quality HED annotations

  1. Specificity: Use most specific appropriate tags
  2. Consistency: Apply same annotation patterns throughout dataset
  3. Completeness: Annotate all relevant aspects of events
  4. Accuracy: Ensure annotations match actual experimental events

Quality checklist

  • All files validate without errors
  • Warnings reviewed and addressed where appropriate
  • Definitions properly documented
  • Schema version appropriate for dataset
  • Annotations consistent across similar events

Performance optimization

Schema caching

The server automatically caches loaded schemas to improve performance:

// Schemas are cached by version string
const schema1 = await schemaCache.getOrCreateSchema('8.4.0');
const schema2 = await schemaCache.getOrCreateSchema('8.4.0'); // Uses cache

Definition reuse

Process definitions once and reuse:

// Define once, use multiple times
const definitions = [
  "(Definition/Fixation, (Event/Sensory-event, (Onset)))",
  "(Definition/Response, (Action/Move, Agent/Human))"
];

// Use in multiple validations
for (const hedString of hedStrings) {
  const result = await validate({
    hedString,
    hedVersion: '8.4.0',
    definitions  // Reuse same definitions
  });
}

Batch operations

// Efficient batch processing
const server = new MCPServer();
await server.connect();

try {
  const results = await Promise.all(
    files.map(file => 
      server.call('validateHedTsv', {
        filePath: file,
        hedVersion: '8.4.0'
      })
    )
  );
} finally {
  await server.disconnect();
}

Performance tips

Memory usage

  • Monitor memory usage with large datasets
  • Process files in batches if memory constrained
  • Clear unused schema cache entries
  • Use streaming for very large files

Speed optimization

  • Reuse server connections for multiple operations
  • Cache schemas and definitions between operations
  • Use inline data to avoid file I/O overhead
  • Disable warnings for production validation

Integration guide

MCP client integration

Basic client setup

import { MCPClient } from '@modelcontextprotocol/client';

const client = new MCPClient({
  server: {
    command: 'node',
    args: ['dist/server.js'],
    cwd: '/path/to/hed-mcp-typescript'
  }
});

await client.connect();

Error handling

async function safeValidation(hedString, hedVersion) {
  try {
    const response = await client.call('tools/call', {
      name: 'validateHedString',
      arguments: { hedString, hedVersion }
    });
    
    const result = JSON.parse(response.content[0].text);
    
    return {
      success: result.errors.length === 0,
      errors: result.errors,
      warnings: result.warnings
    };
  } catch (error) {
    return {
      success: false,
      errors: [{ 
        code: 'CLIENT_ERROR',
        message: error.message,
        severity: 'error'
      }],
      warnings: []
    };
  }
}

Python integration

import asyncio
import json
from mcp_client import MCPClient

class HEDValidator:
    def __init__(self, server_path):
        self.client = MCPClient(server_path)
    
    async def __aenter__(self):
        await self.client.connect()
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self.client.disconnect()
    
    async def validate_string(self, hed_string, hed_version="8.4.0", check_warnings=True):
        """Validate a HED string."""
        response = await self.client.call('tools/call', {
            'name': 'validateHedString',
            'arguments': {
                'hedString': hed_string,
                'hedVersion': hed_version,
                'checkForWarnings': check_warnings
            }
        })
        
        return json.loads(response['content'][0]['text'])
    
    async def validate_file(self, file_path, hed_version="8.4.0", definitions=None):
        """Validate a TSV file."""
        args = {
            'filePath': file_path,
            'hedVersion': hed_version,
            'checkForWarnings': True
        }
        
        if definitions:
            args['definitions'] = definitions
        
        response = await self.client.call('tools/call', {
            'name': 'validateHedTsv',
            'arguments': args
        })
        
        return json.loads(response['content'][0]['text'])

# Usage example
async def main():
    async with HEDValidator('/path/to/hed-mcp-typescript/dist/server.js') as validator:
        # Validate a HED string
        result = await validator.validate_string(
            "Event/Sensory-event, Red, Blue",
            hed_version="8.4.0"
        )
        
        if result['errors']:
            print("Validation errors found:")
            for error in result['errors']:
                print(f"  - {error['message']}")
        else:
            print("HED string is valid!")

if __name__ == "__main__":
    asyncio.run(main())

Command line integration

#!/bin/bash
# validate-dataset.sh - Validate all HED files in a BIDS dataset

DATASET_DIR="$1"
HED_VERSION="8.4.0"

echo "Validating BIDS dataset: $DATASET_DIR"

# Validate sidecar files
find "$DATASET_DIR" -name "*_events.json" | while read file; do
    echo "Validating sidecar: $file"
    # Call validateHedSidecar via MCP client
    validate_sidecar "$file" "$HED_VERSION"
done

# Validate TSV files  
find "$DATASET_DIR" -name "*_events.tsv" | while read file; do
    echo "Validating TSV: $file"
    # Call validateHedTsv via MCP client
    validate_tsv "$file" "$HED_VERSION"
done

echo "Dataset validation complete!"

Development

Project structure

src/
β”œβ”€β”€ server.ts              # Main MCP server (stdio/WebSocket)
β”œβ”€β”€ tools/                 # MCP tools (validation functions)
β”‚   β”œβ”€β”€ validateHedString.ts
β”‚   β”œβ”€β”€ validateHedTsv.ts
β”‚   β”œβ”€β”€ validateHedSidecar.ts
β”‚   └── getFileFromPath.ts
β”œβ”€β”€ resources/             # MCP resources (schema info)
β”‚   └── hedSchema.ts
β”œβ”€β”€ utils/                 # Utility functions
β”‚   β”œβ”€β”€ mcpToZod.ts
β”‚   β”œβ”€β”€ definitionProcessor.ts
β”‚   β”œβ”€β”€ fileReader.ts
β”‚   β”œβ”€β”€ issueFormatter.ts
β”‚   └── schemaCache.ts
└── types/                 # TypeScript type definitions
    └── index.ts

Available scripts

npm run build        # Build the TypeScript project
npm run dev          # Build in watch mode
npm run test         # Run the test suite
npm run test:watch   # Run tests in watch mode
npm run test:coverage # Generate test coverage report
npm run clean        # Clean build artifacts
npm start           # Run stdio MCP server
npm run start:http  # Run HTTP API server

Development Workflow

  1. Clone and install:

    git clone <repository-url>
    cd hed-mcp-typescript
    npm install
  2. Start development:

    npm run dev  # Builds in watch mode
  3. Test your changes:

    npm test
  4. Test with inspector:

    npx @modelcontextprotocol/inspector node dist/server.js

API documentation

For detailed API documentation, see API.md.

Key concepts:

  • FormattedIssue: Standardized error/warning format
  • HedValidationResult: Standard validation response format
  • Schema Caching: Automatic caching of loaded HED schemas
  • Definition Support: Process and use HED definitions during validation

Testing

The project includes comprehensive tests covering:

  • Unit tests: Individual function testing
  • Integration tests: Tool interaction testing
  • Data validation: Real HED data file testing

Run tests

# Run all tests
npm test

# Run with coverage
npm run test:coverage

# Run in watch mode during development
npm run test:watch

# Run only integration tests
npm test -- --testPathPattern=integration

Test data

Test files are located in tests/data/:

  • sub-002_ses-1_task-FacePerception_run-1_events.tsv
  • task-FacePerception_events.json
  • participants_bad.json
  • participants_bad.tsv

Related projects

πŸ“ž Support