Skip to main content
Glama

cortex_run_analyzer_by_name

Run a named analyzer on an observable by providing the analyzer name, data type, and value. Optionally set TLP and PAP levels.

Instructions

Run an analyzer by name instead of ID (convenience wrapper)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
analyzerNameYesThe analyzer name to search for
dataTypeYesThe observable data type
dataYesThe observable value
tlpNoTraffic Light Protocol level (default: 2/AMBER)
papNoPermissible Actions Protocol level (default: 2)

Implementation Reference

  • Handler function for the cortex_run_analyzer_by_name tool. It looks up an analyzer by name (case-insensitive) and data type, then submits a job via client.runAnalyzer(). Returns the job ID and status.
    async ({ analyzerName, dataType, data, tlp, pap }) => {
      try {
        const analyzers = await client.listAnalyzers();
        const match = analyzers.find(
          (a) =>
            a.name.toLowerCase().includes(analyzerName.toLowerCase()) &&
            a.dataTypeList.includes(dataType),
        );
    
        if (!match) {
          return {
            content: [
              {
                type: "text" as const,
                text: `No analyzer found matching "${analyzerName}" that supports data type "${dataType}". Use cortex_list_analyzers to see available analyzers.`,
              },
            ],
            isError: true,
          };
        }
    
        const job = await client.runAnalyzer(match.id, {
          data,
          dataType,
          tlp,
          pap,
        });
    
        return {
          content: [
            {
              type: "text" as const,
              text: JSON.stringify(
                {
                  jobId: job.id,
                  status: job.status,
                  analyzerUsed: { id: match.id, name: match.name },
                  message: `Analysis job submitted to "${match.name}". Use cortex_wait_and_get_report with jobId "${job.id}" to get results.`,
                },
                null,
                2,
              ),
            },
          ],
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text" as const,
              text: `Error running analyzer by name: ${error instanceof Error ? error.message : String(error)}`,
            },
          ],
          isError: true,
        };
      }
    },
  • Input schema for the tool: analyzerName, dataType, data, tlp (default 2/AMBER), and pap (default 2).
    {
      analyzerName: z.string().describe("The analyzer name to search for"),
      dataType: z.enum(DATA_TYPES).describe("The observable data type"),
      data: z.string().describe("The observable value"),
      tlp: z
        .number()
        .int()
        .min(0)
        .max(3)
        .default(2)
        .describe("Traffic Light Protocol level (default: 2/AMBER)"),
      pap: z
        .number()
        .int()
        .min(0)
        .max(3)
        .default(2)
        .describe("Permissible Actions Protocol level (default: 2)"),
    },
  • Registration of the tool via server.tool() with the name 'cortex_run_analyzer_by_name' and a description.
    server.tool(
      "cortex_run_analyzer_by_name",
      "Run an analyzer by name instead of ID (convenience wrapper)",
      {
        analyzerName: z.string().describe("The analyzer name to search for"),
        dataType: z.enum(DATA_TYPES).describe("The observable data type"),
        data: z.string().describe("The observable value"),
        tlp: z
          .number()
          .int()
          .min(0)
          .max(3)
          .default(2)
          .describe("Traffic Light Protocol level (default: 2/AMBER)"),
        pap: z
          .number()
          .int()
          .min(0)
          .max(3)
          .default(2)
          .describe("Permissible Actions Protocol level (default: 2)"),
      },
      async ({ analyzerName, dataType, data, tlp, pap }) => {
        try {
          const analyzers = await client.listAnalyzers();
          const match = analyzers.find(
            (a) =>
              a.name.toLowerCase().includes(analyzerName.toLowerCase()) &&
              a.dataTypeList.includes(dataType),
          );
    
          if (!match) {
            return {
              content: [
                {
                  type: "text" as const,
                  text: `No analyzer found matching "${analyzerName}" that supports data type "${dataType}". Use cortex_list_analyzers to see available analyzers.`,
                },
              ],
              isError: true,
            };
          }
    
          const job = await client.runAnalyzer(match.id, {
            data,
            dataType,
            tlp,
            pap,
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: JSON.stringify(
                  {
                    jobId: job.id,
                    status: job.status,
                    analyzerUsed: { id: match.id, name: match.name },
                    message: `Analysis job submitted to "${match.name}". Use cortex_wait_and_get_report with jobId "${job.id}" to get results.`,
                  },
                  null,
                  2,
                ),
              },
            ],
          };
        } catch (error) {
          return {
            content: [
              {
                type: "text" as const,
                text: `Error running analyzer by name: ${error instanceof Error ? error.message : String(error)}`,
              },
            ],
            isError: true,
          };
        }
      },
    );
  • Exported function called from src/index.ts to register all analyzer tools on the MCP server.
    export function registerAnalyzerTools(
      server: McpServer,
      client: CortexClient,
    ): void {
  • src/index.ts:5-34 (registration)
    Import and invocation of registerAnalyzerTools from the main entry point.
    import { registerAnalyzerTools } from "./tools/analyzers.js";
    import { registerAnalyzerDefinitionTools } from "./tools/analyzer-definitions.js";
    import { registerJobTools } from "./tools/jobs.js";
    import { registerResponderTools } from "./tools/responders.js";
    import { registerResponderDefinitionTools } from "./tools/responder-definitions.js";
    import { registerBulkTools } from "./tools/bulk.js";
    import { registerStatusTools } from "./tools/status.js";
    import { registerOrganizationTools } from "./tools/organizations.js";
    import { registerUserTools } from "./tools/users.js";
    import { registerResources } from "./resources.js";
    import { registerPrompts } from "./prompts.js";
    
    async function main(): Promise<void> {
      const config = getConfig();
    
      if (!config.verifySsl) {
        process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
      }
    
      const server = new McpServer({
        name: "cortex-mcp",
        version: "1.2.0",
        description:
          "MCP server for Cortex - observable analysis and active response engine by StrangeBee/TheHive Project",
      });
    
      const client = new CortexClient(config);
    
      // Core analysis tools
      registerAnalyzerTools(server, client);
Behavior2/5

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

No annotations are provided, and the description is extremely brief, omitting behavioral traits such as job creation, synchronous vs. asynchronous execution, permission requirements, or error handling.

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

Conciseness3/5

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

The description is a single short sentence, which is concise but lacks necessary detail for effective tool usage. It does not earn its place beyond a basic statement.

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

Completeness2/5

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

Given five parameters, no output schema, and no annotations, the description is insufficient. It does not explain workflow, return values, or error scenarios, leaving significant gaps.

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?

Input schema has 100% description coverage, so the description adds no extra meaning beyond parameter labels. Baseline score of 3 applies.

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 runs an analyzer by name, distinguishing it from the ID-based sibling. It identifies itself as a convenience wrapper, making the purpose explicit.

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 when the analyzer name is known instead of ID. It does not list specific exclusions or explicitly mention alternatives, but the sibling list provides context.

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/solomonneas/cortex-mcp'

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