Skip to content

MCP tool reference

The guardlink-mcp server registers 24 tools and 3 resources. Everything below was read from a running guardlink 2.0.0 server over the protocol, not from its source.

Start it with guardlink-mcp or guardlink mcp — both run the same server. See guardlink-mcp for client configuration.

Field Value
Name guardlink
Version 2.0.0
Capabilities resources, tools
Tools 24
Resources 3

Returned in the initialize response and placed in the model’s context by most clients. Reproduced verbatim: this text is part of what the server makes an agent believe, so it belongs in the reference alongside the tools.

Show the instructions the server sends
GuardLink is this project's threat model: security facts developers recorded next to the code — what each component is exposed to, what mitigates it, how data flows between them — parsed into a queryable model. Ask it instead of inferring security context from the source.
WHEN TO REACH FOR WHAT
Opened a file, or about to edit one → guardlink_context(file)
Annotations declared there with line anchors, the assets they name with each
asset's immediate neighbours, open exposures, and the controls the file is
expected to uphold. An empty answer says which kind of empty it is:
scanned_without_annotations means genuinely clean; not_scanned means the parser
never read the file. Do not read them as the same thing.
About to change a shared component → guardlink_graph(from, depth, direction)
Blast radius. Walks data flows and trust boundaries — not shared threats, which
are classifications rather than couplings. Defaults (depth 2, both, summary) are
the affordable setting; detail full costs ~40% more. Check traversal.completeness:
depth_limited means more is reachable, truncated means INCOMPLETE —
frontier_unexplored says what is missing.
A scanner reported a CWE → guardlink_lookup("cwe:CWE-89")
Whether this model declares that weakness class at all, and whether affected
sites are mitigated, accepted, open or confirmed. Check external_id.declared:
false means never heard of it, which is NOT the same as declared-and-clean.
Before you finish → guardlink_validate · After a change → guardlink_diff("HEAD~1")
Cold on an unfamiliar repo → guardlink_status
WRITING ANNOTATIONS
This project has not recorded an annotation mode. Every tool response carries `mode` in its guardlink envelope, observed from the annotations themselves — read that rather than assuming.
Definitions — @asset, @threat, @control with #ids — live in .guardlink/definitions.*. Reuse
existing ids; never redefine one. Never write @accepts or @entitles: both are human
governance decisions. Found a risk with no control? @exposes plus @audit. An
entitlement claims a privilege was always allowed this, so an over-grant hides a
real escalation: propose it (guardlink_entitlement_propose) citing authz code as
file:line, and a human's acceptance writes it. Never for ownership questions (IDOR,
tenant isolation), where both peers hold the capability.
Write with guardlink_annotate_apply, not by hand: pass the source path, not the .gal.
@source is synthesised — never send one. Do send symbol:, which reanchor needs after a
refactor; omitting it means the statement covers the whole asset rather than one symbol.
READING THE ANSWERS
Every response carries a guardlink envelope: annotation_hash, git_sha, mode, root.
Identical hash means identical model — use it to tell a fresh answer from a stale one.
Anything resolving a reference reports matched_via: exact, alias or substring. A
substring match is a suggestion, not an identification. ambiguous with candidates
means several records tied and one was picked arbitrarily — re-ask precisely.
guardlink_lookup understands 26 named query forms and refuses anything else
rather than guessing. Send it a deliberately bad query to get the list.
Tool Summary
guardlink_parse Parse GuardLink annotations and return the threat model as JSON.
guardlink_status Return coverage statistics: asset/threat/control counts, unmitigated exposures, @confirmed count, coverage percentage
guardlink_validate Check annotations for syntax errors, duplicate IDs, and dangling references.
guardlink_suggest Given a file path or code diff, suggest appropriate GuardLink annotations based on code patterns, imports, and function signatures
guardlink_lookup Query the threat model graph.
guardlink_context Everything GuardLink knows about one file: the annotations declared there, the assets they name with each asset’s depth-1 neighbourhood, open exposures and @…
guardlink_graph Blast radius: the neighbourhood around an asset, or the path between two.
guardlink_annotate_apply Write a validated @source block into the annotation sidecar for a file.
guardlink_reanchor Find @source blocks whose recorded file:line no longer holds the symbol they name — the drift external annotations accumulate after a refactor.
guardlink_threat_report Generate an AI threat report using a security framework (STRIDE, DREAD, PASTA, attacker, rapid, general).
guardlink_annotate Build an annotation prompt with project context, GuardLink reference docs, and GAL syntax guidelines.
guardlink_report Generate a markdown threat model report with Mermaid diagram.
guardlink_dashboard Generate an interactive HTML threat model dashboard with diagrams, charts, code annotations, and heatmap.
guardlink_sarif Export findings as SARIF 2.1.0 for GitHub Advanced Security, VS Code, and other SARIF consumers.
guardlink_diff Compare the current threat model against a git ref (commit, branch, tag).
guardlink_threat_reports List saved AI threat reports from .guardlink/threat-reports/ (and legacy .guardlink/analyses/).
guardlink_sync Sync all agent instruction files (CLAUDE.md, .cursorrules, etc.) with the current threat model.
guardlink_clear Remove all GuardLink annotations from source files.
guardlink_unannotated List source files that have no GuardLink annotations.
guardlink_review_list List all unmitigated exposures eligible for governance review, sorted by severity.
guardlink_review_accept Record a governance decision for an unmitigated exposure.
guardlink_entitlement_propose Propose an @entitles claim (an actor is entitled to a capability BY DESIGN) into .guardlink/entitlement-proposals.json.
guardlink_entitlement_list List entitlement proposals and their decisions from .guardlink/entitlement-proposals.json.
guardlink_workspace_info Get workspace configuration for multi-repo threat modeling.

