validate_event_payload
Check analytics event payloads against specifications to identify errors, warnings, and valid fields for proper tracking implementation.
Instructions
Validate a tracking implementation payload against the event spec. Returns errors, warnings, and valid fields.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| event_name | Yes | Name of the event to validate against | |
| payload | Yes | The payload object to validate |
Implementation Reference
- src/mcp-server/tools.js:63-156 (handler)The main handler function for the 'validate_event_payload' tool. It retrieves the event spec, expands properties, validates provided payload fields against expected types and constraints, identifies unknown/missing fields, and returns validation results including errors, warnings, and valid fields.handler: async (args) => { const event = eventsMap.get(args.event_name); if (!event) { throw new NotFoundError('Event', args.event_name); } const expanded = getExpandedProperties(event); const errors = []; const warnings = []; const validFields = []; // Collect all expected properties const expectedProps = new Map(); for (const group of expanded.property_groups) { for (const prop of group.properties) { expectedProps.set(prop.name, prop); } } for (const prop of expanded.additional_properties) { expectedProps.set(prop.name, prop); } // Check provided fields for (const [key, value] of Object.entries(args.payload)) { const prop = expectedProps.get(key); if (!prop) { warnings.push({ field: key, issue: 'Unknown property not in spec' }); continue; } // Remove from expected (field was provided, even if invalid) expectedProps.delete(key); // Type validation const actualType = Array.isArray(value) ? 'array' : typeof value; const expectedType = prop.type === 'timestamp' ? 'string' : prop.type; if (expectedType !== actualType && expectedType !== 'unknown') { errors.push({ field: key, issue: 'Type mismatch', expected: prop.type, got: actualType }); continue; } // Constraint validation if (prop.constraints && prop.constraints !== '-') { if (prop.constraints.startsWith('enum:')) { const allowedValues = prop.constraints.substring(5).split(',').map(s => s.trim()); if (!allowedValues.includes(value)) { errors.push({ field: key, issue: 'Invalid enum value', expected: allowedValues, got: value }); continue; } } else if (prop.constraints.startsWith('regex:')) { const pattern = prop.constraints.substring(6).trim(); try { const regex = new RegExp(pattern); if (!regex.test(value)) { errors.push({ field: key, issue: 'Regex validation failed', expected: pattern, got: value }); continue; } } catch (e) { // Invalid regex pattern in spec } } } validFields.push(key); } // Check for missing properties for (const [name] of expectedProps) { warnings.push({ field: name, issue: 'Missing property' }); } return { valid: errors.length === 0, errors, warnings, valid_fields: validFields }; }
- src/mcp-server/tools.js:49-62 (schema)The input schema defining the expected arguments: event_name (string) and payload (object).inputSchema: { type: 'object', properties: { event_name: { type: 'string', description: 'Name of the event to validate against' }, payload: { type: 'object', description: 'The payload object to validate' } }, required: ['event_name', 'payload'] },
- src/mcp-server/tools.js:47-157 (registration)The tool object definition for 'validate_event_payload' within the exported 'tools' object, which is used by the MCP server to register and dispatch tool calls.validate_event_payload: { description: 'Validate a tracking implementation payload against the event spec. Returns errors, warnings, and valid fields.', inputSchema: { type: 'object', properties: { event_name: { type: 'string', description: 'Name of the event to validate against' }, payload: { type: 'object', description: 'The payload object to validate' } }, required: ['event_name', 'payload'] }, handler: async (args) => { const event = eventsMap.get(args.event_name); if (!event) { throw new NotFoundError('Event', args.event_name); } const expanded = getExpandedProperties(event); const errors = []; const warnings = []; const validFields = []; // Collect all expected properties const expectedProps = new Map(); for (const group of expanded.property_groups) { for (const prop of group.properties) { expectedProps.set(prop.name, prop); } } for (const prop of expanded.additional_properties) { expectedProps.set(prop.name, prop); } // Check provided fields for (const [key, value] of Object.entries(args.payload)) { const prop = expectedProps.get(key); if (!prop) { warnings.push({ field: key, issue: 'Unknown property not in spec' }); continue; } // Remove from expected (field was provided, even if invalid) expectedProps.delete(key); // Type validation const actualType = Array.isArray(value) ? 'array' : typeof value; const expectedType = prop.type === 'timestamp' ? 'string' : prop.type; if (expectedType !== actualType && expectedType !== 'unknown') { errors.push({ field: key, issue: 'Type mismatch', expected: prop.type, got: actualType }); continue; } // Constraint validation if (prop.constraints && prop.constraints !== '-') { if (prop.constraints.startsWith('enum:')) { const allowedValues = prop.constraints.substring(5).split(',').map(s => s.trim()); if (!allowedValues.includes(value)) { errors.push({ field: key, issue: 'Invalid enum value', expected: allowedValues, got: value }); continue; } } else if (prop.constraints.startsWith('regex:')) { const pattern = prop.constraints.substring(6).trim(); try { const regex = new RegExp(pattern); if (!regex.test(value)) { errors.push({ field: key, issue: 'Regex validation failed', expected: pattern, got: value }); continue; } } catch (e) { // Invalid regex pattern in spec } } } validFields.push(key); } // Check for missing properties for (const [name] of expectedProps) { warnings.push({ field: name, issue: 'Missing property' }); } return { valid: errors.length === 0, errors, warnings, valid_fields: validFields }; } },
- src/mcp-server/index.js:79-103 (registration)The generic MCP CallToolRequestSchema handler that dispatches to the specific tool handler based on name, effectively registering all tools from the imported 'tools' object including 'validate_event_payload'.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; const tool = tools[name]; if (!tool) { throw new Error(`Unknown tool: ${name}`); } const result = await tool.handler(args || {}); // Prepend outdated warning if present let responseText = JSON.stringify(result, null, 2); if (outdatedWarning) { responseText = `⚠️ Warning: ${outdatedWarning}\n\n${responseText}`; } return { content: [ { type: 'text', text: responseText } ] }; });