From Gold Datasets to AI Agents: VulnMCP 2.0.0, ML-Gateway 1.4.0, and VulnTrain 3.2.0
Today we are releasing an entire chain at once. VulnTrain 3.2.0 turns a hand-curated gold dataset of CVE-to-ATT&CK mappings into a published multi-label classifier — with the methodology now on arXiv. ML-Gateway 1.4.0 serves that model (and its siblings) over a local REST API, hardened against real-world inputs. And VulnMCP 2.0.0 puts the whole thing — plus the Vulnerability-Lookup API, KEV catalogs, sightings, the GCVE registry, and now the CNA partners of the CVE Program — one tool call away from any MCP-capable AI agent.
In other words: the same pipeline goes from an expert-annotated dataset, through training and evaluation, to a model your chat agent can invoke mid-conversation to tell you which MITRE ATT&CK techniques a fresh CVE is likely to enable.
How the pieces fit together
graph LR
subgraph sources["Data & ground truth"]
VL[("Vulnerability-Lookup<br/>CVE, GHSA, KEV,<br/>sightings, comments")]
CTID["MITRE CTID<br/>expert CVE→ATT&CK mappings"]
end
subgraph vulntrain["VulnTrain (training)"]
DS["Dataset generation<br/>(Hugging Face datasets)"]
TR["Trainers & validators<br/>severity / CWE / ATT&CK"]
end
HF[("Hugging Face<br/>CIRCL models")]
subgraph inference["Inference"]
MLG["ML-Gateway<br/>REST API"]
MCP["VulnMCP<br/>MCP server"]
end
AGENT["AI agents, chat clients,<br/>automated workflows"]
VL --> DS
CTID --> DS
DS --> TR
TR --> HF
HF --> MLG
HF --> MCP
MLG -->|"VLAI enrichment"| VL
VL -->|"REST API"| MCP
MCP --> AGENT
Vulnerability-Lookup feeds the training datasets; VulnTrain produces the models published under the CIRCL organization on Hugging Face; ML-Gateway serves them back to the Vulnerability-Lookup platform (that is where the VLAI severity scores on vulnerability.circl.lu come from); and VulnMCP loads the same models locally and combines them with the live APIs, for AI agents.
VulnMCP 2.0.0
When we introduced VulnMCP in March, it shipped severity classification, CWE prediction, CPE guessing, and the core Vulnerability-Lookup tools. Version 2.0.0 grows the server to 17 tools and reworks the internals to make the next seventeen cheap to add.
ATT&CK techniques in your agent’s toolbox
The headline feature: classify_attack_techniques, backed by
CIRCL/vulnerability-attack-technique-classification-roberta-base,
trained with VulnTrain on the curated gold dataset described below. It is a genuine multi-label classifier: every
technique in the vocabulary is scored independently through a sigmoid head, and scores at or above 0.5 are the model’s
positive predictions — the same threshold used for the F1 metrics during training.
This is how the tool presents itself to an MCP client such as Claude Code:

The classify_attack_techniques tool as exposed by VulnMCP, seen from Claude Code.
Asking it about Log4Shell’s description:
poetry run fastmcp call vulnmcp/server.py classify_attack_techniques \
description="Apache Log4j2 JNDI features do not protect against attacker \
controlled LDAP and other JNDI related endpoints. An attacker who can control \
log messages or log message parameters can execute arbitrary code loaded from \
LDAP servers when message lookup substitution is enabled." top_k=5{
"techniques": [
{"technique": "T1496", "name": "Resource Hijacking", "score": 0.8451, "predicted": true},
{"technique": "T1190", "name": "Exploit Public-Facing Application", "score": 0.7370, "predicted": true},
{"technique": "T1498", "name": "Network Denial of Service", "score": 0.6935, "predicted": true},
{"technique": "T1133", "name": "External Remote Services", "score": 0.6759, "predicted": true},
{"technique": "T1071", "name": "Application Layer Protocol", "score": 0.6717, "predicted": true}
],
"model": "CIRCL/vulnerability-attack-technique-classification-roberta-base"
}Resource Hijacking ranked first is not a glitch — it is the model remembering that the single most common thing attackers actually did with Log4Shell was deploy cryptominers.
CNA partners of the CVE Program
Using the gcve library 0.13.0, VulnMCP can now search the 539 CNA partners of
the CVE Program (mirrored at gcve.eu) by name, country, program role, or organization type — and
retrieve one partner’s full record. The partner short name is the same assignerShortName you see in CVE records,
so an agent can go from a CVE straight to the authority behind it, its disclosure policy, and its advisory feed:
poetry run fastmcp call vulnmcp/server.py get_cna_partner short_name=CIRCL{
"partner": "Computer Incident Response Center Luxembourg (CIRCL)",
"program_role": "CNA",
"organization_type": "CERT",
"country": "Luxembourg",
"metadata": {
"cna_id": "CNA-2026-0027",
"disclosure_policy": [
{"url": "https://www.circl.lu/pub/coordinated-vulnerability-disclosure/"}
],
"security_advisories": {
"advisories": [{"url": "https://vulnerability.circl.lu/search?assigner=CIRCL"}]
},
"root": {"shortName": "ENISA", "organizationName": "EU Agency for Cybersecurity (ENISA)"}
}
}Everything else that landed since 1.0.0
- Russian severity classification —
classify_severitynow routes English, Chinese, and Russian descriptions to the right fine-tuned model automatically, based on the script of the input text. search_commentsandsearch_bundles— community analyses and curated CVE collections from Vulnerability-Lookup, straight into the agent’s context.- KEV-aware search —
search_vulnerabilities cwe=CWE-89 prioritize_kev=trueenriches each result against the KEV catalogs and sorts known-exploited vulnerabilities first.
A few one-liners to give you the flavour:
# Which recent SQL-injection CVEs are actually being exploited?
poetry run fastmcp call vulnmcp/server.py search_vulnerabilities cwe=CWE-89 prioritize_kev=true
# Is this CVE in a KEV catalog, and who has seen it in the wild?
poetry run fastmcp call vulnmcp/server.py get_vulnerability vulnerability_id=CVE-2021-44228 with_sightings=true
# All CNA partners located in Luxembourg
poetry run fastmcp call vulnmcp/server.py search_cna_partners country=LuxembourgThis is not just a demo toolbox: these tools, working together, are what we use to automatically generate our monthly vulnerability reports. An AI agent follows the report prompt shipped in the VulnMCP repository and chains the tools itself — most-sighted vulnerabilities, KEV entries across the CISA, CIRCL, ENISA, and Shadowserver catalogs, contributor comments and bundles, severity classifications — into the report you read at the start of each month.
Under the hood
2.0.0 is a major version for a reason: the internals were restructured. All HTTP plumbing for Vulnerability-Lookup
and cpe-guesser moved into a shared vulnmcp/lookup.py, every MCP tool is now a plain importable Python function,
and the server instructions are assembled from per-skill declarations. That made the project properly testable: the
release ships an offline test suite (51 tests, under a second, every network call and model pipeline faked) with
CI on Python 3.10 and 3.13. transformers and torch are imported lazily, so the server starts in well under a second
and only pays the model-loading cost when a classification tool is actually invoked. And a bare poetry install
now pulls CPU-only torch wheels — CUDA is an explicit --extras cuda opt-in.
ML-Gateway 1.3.0 and 1.4.0
ML-Gateway is the other consumer of these models: a FastAPI-based service that loads them at startup and exposes them over REST, so that a Vulnerability-Lookup instance (or anything else on your network) can classify without touching Python or Hugging Face directly.
1.3.0 added POST /classify/attack-techniques — the same multi-label ATT&CK model, with technique names
resolved from the bundled enterprise ATT&CK STIX data. This is what powers the ATT&CK tab on the CVE pages of
vulnerability.circl.lu:

AI-suggested ATT&CK techniques for CVE-2021-44228 on Vulnerability-Lookup, served by ML-Gateway. Click to open the live page.
You can query the endpoint directly:
curl -s -X POST http://127.0.0.1:8000/classify/attack-techniques \
-H "Content-Type: application/json" \
-d '{"description": "An attacker who can control log messages can execute arbitrary code loaded from LDAP servers.", "top_k": 5}'The endpoint handlers were also deliberately made non-async: inference is CPU-bound, and running it on the event
loop would block every concurrent request. FastAPI moves synchronous handlers to a thread pool, which is exactly
what you want here. Models are preloaded at startup and gunicorn --preload is supported, so workers share memory
pages instead of each loading their own copy.
1.4.0 fixes a subtle production bug worth describing, because anyone serving fine-tuned models can hit it.
Some fine-tuned checkpoints ship without model_max_length in their tokenizer config, and transformers then reports
a huge sentinel value instead. Result: truncation silently does nothing, and the first genuinely long vulnerability
description — CSAF advisories can be enormous — crashes the model with an index error deep in the embedding layer.
ML-Gateway now clamps every tokenizer’s limit to the model’s actual max_position_embeddings (minus RoBERTa’s two
offset slots) immediately after loading, via a shared helper with its own test coverage. Long inputs are truncated;
the server no longer cares how verbose an advisory gets.
VulnTrain 3.2.0: the research behind the model
VulnTrain 3.2.0 ships the complete pipeline behind the ATT&CK classifier, and the accompanying paper is now public:
Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion — Cédric Bonhomme, Alexandre Dulaunoy.
Instead of walking the indirect CWE → CAPEC → ATT&CK chain, the classifier is trained directly on a gold dataset of 1,207 CVEs derived from the expert mappings of the MITRE Center for Threat-Informed Defense, with technique IDs normalized against the current enterprise ATT&CK STIX bundle. The 3.2.0 release includes the whole toolchain:
vulntrain-dataset-attack-generation— builds the CIRCL/vulnerability-attack-techniques dataset from the curated mappings.vulntrain-train-attack-classification— the multi-label trainer: sigmoid head with binary cross-entropy loss, optional per-label weighting, and sub-technique collapsing.vulntrain-validate-attack-classification— evaluation with recall@k and MRR;vulntrain-infer-attack-classificationfor single-CVE inference.vulntrain-dataset-attack-llm-labeling— LLM-assisted label expansion with Ollama and Anthropic backends, structured outputs, and provenance tracking.
The headline numbers: the gold-only model reaches recall@5 of 0.673 ± 0.019. And the negative result is just as interesting as the positive one — LLM-generated labels agreed with expert annotations only about 0.39 of the time, and expanding the training set with them brought no reliable improvement while reducing coverage of rare techniques. Expert-curated data consistently helped; synthetic labels did not. The classifier is limited by label quality, not dataset size. All datasets, models, code, and training logs are public.
This work builds on the original VLAI approach — RoBERTa-based severity classification trained on more than 600,000 real-world vulnerability descriptions — described in VLAI: A RoBERTa-Based Model for Automated Vulnerability Severity Classification, the model that has been scoring vulnerabilities on vulnerability.circl.lu since 2025.
Try it
If you run an MCP-capable client — Claude Code, an IDE assistant, or your own agent framework — VulnMCP is a
poetry install away, and every classification runs locally on CPU. Feedback, ideas, and new skills are very welcome.
References
- VulnMCP: https://github.com/vulnerability-lookup/VulnMCP
- ML-Gateway: https://github.com/vulnerability-lookup/ML-Gateway
- VulnTrain: https://github.com/vulnerability-lookup/VulnTrain
- Models and datasets: https://huggingface.co/CIRCL
- Mapping CVEs to MITRE ATT&CK Techniques: https://arxiv.org/abs/2607.25572
- VLAI (original implementation): https://arxiv.org/abs/2507.03607
- VulnMCP 1.0.0 announcement: https://www.vulnerability-lookup.org/2026/03/25/vulnmcp-1-0-0/
- Vulnerability-Lookup instance operated by CIRCL: https://vulnerability.circl.lu
Funding

AIPITCH (AI-Powered Innovative Toolkit for Cybersecurity Hubs) is a co-funded EU project supported by the European Cybersecurity Competence Centre (ECCC) under the DIGITAL-ECCC-2024-DEPLOY-CYBER-06-ENABLINGTECH program and CIRCL.