Answer a question from the model without changing it.

Parse GuardLink annotations and return the threat model as JSON. Omits unannotated_files by default — on a large repo that list is ~90% of the payload and carries no threat-model information; use guardlink_unannotated, which exists for exactly that data, or set include_unannotated. Prefer guardlink_context for a single file and guardlink_lookup for a specific question; this is the expensive call for when you genuinely need the whole model.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
compact boolean no false Return the compact serialization: stats, assets, ALL unmitigated exposures, threat severity index, flows, boundaries and data classifications, with descriptions capped. Omits resolved mitigations, working controls, comments and validations.
include_unannotated boolean no false Include the unannotated_files list. Off by default; guardlink_unannotated is the dedicated tool for it.
Input schema for guardlink_parse
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"compact": {
"default": false,
"type": "boolean",
"description": "Return the compact serialization: stats, assets, ALL unmitigated exposures, threat severity index, flows, boundaries and data classifications, with descriptions capped. Omits resolved mitigations, working controls, comments and validations."
},
"include_unannotated": {
"default": false,
"type": "boolean",
"description": "Include the unannotated_files list. Off by default; guardlink_unannotated is the dedicated tool for it."
}
}
}

Return coverage statistics: asset/threat/control counts, unmitigated exposures, @confirmed count, coverage percentage

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
Input schema for guardlink_status
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
}
}
}

