createFinding
Create one or more findings in Mallory. A finding is a durable record that a specific problem exists on a specific asset belonging to the caller's own organization — not a chat message and not a note to yourself. It is visible in the Mallory UI to everyone in that organization, and nothing on this server deletes one: a finding filed by mistake can only be marked dismissed with updateFinding.
WRITES IMMEDIATELY. There is no draft, no preview and no confirmation step — calling this tool IS the write. Only call it when the user has asked, in so many words, for findings to be filed in Mallory ("create a finding for that", "file these"). Finishing an investigation is not permission to file its results: report them and let the user decide.
WHAT TO SEND
definition_slug must ALREADY EXIST in the catalog. Look one up with the queryApi tool, path "/v1/finding_definitions" (filter by category or severity to narrow). Never invent a slug, and never substitute a near-match for one that was rejected — that files the wrong kind of finding.
One finding per problem per asset. Five misconfigured buckets are five findings sharing a definition_slug with five different asset_identifier values, not one finding listing five buckets. Send the whole batch in ONE call (max 25): each is created independently, so one duplicate does not block the rest.
asset_type is a provider.service.object value (e.g. aws.s3.bucket, aws.iam.role, github.repo, azure.storage.account), or "generic" when nothing fits. Legacy underscore forms like "s3_bucket" are rejected.
summary / body / remediation are markdown, and are read by people who were not in your conversation: what is wrong, how you established it, and the actual fix.
evidence is one entry per thing you actually OBSERVED — the query and what it returned, the endpoint and its status, the file and the matching line. Three observations are three entries. Never write evidence for something you inferred rather than observed; lower confidence and say so in body instead.
ENUM VALUES ARE CASE-SENSITIVE AND EACH FIELD HAS ITS OWN SET. severity is UPPERCASE (CRITICAL, HIGH, MEDIUM, LOW, INFO) and optional — omit it and the definition's own default applies, which is usually right; override only when this instance is genuinely worse or milder than the type normally is, and say why in body. confidence is lowercase (low, medium, high). Status is not settable here: a finding is created open, and status values are lowercase (see updateFinding).
OUTCOMES come back per finding, in created and failed:
DUPLICATE — an open finding already covers that asset, and
existing_finding_uuidnames it. Say so and move on. Do NOT re-word the title and retry; to change the one that exists, call updateFinding with that uuid.UNKNOWN_DEFINITION — the slug is not in the catalog. Look up a real one; do not guess a neighbouring slug.
INVALID — core rejected a field, most often asset_type. Fix that field, not the slug.
INVALID_ASSET_IDENTIFIER — asset_identifier names no asset (a placeholder such as "unknown", or a bare word such as a tool or data-source name, with asset_type "generic"). Nothing was written. Use the real affected asset from the source data (host:port, hostname, URL, account, repository); never invent one.
PLAN_LIMIT — findings are not included in this tenant's plan. The request was fine, nothing is broken and nothing was written: tell the user, pass on the upgrade link if the outcome carries one, and do not retry or reach for another tool to file it.
list_url is null outside the Mallory chat app — there is no conversation for an MCP call to scope a list to. Read a created finding back with getFinding using the uuid in created, or browse the tenant's findings with listFindings.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| findings | Yes | The findings to create. Pass every finding from one investigation in a single call — each is created independently, so one duplicate does not block the rest. |