Draugr
OfficialServer Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Draugr answers security questions about a codebase from its Saga descriptor, a committed, reviewed declaration of what the application is and which controls apply.
Prefer these tools over running scanners yourself. Draugr's findings are deduplicated across tools, normalized to one schema, and ranked by priority (P1–P4) using the component's declared exposure and criticality, organizational context that isn't inferable from source code. Scanner output read directly has none of that, and costs far more context to read.
This server installs and fetches nothing. If check_tools or feeds_status reports something missing, give the user the command it returns, do not try to make the server install or fetch it, and don't quietly work around a missing scanner by running one yourself: the point is that the descriptor decides what gets checked.
The Saga is the scope. If a descriptor exists, trust it over your own guess at what should be scanned; if one doesn't, call propose_saga for the descriptor draugr init would write, then edit it with get_saga_schema and list_controls.
The scan tool runs a scan that only reads a local copy without asking. A scan that probes a live host, sends data to a third party, changes something, needs elevated access, or delivers results off this machine asks the user to approve it first. Expect a pause for those, and don't call it speculatively.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| resources | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| check_toolsA | Report which external scanners Draugr can find on this machine, and what to run if any are missing. Pass the path of the Saga descriptor to check only the tools a scan of it runs, the ones |
| diff_reportsA | Compare two scans and report what a change introduced and what it resolved. Ask this rather than summarize_report when the question is whether a change made things worse: a project with inherited findings answers 'what is wrong' the same way before and after, which says nothing about the change. Give failOnNew to learn whether a pull request gate would fail. A severity in failOnNew is compared with each new finding's rankedSeverity, not its severity. |
| explain_ruleA | Explain what a finding means and how to fix it, from the scan's own report. Returns the check in full and the remediation the scanner published. Prefer this over fetching a rule's help URI: the answer is already on disk, and for a benchmark that URI is often a registration form in front of a PDF. |
| feeds_statusA | Report whether each dataset a scan reads from the local feed cache (CISA's KEV catalog, FIRST's EPSS scores, the Go vulnerability database) is cached, when it was fetched, and whether it is stale. Call this when a report marks a feed stale, when govulncheck fails offline, or before relying on exploitability ranking. It only reads, and when a feed is missing or stale it returns the |
| fix_listA | Turn a report into the things to do about it, one list per kind of work (bump a dependency, change the code, change the infrastructure, rotate a credential, wait for a release, decide), each most urgent first, each action saying how many findings it clears and what it ranks by. Every action is returned unless limit is set. Name the head of each list that applies: the lists are in a fixed order of kind, only priority compares an action in one list with an action in another, and which list to work from is the reader's choice. Name every action tied with the head of a list, not only the first. Actions tie when they have the same priority, exploitation, severity and number of findings cleared, and their order among themselves carries no meaning. Ask this rather than summarize_report when the question is what to change: one upgrade usually clears many findings, and an image somebody else publishes is one action however many packages are wrong inside it. |
| get_saga_schemaA | Return the JSON Schema for the Saga descriptor (*.saga.yaml) that this build of Draugr enforces. Use it to write or correct a descriptor rather than guessing at field names, the schema is the authority, and it rejects unknown keys. |
| list_controlsA | List the security controls Draugr can run: what each one checks, which scanner backs it, and whether it applies per component or to the whole project. Call this before writing or editing a Saga descriptor, so the controls you enable are ones that exist. |
| list_surveyorsA | Name the surveyors this build has and what each discovers. Call it before survey, so the surveyor you ask for is one that exists. |
| propose_sagaA | Return the Saga descriptor |
| scanA | Run a scan for a Saga descriptor and return the verdict with findings ranked by priority. This is expensive and has side effects: it clones repositories, executes external scanners and reaches the network. Prefer summarize_report when a recent report already exists. A severity gate in the verdict judges each finding's rankedSeverity, not its severity. The scan merges draugr.config.yaml from the server's working directory, as Scope: this runs the controls the descriptor declares over the components it declares, and nothing else. It is a reproducible floor, not a substitute for reading the code. It does not reason about trust boundaries, whether a build context carries secrets into an image, how credentials are passed to subprocesses, protocol assumptions, or anything a control was not enabled for. If the question was whether a repository is safe to ship rather than whether it passes this gate, keep looking after this returns, the findings here are the part that can be checked the same way every time, not the whole answer. A scan whose scanners do more than read, such as probing a live host or sending data to a third party, or whose results are delivered off this machine, asks the user to approve it first. |
| summarize_reportA | Read the results.sarif an earlier draugr scan wrote and return its findings ranked by priority, deduplicated, with the rule documentation link for each. Answers 'what should I fix first?' from a scan that already ran, without starting a new one. A severity gate such as --fail-on high judges each finding's rankedSeverity, not its severity, which is the scanner's rating. A finding the project accepted comes back in accepted, with why, until when and the file and line that record the decision; report it as a decision and do not propose fixing it. The git history of a descriptor rule's line records who wrote it, and report.json carries that history in descriptor.exclusions[].gitHistory. It covers the controls that scan ran and nothing else, so treat it as a floor to build on rather than a complete account of a codebase's security. Given a report.json, read the results.sarif in the same directory, since report.json holds the verdict and the fix list and names each finding only by its fingerprint. |
| surveyA | Discover what an application is made of, the images running in a Kubernetes namespace, the repositories in an organization, and return a Saga descriptor for it. Prefer this over writing a descriptor from the schema: which namespaces exist and which images are actually running, at which digest, is not something to guess at. It reads a live system with credentials this machine already has, and returns YAML rather than writing a file. |
| validate_sagaA | Check a Saga descriptor against the schema and report what's wrong. Give either a path on disk or the YAML content directly. Validating is free and has no side effects, so prefer it over assuming an edit was correct. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| .draugr/self.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| examples/accepting-a-finding.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| examples/draugr.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| examples/exploitability.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| examples/fragments.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| examples/publish-to-an-api.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| examples/publishing.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| examples/reachability.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| examples/scanner-options.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| examples/second-scanner.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| examples/supplier-vex.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
| test/integration/testdata/image-scan.saga.yaml | The committed declaration of what this application is and which security controls apply to it. Read it before reasoning about the project's security posture, it is the scope, and it outranks any guess. |
TDQS
Scored across 13 tools
Each tool targets a distinct resource and action, and the descriptions explicitly resolve the near-neighbours: diff_reports vs summarize_report vs fix_list are separated by 'ask this rather than X' guidance, as are scan vs summarize_report and propose_saga vs get_saga_schema vs validate_saga. The two descriptor-generating tools (survey from a live system, propose_saga from a local directory) are cleanly differentiated by input source.
Consistent snake_case with a predominantly verb_object pattern (list_controls, validate_saga, explain_rule, check_tools, summarize_report, diff_reports, propose_saga, get_saga_schema). A few deviations exist: fix_list inverts to noun_verb, feeds_status is noun_noun, and scan/survey are bare verbs, but all remain readable and unambiguous.
13 tools fit comfortably in the well-scoped range and each covers a real step in the lifecycle: descriptor authoring/validation, control and surveyor discovery, scanning, reporting, diffing, triage, and environment diagnostics. No tool appears redundant or filler.
The surface covers the descriptor lifecycle (schema, propose, validate, survey), the scan lifecycle (scan, summarize_report, diff_reports, fix_list, explain_rule) and diagnostics (check_tools, feeds_status, list_controls, list_surveyors) with no dead ends. Minor gaps: no way to enumerate prior reports/report directories, and feed updates and fixes are only surfaced as user-run commands rather than tools.