Everything GuardLink knows about one file: the annotations declared there, the assets they name with each asset’s depth-1 neighbourhood, open exposures and @confirmed findings, controls the file upholds, and its @assumes/@handles/@owns. Call this when you open or are about to edit a file. Accepts the source path or, in external mode, the .gal path that annotates it. An empty result is explicit about WHY: scanned_without_annotations means the file is genuinely clean, not_scanned means the parser never read it, not_found means nothing is there — do not read them as the same answer. Reports origin_file for annotations that already exist, not a destination for a new one. In external mode a new sidecar goes at .guardlink/annotations/<source path>.gal — the source path mirrored, with .gal appended.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
file string yes File to describe. Absolute, relative or ./-prefixed; resolved against root. In external mode the .gal path resolves to the source file it annotates.
line number no Optional line number. Narrows to the enclosing symbol where the annotation recorded one (@source symbol:). Reports symbol_scope.applied = “unavailable” when no annotation for the file records a symbol, rather than silently returning the whole file.
Input schema for guardlink_context
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"file": {
"type": "string",
"description": "File to describe. Absolute, relative or ./-prefixed; resolved against root. In external mode the .gal path resolves to the source file it annotates."
},
"line": {
"type": "number",
"description": "Optional line number. Narrows to the enclosing symbol where the annotation recorded one (@source symbol:). Reports symbol_scope.applied = \"unavailable\" when no annotation for the file records a symbol, rather than silently returning the whole file."
}
},
"required": [
"file"
]
}

Query the threat model graph. Reaches every relation type the model carries: assets, threats, controls, mitigations, exposures, confirmed, acceptances, transfers, flows, boundaries, validations, audits, ownership, data classification, assumptions, actors, entitlements, shields, features, comments and cross-repo refs. Examples: “threats for #auth”, “owner of #api”, “handles pii”, “assumptions for #api”, “flows into Scanner”, “unmitigated”, “actors”, “entitlements for #ns-admin”. A query that is not one of the supported forms returns no_match listing them — it is never answered by guesswork.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
query string yes A supported query form: “unmitigated”, “confirmed”, “features”, “asset <id>”, “threat <id>”, “control <id>”, “threats for <asset>”, “controls for <asset>”, “exposures for <asset>”, “mitigations for <asset>”, “flows into <asset>”, “flows from <asset>”, “boundary for <asset>”, “owner of <asset>”, “handles <pii|phi|financial|secrets|internal|public>”, “handles for <asset>”, “assumptions for <asset>”, “audits [for <asset>]”, “validations for <asset-or-control>”, “acceptances [for <asset>]”, “transfers [for <threat-or-asset>]”, “actors”, “entitlements [for <actor>]”, “comments [for <file-or-asset>]”, “shields [for <file-or-asset>]”, or a bare identifier. TWO DIFFERENT REF QUERIES, do not confuse them: “cwe:CWE-89” / “CWE-89” / “owasp:A03” asks about external identifiers declared on threats — the scanner bridge, and returns external_id.declared so you can tell ‘never heard of this weakness’ from ‘declared, nothing exposed’; “cross-repo refs” asks about sibling-repo tags from workspace.yaml and is unrelated. Every entitlements row carries inert: an uncited claim is carried and visible but cannot demote a finding (actor-entitlement design §3.4). @comment and @shield record no asset, so scoping them by an asset joins by co-location (same file) and the result says so. Free-form questions are not parsed.
Input schema for guardlink_lookup
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"query": {
"type": "string",
"description": "A supported query form: \"unmitigated\", \"confirmed\", \"features\", \"asset <id>\", \"threat <id>\", \"control <id>\", \"threats for <asset>\", \"controls for <asset>\", \"exposures for <asset>\", \"mitigations for <asset>\", \"flows into <asset>\", \"flows from <asset>\", \"boundary for <asset>\", \"owner of <asset>\", \"handles <pii|phi|financial|secrets|internal|public>\", \"handles for <asset>\", \"assumptions for <asset>\", \"audits [for <asset>]\", \"validations for <asset-or-control>\", \"acceptances [for <asset>]\", \"transfers [for <threat-or-asset>]\", \"actors\", \"entitlements [for <actor>]\", \"comments [for <file-or-asset>]\", \"shields [for <file-or-asset>]\", or a bare identifier. TWO DIFFERENT REF QUERIES, do not confuse them: \"cwe:CWE-89\" / \"CWE-89\" / \"owasp:A03\" asks about external identifiers declared on threats — the scanner bridge, and returns external_id.declared so you can tell 'never heard of this weakness' from 'declared, nothing exposed'; \"cross-repo refs\" asks about sibling-repo tags from workspace.yaml and is unrelated. Every entitlements row carries inert: an uncited claim is carried and visible but cannot demote a finding (actor-entitlement design §3.4). @comment and @shield record no asset, so scoping them by an asset joins by co-location (same file) and the result says so. Free-form questions are not parsed."
}
},
"required": [
"query"
]
}

