Skip to main content
Glama
jeneric
by jeneric

stig-mcp

A local MCP (Model Context Protocol) server that lets an AI assistant, such as GitHub Copilot in VS Code or Claude Code, answer security questions from published guidance instead of from memory. Name a MITRE ATT&CK® technique or threat actor and the system you care about, and the answer gives you:

  • the NIST SP 800-53 security controls that mitigate it;

  • the DISA STIG configuration rules that implement those controls on that system, most severe first, with DISA's check and fix text on request;

  • ATT&CK's own mitigations, and which of its detections work with the logs you collect.

It does not scan or connect to your systems. Its answers come from a knowledge base, a local database of about 6 MB built from those public sources, which you install once. The user guide explains what it does and shows three ways to use it: as a security controls assessor, a system owner, or a SOC analyst.

Prerequisite

stig-mcp is published on PyPI and runs through uvx, which comes with uv. Install uv, then check that uvx --version runs in a new terminal. Restart VS Code or Claude Code after installing uv so it sees the new PATH.

Related MCP server: MITRE ATT&CK MCP Server

Quick start

VS Code (GitHub Copilot)

  1. Click this badge. VS Code opens and offers to install stig-mcp; choose Install.

    Install in VS Code

  2. Open Copilot Chat and set the mode dropdown to Agent. MCP tools are not available in Ask or Edit mode.

  3. Ask: Install the stig-mcp knowledge base. This is a one-time download of about 6 MB. Allow the tool when VS Code asks.

If that doesn't work, see troubleshooting or setting up VS Code by hand.

Claude Code

  1. Inside a Claude Code session (2.1.275 or later), run:

    /plugin install stig-mcp --marketplace jeneric/STIG-MCP
    
  2. Ask: Install the stig-mcp knowledge base. This is a one-time download of about 6 MB. Allow the tool when Claude Code asks.

If that doesn't work, see troubleshooting or setting up Claude Code by hand.

Example prompts

With the knowledge base installed, try:

  1. System owner: What DISA STIG steps mitigate T1078 on Windows 11?

  2. Security controls assessor: Which ATT&CK techniques does APT29 use?

  3. Anyone, to find the right STIG: Which STIG benchmarks apply to RHEL 9?

  4. SOC analyst: What can I detect of APT29 on Windows Server 2022 with Security and Sysmon logs?

More example prompts are in the user guide, with how to get more out of it and how to make sure the agent answers from the server.

Other MCP clients

Use this only if you are not using VS Code or Claude Code. Any client that launches a local (stdio) MCP server works with this configuration, shown in the common mcpServers shape:

{
  "mcpServers": {
    "stig-mcp": {
      "command": "uvx",
      "args": ["stig-mcp"],
      "env": { "UV_SYSTEM_CERTS": "true", "UV_NATIVE_TLS": "true" }
    }
  }
}

The two environment variables let uv download stig-mcp behind a TLS-inspecting proxy. They are harmless on most other hosts; that section names the one exception. Then ask the agent to install the stig-mcp knowledge base, as in the quick start.

docs/install.md has the details:

