Skip to main content
Glama
sapientpants

DeepSource MCP Server

by sapientpants

quality_metrics

Retrieve code quality metrics from DeepSource projects to analyze performance, identify issues, and monitor development progress with optional filtering capabilities.

Instructions

Get quality metrics from a DeepSource project with optional filtering

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectKeyYesDeepSource project key to fetch quality metrics for
shortcodeInNoOptional filter for specific metric shortcodes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
metricsYes

Implementation Reference

  • Top-level handler function for the "quality_metrics" tool. Orchestrates dependency injection (repository factory, logger), invokes the core handler logic, and handles errors.
    export async function handleDeepsourceQualityMetrics(params: DeepsourceQualityMetricsParams) {
      try {
        const baseDeps = createDefaultHandlerDeps({ logger });
        const apiKey = baseDeps.getApiKey();
        const repositoryFactory = new RepositoryFactory({ apiKey });
        const qualityMetricsRepository = repositoryFactory.createQualityMetricsRepository();
    
        const deps: QualityMetricsHandlerDeps = {
          qualityMetricsRepository,
          logger,
        };
    
        const handler = createQualityMetricsHandlerWithRepo(deps);
        const result = await handler(params);
    
        return result;
      } catch (error) {
        // Handle configuration errors and other setup issues
        return MCPErrorFormatter.createErrorResponse(error, 'quality-metrics-setup');
      }
    }
  • Core handler logic (handleQualityMetrics) that fetches metrics from the domain repository, applies filtering, formats response with threshold analysis, and returns MCP-compliant content.
    export function createQualityMetricsHandlerWithRepo(deps: QualityMetricsHandlerDeps) {
      return async function handleQualityMetrics(params: DeepsourceQualityMetricsParams) {
        try {
          const { projectKey, shortcodeIn } = params;
    
          // Validate required parameters using MCP error handling
          validateNonEmptyString(projectKey, 'projectKey');
    
          const projectKeyBranded = asProjectKey(projectKey);
          deps.logger.info('Fetching quality metrics from repository', { projectKey, shortcodeIn });
    
          // Get metrics from repository with server-side filtering if shortcodes specified
          const filteredMetrics = shortcodeIn
            ? await deps.qualityMetricsRepository.findByProjectWithFilter(
                projectKeyBranded,
                shortcodeIn
              )
            : await deps.qualityMetricsRepository.findByProject(projectKeyBranded);
    
          deps.logger.info('Successfully fetched quality metrics', {
            count: filteredMetrics.length,
            projectKey,
          });
    
          const metricsData = {
            metrics: filteredMetrics.map((domainMetric: QualityMetrics) => ({
              name: domainMetric.configuration.name,
              shortcode: domainMetric.configuration.shortcode,
              description: domainMetric.configuration.description,
              positiveDirection: domainMetric.configuration.positiveDirection,
              unit: domainMetric.configuration.unit,
              minValueAllowed: domainMetric.configuration.minAllowed,
              maxValueAllowed: domainMetric.configuration.maxAllowed,
              isReported: domainMetric.configuration.isReported,
              isThresholdEnforced: domainMetric.configuration.isThresholdEnforced,
              items: [
                {
                  id: domainMetric.repositoryId,
                  key: domainMetric.configuration.metricKey,
                  threshold: domainMetric.configuration.threshold?.value ?? null,
                  latestValue: domainMetric.currentValue?.value ?? null,
                  latestValueDisplay: domainMetric.currentValue?.displayValue ?? null,
                  thresholdStatus: domainMetric.thresholdStatus,
                  // Add helpful metadata for threshold values
                  thresholdInfo:
                    domainMetric.configuration.threshold &&
                    domainMetric.currentValue &&
                    domainMetric.configuration.threshold.value !== null &&
                    domainMetric.currentValue.value !== null
                      ? {
                          difference:
                            domainMetric.currentValue.value -
                            domainMetric.configuration.threshold.value,
                          percentDifference:
                            domainMetric.configuration.threshold.value !== 0
                              ? `${(((domainMetric.currentValue.value - domainMetric.configuration.threshold.value) / domainMetric.configuration.threshold.value) * 100).toFixed(2)}%`
                              : 'N/A',
                          isPassing: domainMetric.isCompliant,
                        }
                      : null,
                },
              ],
            })),
            // Add helpful examples for threshold management
            usage_examples: {
              filtering:
                'To filter metrics by type, use the shortcodeIn parameter with specific metric codes (e.g., ["LCV", "BCV"])',
              updating_threshold: 'To update a threshold, use the update_metric_threshold tool',
              updating_settings:
                'To update metric settings (e.g., enable reporting or threshold enforcement), use the update_metric_setting tool',
            },
          };
    
          return {
            content: [
              {
                type: 'text' as const,
                text: JSON.stringify(metricsData),
              },
            ],
          };
        } catch (error) {
          deps.logger.error('Error in handleQualityMetrics', {
            errorType: typeof error,
            errorName: error instanceof Error ? error.name : 'Unknown',
            errorMessage: error instanceof Error ? error.message : String(error),
            errorStack: error instanceof Error ? error.stack : 'No stack available',
          });
    
          // Use MCP-compliant error formatting
          return MCPErrorFormatter.createErrorResponse(error, 'quality-metrics-fetch');
        }
      };
    }
  • Zod-based input and output schema definition for the quality_metrics tool, including parameter descriptions and structured response validation.
    export const qualityMetricsToolSchema = {
      name: 'quality_metrics',
      description: 'Get quality metrics from a DeepSource project with optional filtering',
      inputSchema: {
        projectKey: z.string().describe('DeepSource project key to fetch quality metrics for'),
        shortcodeIn: z
          .array(z.nativeEnum(MetricShortcode))
          .optional()
          .describe('Optional filter for specific metric shortcodes'),
      },
      outputSchema: {
        metrics: z.array(
          z.object({
            name: z.string(),
            shortcode: z.string(),
            description: z.string(),
            positiveDirection: z.string(),
            unit: z.string(),
            minValueAllowed: z.number().nullable(),
            maxValueAllowed: z.number().nullable(),
            isReported: z.boolean(),
            isThresholdEnforced: z.boolean(),
            items: z.array(
              z.object({
                id: z.string(),
                key: z.string(),
                threshold: z.number().nullable(),
                latestValue: z.number().nullable(),
                latestValueDisplay: z.string().nullable(),
                thresholdStatus: z.string(),
                thresholdInfo: z
                  .object({
                    difference: z.number(),
                    percentDifference: z.string(),
                    isPassing: z.boolean(),
                  })
                  .nullable(),
              })
            ),
          })
        ),
      },
    };
  • Main registration function that creates ToolDefinition objects from toolSchemas (including quality_metrics) and their corresponding handlers, then registers them with the ToolRegistry used by MCP server.
    export function registerDeepSourceTools(registry: ToolRegistry): void {
      logger.info('=== REGISTER DEEPSOURCE TOOLS START ===');
      logger.info('Registering DeepSource tools', {
        toolSchemasType: typeof toolSchemas,
        toolSchemasIsArray: Array.isArray(toolSchemas),
        toolSchemasLength: Array.isArray(toolSchemas) ? toolSchemas.length : 'not an array',
        toolSchemaNames: Array.isArray(toolSchemas) ? toolSchemas.map((s) => s.name) : 'not an array',
      });
    
      const toolDefinitions: ToolDefinition[] = [];
    
      // Create tool definitions from schemas and handlers
      for (const schema of toolSchemas) {
        logger.debug(`Processing schema: ${schema.name}`);
        const handler = TOOL_HANDLERS[schema.name];
        if (!handler) {
          logger.warn(`No handler found for tool: ${schema.name}`);
          continue;
        }
    
        logger.debug(`Creating tool definition for: ${schema.name}`);
        const toolDef = createToolDefinition(schema, handler);
        toolDefinitions.push(toolDef);
        logger.debug(`Successfully created tool definition for: ${schema.name}`);
      }
    
      logger.info(`Prepared ${toolDefinitions.length} tool definitions for registration`);
    
      // Register all tools
      registry.registerTools(toolDefinitions);
    
      logger.info('=== REGISTER DEEPSOURCE TOOLS COMPLETE ===', {
        registeredCount: toolDefinitions.length,
        registeredTools: toolDefinitions.map((t) => t.name),
      });
    }
  • TOOL_HANDLERS entry for quality_metrics: adapts raw MCP parameters to handler-specific format and invokes the main handler function.
    quality_metrics: async (params: unknown) => {
      const typedParams = params as Record<string, unknown>;
      const metricsParams: { projectKey: string; shortcodeIn?: MetricShortcode[] } = {
        projectKey: typedParams.projectKey as string,
      };
    
      const shortcodeIn = typedParams.shortcodeIn as MetricShortcode[] | undefined;
      if (shortcodeIn) {
        metricsParams.shortcodeIn = shortcodeIn;
      }
    
      return handleDeepsourceQualityMetrics(metricsParams);
    },
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. It states 'Get' implying a read operation, but lacks details on permissions, rate limits, response format, or potential side effects. This is inadequate for a tool with parameters and output schema.

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 a single, efficient sentence that directly states the tool's function without redundancy. It's appropriately sized and front-loaded, with every word contributing to clarity.

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?

Given the tool has an output schema and 100% schema coverage, the description doesn't need to explain return values or parameters. However, with no annotations and multiple sibling tools, it lacks guidance on usage and behavioral context, making it minimally adequate but incomplete.

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?

Schema description coverage is 100%, so the schema already documents both parameters thoroughly. The description adds minimal value by mentioning 'optional filtering' which aligns with 'shortcodeIn', but doesn't provide additional context beyond what's in the schema, meeting the baseline.

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

Purpose4/5

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

The description clearly states the verb 'Get' and resource 'quality metrics from a DeepSource project', making the purpose understandable. However, it doesn't differentiate this tool from siblings like 'compliance_report' or 'project_issues', which might also provide quality-related data, so it doesn't reach the highest score.

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

Usage Guidelines2/5

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

The description mentions 'optional filtering' but provides no guidance on when to use this tool versus alternatives like 'compliance_report' or 'project_issues'. There's no indication of prerequisites, context, or exclusions, leaving usage unclear.

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/sapientpants/deepsource-mcp-server'

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