Blast radius: the neighbourhood around an asset, or the path between two. Traversal walks the ASSET plane only — @flows (directed), @boundary (undirected, crossable either way) and @transfers (directed). It does NOT hop through shared threats: #path-traversal alone is declared on 10 assets here, so crossing threats would make depth 2 reach most of the graph and depth would stop meaning anything. Threats and controls are still returned for every asset in the neighbourhood, they just are not transited through. Returns a filtered ThreatModel, so the result is a model like any other — minus unannotated_files, which is a whole-repo file inventory rather than subgraph data and is omitted here for the same reason guardlink_parse omits it; guardlink_unannotated owns that list. Use format: “mermaid” for a diagram, or path_to for a route between two assets.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
from string yes Asset to start from. Resolved exactly as “asset X” is — same tiers, same ambiguity reporting. Later hops match canonical identity only, never fuzzily.
path_to string no If set, return the shortest path from from to this asset instead of a neighbourhood. Directed edges are followed forwards; boundaries either way. An unresolvable endpoint and a genuinely disconnected pair are reported differently.
depth number no 2 Hops from from. 0 is the asset alone, 1 matches what “asset X” reports. Clamped to 10. Check traversal.completeness on the result: “complete” means there is nothing more to find at any depth, “depth_limited” means raising this would return more (and frontier_unexplored names what is immediately beyond), “truncated” means the depth-10 ceiling cut it short and the result is INCOMPLETE.
direction string, "in" | "out" | "both" no "both" Which way directed edges are followed. Boundaries are undirected and are crossed in every direction regardless.
kinds string[] no Relation arrays to keep in the returned model. Filters the OUTPUT, not the traversal — excluding “flows” still walks flows, it just omits them from the result. Assets, threats and controls are always kept as the node vocabulary.
format string, "json" | "mermaid" no "json" json returns the filtered ThreatModel plus traversal detail; mermaid renders it with the same generator the dashboard uses.
detail string, "summary" | "full" no "summary" How much per-node detail to return. summary (default) drops description prose and compacts location to an at: "file:line" string — measured at roughly 40% of the payload, and the graph is the same graph either way: identical nodes, identical edges. full returns the complete records and is the only mode whose model is a valid ThreatModel.
feature string no Restrict to one feature before traversing.
file string no Restrict to annotations declared in one file before traversing.
Input schema for guardlink_graph
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"from": {
"type": "string",
"description": "Asset to start from. Resolved exactly as \"asset X\" is — same tiers, same ambiguity reporting. Later hops match canonical identity only, never fuzzily."
},
"path_to": {
"type": "string",
"description": "If set, return the shortest path from `from` to this asset instead of a neighbourhood. Directed edges are followed forwards; boundaries either way. An unresolvable endpoint and a genuinely disconnected pair are reported differently."
},
"depth": {
"default": 2,
"type": "number",
"description": "Hops from `from`. 0 is the asset alone, 1 matches what \"asset X\" reports. Clamped to 10. Check `traversal.completeness` on the result: \"complete\" means there is nothing more to find at any depth, \"depth_limited\" means raising this would return more (and `frontier_unexplored` names what is immediately beyond), \"truncated\" means the depth-10 ceiling cut it short and the result is INCOMPLETE."
},
"direction": {
"default": "both",
"type": "string",
"enum": [
"in",
"out",
"both"
],
"description": "Which way directed edges are followed. Boundaries are undirected and are crossed in every direction regardless."
},
"kinds": {
"type": "array",
"items": {
"type": "string"
},
"description": "Relation arrays to keep in the returned model. Filters the OUTPUT, not the traversal — excluding \"flows\" still walks flows, it just omits them from the result. Assets, threats and controls are always kept as the node vocabulary."
},
"format": {
"default": "json",
"type": "string",
"enum": [
"json",
"mermaid"
],
"description": "json returns the filtered ThreatModel plus traversal detail; mermaid renders it with the same generator the dashboard uses."
},
"detail": {
"default": "summary",
"type": "string",
"enum": [
"summary",
"full"
],
"description": "How much per-node detail to return. summary (default) drops `description` prose and compacts `location` to an `at: \"file:line\"` string — measured at roughly 40% of the payload, and the graph is the same graph either way: identical nodes, identical edges. full returns the complete records and is the only mode whose `model` is a valid ThreatModel."
},
"feature": {
"type": "string",
"description": "Restrict to one feature before traversing."
},
"file": {
"type": "string",
"description": "Restrict to annotations declared in one file before traversing."
}
},
"required": [
"from"
]
}

