Skip to main content
Glama
sapientpants

DeepSource MCP Server

by sapientpants

dependency_vulnerabilities

Identify security vulnerabilities in project dependencies by fetching and analyzing data from DeepSource projects.

Instructions

Get dependency vulnerabilities from a DeepSource project

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectKeyYesDeepSource project key to fetch vulnerabilities for
firstNoNumber of items to retrieve (forward pagination)
afterNoCursor to start retrieving items after (forward pagination)
lastNoNumber of items to retrieve (backward pagination)
beforeNoCursor to start retrieving items before (backward pagination)
page_sizeNoNumber of items per page (alias for first, for convenience)
max_pagesNoMaximum number of pages to fetch (enables automatic multi-page fetching)

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
pageInfoYes
totalCountYes
vulnerabilitiesYes

Implementation Reference

  • Core handler implementation that creates the tool handler function. Fetches dependency vulnerabilities from DeepSource API using client, processes and enriches data with risk assessments, handles pagination, and formats output.
    export const createDependencyVulnerabilitiesHandler = createBaseHandlerFactory(
      'dependency_vulnerabilities',
      async (
        deps: BaseHandlerDeps,
        { projectKey, first, after, last, before }: DeepsourceDependencyVulnerabilitiesParams
      ) => {
        const apiKey = deps.getApiKey();
        deps.logger.debug('API key retrieved from config', {
          length: apiKey.length,
          prefix: `${apiKey.substring(0, 5)}...`,
        });
    
        const client = new DeepSourceClient(apiKey);
    
        deps.logger.info('Fetching dependency vulnerabilities', {
          projectKey,
        });
    
        const params: { first?: number; after?: string; last?: number; before?: string } = {};
        if (first !== undefined) params.first = first;
        if (after !== undefined) params.after = after;
        if (last !== undefined) params.last = last;
        if (before !== undefined) params.before = before;
    
        const vulnerabilities = await client.getDependencyVulnerabilities(projectKey, params);
    
        deps.logger.info('Successfully fetched dependency vulnerabilities', {
          count: vulnerabilities.items.length,
          totalCount: vulnerabilities.totalCount,
          hasNextPage: vulnerabilities.pageInfo?.hasNextPage,
          hasPreviousPage: vulnerabilities.pageInfo?.hasPreviousPage,
        });
    
        const vulnerabilitiesData = {
          vulnerabilities: vulnerabilities.items.map((vulnerability: VulnerabilityOccurrence) => ({
            id: vulnerability.id,
            title: vulnerability.vulnerability.summary || vulnerability.vulnerability.identifier,
            severity: vulnerability.vulnerability.severity,
            cvssScore:
              vulnerability.vulnerability.cvssV3BaseScore ||
              vulnerability.vulnerability.cvssV2BaseScore,
            packageName: vulnerability.package.name,
            packageVersion: vulnerability.packageVersion.version,
            fixedIn:
              vulnerability.vulnerability.fixedVersions.length > 0
                ? vulnerability.vulnerability.fixedVersions[0]
                : null,
            description:
              vulnerability.vulnerability.details || vulnerability.vulnerability.summary || '',
            identifiers: [
              vulnerability.vulnerability.identifier,
              ...vulnerability.vulnerability.aliases,
            ],
            references: vulnerability.vulnerability.referenceUrls,
            // Add metadata to help with risk assessment
            risk_assessment: {
              severity_level: getSeverityLevel(vulnerability.vulnerability.severity),
              cvss_description: describeCvssScore(
                vulnerability.vulnerability.cvssV3BaseScore ||
                  vulnerability.vulnerability.cvssV2BaseScore ||
                  null
              ),
              fixed_version_available: vulnerability.vulnerability.fixedVersions.length > 0,
              remediation_advice: getRemediationAdvice(vulnerability),
            },
          })),
          pageInfo: {
            hasNextPage: vulnerabilities.pageInfo?.hasNextPage || false,
            hasPreviousPage: vulnerabilities.pageInfo?.hasPreviousPage || false,
            startCursor: vulnerabilities.pageInfo?.startCursor || null,
            endCursor: vulnerabilities.pageInfo?.endCursor || null,
          },
          totalCount: vulnerabilities.totalCount,
          // Provide helpful information and guidance
          usage_examples: {
            pagination: {
              next_page: 'For forward pagination, use first and after parameters',
              previous_page: 'For backward pagination, use last and before parameters',
            },
            related_tools: {
              issues: 'Use the project_issues tool to get code issues in the project',
              compliance: 'Use the compliance_report tool to get security compliance reports',
            },
          },
        };
    
        return wrapInApiResponse(vulnerabilitiesData);
      }
    );
  • Zod-based input and output schema definition for the dependency_vulnerabilities MCP tool, including pagination parameters and detailed vulnerability output structure.
    export const dependencyVulnerabilitiesToolSchema = {
      name: 'dependency_vulnerabilities',
      description: 'Get dependency vulnerabilities from a DeepSource project',
      inputSchema: {
        projectKey: z.string().describe('DeepSource project key to fetch vulnerabilities for'),
        first: z.number().optional().describe('Number of items to retrieve (forward pagination)'),
        after: z
          .string()
          .optional()
          .describe('Cursor to start retrieving items after (forward pagination)'),
        last: z.number().optional().describe('Number of items to retrieve (backward pagination)'),
        before: z
          .string()
          .optional()
          .describe('Cursor to start retrieving items before (backward pagination)'),
        page_size: z
          .number()
          .optional()
          .describe('Number of items per page (alias for first, for convenience)'),
        max_pages: z
          .number()
          .optional()
          .describe('Maximum number of pages to fetch (enables automatic multi-page fetching)'),
      },
      outputSchema: {
        vulnerabilities: z.array(
          z.object({
            id: z.string(),
            title: z.string(),
            severity: z.string(),
            cvssScore: z.number().nullable(),
            packageName: z.string(),
            packageVersion: z.string(),
            fixedIn: z.string().nullable(),
            description: z.string(),
            identifiers: z.record(z.string(), z.array(z.string())),
            references: z.array(z.string()),
            risk_assessment: z.object({
              severity_level: z.string(),
              cvss_description: z.string(),
              fixed_version_available: z.boolean(),
              remediation_advice: z.string(),
            }),
          })
        ),
        pageInfo: z.object({
          hasNextPage: z.boolean(),
          hasPreviousPage: z.boolean(),
          startCursor: z.string().nullable(),
          endCursor: z.string().nullable(),
        }),
        totalCount: z.number(),
      },
    };
  • Registers the dependency_vulnerabilities tool in the MCP ToolRegistry, using the schema and a handler that adapts parameters before delegating to the main handler function.
    toolRegistry.registerTool({
      ...dependencyVulnerabilitiesToolSchema,
      handler: async (params) => {
        const adaptedParams = adaptDependencyVulnerabilitiesParams(params);
        return handleDeepsourceDependencyVulnerabilities(adaptedParams);
      },
    });
  • SecurityClient method that performs the GraphQL query to DeepSource API to retrieve dependency vulnerabilities data, extracts and maps the response.
    async getDependencyVulnerabilities(
      projectKey: string,
      params: PaginationParams = {}
    ): Promise<PaginatedResponse<VulnerabilityOccurrence>> {
      try {
        this.logger.info('Fetching dependency vulnerabilities from DeepSource API', {
          projectKey,
        });
    
        const project = await this.findProjectByKey(projectKey);
        if (!project) {
          return BaseDeepSourceClient.createEmptyPaginatedResponse<VulnerabilityOccurrence>();
        }
    
        const normalizedParams = BaseDeepSourceClient.normalizePaginationParams(params);
        const query = SecurityClient.buildVulnerabilitiesQuery();
    
        const response = await this.executeGraphQL(query, {
          login: project.repository.login,
          name: project.repository.name,
          provider: project.repository.provider,
          ...normalizedParams,
        });
    
        if (!response.data) {
          throw new Error('No data received from GraphQL API');
        }
    
        const vulnerabilities = this.extractVulnerabilitiesFromResponse(response.data);
    
        this.logger.info('Successfully fetched dependency vulnerabilities', {
          count: vulnerabilities.length,
        });
    
        return {
          items: vulnerabilities,
          pageInfo: {
            hasNextPage: false, // Simplified for now
            hasPreviousPage: false,
          },
          totalCount: vulnerabilities.length,
        };
      } catch (error) {
        return this.handleVulnerabilitiesError(error);
      }
    }
  • Adapter function that converts raw MCP tool parameters to the typed parameters expected by the handler.
    export function adaptDependencyVulnerabilitiesParams(
      params: unknown
    ): DeepsourceDependencyVulnerabilitiesParams {
      const typedParams = params as Record<string, unknown>;
      const result: DeepsourceDependencyVulnerabilitiesParams = {
        projectKey: typedParams.projectKey as string, // Handler still expects string
      };
    
      const first = typedParams.first as number | undefined;
      if (first !== undefined) result.first = first;
    
      const last = typedParams.last as number | undefined;
      if (last !== undefined) result.last = last;
    
      const after = typedParams.after as string | undefined;
      if (after !== undefined) result.after = after;
    
      const before = typedParams.before as string | undefined;
      if (before !== undefined) result.before = before;
    
      return result;
    }
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It states 'Get dependency vulnerabilities' but doesn't clarify if this is a read-only operation, requires authentication, has rate limits, or what the output entails. For a tool with 7 parameters and no annotations, this is a significant gap in 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 a single, efficient sentence that directly states the tool's purpose without any fluff or redundancy. It's appropriately sized and front-loaded, making it easy for an agent to parse quickly.

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 complexity (7 parameters, no annotations, but with an output schema), the description is minimal. It covers the basic purpose but lacks behavioral context and usage guidelines. The output schema helps, but the description doesn't compensate for the missing annotations or sibling differentiation, making it only adequate.

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?

The schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds no additional meaning beyond the schema, such as explaining relationships between parameters like 'first' and 'page_size'. Baseline 3 is appropriate as the schema does the heavy lifting.

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 the resource 'dependency vulnerabilities from a DeepSource project', which is specific and understandable. However, it doesn't differentiate from sibling tools like 'project_issues' or 'recent_run_issues', which might also relate to vulnerabilities or issues, leaving some ambiguity about when to use this specific tool.

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 provides no guidance on when to use this tool versus alternatives. It doesn't mention sibling tools like 'project_issues' or 'compliance_report', nor does it specify contexts or exclusions for usage, leaving the agent to guess based on tool names alone.

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