Skip to main content
Glama

usage_stats

View usage statistics for multiple AI models including call count, success rate, and average response time.

Instructions

查看各模型的使用统计(调用次数、成功率、平均耗时)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The case handler for 'usage_stats' tool. It calls globalStats.formatStats() and returns the formatted statistics as a text response.
    case 'usage_stats': {
      return {
        content: [
          {
            type: 'text',
            text: globalStats.formatStats(),
          },
        ],
      };
    }
  • Tool registration definition for 'usage_stats' with name, description, and empty input schema (no parameters).
    {
      name: 'usage_stats',
      description: '查看各模型的使用统计(调用次数、成功率、平均耗时)',
      inputSchema: {
        type: 'object',
        properties: {},
      },
    },
  • src/server.ts:259-267 (registration)
    The 'usage_stats' tool is registered as part of the tools array (presumably in a ListTools handler) alongside other tools like history_context and team_dashboard.
    {
      name: 'usage_stats',
      description: '查看各模型的使用统计(调用次数、成功率、平均耗时)',
      inputSchema: {
        type: 'object',
        properties: {},
      },
    },
    {
  • The UsageStats class that provides all statistics data: recording calls, computing per-model and global stats, formatting output. The singleton instance 'globalStats' is exported and used by the handler.
    export class UsageStats {
      private records: CallRecord[] = [];
      private readonly maxRecords: number;
      private readonly startTime: number;
    
      constructor(maxRecords: number = 1000) {
        this.maxRecords = maxRecords;
        this.startTime = Date.now();
      }
    
      /**
       * 记录一次调用
       */
      record(record: Omit<CallRecord, 'duration'>): void {
        const fullRecord: CallRecord = {
          ...record,
          duration: record.endTime - record.startTime,
        };
    
        this.records.push(fullRecord);
    
        // 限制记录数量
        if (this.records.length > this.maxRecords) {
          this.records = this.records.slice(-this.maxRecords);
        }
      }
    
      /**
       * 开始计时
       * @returns 结束计时的函数,调用时传入 success 和可选的 error
       */
      startTimer(model: string, taskType?: string): (success?: boolean, error?: string) => void {
        const startTime = Date.now();
        
        return (success: boolean = true, error?: string) => {
          this.record({
            model,
            startTime,
            endTime: Date.now(),
            success,
            error,
            taskType,
          });
        };
      }
    
      /**
       * 获取模型统计
       */
      getModelStats(model: string): ModelStats | null {
        const modelRecords = this.records.filter(r => r.model === model);
        
        if (modelRecords.length === 0) return null;
    
        const successRecords = modelRecords.filter(r => r.success);
        const durations = successRecords.map(r => r.duration);
    
        return {
          model,
          totalCalls: modelRecords.length,
          successCalls: successRecords.length,
          failedCalls: modelRecords.length - successRecords.length,
          successRate: successRecords.length / modelRecords.length,
          avgDuration: durations.length > 0 
            ? durations.reduce((a, b) => a + b, 0) / durations.length 
            : 0,
          minDuration: durations.length > 0 ? Math.min(...durations) : 0,
          maxDuration: durations.length > 0 ? Math.max(...durations) : 0,
          totalDuration: durations.reduce((a, b) => a + b, 0),
        };
      }
    
      /**
       * 获取全局统计
       */
      getGlobalStats(): GlobalStats {
        const models = new Set(this.records.map(r => r.model));
        const modelStats: ModelStats[] = [];
    
        for (const model of models) {
          const stats = this.getModelStats(model);
          if (stats) modelStats.push(stats);
        }
    
        const successRecords = this.records.filter(r => r.success);
        const totalDuration = this.records
          .filter(r => r.success)
          .reduce((a, b) => a + b.duration, 0);
    
        return {
          totalCalls: this.records.length,
          totalSuccess: successRecords.length,
          totalFailed: this.records.length - successRecords.length,
          totalDuration,
          avgDuration: successRecords.length > 0 
            ? totalDuration / successRecords.length 
            : 0,
          models: modelStats.sort((a, b) => b.totalCalls - a.totalCalls),
          since: this.startTime,
        };
      }
    
      /**
       * 格式化统计信息
       */
      formatStats(): string {
        const stats = this.getGlobalStats();
        const uptime = Math.floor((Date.now() - stats.since) / 1000 / 60);
    
        let output = `📊 **使用统计** (运行 ${uptime} 分钟)\n\n`;
        output += `| 指标 | 数值 |\n|------|------|\n`;
        output += `| 总调用 | ${stats.totalCalls} 次 |\n`;
        output += `| 成功 | ${stats.totalSuccess} 次 |\n`;
        output += `| 失败 | ${stats.totalFailed} 次 |\n`;
        output += `| 平均耗时 | ${(stats.avgDuration / 1000).toFixed(2)}s |\n`;
        output += `| 总耗时 | ${(stats.totalDuration / 1000).toFixed(1)}s |\n\n`;
    
        if (stats.models.length > 0) {
          output += `### 各模型统计\n\n`;
          output += `| 模型 | 调用 | 成功率 | 平均耗时 |\n|------|------|--------|----------|\n`;
          
          for (const model of stats.models) {
            output += `| ${model.model} | ${model.totalCalls} | ${(model.successRate * 100).toFixed(0)}% | ${(model.avgDuration / 1000).toFixed(2)}s |\n`;
          }
        }
    
        return output;
      }
    
      /**
       * 清空统计
       */
      clear(): void {
        this.records = [];
      }
    
      /**
       * 获取最近的调用记录
       */
      getRecentRecords(count: number = 10): CallRecord[] {
        return this.records.slice(-count);
      }
    }
    
    /** 全局统计实例 */
    export const globalStats = new UsageStats();
  • Type definitions (interfaces) used by the UsageStats system: CallRecord (individual call), ModelStats (per-model aggregation), and GlobalStats (overall summary).
    export interface CallRecord {
      /** 模型名称 */
      model: string;
      /** 开始时间 */
      startTime: number;
      /** 结束时间 */
      endTime: number;
      /** 耗时(毫秒) */
      duration: number;
      /** 是否成功 */
      success: boolean;
      /** 错误信息 */
      error?: string;
      /** 任务类型 */
      taskType?: string;
    }
    
    /**
     * 模型统计信息
     */
    export interface ModelStats {
      /** 模型名称 */
      model: string;
      /** 总调用次数 */
      totalCalls: number;
      /** 成功次数 */
      successCalls: number;
      /** 失败次数 */
      failedCalls: number;
      /** 成功率 */
      successRate: number;
      /** 平均耗时(毫秒) */
      avgDuration: number;
      /** 最短耗时 */
      minDuration: number;
      /** 最长耗时 */
      maxDuration: number;
      /** 总耗时 */
      totalDuration: number;
    }
    
    /**
     * 全局统计信息
     */
    export interface GlobalStats {
      /** 总调用次数 */
      totalCalls: number;
      /** 总成功次数 */
      totalSuccess: number;
      /** 总失败次数 */
      totalFailed: number;
      /** 总耗时 */
      totalDuration: number;
      /** 平均耗时 */
      avgDuration: number;
      /** 各模型统计 */
      models: ModelStats[];
      /** 统计开始时间 */
      since: number;
    }
Behavior4/5

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

The description explicitly indicates a read-only operation ('查看'), which is appropriate. With no annotations provided, it carries the full burden; however, no additional behavioral details (e.g., data freshness, side effects) are given, which is acceptable for a simple stateless tool.

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?

A single, clear sentence efficiently communicates the tool's purpose and output. No redundant words.

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

Completeness4/5

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

The description lists the key metrics returned (call count, success rate, average time), which is sufficient for a simple read-only tool with no output schema. However, it does not specify the time range or grouping, leaving minor ambiguity.

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

Parameters4/5

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

The tool has zero parameters, so the description does not need to explain parameter semantics. Baseline of 4 is warranted as per guidelines.

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 verb (查看/view) and the resource (各模型的使用统计/usage statistics for each model), listing specific metrics. It is distinct from sibling tools, which are unrelated to statistics.

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

Usage Guidelines3/5

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

The description implies when to use this tool (to view usage stats), but provides no explicit when-not-to-use conditions or alternatives. Given no sibling tools conflict, this is adequate but not exemplary.

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/7836246/claude-team-mcp'

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