List source files that have no GuardLink annotations. Useful for identifying coverage gaps. Not all files need annotations — only those touching security boundaries (endpoints, auth, data access, I/O, crypto).

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
Input schema for guardlink_unannotated
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
}
}
}

Get workspace configuration for multi-repo threat modeling. Returns workspace name, this repo’s identity, sibling repos, and their tag prefixes. Use this to understand cross-repo references when writing annotations. Returns null fields if the repo is not part of a workspace.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
Input schema for guardlink_workspace_info
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
}
}
}

Validate what is written down, and fix anchors that drifted off their symbol.

Check annotations for syntax errors, duplicate IDs, and dangling references. Returns structured error list.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
Input schema for guardlink_validate
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
}
}
}

Find @source blocks whose recorded file:line no longer holds the symbol they name — the drift external annotations accumulate after a refactor. Reports and proposes; it does not rewrite anything unless you pass apply: true, and it never invents an anchor for a symbol that has disappeared.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
apply boolean no false Rewrite @source lines to the proposed positions. Only blocks whose symbol was found elsewhere are moved; a vanished symbol is always left for a human.
Input schema for guardlink_reanchor
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"apply": {
"default": false,
"type": "boolean",
"description": "Rewrite @source lines to the proposed positions. Only blocks whose symbol was found elsewhere are moved; a vanished symbol is always left for a human."
}
}
}

Propose and apply annotations. These are the tools that change source.

Given a file path or code diff, suggest appropriate GuardLink annotations based on code patterns, imports, and function signatures

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
file string no File path relative to root to analyze
diff string no Git diff text to analyze for new code needing annotations
Input schema for guardlink_suggest
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"file": {
"type": "string",
"description": "File path relative to root to analyze"
},
"diff": {
"type": "string",
"description": "Git diff text to analyze for new code needing annotations"
}
}
}

Build an annotation prompt with project context, GuardLink reference docs, and GAL syntax guidelines. The calling agent should use this prompt to read source files and add security annotations directly. Returns the prompt text — the agent should then read files, decide annotation placement, and write comments.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
prompt string yes Annotation instructions (e.g., “annotate auth endpoints for OWASP Top 10”)
mode string, "inline" | "external" no "inline" Annotation placement mode — inline (default) or external (externalized .gal files)
Input schema for guardlink_annotate
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"prompt": {
"type": "string",
"description": "Annotation instructions (e.g., \"annotate auth endpoints for OWASP Top 10\")"
},
"mode": {
"default": "inline",
"type": "string",
"enum": [
"inline",
"external"
],
"description": "Annotation placement mode — inline (default) or external (externalized .gal files)"
}
},
"required": [
"prompt"
]
}