What this server fetches

  • The MCP server contacts nothing unless check_sources or install_knowledge_base is called. Then it sends HTTPS GET requests to api.github.com (this repository's release listing) and github.com (/jeneric/STIG-MCP/releases/download/...), which redirects to release-assets.githubusercontent.com or objects.githubusercontent.com. Any other URL, a redirect included, is refused. Nothing is uploaded, and there is no telemetry. install_knowledge_base given a file path and its SHA-256 requests nothing at all.

  • stig-mcp-install-kb contacts the same hosts, and nothing at all with --file.

  • stig-mcp-fetch, used only to build the knowledge base yourself, downloads from raw.githubusercontent.com and api.github.com (MITRE ATT&CK, the CTID mapping, the NIST 800-53 catalog) and from dl.dod.cyber.mil (DISA).

PRIVACY.md states what each of these requests sends and what is stored locally.

Documentation

  • docs/install.md: installation details for every client, where the data lives, and troubleshooting.

  • docs/user-guide.md: for a person talking to an LLM that has this server wired in.

  • docs/operations.md: for whoever installs, builds and maintains the knowledge base.

  • SECURITY.md: reporting a vulnerability, and what is in scope.

  • CONTRIBUTING.md: working from a source checkout, running the tests, and the project's conventions.

  • RELEASING.md: for the maintainer, publishing the package to PyPI and the MCP Registry.

  • PRIVACY.md: what the server and the fetch tool contact, and what is stored locally.

Third-party content

The knowledge base aggregates MITRE ATT&CK, CTID mapping, DISA STIG, DISA CCI list, and NIST OSCAL content. See NOTICE for attribution and licensing obligations and licenses/apache-2.0.txt for the Apache 2.0 license text that notice requires.

Development

Developed with the assistance of Claude Code (Anthropic). All changes were reviewed and tested by the maintainer.

Available Tools

9 tools
check_sourcesA

Check whether a newer prebuilt knowledge base is published than the one installed. This contacts only this project's GitHub releases (github.com/jeneric/STIG-MCP). action is "install" (call install_knowledge_base), "upgrade_package" (a newer knowledge base needs a newer stig-mcp; upgrade_to says which), "build_locally" (nothing usable is installed and no release exists for this stig-mcp; build with stig-mcp-fetch and stig-mcp-ingest), or "none"; reason says why. It works even when the knowledge base is not built, and then not_ready says why and what to run.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden and does well: it discloses that it contacts only this project's GitHub releases (network scope), that it works even when the knowledge base is not built, and what not_ready conveys. It still omits whether the call is cached, rate-limited, or purely read-only, so it falls short of a complete behavioral picture.

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?

Front-loaded with the core purpose, then the network scope, then the action/return contract. The enumeration is dense but every clause maps to a real behavior or routing decision; only the nested parenthetical about build_locally is slightly heavy.

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

Completeness5/5

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

No output schema exists, so the description must describe the return contract, and it does: action, reason, not_ready, and upgrade_to. Together with the edge-case note about running before a knowledge base is built, an agent has everything needed to call it and react to its result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes no input parameters, so there is nothing to document; per the baseline, a 0-parameter tool scores 4. The description correctly spends no space on nonexistent inputs.

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?

States a specific verb and resource: check whether a newer prebuilt knowledge base is published than the one installed. It also scopes the network call to this project's GitHub releases, so an agent knows exactly what this check touches, distinct from siblings like install_knowledge_base or list_stigs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It enumerates every outcome of action (install, upgrade_package, build_locally, none) and routes each to the concrete next step, naming install_knowledge_base, upgrade_to, and the stig-mcp-fetch/stig-mcp-ingest path. This is explicit when/when-not guidance tied to alternatives rather than inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

defense_detailsA

Return MITRE's text for ATT&CK defenses named by id: mitigations (M1026), detection strategies (DET0103) and analytics (AN0286), as listed under protect.mitigations and detect in a defenses_for_technique answer or under each technique in a techniques_for_actor answer. ids takes up to 10 per call, matched case-insensitively. A mitigation returns its description and how many techniques it covers; with technique_id it also returns MITRE's text about that mitigation on that technique as technique_description, which is null when that mitigation is not paired with that technique (a revoked id answers for its replacement, reported in technique.redirected_from). A detection strategy returns every analytic in full: description, platforms, log_sources (name, channel and data component) and mutable_elements, the tunables a detection engineer sets. An analytic id returns that analytic alone. Analytics say what to collect, not how to enable it: the enabling steps are in the vendor's documentation. not_found lists ids that matched nothing; if none match, the call is refused. Quote MITRE's text as written and label anything you add as your own. If the knowledge base is not built yet this returns {"status": "not_ready"} with the commands to run, rather than an error.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsYes
technique_idNo

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations, the description carries the full load and does so richly: per-id-family return shapes, technique_description being null when a mitigation is not paired with the technique, revoked ids answering for their replacement via technique.redirected_from, not_found listing unmatched ids, outright refusal when nothing matches, and a {"status": "not_ready"} fallback instead of an error. It even discloses a semantic caveat that analytics describe what to collect, not how to enable it.

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?

Front-loaded with the core action and the id families, then moving into return shapes and edge cases. It is a dense wall of text with long compound sentences, but nearly every clause conveys a distinct behavioral fact rather than repeating structured data.

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

Completeness5/5

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

No output schema and no annotations, yet the description specifies what comes back for each id family, the fields of a detection strategy and analytic, the null/redirect edge cases, the not_found contract, and the not_ready state. An agent has everything needed to call and interpret this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, and it does: ids is documented as taking up to 10 case-insensitively matched identifiers, and technique_id is documented as adding technique_description to the response. It does not state that technique_id is only meaningful for mitigations (not detection strategies or analytics), leaving a small ambiguity.

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?

States a specific verb and resource — return MITRE's text for ATT&CK defenses named by id — and enumerates the three id families it accepts (M1026 mitigations, DET0103 detection strategies, AN0286 analytics). It also tells the agent where those ids come from (protect.mitigations / detect in a defenses_for_technique answer), which separates it from the sibling defenses_for_technique that discovers rather than resolves ids.

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?

Usage context is clear: this is the detail-lookup step after you already hold ids from defenses_for_technique or techniques_for_actor, and chunking is bounded at 10 ids per call. It never explicitly names an alternative tool or states a when-not-to-use condition, so it stops short of the top tier.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

defenses_for_techniqueA

Return the defenses the knowledge base holds for an ATT&CK technique: the 800-53r5 controls CTID maps to it, the DISA STIG findings that implement those controls on the systems you name, and ATT&CK's own mitigations and detection strategy. The answer opens with summary: rules found, rules per CAT, control_counts, mitigation and detection counts (detection counts analytics), cat_i (the CAT I V- ids with their count), then controls_with_rules. Use those counts rather than counting lists yourself. protect.controls maps each control id to its name, family, source and rules. A control's rules include those DISA tags to its enhancements (e.g. AC-6(9) under AC-6), since the ATT&CK mapping names base controls; via, when present, maps each enhancement to the rules that reach the control only through it. Each finding gives its benchmark (stig_id/version, described in resolved_systems), V- id and CAT; titles come with CAT I findings, or with every CAT named in severity; when any are missing, summary.titles reads "CAT I only", so never name or describe an untitled finding without fetching its title (call again with severity naming its CAT); call finding_details with rule ids or V- ids for DISA's check and fix text and the CCIs. severity narrows findings to CAT levels, e.g. ["I"]. A technique id ATT&CK has revoked (e.g. T1562) is answered for its replacement, and the response reports the redirect in technique.redirected_from. Include the product build in system_description where one exists (e.g. 'ESXi 8.0 U3'): some products ship two STIG versions with different remediations, and the build selects the one that applies. benchmark_ids narrows to benchmarks you already know and accepts at most 200; to scope a system you cannot name, pass system_description instead and let the resolver do it. If the knowledge base is not built yet this returns {"status": "not_ready"} with the commands to run, rather than an error. platforms names ATT&CK platforms, e.g. ["Windows"], and detect.applicable then lists the analytics that apply to them; an unknown name is refused with the full list. log_sources names the telemetry you collect, with ATT&CK's log source names, in any case (e.g. ["WinEventLog:Security", "WinEventLog:Sysmon"]); log_sources takes up to 100 names. When platforms is given, detect.detectable lists (and summary.detection counts) only applicable analytics whose every log source is in the list; without platforms, every analytic whose log sources are all collected. detect.analytics maps each analytic id to its name and platforms; detect.applicable and detect.detectable list the qualifying ids and are present only when platforms or log_sources was given (absent: not judged; empty: none qualify). Mitigations are listed by id and name only: call defense_details with M-, DET- or AN- ids for MITRE's text, log sources and tunable elements.

ParametersJSON Schema
NameRequiredDescriptionDefault
severityNo
platformsNo
log_sourcesNo
technique_idYes
benchmark_idsNo
system_descriptionNo

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so richly: it discloses the {"status": "not_ready"} state instead of an error, revoked-technique redirection via technique.redirected_from, the titles degradation rule ('CAT I only') with an explicit warning never to describe untitled findings, the 200-item cap on benchmark_ids and 100 on log_sources, and the precise present/absent/empty semantics of detect.applicable and detect.detectable.

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?

Almost every sentence carries non-redundant information, so the size is largely earned, but it is delivered as one massive unstructured block that jumps between return shape, parameter behavior and error states, making it hard to scan. Bullets or headers would preserve the content with far better retrieval.

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

Completeness5/5

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

There is no output schema, and the description fully assumes that duty by walking through the response layout (summary counts, protect.controls, via mappings, detect.*, mitigations) and explaining how counts should be used rather than recomputed. Combined with the not_ready and redirect handling, an agent has everything needed to call and interpret this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, and it documents all six parameters with formats, constraints and examples: severity narrows to CAT levels (e.g. ["I"]), platforms takes ATT&CK platform names and is validated, log_sources takes ATT&CK log source names case-insensitively up to 100, benchmark_ids caps at 200, and system_description should include the product build because it selects between STIG versions.

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?

States a specific verb and resource up front ('Return the defenses the knowledge base holds for an ATT&CK technique') and enumerates the three content families returned: 800-53r5 controls, DISA STIG findings, and ATT&CK mitigations/detection strategy. It distinguishes itself from siblings by directing detail lookups to finding_details and defense_details rather than doing everything itself.

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?

Gives clear routing conditions: call finding_details for check/fix text or CCIs, defense_details for M-/DET-/AN- ids, pass system_description when you cannot name a system, and benchmark_ids when you already know the benchmark. It does not, however, position itself against other entry points such as search_techniques or techniques_for_actor, so the top-level choice is left implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

finding_detailsA

Return DISA's check and fix text for STIG findings, with each finding's benchmark, release and CCIs. ids takes up to 50 rule ids (SV-...r..._rule) or V- ids as listed under findings in a defenses_for_technique or techniques_for_actor answer, in any case. Prefer the V- id: a rule id carries its release's revision and matches only that release. A V- id that two benchmarks or majors share returns every match, each labeled with its benchmark. not_found lists ids that matched nothing; if none match, the call is refused with an error instead. Quote check_text and fix_text as DISA wrote them, and label anything you add, such as commands or explanations, as your own rather than DISA's. If the knowledge base is not built yet this returns {"status": "not_ready"} with the commands to run, rather than an error.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsYes

TDQS

A4.7/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does: it documents the refusal-on-no-match behavior, the not_found list, the {"status": "not_ready"} response for an unbuilt knowledge base, and the quoting/labeling protocol for check_text and fix_text. These are non-obvious behaviors an agent cannot infer from the schema.

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?

Front-loads the core purpose and the payload contents before the id mechanics, and every sentence adds actionable detail. It is dense and slightly long, but no sentence is filler.

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

Completeness5/5

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

For a single-param tool with no output schema or annotations, the description covers the return contents, id semantics, error/refusal modes, and degraded-state response. An agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate, and it does: it specifies the 50-id cap, the two accepted id formats (SV-...r..._rule and V- ids), the prefer-V- rule, and the multi-benchmark dedup behavior. This is far more than the bare string array in the schema.

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?

States a specific verb and resource: 'Return DISA's check and fix text for STIG findings,' and immediately names the payload fields (benchmark, release, CCIs). It is clearly distinguishable from siblings like defense_details or check_sources.

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?

Tells the agent where ids come from (defenses_for_technique, techniques_for_actor) and which id form to prefer (V- over rule id, with the release-matching rationale). It stops short of explicitly saying when to choose this tool over defense_details or check_sources, so no full exclusion clause.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

install_knowledge_baseA

Install the prebuilt knowledge base this server answers from. With no arguments, download the newest release for this server from this project's GitHub releases (github.com/jeneric/STIG-MCP), verify its SHA-256 and install it; this downloads and verifies about 5 MB and can take several seconds. It is the only tool besides check_sources that uses the network. release pins an exact kb-YYYY-MM-DD tag, for rollback. On a host without network access, pass path (a .sqlite.xz or .sqlite copied from a release) and sha256 (the value its SHA256SUMS lists); nothing is then requested. Call this when another tool returns {"status": "not_ready"}, or when check_sources reports "install".

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNo
sha256No
releaseNo

TDQS

A4.8/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so well: it discloses network dependency ('uses the network'), approximate size and duration ('about 5 MB and can take several seconds'), the SHA-256 verification step, the rollback mechanism via 'release pins an exact kb-YYYY-MM-DD tag', and the no-network branch. This is unusually rich behavioral context for an install/mutate operation.

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?

Every sentence contributes information — download source, verification, size/latency, offline path, trigger conditions — and the primary action is front-loaded. It is somewhat dense and reads as one continuous block rather than clearly separated modes, which costs a point.

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

Completeness4/5

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

For a no-annotation, no-output-schema, 3-parameter tool, the description covers inputs, network behavior, verification, and invocation triggers thoroughly. It does not mention what a successful invocation returns or how failures surface, a minor gap given there is no output schema to lean on.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does: 'release pins an exact kb-YYYY-MM-DD tag, for rollback'; 'path (a .sqlite.xz or .sqlite copied from a release)'; 'sha256 (the value its SHA256SUMS lists)'. Each of the three parameters gets format and purpose beyond the bare schema.

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 states a specific verb and resource ('Install the prebuilt knowledge base this server answers from') and immediately scopes the default behavior (download newest release, verify SHA-256, install). It also differentiates itself from siblings by noting it is 'the only tool besides check_sources that uses the network.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit trigger conditions: 'Call this when another tool returns {"status": "not_ready"}, or when check_sources reports "install".' It also names the conditions under which the offline parameters apply ('On a host without network access, pass path ... and sha256'). Both when-to-use and when-to-use-the-alternative-mode are covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_stigsA

List the STIGs in the knowledge base, optionally filtered by a substring of the title, the benchmark id (e.g. RHEL_9_STIG), or the product keywords. If the knowledge base is not built yet this returns {"status": "not_ready"} with the commands to run, rather than an error.

ParametersJSON Schema
NameRequiredDescriptionDefault
filterNo

TDQS

A4/5.0
Behavior3/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. It adds genuine behavioral value by disclosing the not-ready state return ({"status": "not_ready"}) instead of an error, but says nothing about permissions, pagination, or the shape/ordering of the returned STIG list.

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?

Two sentences, front-loaded with the core purpose and followed by the edge-case behavior. No filler or redundancy.

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

Completeness4/5

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

For a single-param, no-output-schema list tool this is nearly complete: purpose, filter semantics, and the not-ready edge case are all covered. Only the return format of a successful call (fields, ordering, size) is left unspecified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the single 'filter' param is undocumented in the schema, so the description must compensate. It does, explaining that the filter is a substring match against title, benchmark id (with a concrete example, RHEL_9_STIG), or product keywords — meaning the schema alone does not provide.

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?

States a specific verb (List) and resource (STIGs in the knowledge base) and scopes it by the filter dimensions. An agent can immediately distinguish this read/list tool from siblings like search_techniques or mitigations_for_technique.

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 implies usage through the filtering options (title substring, benchmark id, product keywords) but never states when to prefer this over siblings or any prerequisite workflow. It does tell the agent what happens when the KB isn't built, which is useful context, but no explicit when/when-not guidance is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_systemA

Resolve a free-text system description to candidate DISA STIG(s). Returns 'candidates' and 'notes'. limit caps the number of distinct benchmarks returned, not rows: a benchmark holding more than one STIG major (for example vSphere 8.0) contributes every major as its own row, so a caller asking for limit=5 may receive more than 5 rows. Include the product build where one exists (e.g. 'ESXi 8.0 U3'); each candidate reports whether it applies to that build in the 'applicable' field. When the description names a product version this knowledge base does not hold, a note in 'notes' says so and names the versions it does hold. A description naming more than one system is split on 'and' and commas and each part judged separately, so it can carry one such note per part, each quoting the part it is about. When more benchmarks tie with the last benchmark shown than limit allows, a note in 'notes' says how many and suggests calling again with a higher limit. If the knowledge base is not built yet this returns {"status": "not_ready"} with the commands to run, rather than an error.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
system_descriptionYes

TDQS

A4.5/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and discharges it: it explains the limit semantics (caps distinct benchmarks, not rows, and can yield more rows than limit), the 'applicable' field, the tie-overflow note, and the not_ready status with remediation commands instead of an error. This is unusually rich operational disclosure.

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?

Purpose and return shape are front-loaded, and each sentence carries information. It is dense and runs long, with the tie-note and multi-part-note behavior occupying separate sentences that could be tightened, but nothing is filler.

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

Completeness5/5

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

No output schema exists, so the description must describe returns itself; it names 'candidates', 'notes', the 'applicable' field, and the not_ready shape. For a 2-parameter lookup tool with no annotations, everything an agent needs to call and interpret it is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate and does: limit is explained in depth (benchmarks vs rows, multi-major benchmarks contributing several rows), and system_description gets guidance on including build strings and how multi-system input is parsed. Both parameters gain meaning beyond their bare schema titles.

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 opening sentence states a specific verb (resolve) and resource (free-text system description → candidate DISA STIGs), and the tool is clearly distinguishable from siblings like list_stigs or search_techniques. An agent can tell what it returns ('candidates' and 'notes') without opening any schema.

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?

It gives strong input-shaping advice (include the product build, multi-system descriptions are split on 'and'/commas) but never states when to prefer this over list_stigs or another sibling, nor any explicit when-not-to-use condition. Usage is implied rather than contrasted against alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_techniquesA

Search ATT&CK techniques by name or id. Ids and names ATT&CK has revoked also match, returning the replacement technique with redirected_from set to the old id. If the knowledge base is not built yet this returns {"status": "not_ready"} with the commands to run, rather than an error.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryYes

TDQS

A3.8/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does well: it discloses that revoked ids/names still match and return a replacement with redirected_from set, and that an unbuilt knowledge base yields {"status": "not_ready"} with commands rather than an error. It does not mention pagination, result caps, or auth needs, so it is not exhaustive.

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?

Three tight sentences, each earning its place: the core purpose first, then revoked-id behavior, then the not-ready edge case. No filler.

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

Completeness4/5

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

With no output schema and no annotations, the description covers the important edge cases (revoked techniques, unbuilt knowledge base) well. It is only slightly incomplete in not describing the 'limit' parameter or the shape of successful results.

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 coverage is 0%, so the description must compensate. It adds real meaning for 'query' (matches by name or id, including revoked ids), but 'limit' (default 10) is never explained and no query syntax or matching semantics are given.

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?

States a specific verb (search) and resource (ATT&CK techniques) plus the matching keys (name or id). It is clearly distinct from siblings like mitigations_for_technique or techniques_for_actor, but it never names or contrasts those siblings explicitly, so it falls short of a 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 purpose implies when to use it, but there is no explicit when/when-not guidance and no routing to alternatives such as techniques_for_actor or mitigations_for_technique. Usage is left to be inferred from the verb.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

techniques_for_actorA

List an ATT&CK actor's techniques, optionally expanded with defenses for given systems. actor is an ATT&CK group id, name or alias; case, spacing, punctuation and a trailing "Group" or "Team" are ignored, and actor.matched_as then names what matched. actor.also_matches, when present, lists other groups the same label loosely names. A misspelling is not corrected: the error names the closest groups, so call again with the group id of the one meant. The answer opens with summary, which counts the techniques; with include_defenses it adds the same counts defenses_for_technique gives, across every technique. Use those counts rather than counting lists yourself. controls lists each control once with its rule ids, including rules DISA tags to its enhancements, which via names, and findings lists each finding once, without check or fix text (call finding_details for those), each naming its benchmark, V- id and CAT, with titles for CAT I or for the CATs named in severity; summary.titles reads "CAT I only" when the rest are missing, so fetch a title before naming an untitled finding. Each technique lists its control ids grouped by where the mapping came from ("ctid" or "override"). benchmark_ids accepts at most 200; it, severity (CAT levels, e.g. ["I"]), platforms and log_sources are validated always but only take effect with include_defenses. To scope a system you cannot name, pass system_description instead. With include_defenses each technique also lists its ATT&CK mitigations (M-ids), its detection strategy (DET-id), analytics (a map of AN-id to platforms, with applicable and detectable id lists as in defenses_for_technique), and gaps, the coverage classes the call can judge that count that technique as a gap (mitigated_without_rules needs a scoped system, without_applicable_analytic platforms, undetectable log_sources), so read gaps rather than deriving them. mitigations maps each M-id to its name once, while summary.mitigations counts mitigation references across techniques (one on two techniques counts twice). summary.coverage, which comes right after control_counts, counts techniques: without_mitigation, mitigated_without_rules (only when a system was scoped; with severity, no rules at the requested CAT levels), without_applicable_analytic (only with platforms), detectable and undetectable (only with log_sources); summary.detection counts analytics instead. Detection is judged applicability first when platforms is given, then detectability over the applicable analytics. Each technique's applicable and detectable id lists are judged as in defenses_for_technique, so with platforms detectable is always a subset of applicable; log_sources takes up to 100 names. Call defense_details with M-, DET- or AN- ids for MITRE's text. If the knowledge base is not built yet this returns {"status": "not_ready"} with the commands to run, rather than an error.

ParametersJSON Schema
NameRequiredDescriptionDefault
actorYes
severityNo
platformsNo
log_sourcesNo
benchmark_idsNo
include_defensesNo
system_descriptionNo

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations present, the description carries the entire burden and does so unusually well: it discloses that misspellings are not auto-corrected and the error names nearest groups, that benchmark_ids caps at 200 and log_sources at 100, that severity/platforms/log_sources are validated but inert without include_defenses, that controls/findings are de-duplicated, and that an unbuilt knowledge base returns {"status": "not_ready"} rather than an error.

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 purpose is front-loaded, but the body is a single dense paragraph of conditionals and nested return-shape semantics (summary.coverage, gaps, applicable/detectable id lists) with no structural breaks. Much of it is legitimately load-bearing given the complexity, yet grouping into sections would have made it materially easier to scan.

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

Completeness5/5

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

For a 7-parameter tool with no output schema and no annotations, the description covers essentially everything an agent needs: normalization and error behavior, parameter limits, the effect of include_defenses, the shape of summary/counts/coverage/gaps, and the not_ready state. Nothing critical for correct invocation appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does for every one of the seven parameters: actor (id/name/alias, normalization rules, matched_as/also_matches), severity (CAT levels, e.g. ["I"]), platforms, log_sources, benchmark_ids, include_defenses, and system_description. This is far beyond what the bare schema conveys.

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?

Opens with a specific verb and resource: 'List an ATT&CK actor's techniques,' then qualifies scope with 'optionally expanded with defenses for given systems.' It also implicitly separates this tool from siblings by routing sub-data (defenses_for_technique, finding_details, defense_details) elsewhere, so an agent can tell what this tool owns.

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?

Gives concrete conditional guidance: use system_description 'to scope a system you cannot name,' call finding_details for check/fix text, and call defense_details for MITRE's text on M-/DET-/AN- ids. It also instructs the agent to retry with a group id after a misspelling. It never states when this tool should be preferred over siblings like search_techniques, so it stops short of full when/when-not coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.2
    • Addeddefense_details
    • Addeddefenses_for_technique
    • Removedmitigations_for_technique
    • Changedtechniques_for_actor6 fields changed
      • addedInput schema / properties / benchmark_ids
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Benchmark Ids"
        +}
      • addedInput schema / properties / include_defenses
        Added value: +{
        +  "default": false,
        +  "title": "Include Defenses",
        +  "type": "boolean"
        +}
      • removedInput schema / properties / include_mitigations
        Removed value: -{
        -  "default": false,
        -  "title": "Include Mitigations",
        -  "type": "boolean"
        -}
      • addedInput schema / properties / log_sources
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Log Sources"
        +}
      • addedInput schema / properties / platforms
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Platforms"
        +}
      • removedInput schema / properties / stig_ids
        Removed value: -{
        -  "anyOf": [
        -    {
        -      "items": {
        -        "type": "string"
        -      },
        -      "type": "array"
        -    },
        -    {
        -      "type": "null"
        -    }
        -  ],
        -  "default": null,
        -  "title": "Stig Ids"
        -}
  2. 8 tool updatesv0.1.1
    • First observedcheck_sources
    • First observedfinding_details
    • First observedinstall_knowledge_base
    • First observedlist_stigs
    • First observedmitigations_for_technique
    • First observedresolve_system
    • First observedsearch_techniques
    • First observedtechniques_for_actor

