Skip to main content
Glama

mock

Generate mock data for API endpoints from OpenAPI specs to enable frontend development without a backend.

Instructions

Genera datos mock/fake para un endpoint basándose en su spec OpenAPI importada. Útil para frontend sin backend.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesNombre del API importada
methodYesMétodo HTTP del endpoint
pathYesPath del endpoint (ej: "/users", "/blog")
targetNoGenerar mock del body de request o de la response (default: response)
statusNoStatus code de la respuesta a mockear (default: "200" o "201")
countNoNúmero de items mock a generar si el schema es un array (default: 3)

Implementation Reference

  • Main handler function 'generateMockData' that generates fake/mock data based on an OpenAPI schema. Handles objects, arrays, strings (with format-specific generation like date-time, email, uuid, etc.), numbers, and booleans.
    function generateMockData(schema: ApiSpecSchema, depth = 0): unknown {
      if (depth > 8) return null
    
      // If example exists, use it
      if (schema.example !== undefined) return schema.example
    
      // If enum, pick first value
      if (schema.enum && schema.enum.length > 0) {
        return schema.enum[Math.floor(Math.random() * schema.enum.length)]
      }
    
      switch (schema.type) {
        case 'object': {
          if (!schema.properties) return {}
          const obj: Record<string, unknown> = {}
          for (const [key, propSchema] of Object.entries(schema.properties)) {
            obj[key] = generateMockData(propSchema, depth + 1)
          }
          return obj
        }
    
        case 'array': {
          if (!schema.items) return []
          const count = Math.floor(Math.random() * 3) + 1 // 1-3 items
          return Array.from({ length: count }, () =>
            generateMockData(schema.items!, depth + 1),
          )
        }
    
        case 'string': {
          switch (schema.format) {
            case 'date-time':
              return new Date().toISOString()
            case 'date':
              return new Date().toISOString().split('T')[0]
            case 'email':
              return `user${Math.floor(Math.random() * 1000)}@example.com`
            case 'uri':
            case 'url':
              return 'https://example.com/resource'
            case 'uuid':
              return crypto.randomUUID()
            case 'ipv4':
              return `192.168.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`
            default: {
              // Use description or key name for smarter generation
              const desc = (schema.description ?? '').toLowerCase()
              if (desc.includes('name') || desc.includes('nombre'))
                return `Test User ${Math.floor(Math.random() * 100)}`
              if (desc.includes('title') || desc.includes('título'))
                return `Test Title ${Math.floor(Math.random() * 100)}`
              if (desc.includes('description') || desc.includes('descripción'))
                return 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
              if (desc.includes('password') || desc.includes('contraseña'))
                return 'TestPass123!'
              if (desc.includes('slug'))
                return `test-slug-${Math.floor(Math.random() * 1000)}`
              if (desc.includes('phone') || desc.includes('teléfono'))
                return '+34612345678'
              return `mock-string-${Math.floor(Math.random() * 10000)}`
            }
          }
        }
    
        case 'number':
        case 'integer':
          return Math.floor(Math.random() * 1000)
    
        case 'boolean':
          return Math.random() > 0.5
    
        default:
          return null
      }
    }
  • Tool handler function 'registerMockTool' that registers the 'mock' tool with the MCP server. Contains the main logic for looking up an API spec endpoint by method+path, extracting the request/response schema, and calling generateMockData to produce fake data.
    export function registerMockTool(server: McpServer, storage: Storage): void {
      server.tool(
        'mock',
        'Genera datos mock/fake para un endpoint basándose en su spec OpenAPI importada. Útil para frontend sin backend.',
        {
          name: z.string().describe('Nombre del API importada'),
          method: z
            .enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'])
            .describe('Método HTTP del endpoint'),
          path: z.string().describe('Path del endpoint (ej: "/users", "/blog")'),
          target: z
            .enum(['request', 'response'])
            .optional()
            .describe('Generar mock del body de request o de la response (default: response)'),
          status: z
            .string()
            .optional()
            .describe('Status code de la respuesta a mockear (default: "200" o "201")'),
          count: z
            .number()
            .optional()
            .describe('Número de items mock a generar si el schema es un array (default: 3)'),
        },
        async (params) => {
          try {
            const spec = await storage.getSpec(params.name)
            if (!spec) {
              return {
                content: [
                  {
                    type: 'text' as const,
                    text: `Error: API '${params.name}' no encontrada. Usa api_import para importarla primero.`,
                  },
                ],
                isError: true,
              }
            }
    
            const endpoint = spec.endpoints.find(
              (ep) => ep.method === params.method && ep.path === params.path,
            )
    
            if (!endpoint) {
              return {
                content: [
                  {
                    type: 'text' as const,
                    text: `Error: Endpoint ${params.method} ${params.path} no encontrado en '${params.name}'.`,
                  },
                ],
                isError: true,
              }
            }
    
            const target = params.target ?? 'response'
            let schema: ApiSpecSchema | undefined
    
            if (target === 'request') {
              // Get request body schema
              const content = endpoint.requestBody?.content
              if (content) {
                const jsonContent = content['application/json']
                schema = jsonContent?.schema
              }
    
              if (!schema) {
                return {
                  content: [
                    {
                      type: 'text' as const,
                      text: `Error: El endpoint ${params.method} ${params.path} no tiene un body schema definido.`,
                    },
                  ],
                  isError: true,
                }
              }
            } else {
              // Get response body schema
              const statusCode = params.status ?? (params.method === 'POST' ? '201' : '200')
              const response = endpoint.responses?.[statusCode]
    
              if (!response) {
                // Try to find any 2xx response
                const twoXX = Object.keys(endpoint.responses ?? {}).find((s) => s.startsWith('2'))
                if (twoXX && endpoint.responses) {
                  const fallbackResp = endpoint.responses[twoXX]
                  const content = fallbackResp?.content
                  if (content) {
                    const jsonContent = content['application/json']
                    schema = jsonContent?.schema
                  }
                }
              } else {
                const content = response.content
                if (content) {
                  const jsonContent = content['application/json']
                  schema = jsonContent?.schema
                }
              }
    
              if (!schema) {
                return {
                  content: [
                    {
                      type: 'text' as const,
                      text: `Error: No se encontró un schema de respuesta para ${params.method} ${params.path}.`,
                    },
                  ],
                  isError: true,
                }
              }
            }
    
            // Generate mock data
            let mockData: unknown
    
            if (schema.type === 'array' && params.count) {
              // Generate specific number of items
              mockData = Array.from({ length: params.count }, () =>
                generateMockData(schema!.items ?? { type: 'object' }),
              )
            } else {
              mockData = generateMockData(schema)
            }
    
            const label = target === 'request' ? 'REQUEST BODY' : 'RESPONSE'
    
            return {
              content: [
                {
                  type: 'text' as const,
                  text: [
                    `Mock ${label} para ${params.method} ${params.path}:`,
                    '',
                    '```json',
                    JSON.stringify(mockData, null, 2),
                    '```',
                    '',
                    'Datos generados automáticamente desde el spec OpenAPI.',
                    target === 'request'
                      ? 'Puedes usar estos datos directamente en un request.'
                      : 'Estos son datos de ejemplo que devolvería el endpoint.',
                  ].join('\n'),
                },
              ],
            }
          } catch (error) {
            const message = error instanceof Error ? error.message : String(error)
            return {
              content: [{ type: 'text' as const, text: `Error: ${message}` }],
              isError: true,
            }
          }
        },
      )
  • Type definition for 'ApiSpecSchema' which describes the OpenAPI schema structure used by generateMockData (type, format, properties, items, enum, example, etc.).
    export interface ApiSpecSchema {
      type?: string
      format?: string
      properties?: Record<string, ApiSpecSchema>
      items?: ApiSpecSchema
      required?: string[]
      enum?: unknown[]
      description?: string
      example?: unknown
      $ref?: string
    }
  • src/server.ts:69-70 (registration)
    Registration point where 'registerMockTool(server, storage)' is called in the MCP server factory.
    registerMockTool(server, storage)
    registerLoadTestTool(server, storage)
  • Test helper 'createMockFetch' and 'installMockFetch' for creating a mock fetch function used in tests (unrelated to the 'mock' tool itself, but shares naming).
    export function createMockFetch() {
      return vi.fn(async (url: string | URL, init?: RequestInit) => {
        const urlStr = url.toString()
        const method = init?.method ?? 'GET'
        const bodyStr = init?.body as string | undefined
    
        // Parse request headers
        const reqHeaders: Record<string, string> = {}
        if (init?.headers) {
          const entries = init.headers instanceof Headers
            ? Array.from(init.headers.entries())
            : Object.entries(init.headers as Record<string, string>)
          for (const [k, v] of entries) {
            reqHeaders[k] = v
          }
        }
    
        // Invalid URLs
        if (!urlStr.startsWith('http://') && !urlStr.startsWith('https://')) {
          throw new TypeError(`Invalid URL: ${urlStr}`)
        }
    
        // Simulate httpbin.org/get
        if (urlStr.includes('/get')) {
          const responseBody = {
            url: urlStr.split('?')[0],
            headers: {
              ...reqHeaders,
              ...(reqHeaders['Authorization'] ? { Authorization: reqHeaders['Authorization'] } : {}),
            },
            args: Object.fromEntries(new URL(urlStr).searchParams.entries()),
          }
    
          return new Response(JSON.stringify(responseBody), {
            status: 200,
            statusText: 'OK',
            headers: { 'content-type': 'application/json', 'content-length': '256' },
          })
        }
    
        // Simulate httpbin.org/post
        if (urlStr.includes('/post')) {
          let json = null
          try {
            json = bodyStr ? JSON.parse(bodyStr) : null
          } catch { /* not JSON */ }
    
          const responseBody = {
            url: urlStr.split('?')[0],
            headers: reqHeaders,
            json,
            data: bodyStr ?? '',
          }
    
          return new Response(JSON.stringify(responseBody), {
            status: 200,
            statusText: 'OK',
            headers: { 'content-type': 'application/json', 'content-length': '256' },
          })
        }
    
        // Simulate httpbin.org/headers
        if (urlStr.includes('/headers')) {
          const responseBody = {
            headers: reqHeaders,
          }
    
          return new Response(JSON.stringify(responseBody), {
            status: 200,
            statusText: 'OK',
            headers: { 'content-type': 'application/json', 'content-length': '128' },
          })
        }
    
        // Simulate httpbin.org/status/{code}
        const statusMatch = urlStr.match(/\/status\/(\d+)/)
        if (statusMatch) {
          const code = parseInt(statusMatch[1])
          return new Response('', {
            status: code,
            statusText: `Status ${code}`,
            headers: { 'content-length': '0' },
          })
        }
    
        // Default: 200 OK with echo
        return new Response(JSON.stringify({ method, url: urlStr }), {
          status: 200,
          statusText: 'OK',
          headers: { 'content-type': 'application/json', 'content-length': '64' },
        })
      })
    }
    
    /**
     * Installs mock fetch globally. Call in beforeAll/beforeEach.
     * Returns the mock for assertions.
     */
    export function installMockFetch() {
      const mockFetch = createMockFetch()
      vi.stubGlobal('fetch', mockFetch)
      return mockFetch
    }
    
    /**
     * Restores original fetch. Call in afterAll/afterEach.
     */
    export function restoreFetch() {
      vi.unstubAllGlobals()
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must disclose behavior. It only states it generates mock data but does not mention if it is read-only, what happens if the spec is missing, or any side effects. This is insufficient for full transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very concise with two sentences, front-loaded with the action and context. Every word is meaningful with no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has no output schema and 6 parameters, but the description does not explain what the output looks like or what to expect from the generated data. This lack of completeness could confuse an AI agent about the return format.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All parameters have descriptions in the input schema (100% coverage), so the description adds no additional meaning beyond what the schema already provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool generates mock/fake data for an endpoint using an imported OpenAPI spec, with a specific use case for frontend without backend. It is distinct from sibling tools which focus on API details, imports, or testing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions it's useful for frontend without backend, providing a clear context of use. However, it does not explicitly state when not to use it or mention alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/cocaxcode/api-testing-mcp'

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