Write a validated @source block into the annotation sidecar for a file. Unlike guardlink_annotate — which returns a prompt for you to act on — this writes the annotations itself, into .guardlink/annotations/, never into source. Rejected with the reason, before anything touches disk: a line the parser cannot read, a #reference that is not declared in .guardlink/definitions.*, a source file that does not exist, and @accepts or @entitles, which are human governance decisions — for an entitlement use guardlink_entitlement_propose, which files it for human acceptance instead of writing it. Idempotent: re-applying the same block is a no-op, not a duplicate. Definitions come first — if you need a new asset, threat or control, declare it before you reference it, or pass allow_undeclared_refs to write ahead of the definition and get a warning instead.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
file string yes Source file the annotations describe. Must exist — the sidecar is named after it, and one for a missing file puts annotations into the model that describe nothing. The sidecar path is derived from it; you do not choose where it is written.
line number yes Line in that file the block anchors to
symbol string no Enclosing symbol name. Strongly recommended — it is what lets guardlink_reanchor detect drift after a refactor.
annotations string[] yes Raw GAL lines with no comment prefix, e.g. [‘@exposes #api to #sqli [critical] – “concatenated”’]. Do NOT include @source; the header is generated.
dry_run boolean no false Validate and return the diff without writing
allow_undeclared_refs boolean no false Write even though a #reference is not declared yet, returning it in warnings. For a deliberate forward reference when the definition is coming; the default rejects, because an undeclared reference is usually a typo.
Input schema for guardlink_annotate_apply
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"file": {
"type": "string",
"description": "Source file the annotations describe. Must exist — the sidecar is named after it, and one for a missing file puts annotations into the model that describe nothing. The sidecar path is derived from it; you do not choose where it is written."
},
"line": {
"type": "number",
"description": "Line in that file the block anchors to"
},
"symbol": {
"type": "string",
"description": "Enclosing symbol name. Strongly recommended — it is what lets guardlink_reanchor detect drift after a refactor."
},
"annotations": {
"type": "array",
"items": {
"type": "string"
},
"description": "Raw GAL lines with no comment prefix, e.g. ['@exposes #api to #sqli [critical] -- \"concatenated\"']. Do NOT include @source; the header is generated."
},
"dry_run": {
"default": false,
"type": "boolean",
"description": "Validate and return the diff without writing"
},
"allow_undeclared_refs": {
"default": false,
"type": "boolean",
"description": "Write even though a #reference is not declared yet, returning it in warnings. For a deliberate forward reference when the definition is coming; the default rejects, because an undeclared reference is usually a typo."
}
},
"required": [
"file",
"line",
"annotations"
]
}

Remove all GuardLink annotations from source files. Use –dry-run to preview without modifying files. WARNING: destructive operation — requires explicit user confirmation before calling without dry-run.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
dry_run boolean no true If true, only show what would be removed
include_definitions boolean no false Also clear .guardlink/definitions files
Input schema for guardlink_clear
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"dry_run": {
"default": true,
"type": "boolean",
"description": "If true, only show what would be removed"
},
"include_definitions": {
"default": false,
"type": "boolean",
"description": "Also clear .guardlink/definitions files"
}
}
}

Sync all agent instruction files (CLAUDE.md, .cursorrules, etc.) with the current threat model. Injects live asset/threat/control IDs, open exposures, and data flows so every coding agent knows the current security posture. Run after adding or changing annotations.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
Input schema for guardlink_sync
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
}
}
}

Project the model into a report, a diagram, SARIF, or a diff.

Generate a markdown threat model report with Mermaid diagram. Also writes threat-model.json alongside.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
output string no "threat-model.md" Output filename (default: threat-model.md)
Input schema for guardlink_report
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"output": {
"default": "threat-model.md",
"type": "string",
"description": "Output filename (default: threat-model.md)"
}
}
}