TDQS

A4.2/5.0

Scored across 9 tools

Disambiguation4/5

Most tools target distinct resources: resolve_system finds benchmarks, list_stigs enumerates them, finding_details and defense_details fetch text for specific ids, and install/check handle the knowledge base. The main overlap is between defenses_for_technique and techniques_for_actor, since the latter's include_defenses effectively re-runs the former's logic, and resolve_system vs list_stigs both deal with the benchmark catalog. The very detailed descriptions mitigate most of this, so an agent can usually pick correctly.

Naming Consistency4/5

All names use snake_case consistently, with no casing chaos. The convention is only split between action-led names (resolve_system, list_stigs, search_techniques, check_sources, install_knowledge_base) and noun-phrase lookups (finding_details, defense_details, defenses_for_technique, techniques_for_actor), which reads a bit mixed but remains predictable and readable.

Tool Count5/5

Nine tools is well within a healthy range and each appears to earn its place: a handful of query tools, two detail-fetch tools, and two knowledge-base lifecycle tools. Nothing feels redundant or thin.

Completeness4/5

The surface covers the full workflow: resolving systems, listing STIGs, fetching finding check/fix text, mapping techniques/actors to defenses and controls, fetching MITRE defense text, and installing/updating the knowledge base. A minor gap is a direct control-id lookup (controls are only reachable through technique/actor queries), but this is largely workable.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    F
    maintenance
    Enables querying the MITRE ATT\&CK framework for adversarial tactics, techniques, mitigations, and detection methods through natural language, supporting both ID-based and fuzzy name-based searches.
    3
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI-native access to the MITRE ATT\&CK framework, allowing LLMs and agents to query techniques, threat groups, software, and generate ATT\&CK Navigator layers for threat intelligence and security workflows.
    65
    37 npm
    5
    Apache 2.0
  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides search, detail lookup, and gap listing tools for a security control inventory, enabling natural language queries about control status and gaps.
    -