stig-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. stig_mcp-0.1.0/LICENSE +21 -0
  2. stig_mcp-0.1.0/MANIFEST.in +3 -0
  3. stig_mcp-0.1.0/NOTICE +102 -0
  4. stig_mcp-0.1.0/PKG-INFO +215 -0
  5. stig_mcp-0.1.0/README.md +196 -0
  6. stig_mcp-0.1.0/licenses/apache-2.0.txt +202 -0
  7. stig_mcp-0.1.0/pyproject.toml +96 -0
  8. stig_mcp-0.1.0/setup.cfg +4 -0
  9. stig_mcp-0.1.0/stig_mcp/__init__.py +0 -0
  10. stig_mcp-0.1.0/stig_mcp/applicability.py +254 -0
  11. stig_mcp-0.1.0/stig_mcp/applicability.yaml +34 -0
  12. stig_mcp-0.1.0/stig_mcp/ingest/__init__.py +0 -0
  13. stig_mcp-0.1.0/stig_mcp/ingest/attack_parser.py +199 -0
  14. stig_mcp-0.1.0/stig_mcp/ingest/catalog.py +259 -0
  15. stig_mcp-0.1.0/stig_mcp/ingest/cci_parser.py +67 -0
  16. stig_mcp-0.1.0/stig_mcp/ingest/config.py +140 -0
  17. stig_mcp-0.1.0/stig_mcp/ingest/control_catalog.py +59 -0
  18. stig_mcp-0.1.0/stig_mcp/ingest/control_id.py +14 -0
  19. stig_mcp-0.1.0/stig_mcp/ingest/currency.py +106 -0
  20. stig_mcp-0.1.0/stig_mcp/ingest/fetch.py +1016 -0
  21. stig_mcp-0.1.0/stig_mcp/ingest/id_corrections.py +149 -0
  22. stig_mcp-0.1.0/stig_mcp/ingest/id_corrections.yaml +38 -0
  23. stig_mcp-0.1.0/stig_mcp/ingest/inventory.py +365 -0
  24. stig_mcp-0.1.0/stig_mcp/ingest/library.py +282 -0
  25. stig_mcp-0.1.0/stig_mcp/ingest/mapping_loader.py +109 -0
  26. stig_mcp-0.1.0/stig_mcp/ingest/orchestrator.py +1479 -0
  27. stig_mcp-0.1.0/stig_mcp/ingest/severity.py +10 -0
  28. stig_mcp-0.1.0/stig_mcp/ingest/stig_parser.py +192 -0
  29. stig_mcp-0.1.0/stig_mcp/ingest/upstream.py +174 -0
  30. stig_mcp-0.1.0/stig_mcp/kb/__init__.py +0 -0
  31. stig_mcp-0.1.0/stig_mcp/kb/actor_match.py +125 -0
  32. stig_mcp-0.1.0/stig_mcp/kb/db.py +64 -0
  33. stig_mcp-0.1.0/stig_mcp/kb/freshness.py +145 -0
  34. stig_mcp-0.1.0/stig_mcp/kb/install.py +413 -0
  35. stig_mcp-0.1.0/stig_mcp/kb/queries.py +368 -0
  36. stig_mcp-0.1.0/stig_mcp/kb/releases.py +402 -0
  37. stig_mcp-0.1.0/stig_mcp/kb/schema.sql +123 -0
  38. stig_mcp-0.1.0/stig_mcp/resolver/__init__.py +0 -0
  39. stig_mcp-0.1.0/stig_mcp/resolver/aliases.yaml +54 -0
  40. stig_mcp-0.1.0/stig_mcp/resolver/normalize.py +207 -0
  41. stig_mcp-0.1.0/stig_mcp/resolver/resolver.py +938 -0
  42. stig_mcp-0.1.0/stig_mcp/server/__init__.py +0 -0
  43. stig_mcp-0.1.0/stig_mcp/server/app.py +284 -0
  44. stig_mcp-0.1.0/stig_mcp/server/readiness.py +115 -0
  45. stig_mcp-0.1.0/stig_mcp/server/tools.py +848 -0
  46. stig_mcp-0.1.0/stig_mcp.egg-info/PKG-INFO +215 -0
  47. stig_mcp-0.1.0/stig_mcp.egg-info/SOURCES.txt +49 -0
  48. stig_mcp-0.1.0/stig_mcp.egg-info/dependency_links.txt +1 -0
  49. stig_mcp-0.1.0/stig_mcp.egg-info/entry_points.txt +6 -0
  50. stig_mcp-0.1.0/stig_mcp.egg-info/requires.txt +3 -0
  51. stig_mcp-0.1.0/stig_mcp.egg-info/top_level.txt +1 -0
