Skip to main content
Glama
paulsham

Wiki Analytics Specification MCP Server

by paulsham

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
NameRequiredDescriptionDefault
event_nameYesName of the event to validate against
payloadYesThe payload object to validate

Implementation Reference

  • 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
      };
    }
  • 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']
    },
  • 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
        };
      }
    },
  • 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
          }
        ]
      };
    });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/paulsham/wiki-mcp-analytics-test-1.1.0'

If you have feedback or need assistance with the MCP directory API, please join our Discord server