Tool Fingerprint: SDK-Computed Tool Identity

Asqav binds the identity of the tool an agent invoked into the signed receipt via tool_fingerprint, a 32-character truncation of the SHA-256 over {"tool_name": <name>, "schema": <schema>}. The fingerprint travels on the sign wire as SDK-supplied metadata so two tools with identical names but different schemas produce different receipts.

What is the tool_fingerprint field?

tool_fingerprint is an OPTIONAL string on POST /api/v1/agents/{id}/sign. The wire format is 32 lowercase hex characters (128 bits), enforced by the Pydantic guard tool_fingerprint_not_32_hex_chars. The value is the first 32 hex chars of sha256({"tool_name": <name>, "schema": <schema>}) canonicalised under JCS.

The SDK computes the fingerprint internally: pass tool_name and tool_schema to Agent.sign and the SDK derives the 32-hex value byte-deterministically so two producers with the same tool definition return the same fingerprint. The cloud accepts the pre-computed fingerprint from the SDK rather than recomputing server-side, which means the fingerprint covers exactly the tool surface the SDK observed at runtime.

How does Asqav address tool naming collisions?

The NSA CSI flags name collisions as an active threat vector in the security concerns chapter:

When multiple servers are connected, multiple equivalent tools could exist, but with different semantics, possibly causing the AI to invoke the wrong one. Standard suggestions for mitigations of this confusion include namespacing of tool, prompt, and resource names. While the MCP specification supports it through the use of URIs (path-based namespacing), tool names are simple strings, with no inherent uniqueness. This means that name collisions between tools must be detected and resolved before tools can be considered for invocation. NSA CSI U/OO/6030316-26, p.8

Asqav reads this as: tool names alone do not identify a tool. The tool_fingerprint is the binding the NSA recommendation calls for. Two users.list tools registered against the same agent from different MCP servers produce different schema canonical-JSON bytes, which produce different fingerprints, which produce different receipts. A SIEM query against tool_fingerprint can detect the collision after the fact, even when both invocations carry identical tool_name strings.

How do I compute and supply a tool fingerprint?

The Python and TypeScript SDKs both compute the fingerprint for you. Pass the tool name plus a JSON-schema dict to the sign call and the SDK derives the 32-character token internally before the request leaves the process.

JSON wire example

json
{
  "action_type": "mcp:tool_call",
  "tool_name": "users.list",
  "tool_fingerprint": "a3f5c8d2e1b4789f0a3f5c8d2e1b4789"
}

Python SDK

python
import asqav

asqav.init()
agent = asqav.Agent.create("crm-bot")

tool_name = "users.list"
tool_schema = {
    "type": "object",
    "properties": {
        "cursor": {"type": ["string", "null"]},
        "limit": {"type": "integer", "minimum": 1, "maximum": 200},
    },
    "required": [],
}

receipt = agent.sign(
    "mcp:tool_call",
    {"tool": tool_name, "args": {"cursor": None, "limit": 50}},
    tool_name=tool_name,
    tool_schema=tool_schema,
)

curl

bash
curl -X POST https://api.asqav.com/api/v1/agents/agt_crm_001/sign \
  -H "X-API-Key: $ASQAV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action_type": "mcp:tool_call",
    "tool_name": "users.list",
    "tool_fingerprint": "a3f5c8d2e1b4789f0a3f5c8d2e1b4789"
  }'

What does the fingerprint cover?

The canonicalised JSON object the SDK hashes is {"tool_name": <string>, "schema": <object>}. The schema is the JSON-schema dict the MCP server advertised at tools/list time. When the schema includes a module_path annotation (some frameworks emit this, some do not), it lands inside schema and contributes to the fingerprint. Tools that change their schema (a new required field, a renamed property, a different enum vocabulary) produce a different fingerprint even when the name is unchanged.

This is intentional. A tool whose schema changes mid-session is a security event the NSA recommendation calls out as "silent capability drift". The new fingerprint surfaces the drift in the receipt stream without requiring a per-tool watcher.

How does a verifier detect a collision?

Collision detection is an OFFLINE comparison the relying party runs. The verifier holds the receipt and the schema it expected, recomputes the fingerprint over {tool_name, schema} locally, and compares to the signed tool_fingerprint carried in the envelope. A SIEM query that groups by (tool_name, tool_fingerprint) and flags count(distinct tool_fingerprint) > 1 per tool_name per day detects every collision.

Related documentation