stig_mcp-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eric Miller
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ # setuptools adds tests/test*.py to the sdist implicitly. The suite needs its fixtures,
2
+ # conftest subtree and tools/ to run, so ship none of it; build from the git tag to test.
3
+ prune tests
stig_mcp-0.1.0/NOTICE ADDED
@@ -0,0 +1,102 @@
1
+ Third-party notices for stig-mcp
2
+ =================================
3
+
4
+ This knowledge base aggregates content from five upstream sources. This file
5
+ records the attribution and licensing obligations that travel with it. Any
6
+ distributed copy of a built knowledge base must carry this notice and the license
7
+ texts under licenses/ with it.
8
+
9
+ MITRE ATT&CK®
10
+ -------------
11
+
12
+ Technique names, descriptions, and ids ingested from the MITRE ATT&CK®
13
+ Enterprise STIX bundle (`enterprise-attack.json`) originate with MITRE and
14
+ carry the following statement, embedded in that bundle by MITRE:
15
+
16
+ Copyright 2015-2026, The MITRE Corporation. MITRE ATT&CK and ATT&CK are
17
+ registered trademarks of The MITRE Corporation.
18
+
19
+ MITRE's ATT&CK Terms of Use grants a license to use ATT&CK and authorizes
20
+ copies made for those purposes, on the condition that both the copyright
21
+ designation and the license paragraph below travel with each copy. Both are
22
+ quoted verbatim from the LICENSE section of
23
+ https://attack.mitre.org/resources/legal-and-branding/terms-of-use/,
24
+ captured 2026-08-08 (the year in the designation reflects that capture date,
25
+ not a fixed value):
26
+
27
+ The MITRE Corporation (MITRE) hereby grants you a non-exclusive,
28
+ royalty-free license to use ATT&CK® for research, development, and
29
+ commercial purposes. Any copy you make for such purposes is authorized
30
+ provided that you reproduce MITRE's copyright designation and this
31
+ license in any such copy.
32
+
33
+ © 2026 The MITRE Corporation. This work is reproduced and distributed
34
+ with the permission of The MITRE Corporation.
35
+
36
+ stig-mcp is not affiliated with, sponsored by, or endorsed by MITRE.
37
+
38
+ Center for Threat-Informed Defense (CTID) mappings
39
+ ---------------------------------------------------
40
+
41
+ The ATT&CK-to-NIST 800-53r5 mapping data ingested from CTID's
42
+ `mappings-explorer` project (`ctid_mappings.json`) is licensed under the
43
+ Apache License, Version 2.0. The full license text is included at
44
+ licenses/apache-2.0.txt. The project carries this notice:
45
+
46
+ © 2024 MITRE. Approved for public release. Document number(s) CT0104.
47
+
48
+ Each mapping record also names the ATT&CK technique it maps, and those names
49
+ fall under the ATT&CK terms above. stig-mcp transforms and subsets this data
50
+ into its knowledge base.
51
+
52
+ DISA STIG content
53
+ -----------------
54
+
55
+ STIG rule metadata, check text, and fix text are ingested from the unclassified
56
+ (`U_`) SRG-STIG Library Compilation, the Rev 4 SRG-STIG Sunset Compilation, and
57
+ individual STIG archives published by the Defense Information Systems Agency
58
+ (DISA) on DoD Cyber Exchange. The
59
+ compilation's readme (SRG-STIG Library Compilation Readme, V2R1, 06 August
60
+ 2024) describes the `U_` compilation as containing "only publicly releasable
61
+ STIGs and related content for download by the general public", and states:
62
+
63
+ The compilations may be used and distributed in the same manner as
64
+ individually downloaded documents.
65
+
66
+ Cyber Exchange's Privacy & Security page
67
+ (https://www.cyber.mil/privacy-security/, captured 2026-09-26; archived copy at
68
+ https://web.archive.org/web/20250118065122/https://public.cyber.mil/privacy-security/)
69
+ states: "Information presented on Cyber Exchange is considered public
70
+ information and may be distributed or copied. Use of appropriate
71
+ byline/photo/image credits is requested."
72
+
73
+ Credit: STIG content courtesy of the Defense Information Systems Agency (DISA),
74
+ DoD Cyber Exchange, https://www.cyber.mil/stigs/.
75
+
76
+ Many STIGs are developed jointly by a product vendor and DISA, as the overview
77
+ document of each such STIG states. Text written by DISA is a work of the United
78
+ States Government and is not subject to copyright protection in the United
79
+ States; this notice makes no such claim for vendor-contributed text, whose
80
+ distribution rests on DISA's release statements above. stig-mcp-fetch refuses
81
+ controlled (`CUI_`) content, and stig-mcp-ingest and stig-mcp-extract refuse
82
+ any source file or archive member with a `CUI_` path component; an operator
83
+ who places sources by hand remains responsible for content that is controlled
84
+ but not so named.
85
+
86
+ DISA CCI list
87
+ -------------
88
+
89
+ The Control Correlation Identifier list is published by DISA on Cyber Exchange
90
+ as the public download `U_CCI_List.zip`, from which stig-mcp-fetch extracts
91
+ `U_CCI_List.xml`. The Privacy & Security statement quoted above applies to it.
92
+
93
+ NIST SP 800-53 Revision 5 control catalog
94
+ ------------------------------------------
95
+
96
+ The NIST SP 800-53 Revision 5 OSCAL control catalog
97
+ (`nist_800_53_rev5_catalog.json`) is a work of the United States Government and
98
+ is in the public domain within the United States. NIST additionally waives
99
+ copyright and related rights in the work worldwide through the CC0 1.0
100
+ Universal public domain dedication
101
+ (https://creativecommons.org/publicdomain/zero/1.0/), per
102
+ https://github.com/usnistgov/oscal-content/blob/main/LICENSE.md.
@@ -0,0 +1,215 @@
1
+ Metadata-Version: 2.4
2
+ Name: stig-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server mapping MITRE ATT&CK® -> NIST 800-53r5 -> DISA STIG fix/check steps
5
+ Author: Eric Miller
6
+ License-Expression: MIT
7
+ Project-URL: Source, https://github.com/jeneric/STIG-MCP
8
+ Project-URL: Issues, https://github.com/jeneric/STIG-MCP/issues
9
+ Project-URL: Security, https://github.com/jeneric/STIG-MCP/security/policy
10
+ Requires-Python: >=3.11
11
+ Description-Content-Type: text/markdown
12
+ License-File: NOTICE
13
+ License-File: LICENSE
14
+ License-File: licenses/apache-2.0.txt
15
+ Requires-Dist: defusedxml>=0.7.1
16
+ Requires-Dist: mcp<3,>=2.2
17
+ Requires-Dist: pyyaml>=6.0.3
18
+ Dynamic: license-file
19
+
20
+ # stig-mcp
21
+
22
+ Local MCP server that maps MITRE ATT&CK® techniques (and actors) to the NIST
23
+ 800-53r5 controls that mitigate them, with the DISA STIG fix and check steps for
24
+ the systems under consideration, severity-ordered.
25
+
26
+ <!-- mcp-name: io.github.jeneric/stig-mcp -->
27
+
28
+ ## Install
29
+
30
+ This project uses [UV](https://docs.astral.sh/uv/). Install dependencies with:
31
+
32
+ uv sync
33
+
34
+ ## Quickstart
35
+
36
+ 1. `uv sync`: install dependencies, then wire the server into a client (see "Run the
37
+ server" below) and start it.
38
+ 2. Ask the agent to install the knowledge base. It calls the `install_knowledge_base`
39
+ tool, which downloads the newest published release from this project's GitHub releases
40
+ and verifies its SHA-256 before installing it. From a terminal the same is
41
+ `uv run stig-mcp-install-kb`. A host that cannot reach GitHub installs from a file; see
42
+ [docs/operations.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/operations.md), "Install a prebuilt knowledge base". Until the
43
+ first knowledge-base release is published, the install says so and names the build
44
+ commands in the next step.
45
+ 3. Or build it yourself: `uv run stig-mcp-fetch` downloads ATT&CK, the CTID mapping, the
46
+ 800-53 catalog, and DISA's STIG content. **This transfers roughly a gigabyte** and
47
+ refuses to start with less than 2 GiB free. Then `uv run stig-mcp-ingest` builds the
48
+ knowledge base.
49
+
50
+ On a host that cannot reach `dl.dod.cyber.mil`, place the artifacts in the sources
51
+ directory yourself and go straight to `stig-mcp-ingest`. That is a first-class path rather
52
+ than a fallback: the ingest reads a directory and never consults the fetch. See
53
+ [docs/operations.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/operations.md), "Placing the sources by hand".
54
+
55
+ Afterwards, `uv run stig-mcp-fetch --check` reports what MITRE ATT&CK, CTID, NIST and DISA
56
+ have published since, exiting 10 when there is something to take and 3 when a source could not
57
+ be reached, and `--refresh` takes it.
58
+ Neither rebuilds the knowledge base; see "Keeping current" in the same document.
59
+
60
+ ## Run the server
61
+
62
+ uv run stig-mcp
63
+
64
+ This is a stdio MCP server: it speaks JSON-RPC on stdin/stdout and logs to stderr,
65
+ so it is launched by an MCP client rather than run standalone.
66
+
67
+ It starts whether or not the knowledge base exists, and it never answers from one it
68
+ cannot trust. Called before the knowledge base is installed, or against one an older release
69
+ wrote, every tool returns a `not_ready` payload instead of an answer: the reason, which
70
+ source files it can and cannot see, the sources directory it looked in, and the next steps,
71
+ led by the `install_knowledge_base` tool and followed by the commands to run, each in both its
72
+ console-script and `python -m` form. That is deliberate, so an agent can read the remedy from
73
+ the tool result rather than the operator having to find a log pane. Install or rebuild the
74
+ knowledge base and the running server picks it up without a restart.
75
+
76
+ The `check_sources` tool tells an agent whether a newer knowledge base is published. It and
77
+ `install_knowledge_base` are the only two tools that contact the network, and they reach
78
+ only this project's GitHub releases.
79
+
80
+ ### GitHub Copilot in VS Code
81
+
82
+ Create `.vscode/mcp.json` in this repository (git-ignored, so it stays local):
83
+
84
+ ```json
85
+ {
86
+ "servers": {
87
+ "stig-mcp": {
88
+ "type": "stdio",
89
+ "command": "uv",
90
+ "args": ["run", "stig-mcp"],
91
+ "cwd": "${workspaceFolder}"
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ Then:
98
+
99
+ 1. Open Copilot Chat and set the mode dropdown to **Agent**. MCP tools are not
100
+ available in Ask or Edit mode.
101
+ 2. Command Palette (`Ctrl+Shift+P`, or `Cmd+Shift+P` on macOS) and run
102
+ **MCP: List Servers**, select `stig-mcp`, then **Start**. Trust the server when
103
+ prompted, since it runs a local command.
104
+ 3. Click **Configure Tools** in the chat input to confirm the eight tools are listed
105
+ and enabled.
106
+ 4. Reference a tool explicitly to verify the wiring, rather than hoping the model
107
+ picks it up on its own. See [docs/user-guide.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/user-guide.md)'s "Getting the
108
+ LLM to use the server" for a prompt shape that reliably does this.
109
+
110
+ Copilot saves a tool answer over 8 KB to a temporary file and reads it back, so with
111
+ manual permissions it asks to read a file named like `…copilot-tool-output-….txt`
112
+ outside the workspace. That file is this server's answer; allow it.
113
+
114
+ To debug, run **MCP: List Servers**, select the server, and choose **Show Output**.
115
+ The two common failures are that `uv` is not on the `PATH` VS Code inherited, which
116
+ looks like a broken server but is a missing command, and an absent knowledge base.
117
+ For the first, use uv's absolute path (`which uv`) as `command`. For the second, see
118
+ [docs/operations.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/operations.md).
119
+
120
+ ### Other clients
121
+
122
+ Any MCP client that launches a stdio server works. `uv run` locates the project from
123
+ the working directory, so a client that starts elsewhere needs `--directory`, which
124
+ makes the command independent of where it is launched:
125
+
126
+ uv run --directory /path/to/STIG-MCP stig-mcp
127
+
128
+ For Claude Code, from the repository root:
129
+
130
+ claude mcp add stig-mcp -- uv run stig-mcp
131
+
132
+ By default the knowledge base is not found relative to the working directory, so only `uv`
133
+ cares where the client starts the server. Where it *is* found depends on whether this is a
134
+ checkout or an installed copy. (A relative `STIG_MCP_DATA` does resolve against the working
135
+ directory, so give it an absolute path if the client's is not yours.)
136
+
137
+ ### Where the data lives
138
+
139
+ Two environment variables override the defaults, and the defaults differ between a source
140
+ checkout and an installed copy:
141
+
142
+ | | source checkout | installed, POSIX and macOS | installed, Windows |
143
+ |---|---|---|---|
144
+ | data directory (`STIG_MCP_DATA`) | `stig_mcp/data/` | `$XDG_DATA_HOME/stig-mcp`, else `~/.local/share/stig-mcp` | `$XDG_DATA_HOME/stig-mcp`, else `%LOCALAPPDATA%\stig-mcp`, else `~\.local\share\stig-mcp` |
145
+ | mapping overrides (`STIG_MCP_OVERRIDES`) | `overrides.yaml` at the repository root | `$XDG_CONFIG_HOME/stig-mcp/overrides.yaml`, else `~/.config/stig-mcp/overrides.yaml` | `$XDG_CONFIG_HOME/stig-mcp/overrides.yaml`, else `%LOCALAPPDATA%\stig-mcp\overrides.yaml`, else `~\.config\stig-mcp\overrides.yaml` |
146
+
147
+ A checkout is a directory holding both the package and the `pyproject.toml` that declares
148
+ it, so an editable install counts as one. XDG is used on POSIX, including macOS. On Windows
149
+ with the XDG variables unset, the default is `%LOCALAPPDATA%`, because a roaming profile
150
+ copies `~/.local/share` at every logon and logoff, and this project's downloads can run to a
151
+ gigabyte; when
152
+ `%LOCALAPPDATA%` is set this puts the mapping overrides file inside the data directory rather
153
+ than beside it, since Windows has one such variable rather than XDG's separate data and config
154
+ locations. (With `%LOCALAPPDATA%` unset, Windows falls back to the same separate `~/.config`
155
+ and `~/.local/share` trees POSIX uses, so the two stay apart in that case, same as the table
156
+ above shows.)
157
+
158
+ **The XDG variables are read first on every platform, Windows included**, as the table's
159
+ Windows column shows: a Windows host with `XDG_DATA_HOME` set uses it and never reaches
160
+ `%LOCALAPPDATA%`, so the roaming argument above holds only where that variable is unset. The
161
+ order is kept so that an existing install's data directory never moves under it.
162
+ `STIG_MCP_DATA` and `STIG_MCP_OVERRIDES` outrank everything above and are the escape hatch
163
+ everywhere, for a native location or any other.
164
+
165
+ `stig-mcp-ingest` creates the data directory if it does not exist. It refuses to run when
166
+ `STIG_MCP_OVERRIDES` names a file that is not there, rather than silently applying no
167
+ overrides; a missing file at the default location is fine, because that file is optional.
168
+
169
+ ## What this server fetches
170
+
171
+ - The MCP server contacts nothing unless `check_sources` or `install_knowledge_base` is
172
+ called. Then it sends HTTPS GET requests to `api.github.com` (this repository's release
173
+ listing) and `github.com` (`/jeneric/STIG-MCP/releases/download/...`), which redirects to
174
+ `release-assets.githubusercontent.com` or `objects.githubusercontent.com`. Any other URL, a
175
+ redirect included, is refused. Nothing is uploaded, and there is no telemetry.
176
+ `install_knowledge_base` given a file path and its SHA-256 requests nothing at all.
177
+ - `stig-mcp-install-kb` contacts the same hosts, and nothing at all with `--file`.
178
+ - `stig-mcp-fetch`, used only to build the knowledge base yourself, downloads from
179
+ `raw.githubusercontent.com` and `api.github.com` (MITRE ATT&CK, the CTID mapping, the NIST
180
+ 800-53 catalog) and from `dl.dod.cyber.mil` (DISA).
181
+
182
+ [PRIVACY.md](https://github.com/jeneric/STIG-MCP/blob/main/PRIVACY.md) states what each of these requests sends and what is stored locally.
183
+
184
+ ## Example prompts
185
+
186
+ With the knowledge base installed and the server wired into an agent, these are answered
187
+ from it:
188
+
189
+ 1. `What DISA STIG steps mitigate T1078 on Windows 11?`
190
+ 2. `Which ATT&CK techniques does APT29 use?`
191
+ 3. `Which STIG benchmarks apply to RHEL 9?`
192
+
193
+ ## Documentation
194
+
195
+ - [docs/operations.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/operations.md): for whoever installs, builds and maintains the knowledge base.
196
+ - [docs/user-guide.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/user-guide.md): for a person talking to an LLM that has this server wired in.
197
+ - [SECURITY.md](https://github.com/jeneric/STIG-MCP/blob/main/SECURITY.md): reporting a vulnerability, and what is in scope.
198
+ - [RELEASING.md](https://github.com/jeneric/STIG-MCP/blob/main/RELEASING.md): for the maintainer, publishing the package to PyPI and the MCP Registry.
199
+ - [PRIVACY.md](https://github.com/jeneric/STIG-MCP/blob/main/PRIVACY.md): what the server and the fetch tool contact, and what is stored locally.
200
+
201
+ ## Third-party content
202
+
203
+ The knowledge base aggregates MITRE ATT&CK, CTID mapping, DISA STIG, DISA CCI
204
+ list, and NIST OSCAL content. See [NOTICE](https://github.com/jeneric/STIG-MCP/blob/main/NOTICE) for attribution and licensing obligations
205
+ and [licenses/apache-2.0.txt](https://github.com/jeneric/STIG-MCP/blob/main/licenses/apache-2.0.txt) for the Apache 2.0
206
+ license text that notice requires.
207
+
208
+ ## Development
209
+
210
+ Developed with the assistance of Claude Code (Anthropic). All changes were reviewed and
211
+ tested by the maintainer.
212
+
213
+ ## Tests
214
+
215
+ uv run pytest
@@ -0,0 +1,196 @@
1
+ # stig-mcp
2
+
3
+ Local MCP server that maps MITRE ATT&CK® techniques (and actors) to the NIST
4
+ 800-53r5 controls that mitigate them, with the DISA STIG fix and check steps for
5
+ the systems under consideration, severity-ordered.
6
+
7
+ <!-- mcp-name: io.github.jeneric/stig-mcp -->
8
+
9
+ ## Install
10
+
11
+ This project uses [UV](https://docs.astral.sh/uv/). Install dependencies with:
12
+
13
+ uv sync
14
+
15
+ ## Quickstart
16
+
17
+ 1. `uv sync`: install dependencies, then wire the server into a client (see "Run the
18
+ server" below) and start it.
19
+ 2. Ask the agent to install the knowledge base. It calls the `install_knowledge_base`
20
+ tool, which downloads the newest published release from this project's GitHub releases
21
+ and verifies its SHA-256 before installing it. From a terminal the same is
22
+ `uv run stig-mcp-install-kb`. A host that cannot reach GitHub installs from a file; see
23
+ [docs/operations.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/operations.md), "Install a prebuilt knowledge base". Until the
24
+ first knowledge-base release is published, the install says so and names the build
25
+ commands in the next step.
26
+ 3. Or build it yourself: `uv run stig-mcp-fetch` downloads ATT&CK, the CTID mapping, the
27
+ 800-53 catalog, and DISA's STIG content. **This transfers roughly a gigabyte** and
28
+ refuses to start with less than 2 GiB free. Then `uv run stig-mcp-ingest` builds the
29
+ knowledge base.
30
+
31
+ On a host that cannot reach `dl.dod.cyber.mil`, place the artifacts in the sources
32
+ directory yourself and go straight to `stig-mcp-ingest`. That is a first-class path rather
33
+ than a fallback: the ingest reads a directory and never consults the fetch. See
34
+ [docs/operations.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/operations.md), "Placing the sources by hand".
35
+
36
+ Afterwards, `uv run stig-mcp-fetch --check` reports what MITRE ATT&CK, CTID, NIST and DISA
37
+ have published since, exiting 10 when there is something to take and 3 when a source could not
38
+ be reached, and `--refresh` takes it.
39
+ Neither rebuilds the knowledge base; see "Keeping current" in the same document.
40
+
41
+ ## Run the server
42
+
43
+ uv run stig-mcp
44
+
45
+ This is a stdio MCP server: it speaks JSON-RPC on stdin/stdout and logs to stderr,
46
+ so it is launched by an MCP client rather than run standalone.
47
+
48
+ It starts whether or not the knowledge base exists, and it never answers from one it
49
+ cannot trust. Called before the knowledge base is installed, or against one an older release
50
+ wrote, every tool returns a `not_ready` payload instead of an answer: the reason, which
51
+ source files it can and cannot see, the sources directory it looked in, and the next steps,
52
+ led by the `install_knowledge_base` tool and followed by the commands to run, each in both its
53
+ console-script and `python -m` form. That is deliberate, so an agent can read the remedy from
54
+ the tool result rather than the operator having to find a log pane. Install or rebuild the
55
+ knowledge base and the running server picks it up without a restart.
56
+
57
+ The `check_sources` tool tells an agent whether a newer knowledge base is published. It and
58
+ `install_knowledge_base` are the only two tools that contact the network, and they reach
59
+ only this project's GitHub releases.
60
+
61
+ ### GitHub Copilot in VS Code
62
+
63
+ Create `.vscode/mcp.json` in this repository (git-ignored, so it stays local):
64
+
65
+ ```json
66
+ {
67
+ "servers": {
68
+ "stig-mcp": {
69
+ "type": "stdio",
70
+ "command": "uv",
71
+ "args": ["run", "stig-mcp"],
72
+ "cwd": "${workspaceFolder}"
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ Then:
79
+
80
+ 1. Open Copilot Chat and set the mode dropdown to **Agent**. MCP tools are not
81
+ available in Ask or Edit mode.
82
+ 2. Command Palette (`Ctrl+Shift+P`, or `Cmd+Shift+P` on macOS) and run
83
+ **MCP: List Servers**, select `stig-mcp`, then **Start**. Trust the server when
84
+ prompted, since it runs a local command.
85
+ 3. Click **Configure Tools** in the chat input to confirm the eight tools are listed
86
+ and enabled.
87
+ 4. Reference a tool explicitly to verify the wiring, rather than hoping the model
88
+ picks it up on its own. See [docs/user-guide.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/user-guide.md)'s "Getting the
89
+ LLM to use the server" for a prompt shape that reliably does this.
90
+
91
+ Copilot saves a tool answer over 8 KB to a temporary file and reads it back, so with
92
+ manual permissions it asks to read a file named like `…copilot-tool-output-….txt`
93
+ outside the workspace. That file is this server's answer; allow it.
94
+
95
+ To debug, run **MCP: List Servers**, select the server, and choose **Show Output**.
96
+ The two common failures are that `uv` is not on the `PATH` VS Code inherited, which
97
+ looks like a broken server but is a missing command, and an absent knowledge base.
98
+ For the first, use uv's absolute path (`which uv`) as `command`. For the second, see
99
+ [docs/operations.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/operations.md).
100
+
101
+ ### Other clients
102
+
103
+ Any MCP client that launches a stdio server works. `uv run` locates the project from
104
+ the working directory, so a client that starts elsewhere needs `--directory`, which
105
+ makes the command independent of where it is launched:
106
+
107
+ uv run --directory /path/to/STIG-MCP stig-mcp
108
+
109
+ For Claude Code, from the repository root:
110
+
111
+ claude mcp add stig-mcp -- uv run stig-mcp
112
+
113
+ By default the knowledge base is not found relative to the working directory, so only `uv`
114
+ cares where the client starts the server. Where it *is* found depends on whether this is a
115
+ checkout or an installed copy. (A relative `STIG_MCP_DATA` does resolve against the working
116
+ directory, so give it an absolute path if the client's is not yours.)
117
+
118
+ ### Where the data lives
119
+
120
+ Two environment variables override the defaults, and the defaults differ between a source
121
+ checkout and an installed copy:
122
+
123
+ | | source checkout | installed, POSIX and macOS | installed, Windows |
124
+ |---|---|---|---|
125
+ | data directory (`STIG_MCP_DATA`) | `stig_mcp/data/` | `$XDG_DATA_HOME/stig-mcp`, else `~/.local/share/stig-mcp` | `$XDG_DATA_HOME/stig-mcp`, else `%LOCALAPPDATA%\stig-mcp`, else `~\.local\share\stig-mcp` |
126
+ | mapping overrides (`STIG_MCP_OVERRIDES`) | `overrides.yaml` at the repository root | `$XDG_CONFIG_HOME/stig-mcp/overrides.yaml`, else `~/.config/stig-mcp/overrides.yaml` | `$XDG_CONFIG_HOME/stig-mcp/overrides.yaml`, else `%LOCALAPPDATA%\stig-mcp\overrides.yaml`, else `~\.config\stig-mcp\overrides.yaml` |
127
+
128
+ A checkout is a directory holding both the package and the `pyproject.toml` that declares
129
+ it, so an editable install counts as one. XDG is used on POSIX, including macOS. On Windows
130
+ with the XDG variables unset, the default is `%LOCALAPPDATA%`, because a roaming profile
131
+ copies `~/.local/share` at every logon and logoff, and this project's downloads can run to a
132
+ gigabyte; when
133
+ `%LOCALAPPDATA%` is set this puts the mapping overrides file inside the data directory rather
134
+ than beside it, since Windows has one such variable rather than XDG's separate data and config
135
+ locations. (With `%LOCALAPPDATA%` unset, Windows falls back to the same separate `~/.config`
136
+ and `~/.local/share` trees POSIX uses, so the two stay apart in that case, same as the table
137
+ above shows.)
138
+
139
+ **The XDG variables are read first on every platform, Windows included**, as the table's
140
+ Windows column shows: a Windows host with `XDG_DATA_HOME` set uses it and never reaches
141
+ `%LOCALAPPDATA%`, so the roaming argument above holds only where that variable is unset. The
142
+ order is kept so that an existing install's data directory never moves under it.
143
+ `STIG_MCP_DATA` and `STIG_MCP_OVERRIDES` outrank everything above and are the escape hatch
144
+ everywhere, for a native location or any other.
145
+
146
+ `stig-mcp-ingest` creates the data directory if it does not exist. It refuses to run when
147
+ `STIG_MCP_OVERRIDES` names a file that is not there, rather than silently applying no
148
+ overrides; a missing file at the default location is fine, because that file is optional.
149
+
150
+ ## What this server fetches
151
+
152
+ - The MCP server contacts nothing unless `check_sources` or `install_knowledge_base` is
153
+ called. Then it sends HTTPS GET requests to `api.github.com` (this repository's release
154
+ listing) and `github.com` (`/jeneric/STIG-MCP/releases/download/...`), which redirects to
155
+ `release-assets.githubusercontent.com` or `objects.githubusercontent.com`. Any other URL, a
156
+ redirect included, is refused. Nothing is uploaded, and there is no telemetry.
157
+ `install_knowledge_base` given a file path and its SHA-256 requests nothing at all.
158
+ - `stig-mcp-install-kb` contacts the same hosts, and nothing at all with `--file`.
159
+ - `stig-mcp-fetch`, used only to build the knowledge base yourself, downloads from
160
+ `raw.githubusercontent.com` and `api.github.com` (MITRE ATT&CK, the CTID mapping, the NIST
161
+ 800-53 catalog) and from `dl.dod.cyber.mil` (DISA).
162
+
163
+ [PRIVACY.md](https://github.com/jeneric/STIG-MCP/blob/main/PRIVACY.md) states what each of these requests sends and what is stored locally.
164
+
165
+ ## Example prompts
166
+
167
+ With the knowledge base installed and the server wired into an agent, these are answered
168
+ from it:
169
+
170
+ 1. `What DISA STIG steps mitigate T1078 on Windows 11?`
171
+ 2. `Which ATT&CK techniques does APT29 use?`
172
+ 3. `Which STIG benchmarks apply to RHEL 9?`
173
+
174
+ ## Documentation
175
+
176
+ - [docs/operations.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/operations.md): for whoever installs, builds and maintains the knowledge base.
177
+ - [docs/user-guide.md](https://github.com/jeneric/STIG-MCP/blob/main/docs/user-guide.md): for a person talking to an LLM that has this server wired in.
178
+ - [SECURITY.md](https://github.com/jeneric/STIG-MCP/blob/main/SECURITY.md): reporting a vulnerability, and what is in scope.
179
+ - [RELEASING.md](https://github.com/jeneric/STIG-MCP/blob/main/RELEASING.md): for the maintainer, publishing the package to PyPI and the MCP Registry.
180
+ - [PRIVACY.md](https://github.com/jeneric/STIG-MCP/blob/main/PRIVACY.md): what the server and the fetch tool contact, and what is stored locally.
181
+
182
+ ## Third-party content
183
+
184
+ The knowledge base aggregates MITRE ATT&CK, CTID mapping, DISA STIG, DISA CCI
185
+ list, and NIST OSCAL content. See [NOTICE](https://github.com/jeneric/STIG-MCP/blob/main/NOTICE) for attribution and licensing obligations
186
+ and [licenses/apache-2.0.txt](https://github.com/jeneric/STIG-MCP/blob/main/licenses/apache-2.0.txt) for the Apache 2.0
187
+ license text that notice requires.
188
+
189
+ ## Development
190
+
191
+ Developed with the assistance of Claude Code (Anthropic). All changes were reviewed and
192
+ tested by the maintainer.
193
+
194
+ ## Tests
195
+
196
+ uv run pytest