Skip to main content
Glama
Kong

Kong Konnect MCP Server

Official
by Kong

get_consumer_requests

Retrieve and analyze API request data for a specific consumer in Kong Konnect, including usage statistics, latency metrics, and detailed request logs.

Instructions

Retrieve and analyze API requests made by a specific consumer.

INPUT:

  • consumerId: String - ID of the consumer to analyze. The format of this field must be "controlPlaneID:consumerId".

  • timeRange: String - Time range for data retrieval (15M, 1H, 6H, 12H, 24H, 7D)

  • successOnly: Boolean - Filter to only show successful (2xx) requests (default: false)

  • failureOnly: Boolean - Filter to only show failed (non-2xx) requests (default: false)

  • maxResults: Number - Maximum number of results to return (1-1000)

OUTPUT:

  • metadata: Object - Contains consumerId, totalRequests, timeRange, and filters

  • statistics: Object - Usage statistics including:

    • averageLatencyMs: Number - Average response time in milliseconds

    • successRate: Number - Percentage of successful requests

    • statusCodeDistribution: Array - Breakdown of requests by status code

    • serviceDistribution: Array - Breakdown of requests by service

  • requests: Array - List of requests with details for each request

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
consumerIdYesConsumer ID to filter by (obtainable from analyze-failed-requests or query-api-requests tools)
timeRangeNoTime range for data retrieval (15M = 15 minutes, 1H = 1 hour, etc.)1H
successOnlyNoShow only successful (2xx) requests
failureOnlyNoShow only failed (non-2xx) requests
maxResultsNoNumber of items to return per page

Implementation Reference

  • The main handler function that queries API requests filtered by consumer ID, optionally success/failure status, computes aggregated statistics (average latency, success rate, status code and service distributions), and returns structured metadata, statistics, and detailed request list.
    export async function getConsumerRequests(
      api: KongApi,
      consumerId: string,
      timeRange: string,
      successOnly = false,
      failureOnly = false,
      maxResults = 100
    ) {
      try {
        // Build filters array
        const filters: ApiRequestFilter[] = [
          {
            field: "consumer",
            operator: "in",
            value: [consumerId]
          }
        ];
    
        // Add status code filter if needed
        if (successOnly) {
          filters.push({
            field: "status_code_grouped",
            operator: "in",
            value: ["2XX"]
          });
        } else if (failureOnly) {
          filters.push({
            field: "status_code_grouped",
            operator: "in",
            value: ["4XX", "5XX"]
          });
        }
    
        const result = await api.queryApiRequests(timeRange, filters, maxResults);
        
        // Calculate some statistics if we have results
        let avgLatency = 0;
        let successRate = 0;
        let statusCodeCounts: Record<string, number> = {};
        let serviceBreakdown: Record<string, { count: number, statusCodes: Record<string, number> }> = {};
        
        if (result.results.length > 0) {
          // Calculate average latency
          avgLatency = result.results.reduce((sum, req) => sum + (req.latencies_response_ms || 0), 0) / result.results.length;
          
          // Calculate success rate
          const successCount = result.results.filter(req => {
            const status = req.status_code ?? req.response_http_status ?? 0; // Default to 0 if both are undefined
            return status >= 200 && status < 300;
          }).length;
          successRate = (successCount / result.results.length) * 100;
          
          // Count status codes
          result.results.forEach(req => {
            const status = req.status_code ?? req.response_http_status ?? 0; // Default to 0 if both are undefined
            statusCodeCounts[status] = (statusCodeCounts[status] || 0) + 1;
          });
          
          // Service breakdown
          result.results.forEach(req => {
            const service = req.gateway_service ?? "unknown"; // Using ?? instead of || for null/undefined handling
            if (!serviceBreakdown[service]) {
              serviceBreakdown[service] = { count: 0, statusCodes: {} };
            }
            serviceBreakdown[service].count++;
            
            const status = req.status_code ?? req.response_http_status ?? 0; // Default to 0 if both are undefined
            serviceBreakdown[service].statusCodes[status] = (serviceBreakdown[service].statusCodes[status] || 0) + 1;
          });
        }
    
        // Format the response in a readable way
        return {
          metadata: {
            consumerId: consumerId,
            totalRequests: result.results.length,
            timeRange: {
              start: result.meta.time_range.start,
              end: result.meta.time_range.end,
            },
            filters: {
              successOnly,
              failureOnly
            }
          },
          statistics: {
            averageLatencyMs: parseFloat(avgLatency.toFixed(2)),
            successRate: parseFloat(successRate.toFixed(2)),
            statusCodeDistribution: Object.entries(statusCodeCounts).map(([code, count]) => ({
              statusCode: parseInt(code),
              count: count,
              percentage: parseFloat(((count / result.results.length) * 100).toFixed(2))
            })).sort((a, b) => b.count - a.count),
            serviceDistribution: Object.entries(serviceBreakdown).map(([service, data]) => ({
              serviceId: service,
              count: data.count,
              percentage: parseFloat(((data.count / result.results.length) * 100).toFixed(2)),
              statusCodeBreakdown: Object.entries(data.statusCodes).map(([code, count]) => ({
                statusCode: parseInt(code),
                count: count
              })).sort((a, b) => b.count - a.count)
            })).sort((a, b) => b.count - a.count)
          },
          requests: result.results.map(req => ({
            timestamp: req.request_start,
            httpMethod: req.http_method,
            uri: req.request_uri,
            statusCode: req.status_code || req.response_http_status,
            serviceId: req.gateway_service,
            routeId: req.route,
            latency: {
              totalMs: req.latencies_response_ms,
              gatewayMs: req.latencies_kong_gateway_ms,
              upstreamMs: req.latencies_upstream_ms
            },
            clientIp: req.client_ip,
            traceId: req.trace_id
          }))
        };
      } catch (error) {
        throw error;
      }
  • Zod input schema defining required consumerId, timeRange, optional successOnly/failureOnly flags, and maxResults for the get_consumer_requests tool.
    export const getConsumerRequestsParameters = () => z.object({
      consumerId: z.string()
        .describe("Consumer ID to filter by (obtainable from analyze-failed-requests or query-api-requests tools)"),
      timeRange: timeRangeSchema,
      successOnly: z.boolean()
        .default(false)
        .describe("Show only successful (2xx) requests"),
      failureOnly: z.boolean()
        .default(false)
        .describe("Show only failed (non-2xx) requests"),
      maxResults: pageSizeSchema,
    });
  • src/tools.ts:24-30 (registration)
    Tool definition object exported from tools.ts listing, specifying method name, name, description prompt function, parameters schema function, and category; used for MCP tool registration.
    {
      method: "get_consumer_requests",
      name: "Get Consumer Requests",
      description: prompts.getConsumerRequestsPrompt(),
      parameters: parameters.getConsumerRequestsParameters(),
      category: "analytics"
    },
  • src/index.ts:62-71 (registration)
    Switch case dispatcher in the main MCP server that maps the 'get_consumer_requests' method to the analytics handler function, passing API instance and validated args.
    case "get_consumer_requests":
      result = await analytics.getConsumerRequests(
        this.api,
        args.consumerId,
        args.timeRange,
        args.successOnly,
        args.failureOnly,
        args.maxResults
      );
      break;
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure. While it describes what data is retrieved and analyzed, it doesn't mention important behavioral aspects like rate limits, authentication requirements, data freshness, or whether this is a read-only operation. The description provides functional information but lacks operational context.

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

Conciseness4/5

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

The description is well-structured with clear sections (purpose statement, INPUT, OUTPUT) and uses bullet points effectively. While somewhat verbose in repeating schema information, every sentence serves a purpose and the information is front-loaded with the core purpose statement first.

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

Completeness3/5

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

For a tool with 5 parameters, no annotations, and no output schema, the description provides adequate functional coverage but lacks operational context. The OUTPUT section helpfully describes the return structure, compensating for the missing output schema, but doesn't address behavioral aspects like permissions, rate limits, or data limitations that would be important for an API analysis tool.

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?

With 100% schema description coverage, the schema already documents all parameters thoroughly. The description's INPUT section essentially repeats what's in the schema without adding significant additional context or clarifying relationships between parameters (like how successOnly and failureOnly interact). Baseline 3 is appropriate when schema does the heavy lifting.

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's purpose with specific verbs ('retrieve and analyze') and resource ('API requests made by a specific consumer'). It distinguishes itself from sibling tools like 'query_api_requests' by focusing specifically on consumer-level analysis rather than general API request querying.

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 implies usage context by specifying it's for analyzing consumer-specific API requests, but doesn't explicitly state when to use this tool versus alternatives like 'query_api_requests' or 'list_consumers'. It provides clear filtering capabilities but lacks explicit guidance on tool selection scenarios.

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/Kong/mcp-konnect'

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