Skip to main content
Glama

Get Findings

get_findings

Retrieve structured vulnerability findings from penetration tests with severity, CVSS scores, descriptions, and remediation guidance. Filter results by severity level to focus on critical issues.

Instructions

Get structured vulnerability findings for a pentest. Each finding includes severity, CVSS, CWE, description, PoC, remediation, and retest command. Use the severity filter to narrow results.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pentest_idYesThe pentest ID (UUID)
severityNoFilter findings by severity level

Implementation Reference

  • The async function handling the 'get_findings' tool request, which fetches pentest data and formats the findings.
    async ({ pentest_id, severity }) => {
      try {
        const scan = await client.getPentest(pentest_id);
        let findings = scan.findings ?? [];
    
        if (severity) {
          findings = findings.filter((f) => f.severity === severity);
        }
    
        if (findings.length === 0) {
          return {
            content: [
              {
                type: "text" as const,
                text: severity
                  ? `No ${severity} findings for pentest ${pentest_id}.`
                  : `No findings for pentest ${pentest_id}.`,
              },
            ],
          };
        }
    
        const MAX_DISPLAY = 20;
        const displayed = findings.slice(0, MAX_DISPLAY);
        const lines = [
          `Findings for pentest ${pentest_id}${severity ? ` (${severity} only)` : ""}:`,
          `Total: ${findings.length}`,
          "",
          ...displayed.map((f, i) => formatFinding(f, i)),
        ];
    
        if (findings.length > MAX_DISPLAY) {
          lines.push(
            "",
            `... showing ${MAX_DISPLAY} of ${findings.length} findings. Use severity filter to narrow results.`,
          );
        }
    
        return { content: [{ type: "text" as const, text: lines.join("\n") }] };
      } catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return {
          content: [{ type: "text" as const, text: `Failed to get findings: ${message}` }],
          isError: true,
        };
      }
    },
  • Input schema definition for the 'get_findings' tool using Zod.
    inputSchema: z.object({
      pentest_id: z.string().uuid().describe("The pentest ID (UUID)"),
      severity: z
        .enum(["critical", "high", "medium", "low", "info"])
        .optional()
        .describe("Filter findings by severity level"),
    }),
  • The registration function that defines the 'get_findings' tool within the MCP server.
    export function registerGetFindings(server: McpServer, client: TurboPentestClient): void {
      server.registerTool(
        "get_findings",
        {
          title: "Get Findings",
          description:
            "Get structured vulnerability findings for a pentest. " +
            "Each finding includes severity, CVSS, CWE, description, PoC, remediation, and retest command. " +
            "Use the severity filter to narrow results.",
          inputSchema: z.object({
            pentest_id: z.string().uuid().describe("The pentest ID (UUID)"),
            severity: z
              .enum(["critical", "high", "medium", "low", "info"])
              .optional()
              .describe("Filter findings by severity level"),
          }),
        },
        async ({ pentest_id, severity }) => {
          try {
            const scan = await client.getPentest(pentest_id);
            let findings = scan.findings ?? [];
    
            if (severity) {
              findings = findings.filter((f) => f.severity === severity);
            }
    
            if (findings.length === 0) {
              return {
                content: [
                  {
                    type: "text" as const,
                    text: severity
                      ? `No ${severity} findings for pentest ${pentest_id}.`
                      : `No findings for pentest ${pentest_id}.`,
                  },
                ],
              };
            }
    
            const MAX_DISPLAY = 20;
            const displayed = findings.slice(0, MAX_DISPLAY);
            const lines = [
              `Findings for pentest ${pentest_id}${severity ? ` (${severity} only)` : ""}:`,
              `Total: ${findings.length}`,
              "",
              ...displayed.map((f, i) => formatFinding(f, i)),
            ];
    
            if (findings.length > MAX_DISPLAY) {
              lines.push(
                "",
                `... showing ${MAX_DISPLAY} of ${findings.length} findings. Use severity filter to narrow results.`,
              );
            }
    
            return { content: [{ type: "text" as const, text: lines.join("\n") }] };
          } catch (error) {
            const message = error instanceof Error ? error.message : String(error);
            return {
              content: [{ type: "text" as const, text: `Failed to get findings: ${message}` }],
              isError: true,
            };
          }
        },
      );
    }
  • Helper function to format a single finding into a readable string.
    function formatFinding(f: Finding, index: number): string {
      const lines = [
        `[${index + 1}] ${f.severity.toUpperCase()}: ${f.title}`,
        `    Tool: ${f.sourceTool}`,
      ];
    
      if (f.cvss !== null) lines.push(`    CVSS: ${f.cvss}${f.cvssVector ? ` (${f.cvssVector})` : ""}`);
      if (f.cweId) lines.push(`    CWE: ${f.cweId}`);
      if (f.owaspCategory) lines.push(`    OWASP: ${f.owaspCategory}`);
      if (f.affectedUrl) lines.push(`    URL: ${f.affectedUrl}`);
      if ((f.cveIds ?? []).length > 0) lines.push(`    CVEs: ${f.cveIds.join(", ")}`);
      if (f.description) lines.push(`    Description: ${f.description}`);
      if (f.proofOfExploit) lines.push(`    PoC: ${f.proofOfExploit}`);
      if (f.remediation) lines.push(`    Remediation: ${f.remediation}`);
      if (f.retestCommand) lines.push(`    Retest: ${f.retestCommand}`);
    
      return lines.join("\n");
Behavior2/5

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

No annotations are provided, so the description carries full burden. It mentions the tool retrieves 'structured vulnerability findings' and includes a severity filter, but doesn't disclose behavioral traits like whether this is a read-only operation, potential rate limits, authentication needs, pagination, or what happens if no findings exist. For a tool with no annotations, this leaves significant gaps in understanding its behavior.

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 concise and front-loaded: the first sentence defines the core purpose and key attributes, and the second sentence provides usage guidance. Both sentences earn their place by adding value. It could be slightly more structured (e.g., bullet points for attributes), but it's efficient with zero waste.

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 no annotations and no output schema, the description is moderately complete for a read operation. It covers the purpose and basic usage but lacks details on behavioral aspects (e.g., response format, error handling) and doesn't fully compensate for the missing output schema. It's adequate but has clear gaps for a tool retrieving structured data.

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%, with clear descriptions for both parameters (pentest_id as UUID, severity as enum filter). The description adds minimal value beyond the schema: it mentions 'severity filter' but doesn't explain parameter interactions or semantics further. Baseline 3 is appropriate since 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 tool's purpose: 'Get structured vulnerability findings for a pentest' with specific attributes listed (severity, CVSS, CWE, etc.). It distinguishes from siblings like 'download_report' or 'get_pentest' by focusing on vulnerability findings rather than reports or pentest metadata. However, it doesn't explicitly contrast with all siblings (e.g., 'list_domains'), keeping it at 4 rather than 5.

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 provides some usage context: 'Use the severity filter to narrow results' implies this tool is for retrieving findings, possibly with filtering. However, it lacks explicit guidance on when to use this vs. alternatives like 'download_report' (which might include findings) or prerequisites (e.g., requires a pentest_id). The context is implied but not comprehensive.

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/IntegSec/turbopentest-mcp'

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