Generate an interactive HTML threat model dashboard with diagrams, charts, code annotations, and heatmap.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
output string no "threat-dashboard.html" Output filename (default: threat-dashboard.html)
Input schema for guardlink_dashboard
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"output": {
"default": "threat-dashboard.html",
"type": "string",
"description": "Output filename (default: threat-dashboard.html)"
}
}
}

Export findings as SARIF 2.1.0 for GitHub Advanced Security, VS Code, and other SARIF consumers.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
output string no "guardlink.sarif.json" Output filename (default: guardlink.sarif.json)
Input schema for guardlink_sarif
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"output": {
"default": "guardlink.sarif.json",
"type": "string",
"description": "Output filename (default: guardlink.sarif.json)"
}
}
}

Compare the current threat model against a git ref (commit, branch, tag). Shows added/removed/changed annotations, new unmitigated exposures.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
ref string no "HEAD~1" Git ref to compare against (e.g. HEAD~1, main, v1.0)
Input schema for guardlink_diff
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"ref": {
"default": "HEAD~1",
"type": "string",
"description": "Git ref to compare against (e.g. HEAD~1, main, v1.0)"
}
}
}

Generate an AI threat report using a security framework (STRIDE, DREAD, PASTA, attacker, rapid, general). If an LLM API key is set in environment, runs analysis internally and saves result. If no API key is set, returns the framework prompt and serialized threat model for the calling agent to analyze directly — write the result as markdown to .guardlink/threat-reports/.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
framework string, "stride" | "dread" | "pasta" | "attacker" | "rapid" | "general" no "general" Analysis framework
provider string no LLM provider: anthropic, openai, google, openrouter, deepseek (auto-detected from env)
model string no Model name override
custom_prompt string no Custom analysis prompt to replace the framework header
web_search boolean no Enable web search grounding for real-time vulnerability intelligence (OpenAI)
thinking boolean no Enable extended thinking / reasoning mode (Anthropic, DeepSeek)
Input schema for guardlink_threat_report
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"framework": {
"default": "general",
"type": "string",
"enum": [
"stride",
"dread",
"pasta",
"attacker",
"rapid",
"general"
],
"description": "Analysis framework"
},
"provider": {
"type": "string",
"description": "LLM provider: anthropic, openai, google, openrouter, deepseek (auto-detected from env)"
},
"model": {
"type": "string",
"description": "Model name override"
},
"custom_prompt": {
"type": "string",
"description": "Custom analysis prompt to replace the framework header"
},
"web_search": {
"type": "boolean",
"description": "Enable web search grounding for real-time vulnerability intelligence (OpenAI)"
},
"thinking": {
"type": "boolean",
"description": "Enable extended thinking / reasoning mode (Anthropic, DeepSeek)"
}
}
}

List saved AI threat reports from .guardlink/threat-reports/ (and legacy .guardlink/analyses/). Returns filename, framework, timestamp, and model used.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
Input schema for guardlink_threat_reports
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
}
}
}

Review unmitigated exposures and propose entitlements. Acceptance stays with a human at a terminal.

List all unmitigated exposures eligible for governance review, sorted by severity. Returns exposure IDs, details, and severity. Use guardlink_review_accept to record decisions. IMPORTANT: Acceptance decisions require explicit human confirmation — do not accept exposures without asking the user first.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
severity string no Filter by severity: “critical,high” etc.
Input schema for guardlink_review_list
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"severity": {
"description": "Filter by severity: \"critical,high\" etc.",
"type": "string"
}
}
}

Record a governance decision for an unmitigated exposure. Writes @accepts + @audit (for accept) or @audit (for remediate) directly into the source file. IMPORTANT: This modifies source files. Only call after explicit human confirmation of the decision and justification.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
exposure_id string yes Exposure ID from guardlink_review_list
decision string, "accept" | "remediate" | "skip" yes accept = risk acknowledged; remediate = planned fix; skip = no action
justification string yes Required explanation for accept/remediate decisions
Input schema for guardlink_review_accept
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"exposure_id": {
"type": "string",
"description": "Exposure ID from guardlink_review_list"
},
"decision": {
"type": "string",
"enum": [
"accept",
"remediate",
"skip"
],
"description": "accept = risk acknowledged; remediate = planned fix; skip = no action"
},
"justification": {
"type": "string",
"description": "Required explanation for accept/remediate decisions"
}
},
"required": [
"exposure_id",
"decision",
"justification"
]
}

Propose an @entitles claim (an actor is entitled to a capability BY DESIGN) into .guardlink/entitlement-proposals.json. This writes NOTHING to source: a human accepts the proposal with “guardlink entitle”, and only that writes the annotation. Cite the authorization code as file:line in the rationale — without a citation the entitlement is inert and will never affect triage. Never propose one for an ownership question (IDOR, tenant/namespace isolation, CWE-639/862/863): both peers hold the capability, so an entitlement cannot say whose object it was. When unsure which role the code requires, under-grant or write @exposes + @audit instead.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
actor string yes Actor ref — #id of a declared @actor, or its declared name
capability string yes Capability — one identifier, never prose (e.g. configure-archival-destination). It is the join key.
asset string no Optional “on <asset>” context ref
threat string no Threat class this claim is meant to answer for — supply it, it is what enables the ownership-class check
rationale string yes Why this is by design. MUST contain a file:line pointer at the authz check, e.g. “By design: namespace config. Authz: common/api/metadata.go:189”
file string yes Repo-relative source file the accepted @entitles should be written to
line integer, > 0, ≤ 9007199254740991 yes 1-indexed anchor line in file — normally the @exposes line the claim answers for
proposed_by string no Agent or person filing this, e.g. “claude-code”
Input schema for guardlink_entitlement_propose
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"actor": {
"type": "string",
"description": "Actor ref — #id of a declared @actor, or its declared name"
},
"capability": {
"type": "string",
"description": "Capability — one identifier, never prose (e.g. configure-archival-destination). It is the join key."
},
"asset": {
"description": "Optional \"on <asset>\" context ref",
"type": "string"
},
"threat": {
"description": "Threat class this claim is meant to answer for — supply it, it is what enables the ownership-class check",
"type": "string"
},
"rationale": {
"type": "string",
"description": "Why this is by design. MUST contain a file:line pointer at the authz check, e.g. \"By design: namespace config. Authz: common/api/metadata.go:189\""
},
"file": {
"type": "string",
"description": "Repo-relative source file the accepted @entitles should be written to"
},
"line": {
"type": "integer",
"exclusiveMinimum": 0,
"maximum": 9007199254740991,
"description": "1-indexed anchor line in `file` — normally the @exposes line the claim answers for"
},
"proposed_by": {
"description": "Agent or person filing this, e.g. \"claude-code\"",
"type": "string"
}
},
"required": [
"actor",
"capability",
"rationale",
"file",
"line"
]
}

List entitlement proposals and their decisions from .guardlink/entitlement-proposals.json. Use it to see what has been proposed, what a human accepted, and what was rejected or deferred — a rejected claim should not be re-filed, and an accepted one is already in source. Accepting is not available to agents: it is a human decision made with “guardlink entitle”.

Task support: forbidden

Parameter Type Required Default Description
root string no "." Project root directory
status string no Filter by status: “proposed”, “accepted,rejected”, etc.
Input schema for guardlink_entitlement_list
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"root": {
"default": ".",
"type": "string",
"description": "Project root directory"
},
"status": {
"description": "Filter by status: \"proposed\", \"accepted,rejected\", etc.",
"type": "string"
}
}
}
URI Name Description
guardlink://model threat-model Full ThreatModel JSON for the current project
guardlink://definitions definitions All defined assets, threats, and controls with their IDs
guardlink://unmitigated unmitigated List of unmitigated exposures — assets exposed to threats with no @mitigates or @accepts