Guide

Agents

The same hash tools over MCP and Pi and OMP and the AI SDK. What they take and what they refuse and what the model reads back

Same tools, every host

The MCP server, the Pi and OMP extensions and the AI SDK tools in @agntn/hashes/ai all call the executors in src/tool-operations.ts. Same arguments, same checks, same text back, and a fix lands once. This site runs those executors too, so the Full tool response dialogs on the landing and in the playground are exactly what a model reads.

ToolDoesArguments
hash_computeDigest of text or bytesalgorithm, input, inputEncoding, encoding, salt, parameters
hash_hmacHMAC with a keyalgorithm, input, inputEncoding, key, keyEncoding, encoding
hash_verifyCompare with an expected digestalgorithm, input, inputEncoding, expected, encoding, salt, parameters
hash_algorithmsThe list, one family, or one algorithm's optionsfamily or algorithm, both optional

parameters carries what an algorithm declares beyond encoding, key and salt: seed for xxHash, N, r, p and keyLength for scrypt, iterations, digest and keyLength for PBKDF2. A model that isn't sure calls hash_algorithms with the name first. The descriptions say so, because otherwise models guess.

What a model reads

Two lines. The digest, then what it is:

text
751e76e8199196d454941c45d1b3a323f1433bd6
hash160, hex, 20 bytes

For a KDF the second line also carries the salt and every cost, since an MCP client sees only this text and the next hash_verify needs all of it:

text
c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a
pbkdf2, hex, 32 bytes, iterations 4096, digest sha256, keyLength 32, salt 73616c74

hash_verify answers MATCH or MISMATCH with both digests. hash_algorithms lists one line per algorithm, family, size and HMAC support included. The Pi and OMP extensions and the AI SDK also hand the host structured details next to the text.

Bytes, not letters

inputEncoding is utf8 by default. hex and base64 hash the bytes they spell, which is what you want for a public key, a raw transaction or a script. Without it, hash160 of a public key hashes 66 characters of text and answers with a perfectly valid digest of the wrong thing. hex takes no 0x prefix.

keyEncoding does the same for an HMAC key. A BIP32 chain code keys the HMAC as 32 bytes, not as 64 letters.

What they refuse

Every schema is closed. A misspelled argument is an error, not a quiet default:

text
Invalid option salt_hex=(unknown): hash_compute takes only algorithm, input, inputEncoding, encoding, salt, parameters

That one matters. Dropping salt_hex would have hashed with a fresh random salt and a model would never know why its digest doesn't reproduce.

The bounds sit in the schema and are checked again in the executor, because a host is free to skip schema validation. Input up to a million characters, key up to ten thousand, a salt of 1 to 256 bytes in hex, at most eight parameters. KDF costs are capped too, Salted KDFs has the numbers. Nothing is written anywhere and there's no network to reach.

MCP

shell
hashes mcp
claude mcp add hashes --scope user -- npx -y @agntn/hashes mcp

Or in a client's config:

json
{
  "mcpServers": {
    "hashes": { "command": "npx", "args": ["-y", "@agntn/hashes", "mcp"] }
  }
}

stdio, every tool read-only and idempotent. A call that fails the schema or throws a HashError comes back as a tool error with the reason, and the session carries on.

Pi and OMP

shell
pi install npm:@agntn/hashes
omp install @agntn/hashes

Both extensions are declared in package.json and ship as source the host loads directly.

AI SDK

ts
import { generateText } from "ai";
import { hashTools } from "@agntn/hashes/ai";

await generateText({
  model,
  tools: hashTools,
  prompt: "What's the HASH160 of 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798?",
});

hashTools holds all of them under the same names. Each one is also exported alone, hashComputeTool and friends, if you want to hand a model fewer.