Skip to content

Latest commit

 

History

History
107 lines (81 loc) · 5.06 KB

File metadata and controls

107 lines (81 loc) · 5.06 KB

MCP Resources (v1.23.0)

ContrastAPI exposes the ATLAS / D3FEND / CWE catalogs as MCP resources/* so agents can browse without spending a tool slot. Resources are pure local-DB lookups — no rate limit, no upstream API, no auth.

URI map

URI Type Returns
atlas://catalog static All ATLAS techniques + case studies (slim summary)
atlas://technique/{technique_id} template Full ATLAS technique record
atlas://case-study/{case_study_id} template Full ATLAS case study
d3fend://catalog static All D3FEND defenses (slim summary)
d3fend://defense/{defense_id} template Full D3FEND defense + ATT&CK mappings
cwe://catalog static All CWE weaknesses (id+name+abstract_type)
cwe://weakness/{cwe_id} template Full CWE record incl. mitigations + examples

{technique_id} accepts ATLAS format AML.T#### or AML.T####.###. {cwe_id} accepts CWE-79 or just 79 (auto-prefixed). All MIME types are application/json.

Why resources, not tools?

Tools and resources cover different use-cases:

  • Resources — "I know exactly which catalog row I want." Browse-style. Cheap. No filtering / pivots.
  • Tools (atlas_technique_search, d3fend_defense_search, cwe_lookup, ...) — "I want to filter / pivot / chain." Carries a rate budget but supports parameters and emits next_calls pivot hints.

Reach for resources when an agent already has a CWE id or a D3FEND slug from a prior tool call and you want to drill the full record without re-running the search.

Discovery

# List static resources (3 catalogs)
curl -X POST https://api.contrastcyber.com/mcp/ \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"resources/list","params":{}}'

# List URI templates (4 detail-resource templates)
curl -X POST https://api.contrastcyber.com/mcp/ \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":2,"method":"resources/templates/list","params":{}}'

Read

# Full ATLAS technique
curl -X POST https://api.contrastcyber.com/mcp/ \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":3,"method":"resources/read","params":{"uri":"atlas://technique/AML.T0051"}}'

# CWE-79 (bare-number form auto-prefixes)
curl -X POST https://api.contrastcyber.com/mcp/ \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":4,"method":"resources/read","params":{"uri":"cwe://weakness/79"}}'

# Full D3FEND catalog (149 defenses, slim)
curl -X POST https://api.contrastcyber.com/mcp/ \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":5,"method":"resources/read","params":{"uri":"d3fend://catalog"}}'

Catalog payload shape (slim by design)

The CWE catalog has 944 rows in production; full descriptions blow past most agent context budgets. Catalog responses therefore carry only id + name + key fields per row. Use the per-id template URI when you need the full record.

// atlas://catalog
{
  "techniques": [{"technique_id": "AML.T0051", "name": "LLM Prompt Injection", "tactics": ["AML.TA0011"], "subtechnique_of": null}, ...],
  "case_studies": [{"case_study_id": "AML.CS0000", "name": "Evasion of Deep Learning Detector"}, ...],
  "totals": {"techniques": 167, "case_studies": 57},
  "truncated": false
}

// d3fend://catalog
{
  "defenses": [{"defense_id": "TokenBinding", "label": "Token Binding", "tactic": "Harden", "artifact": "Token", "parent_label": "Authentication"}, ...],
  "totals": {"defenses": 149},
  "truncated": false
}

// cwe://catalog
{
  "weaknesses": [{"cwe_id": "CWE-79", "name": "Improper Neutralization of Input ...", "abstract_type": "Base"}, ...],
  "totals": {"weaknesses": 944},
  "truncated": false,
  "note": "Slim view (cwe_id + name + abstract_type only). Read cwe://weakness/{id} for description, mitigations, examples."
}

The truncated boolean is true when the in-memory listing length is below the table count — surfaced honestly so clients fall back to the search tools (atlas_technique_search, d3fend_defense_search) instead of trusting an incomplete catalog. Today it is always false in production (catalog sizes well within the listing cap); the flag is forward-compatible.

Errors

A well-formed but unknown id surfaces as a JSON-RPC error response (not a 200-with-empty-body) so agents can branch on it cleanly:

  • atlas://technique/AML.T9999 (well-formed, not in catalog) → JSON-RPC error
  • atlas://technique/not-an-id (malformed) → JSON-RPC error (validator rejects before DB lookup)
  • cwe://weakness/0 (well-formed, not in catalog) → JSON-RPC error

Cache strategy

Catalog data ships with the server (synced from upstream on a schedule — ATLAS ~6 months, D3FEND ~yearly, CWE ~weekly). Resources read directly from SQLite on each call; no MCP-layer cache, no TTL. Upstream sync cadence is the only cache.