HED MCP Server¶
A Model Context Protocol (MCP) server for validating HED (Hierarchical Event Descriptor) data.
HED MCP TypeScript Server¶
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, Property/Sensory-property/Visual/Color/Red
Using Definitions¶
Def/StimulusOnset, Property/Sensory-property/Visual/Color/Blue
Schema Versions¶
HED schemas evolve over time. Use the latest version whenever possible:
Standard HED:
8.4.0- Basic vocabularyLibrary schemas:
lang_1.1.0- Language-related tagsscore_2.1.0- EEG features based on SCORE standard
🔧 Installation¶
Prerequisites¶
Before using the HED MCP Server, ensure you have:
Node.js 18+: Download from nodejs.org
Basic understanding of HED: Familiarity with HED concepts is helpful
MCP-compatible client: Such as the MCP Inspector or custom client
Install Dependencies¶
npm install
Build the Server¶
npm run build
This creates the distribution files in the dist/ directory.
Test the Installation¶
npx @modelcontextprotocol/inspector node dist/server.js
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
│ ├── schemaCache.ts # Schema caching system
│ ├── definitionProcessor.ts
│ ├── fileReader.ts
│ ├── issueFormatter.ts
│ └── mcpToZod.ts
└── types/ # TypeScript definitions
Examples (examples/)
├── http-server.ts # HTTP REST API server example
├── hed-validator.html # Browser validation interface
├── hed-demo.html # Interactive demo and guide
├── mcp-client.js # MCP protocol client example
└── ... # Additional examples and utilities
└── index.ts
Data Flow¶
Client request → MCP server
Schema loading → Cache or load from network
Data processing → Parse and validate
Issue formatting → Standardize error/Warning format
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
� Quick start¶
Run with MCP Inspector¶
The fastest way to test the server is using the MCP Inspector:
npx @modelcontextprotocol/inspector node dist/server.js
This opens a web interface where you can interact with the server and test all available tools.
Basic server rest¶
Test the server directly:
# Standard MCP server (stdio mode)
npm start
# WebSocket mode
node dist/server.js --websocket --port=8080
# HTTP REST API server
npm run start:http
Or test with the included client:
node test-mcp-client.js
First steps¶
Open the MCP Inspector in your browser
Initialize the server - this happens automatically
List available tools to see what’s available
Try a simple validation with
validateHedString
🛠 Available tools¶
Tool |
Description |
Required parameters |
Optional parameters |
|---|---|---|---|
|
Validates HED tag strings |
|
|
|
Validates TSV files with HED |
|
|
|
Validates HED sidecar JSON files |
|
|
|
Reads files from filesystem |
|
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 validatehedVersion(required): Schema version (e.g., “8.4.0”)checkForWarnings(optional): Include warnings in resultsdefinitions(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 filehedVersion(required): Schema versioncheckForWarnings(optional): Include warningsfileData(optional): Inline TSV datajsonData(optional): Sidecar data as JSON stringdefinitions(optional): Definition strings
Best practices:
Use
fileDatafor small datasets to avoid file I/OInclude sidecar data via
jsonDatafor complete validationProcess 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 filehedVersion(required): Schema versioncheckForWarnings(optional): Include warningsfileData(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)
💡 Usage examples¶
Validate a HED string¶
{
"method": "tools/call",
"params": {
"name": "validateHedString",
"arguments": {
"hedString": "Event/Sensory-event, Red, Blue, (Green, Large)",
"hedVersion": "8.4.0",
"checkForWarnings": true
}
}
}
Validate a TSV File¶
{
"method": "tools/call",
"params": {
"name": "validateHedTsv",
"arguments": {
"filePath": "/tests/data/sub-002_ses-1_task-FacePerception_run-1_events.tsv",
"hedVersion": "8.4.0",
"checkForWarnings": true,
"definitions": [
"(Definition/Fixation, (Sensory-event, Visual-presentation, (Image, Cross))",
"(Definition/ButtonPress, (Press, Mouse-button))"
]
}
}
}
Validate a BIDS JSON sidecar¶
{
"method": "tools/call",
"params": {
"name": "validateHedSidecar",
"arguments": {
"filePath": "/tests/data/task-FacePerception_events.json",
"hedVersion": "8.4.0",
"checkForWarnings": false
}
}
}
Read a File¶
{
"method": "tools/call",
"params": {
"name": "getFileFromPath",
"arguments": {
"filePath": "/path/to/data/events.tsv"
}
}
}
Working with HED Data¶
Validation Workflow¶
Schema Selection: Choose appropriate HED schema version
Definition Setup: Prepare any custom definitions
Data Validation: Run appropriate validation tool
Issue Resolution: Address errors and warnings
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¶
TAG_INVALID: Tag not found in schema
Check spelling and capitalization
Verify tag exists in specified schema version
Consider using extension tags if appropriate
DEFINITION_INVALID: Malformed definition
Ensure proper parentheses around definition content
Check that definition name follows conventions
Verify definition content is valid HED
SCHEMA_LOAD_FAILED: Invalid schema version
Verify schema version exists
Check network connectivity for schema download
Use stable, released schema versions
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¶
TAG_EXTENDED: Extension tag used
Consider using more specific standard tags
Acceptable for novel experimental paradigms
Document extensions for reproducibility
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¶
Specificity: Use most specific appropriate tags
Consistency: Apply same annotation patterns throughout dataset
Completeness: Annotate all relevant aspects of events
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
🌐 Browser usage¶
The HED MCP server can be used in browsers through several approaches. All browser files are located in the examples/ directory.
Option 1: Complete Validation Interface¶
Open examples/hed-validator.html for a full-featured web interface:
Multiple validation modes: String, TSV, and Sidecar validation
Modern UI: Clean, responsive design with professional styling
Real-time feedback: Instant validation results with detailed error reporting
Multiple HED versions: Support for different schema versions and libraries
# Serve the examples locally
npx serve examples/
# Or open directly in browser
open examples/hed-validator.html
Option 2: Interactive Demo & Integration Guide¶
View examples/hed-demo.html for:
Live examples: Pre-configured validation scenarios
Integration guide: Complete API documentation and code examples
Developer tools: Quick validation form for testing
Option 3: Browser Client Library¶
Include the modern browser client in your web application:
<link rel="stylesheet" href="examples/hed-validator.css">
<script src="examples/hed-validator-client.js"></script>
<script>
// Create validator client (auto-detects server availability)
const validator = new HEDValidatorClient();
// Validate HED string
const result = await validator.validateString('Event/Sensory-event, Red');
// Or create a pre-built validation form
HEDValidatorClient.createValidationForm('my-container');
</script>
Option 4: Full HTTP API Integration¶
For complete server-based validation, run the HTTP API server:
npm run build
node dist/examples/http-server.js
The browser client automatically detects and uses the server at http://localhost:3000/api/hed/.
Quick Start: Open examples/hed-validator.html to immediately start validating HED data in your browser!
Web application integration¶
<!DOCTYPE html>
<html>
<head>
<title>HED Validator</title>
</head>
<body>
<textarea id="hedInput" placeholder="Enter HED string..."></textarea>
<button onclick="validateHED()">Validate</button>
<div id="results"></div>
<script>
async function validateHED() {
const hedString = document.getElementById('hedInput').value;
try {
const response = await fetch('/api/validate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
hedString,
hedVersion: '8.4.0',
checkForWarnings: true
})
});
const result = await response.json();
displayResults(result);
} catch (error) {
console.error('Validation failed:', error);
}
}
function displayResults(result) {
const resultsDiv = document.getElementById('results');
if (result.errors.length === 0) {
resultsDiv.innerHTML = '<p style="color: green;">✅ Valid HED string!</p>';
} else {
resultsDiv.innerHTML = '<p style="color: red;">❌ Validation errors:</p>';
result.errors.forEach(error => {
resultsDiv.innerHTML += `<p>• ${error.message}</p>`;
});
}
if (result.warnings.length > 0) {
resultsDiv.innerHTML += '<p style="color: orange;">⚠️ Warnings:</p>';
result.warnings.forEach(warning => {
resultsDiv.innerHTML += `<p>• ${warning.message}</p>`;
});
}
}
</script>
</body>
</html>
⚙️ Configuration¶
MCP client configuration¶
Add to your MCP client configuration:
{
"servers": {
"hed-mcp": {
"command": "node",
"args": ["dist/server.js"],
"cwd": "/path/to/hed-mcp-typescript"
}
}
}
WebSocket mode¶
Run the server in WebSocket mode for browser-based MCP clients:
node dist/server.js --websocket --port=8080
Environment variables¶
The server respects standard Node.js environment variables:
NODE_ENV: Set todevelopmentfor verbose loggingDEBUG: Enable debug output for troubleshooting
Debug mode¶
Enable debug logging:
DEBUG=* node dist/server.js
Or in MCP client configuration:
{
"servers": {
"hed-mcp": {
"command": "node",
"args": ["dist/server.js"],
"env": {
"DEBUG": "*"
}
}
}
}
Definition management¶
Definition best practices¶
Naming: Use descriptive, unique names
Structure: Keep definitions simple and focused
Reusability: Design for reuse across similar experiments
Documentation: Document purpose and usage
Definition examples¶
// Simple stimulus definition
"(Definition/RedCircle, (Event/Sensory-event, (Red, Circle)))"
// Complex behavioral definition
"(Definition/CorrectResponse, (Action/Move, Agent/Human, (Correct-action, (Voluntary))))"
// Hierarchical definitions
"(Definition/VisualStimulus, (Event/Sensory-event, Property/Sensory-property/Visual))"
"(Definition/RedVisualStimulus, (Def/VisualStimulus, Red))"
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¶
Clone and install:
git clone <repository-url> cd hed-mcp-typescript npm install
Start development:
npm run dev # Builds in watch mode
Test your changes:
npm test
Test with inspector:
npx @modelcontextprotocol/inspector node dist/server.js
🚨 Troubleshooting¶
Common issues¶
Issue: Server won’t start¶
Symptoms: Server exits immediately or shows connection errors
Solutions:
Check Node.js version (requires 18+)
Verify build completed successfully:
npm run buildCheck for port conflicts
Review error messages in console
Issue: Schema loading failures¶
Symptoms: SCHEMA_LOAD_FAILED errors
Solutions:
Verify internet connectivity for schema downloads
Use exact schema version strings
Check schema cache directory permissions
Try clearing cache: delete node_modules and reinstall
Issue: File reading errors¶
Symptoms: FILE_READ_ERROR when accessing files
Solutions:
Verify file paths are absolute
Check file permissions and existence
Use inline data (
fileData) for testingEnsure proper file encoding (UTF-8)
Issue: Validation inconsistencies¶
Symptoms: Different results from same input
Solutions:
Ensure consistent schema versions
Clear schema cache if needed
Check for concurrent validation conflicts
Verify definition ordering and consistency
Performance issues¶
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
📖 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.tsvtask-FacePerception_events.jsonparticipants_bad.jsonparticipants_bad.tsv
🤝 Contributing¶
Fork the repository
Create a feature branch:
git checkout -b feature/amazing-featureMake your changes and add tests
Run the test suite:
npm testCommit your changes:
git commit -m 'Add amazing feature'Push to the branch:
git push origin feature/amazing-featureOpen a Pull Request
Code style¶
Use TypeScript strict mode
Follow existing naming conventions
Add JSDoc comments for public APIs
Ensure all tests pass before submitting
📄 License¶
This project is licensed under the ISC License - see the LICENSE file for details.
📞 Support¶
Documentation: