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.
Server
Section titled “Server”| Field | Value |
|---|---|
| Name | guardlink |
| Version | 2.0.0 |
| Capabilities | resources, tools |
| Tools | 24 |
| Resources | 3 |
Server instructions
Section titled “Server instructions”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.*. Reuseexisting ids; never redefine one. Never write @accepts or @entitles: both are humangovernance decisions. Found a risk with no control? @exposes plus @audit. Anentitlement claims a privilege was always allowed this, so an over-grant hides areal escalation: propose it (guardlink_entitlement_propose) citing authz code asfile: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 arefactor; 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. Asubstring match is a suggestion, not an identification. ambiguous with candidatesmeans several records tied and one was picked arbitrarily — re-ask precisely.
guardlink_lookup understands 26 named query forms and refuses anything elserather 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. |
Read the model
Section titled “Read the model”Answer a question from the model without changing it.
guardlink_parse
Section titled “guardlink_parse”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." } }}guardlink_status
Section titled “guardlink_status”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" } }}guardlink_context
Section titled “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 @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" ]}guardlink_lookup
Section titled “guardlink_lookup”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" ]}guardlink_graph
Section titled “guardlink_graph”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" ]}guardlink_unannotated
Section titled “guardlink_unannotated”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" } }}guardlink_workspace_info
Section titled “guardlink_workspace_info”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" } }}Check and repair
Section titled “Check and repair”Validate what is written down, and fix anchors that drifted off their symbol.
guardlink_validate
Section titled “guardlink_validate”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" } }}guardlink_reanchor
Section titled “guardlink_reanchor”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." } }}Write annotations
Section titled “Write annotations”Propose and apply annotations. These are the tools that change source.
guardlink_suggest
Section titled “guardlink_suggest”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" } }}guardlink_annotate
Section titled “guardlink_annotate”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" ]}guardlink_annotate_apply
Section titled “guardlink_annotate_apply”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" ]}guardlink_clear
Section titled “guardlink_clear”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" } }}guardlink_sync
Section titled “guardlink_sync”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" } }}Export and report
Section titled “Export and report”Project the model into a report, a diagram, SARIF, or a diff.
guardlink_report
Section titled “guardlink_report”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)" } }}guardlink_dashboard
Section titled “guardlink_dashboard”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)" } }}guardlink_sarif
Section titled “guardlink_sarif”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)" } }}guardlink_diff
Section titled “guardlink_diff”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)" } }}guardlink_threat_report
Section titled “guardlink_threat_report”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)" } }}guardlink_threat_reports
Section titled “guardlink_threat_reports”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" } }}Governance
Section titled “Governance”Review unmitigated exposures and propose entitlements. Acceptance stays with a human at a terminal.
guardlink_review_list
Section titled “guardlink_review_list”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" } }}guardlink_review_accept
Section titled “guardlink_review_accept”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" ]}guardlink_entitlement_propose
Section titled “guardlink_entitlement_propose”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" ]}guardlink_entitlement_list
Section titled “guardlink_entitlement_list”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" } }}Resources
Section titled “Resources”| 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 |

