toolkit-mcp-server
Server Details
Generate IDs, QR codes, and hashes, encode values, geolocate IPs, plus gated host diagnostics.
- Status
- Healthy
- Uptime
- 99.9% over 82 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- cyanheads/toolkit-mcp-server
- GitHub Stars
- 20
- Server Listing
- toolkit-mcp-server
- ChatGPT
- –
- Claude
- –
TDQS
Scored across 5 tools
Each tool targets a clearly distinct operation: reversible encoding/decoding, CSPRNG identifier minting, QR rendering, IP geolocation, and hashing/HMAC. The only surface-level overlap — base64/hex options appearing in both encode_value and hash_value — is resolved by the fact that only one of them transforms reversibly. An agent can select the right tool purely from the name plus a glance at the description.
All five names follow the identical `toolkit_<verb>_<noun>` snake_case pattern with a shared server prefix. Verb choices (encode, generate, geolocate, hash) accurately mirror the action, so the pattern is both consistent and informative.
Five tools is a compact, well-scoped set for a general developer-utility server, and each one covers a genuinely different need with no filler. Nothing suggests a tool that should be split or merged.
Each tool covers its own lifecycle well (encode has both directions, hash has generate plus timing-safe compare, ID generation supports batch formats). Remaining gaps are minor for a grab-bag toolkit — there is no UUID parse/validate or v7 timestamp extraction, and no inverse operation for QR encoding — but agents can work around these with the existing tools.
Available Tools
5 toolstoolkit_encode_valuetoolkit-mcp-server: encode valueARead-onlyIdempotentInspect
Encode or decode a value across base64, base64url, hex, or URL (percent) encoding, in either direction. Set operation to "encode" to transform raw UTF-8 text into the chosen encoding, or "decode" to recover the original bytes from an encoded value. Decoded bytes come back as UTF-8 text by default; set outputEncoding to "hex", "base64", or "base64url" (unpadded, the form JWK members, JWS signatures, and PKCE code challenges use) to receive them re-encoded instead, which is lossless for binary data and transcodes between encodings (a base64 digest to hex, or hex key bytes to base64url, for example). Decoding never substitutes replacement characters: bytes that are not valid UTF-8 text are reported as a recoverable error that points at outputEncoding. Whitespace in hex, base64, and base64url values is ignored, so line-wrapped MIME bodies and PEM bodies decode as-is (drop PEM's -----BEGIN/END----- lines, which are not base64). base64url uses the URL-safe alphabet (- and _ instead of + and /); url applies encodeURIComponent and percent-decoding. A value that is malformed for the chosen encoding is reported as a recoverable error, not a silent best-effort.
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | The value to transform — raw text for encode, an encoded string for decode. Whitespace is ignored when decoding hex, base64, or base64url; a url value is taken literally. | |
| encoding | Yes | The encoding to apply: base64, URL-safe base64url, hex, or URL percent-encoding. | |
| operation | Yes | "encode" transforms text into the encoding; "decode" recovers the bytes from an encoded value. | |
| outputEncoding | No | Decode only: how the recovered bytes are returned. utf8 (used when omitted) returns text and fails when the bytes are not valid UTF-8; hex, base64, and base64url (unpadded) return the raw bytes re-encoded, losslessly. Rejected when operation is "encode". |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| result | No | The transformed value: encoded text for encode; for decode, the recovered bytes as UTF-8 text, hex, base64, or unpadded base64url per outputEncoding. |
| encoding | No | The encoding that was applied. |
| operation | No | The operation that was performed. |
| outputEncoding | No | How result renders the decoded bytes: utf8 text, hex, base64, or unpadded base64url. Present for operation "decode". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/closed-world, but the description goes well beyond them: it promises recoverable errors rather than silent best-effort on malformed input, guarantees no replacement-character substitution on invalid UTF-8, documents whitespace tolerance for hex/base64/base64url, and notes outputEncoding is rejected when encoding.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and direction are front-loaded in the first sentence, and each subsequent sentence covers a distinct concern (direction, output form, error policy, whitespace, alphabet details). It is dense and runs long, with some detail (base64url alphabet characters) that borders on tutorial rather than tool selection.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter, enum-heavy transform tool with an output schema already describing return shape, the description covers everything an agent needs: mode selection, binary-safe output, whitespace handling, and precise failure semantics. Nothing material about calling it correctly is left out.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns more by adding meaning the schema lacks — that base64url output is unpadded and is the form used by JWK members, JWS signatures, and PKCE challenges, and that url applies encodeURIComponent with literal input on decode. It does not, however, cover every parameter nuance beyond what the schema already states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb pair (encode/decode) on a specific resource (a value) across four named encodings, in either direction. It is clearly distinguishable from siblings like toolkit_hash_value or toolkit_generate_id, which do not transform between encodings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent when to pick operation=encode versus decode, and when to supply outputEncoding (binary data, or transcoding between encodings such as base64 digest to hex). It gives a concrete operational caveat for PEM bodies (drop the BEGIN/END lines). It does not name a sibling tool or state when not to use this one, which keeps it below a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
toolkit_generate_idtoolkit-mcp-server: generate idARead-onlyInspect
Mint cryptographically-random identifiers using the platform CSPRNG — the correct source for IDs that must be unpredictable, unlike model-generated values. type selects the format: uuid_v4 (random, the default), uuid_v7 (time-ordered, sortable by creation), or ulid (26-char Crockford-base32, lexicographically sortable). Set count to mint a batch in one call (up to 1000); the returned ids array always contains exactly count values and is never truncated. For uuid_v7 and ulid, a batch is monotonic — strictly increasing even within the same millisecond — so the ids array stays in sorted creation order; ids minted in the same millisecond are separated by random gaps, so no id in a batch can be derived from another. IDs from this tool feed into toolkit_generate_qr (pass ids[0] as data) to create a scannable code.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Identifier format: uuid_v4 (random), uuid_v7 (time-ordered), or ulid (sortable Crockford-base32). | uuid_v4 |
| count | No | How many identifiers to mint (1–1000). The full batch is always returned. |
Output Schema
| Name | Required | Description |
|---|---|---|
| ids | No | The minted identifiers — exactly count of them, in mint order; for uuid_v7 and ulid that order is strictly increasing (sorted by creation), with random gaps between ids minted in the same millisecond. |
| type | No | The identifier format that was minted. |
| count | No | The number of identifiers minted (equals the requested count). |
| error | No | Present when the call failed. Absent on success. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, but the description goes far beyond: it discloses the source (platform CSPRNG), output guarantees ('always contains exactly count values and is never truncated'), monotonic ordering for uuid_v7/ulid, strict increasing within the same millisecond, and the security property that 'no id in a batch can be derived from another'. This rich behavioral disclosure is not present in annotations and is critical for correct use.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Each sentence earns its place: purpose and source are front-loaded, then type semantics, batch behavior, ordering guarantees, and downstream integration. There is no fluff or repetition of schema verbatim; the description is dense but well-structured, guiding the agent from conceptual purpose to invocation details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter tool with an output schema and clear annotations, the description fully covers what an agent needs: when to use, format selection, batching limits, return-count guarantees, ordering behavior, and integration with a sibling. No critical information is missing, and the output schema handles return-shape details.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds meaningful semantics beyond the schema: it explains the default (uuid_v4), clarifies each type's ordering properties, specifies 'up to 1000' for count, and introduces the guarantee that the full batch is always returned without truncation. This adds real value over the schema alone, though the schema already covers basic type and count limits.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description opens with 'Mint cryptographically-random identifiers using the platform CSPRNG' — a specific verb ('mint'), resource ('identifiers'), and method (CSPRNG). It distinguishes this tool from siblings by stating it is the correct source for unpredictable IDs and explicitly contrasts with 'model-generated values'. The purpose is unambiguous and differentiates from toolkit_hash_value, toolkit_encode_value, etc.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description says to use this tool when IDs 'must be unpredictable' and indicates 'unlike model-generated values' — an explicit when-not. It also provides a concrete downstream workflow: 'feed into toolkit_generate_qr (pass ids[0] as data)', which acts as a usage directive. Combined with format-selection guidance for type and batching with count, the agent knows exactly when and how to invoke it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
toolkit_generate_qrtoolkit-mcp-server: generate QR codeARead-onlyIdempotentInspect
Encode text or a URL into a QR code. data is the content to encode (a link, a generated identifier such as toolkit_generate_id's ids[0], or any string). format selects the output: svg returns inline SVG markup sized in pixels, png_base64 returns base64-encoded PNG bytes (with mimeType and byteLength), and terminal returns plain Unicode half-block characters (no escape codes) for a monospace display, drawn for a dark background: light modules, quiet zone included, are blocks and dark modules are spaces. errorCorrection (L/M/Q/H) trades data capacity for damage tolerance, margin sets the quiet-zone width in modules, and scale sets pixels per module for svg and png_base64, so both are (modules + 2 × margin) × scale pixels per side. The returned version (1–40) reflects how dense the encoded data is. png_base64 rejects an image past 2048 px per side with a typed raster_too_large error, so a dense symbol needs a lower scale; svg is vector markup and carries no such limit.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | The text or URL to encode, stored as UTF-8. Capacity is counted in bytes: 2953 UTF-8 bytes is the absolute ceiling (QR version 40, level L, byte mode). The 2953-character limit here is only an upper bound, since a non-ASCII character takes 2–4 bytes. Usable capacity drops at higher errorCorrection levels, so over-capacity data is rejected with a typed data_too_large error rather than a generic failure. | |
| scale | No | Pixels per module for svg (its width and height) and png_base64. Ignored for terminal. png_base64 also bounds the whole image at 2048 px per side, so a dense symbol or a wide margin admits a lower scale than 32 there. | |
| format | No | Output format: svg markup, png_base64 (raster bytes), or terminal (plain Unicode half-blocks, drawn for a dark background). | svg |
| margin | No | Quiet-zone width in modules around the symbol. The spec recommends 4. | |
| errorCorrection | No | Error-correction level: L (~7% recoverable) to H (~30%). Higher tolerance lowers data capacity. | M |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| format | No | The format that was produced. |
| content | No | The QR artifact: SVG markup, the terminal half-block grid (newline-separated rows), or base64 PNG bytes for png_base64. |
| version | No | QR symbol version (1–40); higher versions hold denser data and indicate denser content. |
| mimeType | No | MIME type of content for image formats. Absent for the terminal format. |
| byteLength | No | Decoded byte size of the PNG. Present only for png_base64. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description discloses significant behavioral detail: format-specific output shapes (SVG markup, base64 PNG bytes with mimeType and byteLength, terminal Unicode blocks), typed error conditions (data_too_large, raster_too_large), the pixel-size formula, and the version range reflecting data density. It even clarifies terminal rendering for dark backgrounds. This far exceeds what annotations alone provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is information-dense and front-loaded with the core purpose in the first sentence. Each subsequent sentence introduces a distinct parameter or constraint, and the flow from format to error behavior is logical. It is longer than two sentences, but given the three output formats and several interacting parameters, the length is justified without wasteful repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 5 parameters, 3 formats, and a moderately complex output, the description is thorough: it covers all parameters, format-specific behaviors, encoding boundaries, and error conditions. An output schema exists, so return values are already documented. No critical information an agent needs to invoke the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema already has 100% parameter coverage, the description adds meaningful semantics not present in the schema: how scale and margin combine into final image dimensions, which parameters are ignored by which format, how errorCorrection trades capacity against tolerance, and the pixel limit interaction with scale for png_base64. This elevates the description well above the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Encode text or a URL into a QR code', which clearly states the tool's function. It goes beyond the title by naming concrete use cases (links, generated identifiers, strings) and enumerating the three output formats. Sibling tools like toolkit_encode_value, toolkit_generate_id, and toolkit_hash_value are clearly different in purpose, so an agent can distinguish this tool without confusion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides rich context for when to use the tool: what kinds of data are acceptable (links, identifiers, arbitrary strings), what each format yields, and how parameters interact. It does not explicitly state when not to use this tool or name alternative siblings for specific scenarios, but the sibling set is distinct enough that the usage is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
toolkit_geolocate_iptoolkit-mcp-server: geolocate IPARead-onlyIdempotentInspect
Resolve a public IP or dotted hostname to country, region, city, coordinates, ASN, AS holder and name, organization, ISP, timezone, and proxy/hosting/mobile flags. Supply target for one lookup or targets for an ordered batch, never both; blank target and empty targets are unset. Batches process the first 100 positions (duplicates retained) and disclose every remainder in unprocessedTargets; at most 1000 inputs are accepted. Each batch position reports its result or an error with recovery, so cached and local outcomes survive quota refusals. The provider is called directly, never the target. Hostnames are DNS-resolved and resolvedIp names the located address. Private/reserved addresses have no public geolocation. Results are best-effort, city-level at best; VPNs, proxies, mobile NAT, and anycast defeat IP-to-location. Read proxy, hosting, and mobile before trusting coordinates: true describes infrastructure, not the user. org can name a customer or sub-allocation rather than the network operator; read isp, asHolder, and asName for the operator. Absent metadata remains unknown. Provider-supplied names are third-party registry text; content[] escapes them so they read as literal text, never as Markdown. source names the provider. Single and batch quotas are independent; cache hits consume neither quota.
| Name | Required | Description | Default |
|---|---|---|---|
| target | No | One public IP or dotted hostname; mutually exclusive with nonempty targets. | |
| targets | No | Ordered public IPs or dotted hostnames; first 100 positions are served, every remainder is disclosed. Mutually exclusive with nonblank target. |
Output Schema
| Name | Required | Description |
|---|---|---|
| asn | No | Autonomous System number, e.g. "AS15169". Absent on providers that omit it. |
| isp | No | Internet service provider for the address, e.g. "Cloudflare, Inc". Absent when unknown. |
| org | No | Organization the address is registered to, e.g. "Google LLC"; often a customer or sub-allocation label rather than the network operator. Carries asHolder, else isp, when the provider names no organization. Absent when all three are unknown. |
| city | No | City name. Absent when unknown. |
| error | No | Present when the call failed. Absent on success. |
| proxy | No | True when the address is a known proxy, VPN, or Tor exit — the location describes the exit node, not the user. Absent when the provider does not report it. |
| asName | No | Registry name of the autonomous system, e.g. "CLOUDFLARENET". Absent when the provider omits it. |
| mobile | No | True when the address belongs to a mobile carrier network, where NAT can place the location far from the device. Absent when unreported. |
| region | No | Region or state name. Absent when unknown. |
| source | No | The provider that answered the lookup, e.g. "ip-api". |
| target | No | The target as supplied (IP or hostname). |
| country | No | Country name. Absent when the provider does not report it. |
| hosting | No | True when the address belongs to a hosting or datacenter network, so the location is a facility rather than a person. Absent when unreported. |
| results | No | Ordered results or failures for the first 100 input positions. |
| asHolder | No | Holder of the autonomous system as the provider names it after the ASN, e.g. "Cloudflare, Inc." for AS13335. Absent when the provider reports no AS or no holder name. |
| latitude | No | Latitude in decimal degrees. Absent when unknown. |
| timezone | No | IANA timezone, e.g. "America/Los_Angeles". Absent when unknown. |
| longitude | No | Longitude in decimal degrees. Absent when unknown. |
| resolvedIp | No | The IP that was actually located (a supplied hostname is resolved to this first). |
| countryCode | No | ISO 3166-1 alpha-2 country code. Absent when unknown. |
| failedCount | No | Number of failed processed targets. |
| unprocessedTargets | No | Every input position past the first 100; resubmit these targets in another batch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the readOnly/openWorld/idempotent annotations: it discloses batch truncation at 100 positions with remainder surfaced in unprocessedTargets, a 1000-input cap, per-position error reporting that preserves cached results across quota refusals, independent single vs batch quotas, and that cache hits consume no quota. It also warns the provider is called directly (never the target), that hostnames are DNS-resolved with resolvedIp reported, and that results are best-effort city-level and defeatable by VPN/anycast.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads purpose, then invocation rules, then limits, then interpretation caveats — a sensible order with no filler sentences. It is dense and long enough that a reader must work through several clauses, but nearly every clause carries operational information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists, the description supplies the interpretive layer an agent needs: read proxy/hosting/mobile before trusting coordinates, org may name a customer rather than the operator so prefer isp/asHolder/asName, absent metadata stays unknown, and content[] escapes third-party registry strings so they are literal text. Nothing essential to calling or interpreting the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, but the description adds semantics the schema cannot express: mutual exclusivity of target/targets, blank-as-unset, duplicate retention, and the first-100-of-many processing rule. That meaningfully exceeds the baseline set by a fully documented schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource ('Resolve a public IP or dotted hostname') and enumerates the exact fields returned (country, region, city, coordinates, ASN, org, ISP, timezone, proxy/hosting/mobile flags). Sibling tools are unrelated utility functions (hash, encode, QR, ID), so no differentiation is required.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete invocation guidance: use target for one lookup, targets for an ordered batch, never both, and blank/empty values count as unset. It does not name an alternative tool or a when-not-to-use case beyond private/reserved addresses having no public geolocation, which keeps it from a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
toolkit_hash_valuetoolkit-mcp-server: hash valueARead-onlyIdempotentInspect
Generate a cryptographic digest or HMAC of a value, or verify a value against an expected digest. Set operation to "generate" for a digest, or "compare" to constant-time-check value against the expected digest — compare is timing-safe and avoids manual string equality checks. Omitting operation compares when expected is supplied and generates otherwise. Algorithm defaults to sha256; sha384 and sha512 are also secure, while md5 and sha1 are exposed ONLY for checksum and file-integrity compatibility and for verifying existing HMAC-SHA1 signatures, and must not be used for passwords, new signatures, or any other security purpose. Set secret to compute HMAC(algorithm, secret, value) instead of a plain digest, for generate and compare alike — the check behind webhook signatures such as GitHub's X-Hub-Signature-256 (pass the header value as expected) and HS256 JWT signatures; secretEncoding says how secret is written (utf8 default, hex, base64, or base64url for a JWK k), the result carries hmac: true, and the secret is never echoed back. digestEncoding selects the generated digest form: lowercase hex (default), base64, base64url (unpadded, the JWS signature form), or sri (-, the npm lockfile integrity and Subresource Integrity form, sha256/sha384/sha512 only, plain digests only). expected is recognized by its shape at the algorithm's digest length, so a published checksum can be pasted as-is: a bare hex, base64, or base64url digest; SRI, which may hold several space-separated entries as an npm integrity field can and matches when any entry for algorithm does; one checksum-file line as sha256sum, shasum, md5, or openssl dgst prints it ( , or SHA256 () = ); or a digest prefixed sha256: or sha256= (OCI and release-asset digests, webhook signature headers). A tag or prefix naming another algorithm fails rather than being ignored, and a multi-line checksum file must be cut to the one line for the file. inputEncoding controls how value is read before hashing (utf8 default, or hex/base64 for raw binary data) so binary blobs need no decode round-trip. The canonical use is matching a download against a vendor-published checksum or a lockfile integrity entry.
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | The data to hash, interpreted per inputEncoding (raw text by default). | |
| secret | No | HMAC key. When non-empty, the digest is HMAC(algorithm, secret, value) instead of a plain hash, for generate and compare alike. Read per secretEncoding and used exactly as sent, never trimmed; an empty string counts as absent. Never echoed in the result or in error messages. | |
| expected | No | The digest to compare against, recognized from its shape at the algorithm's digest length: hex (any case), standard base64, or base64url, bare or prefixed as <algorithm>:<digest> or <algorithm>=<digest>; SRI (<algorithm>-<base64>); or one checksum-file line, <hex> <file> (sha256sum, shasum, md5 -r) or SHA256 (<file>) = <digest> (BSD, --tag, openssl dgst). A string of only hex digits is always read as hex; hex split by whitespace is rejected, as is a <hex> <file> line whose file name is only hex digits. An SRI value may carry several space-separated entries: entries for other algorithms are skipped, and it matches when any entry for algorithm matches. A tag or prefix naming another algorithm is rejected, as is a whole multi-line checksum file. Supplying it with operation omitted runs a compare; it is rejected with operation "generate". | |
| algorithm | No | Digest algorithm. sha256 (default), sha384, or sha512 for security; md5/sha1 are for checksums and for verifying existing HMAC-SHA1 signatures only — not for new security use. | sha256 |
| operation | No | "generate" produces a digest; "compare" constant-time-checks value against expected. When omitted, resolves to "compare" if expected is supplied and "generate" otherwise. | |
| inputEncoding | No | How value is decoded before hashing: utf8 text, hex, or base64. | utf8 |
| digestEncoding | No | Form of the generated digest: lowercase hex (default), standard base64, base64url (URL-safe alphabet, unpadded — the JWS signature form), or sri (<algorithm>-<base64>, sha256/sha384/sha512 only, and not with secret). Applies to operation "generate". | hex |
| secretEncoding | No | How secret is written: utf8 text (default, as a webhook signing secret is), hex, base64, or base64url (as a JWK k member is). Read only when secret is non-empty. | utf8 |
Output Schema
| Name | Required | Description |
|---|---|---|
| hmac | No | Present (true) when the digest is an HMAC keyed by secret; absent for a plain digest. |
| error | No | Present when the call failed. Absent on success. |
| digest | No | Digest of value in the requested digestEncoding: lowercase hex, base64, unpadded base64url, or <algorithm>-<base64>; the HMAC when hmac is true. Present for operation "generate". |
| matches | No | Constant-time equality of the computed digest (the HMAC when hmac is true) against expected. Present for operation "compare". |
| algorithm | No | The algorithm used. |
| operation | No | The operation performed, after resolving an omitted operation. |
| lengthInBytes | No | Digest size in bytes (32 for sha256, 48 for sha384, 64 for sha512, 20 for sha1, 16 for md5). Present for "generate". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered. The description goes well beyond that: constant-time comparison semantics, that the secret is never echoed back in results or errors, that md5/sha1 are exposed only for compatibility and must not be used for passwords or new signatures, and that multi-line checksum files must be cut to one line.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and mode selection, which is good. But it is very long and dense, with several sentences packing multiple clauses each, so a reader must work through a lot to extract the operational rules; some detail (e.g., the tag/prefix rejection rule) repeats what the schema already says.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a complex tool with 8 parameters, 5 enums, and multiple interacting encodings. Given that an output schema exists, the description does not need to explain return values, and it still covers every behavioral edge an agent must know to call it correctly: operation defaulting, HMAC vs plain digest, encoding choices, expected-shape matching, and algorithm restrictions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so this is over baseline. The description adds meaning the schema does not fully convey: how expected is recognized by shape and digest length, the exact checksum-file line formats accepted, that SRI may hold multiple space-separated entries and matches on any, that a prefix naming another algorithm fails rather than being ignored, that digestEncoding sri is plain-digest-only, and that secretEncoding base64url is the JWK k form.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource statement covering both modes (generate a digest/HMAC, or verify against an expected digest). It clearly distinguishes itself from siblings like toolkit_encode_value or toolkit_generate_id, which do different jobs entirely.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly defines when to use 'generate' vs 'compare', gives the default resolution rule when operation is omitted, and tells the agent to use compare for timing-safe checks instead of manual string equality. It also states which cases call for the weak algorithms and which do not, plus the 'canonical use' of matching a download against a vendor checksum.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
- Changed
toolkit_encode_value5 fields changed- changed
Input schema / properties / outputEncoding / descriptionPrevious value: -"Decode only: how the recovered bytes are returned. utf8 (used when omitted) returns text and fails when the bytes are not valid UTF-8; hex and base64 return the raw bytes re-encoded, losslessly. Rejected when operation is \"encode\"."New value: +"Decode only: how the recovered bytes are returned. utf8 (used when omitted) returns text and fails when the bytes are not valid UTF-8; hex, base64, and base64url (unpadded) return the raw bytes re-encoded, losslessly. Rejected when operation is \"encode\"." - changed
Input schema / properties / outputEncoding / enumPrevious value: -[ - "utf8", - "hex", - "base64" -]New value: +[ + "utf8", + "hex", + "base64", + "base64url" +] - changed
Output schema / properties / outputEncoding / descriptionPrevious value: -"How result renders the decoded bytes: utf8 text, hex, or base64. Present for operation \"decode\"."New value: +"How result renders the decoded bytes: utf8 text, hex, base64, or unpadded base64url. Present for operation \"decode\"." - changed
Output schema / properties / outputEncoding / enumPrevious value: -[ - "utf8", - "hex", - "base64" -]New value: +[ + "utf8", + "hex", + "base64", + "base64url" +] - changed
Output schema / properties / result / descriptionPrevious value: -"The transformed value: encoded text for encode; for decode, the recovered bytes as UTF-8 text, hex, or base64 per outputEncoding."New value: +"The transformed value: encoded text for encode; for decode, the recovered bytes as UTF-8 text, hex, base64, or unpadded base64url per outputEncoding."
- Changed
toolkit_geolocate_ip6 fields changed- added
Output schema / properties / asHolderAdded value: +{ + "description": "Holder of the autonomous system as the provider names it after the ASN, e.g. \"Cloudflare, Inc.\" for AS13335. Absent when the provider reports no AS or no holder name.", + "maxLength": 256, + "type": "string" +} - added
Output schema / properties / asNameAdded value: +{ + "description": "Registry name of the autonomous system, e.g. \"CLOUDFLARENET\". Absent when the provider omits it.", + "maxLength": 256, + "type": "string" +} - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `rate_limited`: The endpoint request quota or provider cooldown is exhausted. `unresolvable_host`: A hostname target failed DNS resolution. `private_target`: The target resolves to a private/reserved IP with no public geolocation. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `rate_limited`: The endpoint request quota or provider cooldown is exhausted. `unresolvable_host`: A hostname target failed DNS resolution. `private_target`: The target resolves to a private/reserved IP, or to a public-format IP the provider reports as unlocatable (reserved, unrouted, or bogon); neither has public geolocation. Other values are possible when a failure originates below the handler." - added
Output schema / properties / ispAdded value: +{ + "description": "Internet service provider for the address, e.g. \"Cloudflare, Inc\". Absent when unknown.", + "maxLength": 256, + "type": "string" +} - changed
Output schema / properties / org / descriptionPrevious value: -"Owning organization or ISP, e.g. \"Google LLC\". Absent when unknown."New value: +"Organization the address is registered to, e.g. \"Google LLC\"; often a customer or sub-allocation label rather than the network operator. Carries asHolder, else isp, when the provider names no organization. Absent when all three are unknown." - changed
Output schema / properties / results / items / anyOfPrevious value: -[ - { - "additionalProperties": false, - "description": "Normalized geolocation metadata for one target.", - "properties": { - "asn": { - "description": "Autonomous System number, e.g. \"AS15169\". Absent on providers that omit it.", - "maxLength": 256, - "type": "string" - }, - "city": { - "description": "City name. Absent when unknown.", - "maxLength": 256, - "type": "string" - }, - "country": { - "description": "Country name. Absent when the provider does not report it.", - "maxLength": 256, - "type": "string" - }, - "countryCode": { - "description": "ISO 3166-1 alpha-2 country code. Absent when unknown.", - "maxLength": 256, - "type": "string" - }, - "hosting": { - "description": "True when the address belongs to a hosting or datacenter network, so the location is a facility rather than a person. Absent when unreported.", - "type": "boolean" - }, - "latitude": { - "description": "Latitude in decimal degrees. Absent when unknown.", - "type": "number" - }, - "longitude": { - "description": "Longitude in decimal degrees. Absent when unknown.", - "type": "number" - }, - "mobile": { - "description": "True when the address belongs to a mobile carrier network, where NAT can place the location far from the device. Absent when unreported.", - "type": "boolean" - }, - "org": { - "description": "Owning organization or ISP, e.g. \"Google LLC\". Absent when unknown.", - "maxLength": 256, - "type": "string" - }, - "proxy": { - "description": "True when the address is a known proxy, VPN, or Tor exit — the location describes the exit node, not the user. Absent when the provider does not report it.", - "type": "boolean" - }, - "region": { - "description": "Region or state name. Absent when unknown.", - "maxLength": 256, - "type": "string" - }, - "resolvedIp": { - "description": "The IP that was actually located (a supplied hostname is resolved to this first).", - "type": "string" - }, - "source": { - "description": "The provider that answered the lookup, e.g. \"ip-api\".", - "type": "string" - }, - "target": { - "description": "The target as supplied (IP or hostname).", - "type": "string" - }, - "timezone": { - "description": "IANA timezone, e.g. \"America/Los_Angeles\". Absent when unknown.", - "maxLength": 256, - "type": "string" - } - }, - "required": [ - "target", - "resolvedIp", - "source" - ], - "type": "object" - }, - { - "additionalProperties": false, - "description": "A failed batch target with recovery guidance.", - "properties": { - "error": { - "additionalProperties": false, - "description": "Failure for this input position.", - "properties": { - "message": { - "description": "Server-authored failure message.", - "type": "string" - }, - "reason": { - "description": "Why this target could not be located.", - "enum": [ - "unresolvable_host", - "private_target", - "rate_limited", - "provider_unavailable" - ], - "type": "string" - }, - "recovery": { - "additionalProperties": false, - "description": "Recovery guidance for the failed target.", - "properties": { - "hint": { - "description": "How to recover this target lookup.", - "type": "string" - } - }, - "required": [ - "hint" - ], - "type": "object" - }, - "waitTimeSeconds": { - "description": "Seconds to wait before retrying a rate-limited target.", - "type": "number" - } - }, - "required": [ - "reason", - "message", - "recovery" - ], - "type": "object" - }, - "target": { - "description": "The failed target as supplied.", - "type": "string" - } - }, - "required": [ - "target", - "error" - ], - "type": "object" - } -]New value: +[ + { + "additionalProperties": false, + "description": "Normalized geolocation metadata for one target.", + "properties": { + "asHolder": { + "description": "Holder of the autonomous system as the provider names it after the ASN, e.g. \"Cloudflare, Inc.\" for AS13335. Absent when the provider reports no AS or no holder name.", + "maxLength": 256, + "type": "string" + }, + "asName": { + "description": "Registry name of the autonomous system, e.g. \"CLOUDFLARENET\". Absent when the provider omits it.", + "maxLength": 256, + "type": "string" + }, + "asn": { + "description": "Autonomous System number, e.g. \"AS15169\". Absent on providers that omit it.", + "maxLength": 256, + "type": "string" + }, + "city": { + "description": "City name. Absent when unknown.", + "maxLength": 256, + "type": "string" + }, + "country": { + "description": "Country name. Absent when the provider does not report it.", + "maxLength": 256, + "type": "string" + }, + "countryCode": { + "description": "ISO 3166-1 alpha-2 country code. Absent when unknown.", + "maxLength": 256, + "type": "string" + }, + "hosting": { + "description": "True when the address belongs to a hosting or datacenter network, so the location is a facility rather than a person. Absent when unreported.", + "type": "boolean" + }, + "isp": { + "description": "Internet service provider for the address, e.g. \"Cloudflare, Inc\". Absent when unknown.", + "maxLength": 256, + "type": "string" + }, + "latitude": { + "description": "Latitude in decimal degrees. Absent when unknown.", + "type": "number" + }, + "longitude": { + "description": "Longitude in decimal degrees. Absent when unknown.", + "type": "number" + }, + "mobile": { + "description": "True when the address belongs to a mobile carrier network, where NAT can place the location far from the device. Absent when unreported.", + "type": "boolean" + }, + "org": { + "description": "Organization the address is registered to, e.g. \"Google LLC\"; often a customer or sub-allocation label rather than the network operator. Carries asHolder, else isp, when the provider names no organization. Absent when all three are unknown.", + "maxLength": 256, + "type": "string" + }, + "proxy": { + "description": "True when the address is a known proxy, VPN, or Tor exit — the location describes the exit node, not the user. Absent when the provider does not report it.", + "type": "boolean" + }, + "region": { + "description": "Region or state name. Absent when unknown.", + "maxLength": 256, + "type": "string" + }, + "resolvedIp": { + "description": "The IP that was actually located (a supplied hostname is resolved to this first).", + "type": "string" + }, + "source": { + "description": "The provider that answered the lookup, e.g. \"ip-api\".", + "type": "string" + }, + "target": { + "description": "The target as supplied (IP or hostname).", + "type": "string" + }, + "timezone": { + "description": "IANA timezone, e.g. \"America/Los_Angeles\". Absent when unknown.", + "maxLength": 256, + "type": "string" + } + }, + "required": [ + "target", + "resolvedIp", + "source" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "A failed batch target with recovery guidance.", + "properties": { + "error": { + "additionalProperties": false, + "description": "Failure for this input position.", + "properties": { + "message": { + "description": "Server-authored failure message.", + "type": "string" + }, + "reason": { + "description": "Why this target could not be located.", + "enum": [ + "unresolvable_host", + "private_target", + "rate_limited", + "provider_unavailable" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": false, + "description": "Recovery guidance for the failed target.", + "properties": { + "hint": { + "description": "How to recover this target lookup.", + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "waitTimeSeconds": { + "description": "Seconds to wait before retrying a rate-limited target.", + "type": "number" + } + }, + "required": [ + "reason", + "message", + "recovery" + ], + "type": "object" + }, + "target": { + "description": "The failed target as supplied.", + "type": "string" + } + }, + "required": [ + "target", + "error" + ], + "type": "object" + } +]
- Changed
toolkit_hash_value11 fields changed- changed
Input schema / properties / algorithm / descriptionPrevious value: -"Digest algorithm. sha256 (default), sha384, or sha512 for security; md5/sha1 are checksum/compat only — not for security."New value: +"Digest algorithm. sha256 (default), sha384, or sha512 for security; md5/sha1 are for checksums and for verifying existing HMAC-SHA1 signatures only — not for new security use." - changed
Input schema / properties / digestEncoding / descriptionPrevious value: -"Form of the generated digest: lowercase hex (default), standard base64, or sri (<algorithm>-<base64>, sha256/sha384/sha512 only). Applies to operation \"generate\"."New value: +"Form of the generated digest: lowercase hex (default), standard base64, base64url (URL-safe alphabet, unpadded — the JWS signature form), or sri (<algorithm>-<base64>, sha256/sha384/sha512 only, and not with secret). Applies to operation \"generate\"." - changed
Input schema / properties / digestEncoding / enumPrevious value: -[ - "hex", - "base64", - "sri" -]New value: +[ + "hex", + "base64", + "base64url", + "sri" +] - changed
Input schema / properties / expected / descriptionPrevious value: -"The digest to compare against, as hex (any case), standard base64, or SRI (<algorithm>-<base64>); the form is recognized from its shape at the algorithm's digest length, and a string of only hex digits is always read as hex. An SRI value may carry several space-separated entries: entries for other algorithms are skipped, and it matches when any entry for algorithm matches. Supplying it with operation omitted runs a compare; it is rejected with operation \"generate\"."New value: +"The digest to compare against, recognized from its shape at the algorithm's digest length: hex (any case), standard base64, or base64url, bare or prefixed as <algorithm>:<digest> or <algorithm>=<digest>; SRI (<algorithm>-<base64>); or one checksum-file line, <hex> <file> (sha256sum, shasum, md5 -r) or SHA256 (<file>) = <digest> (BSD, --tag, openssl dgst). A string of only hex digits is always read as hex; hex split by whitespace is rejected, as is a <hex> <file> line whose file name is only hex digits. An SRI value may carry several space-separated entries: entries for other algorithms are skipped, and it matches when any entry for algorithm matches. A tag or prefix naming another algorithm is rejected, as is a whole multi-line checksum file. Supplying it with operation omitted runs a compare; it is rejected with operation \"generate\"." - added
Input schema / properties / secretAdded value: +{ + "description": "HMAC key. When non-empty, the digest is HMAC(algorithm, secret, value) instead of a plain hash, for generate and compare alike. Read per secretEncoding and used exactly as sent, never trimmed; an empty string counts as absent. Never echoed in the result or in error messages.", + "type": "string" +} - added
Input schema / properties / secretEncodingAdded value: +{ + "default": "utf8", + "description": "How secret is written: utf8 text (default, as a webhook signing secret is), hex, base64, or base64url (as a JWK k member is). Read only when secret is non-empty.", + "enum": [ + "utf8", + "hex", + "base64", + "base64url" + ], + "type": "string" +} - changed
Output schema / properties / digest / descriptionPrevious value: -"Digest of value in the requested digestEncoding: lowercase hex, base64, or <algorithm>-<base64>. Present for operation \"generate\"."New value: +"Digest of value in the requested digestEncoding: lowercase hex, base64, unpadded base64url, or <algorithm>-<base64>; the HMAC when hmac is true. Present for operation \"generate\"." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `missing_expected`: operation is \"compare\" but no expected digest was supplied. `expected_without_compare`: operation is \"generate\" but an expected digest was also supplied, so it would be ignored. `expected_malformed`: expected is not a hex, standard base64, or sha256/sha384/sha512 SRI digest, or an SRI value holds a token that is not an SRI entry. `expected_length_mismatch`: expected is a recognized digest form but its length does not match the algorithm, so compare would always fail. `expected_algorithm_mismatch`: expected is SRI and none of its entries names the chosen algorithm. `sri_unsupported_algorithm`: digestEncoding is \"sri\" and algorithm is md5 or sha1, which SRI does not define. `invalid_input_encoding`: value is not valid for the declared inputEncoding (e.g. non-hex characters with inputEncoding \"hex\"). Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `missing_expected`: operation is \"compare\" but no expected digest was supplied. `expected_without_compare`: operation is \"generate\" but an expected digest was also supplied, so it would be ignored. `expected_malformed`: expected is not a digest in any form the tool reads, spans several lines (a whole checksum file), or is an SRI value holding a token that is not an SRI entry. `expected_length_mismatch`: expected is a recognized digest form but its length does not match the algorithm, so compare would always fail. `expected_algorithm_mismatch`: expected names an algorithm other than the chosen one, in a checksum-line tag, an <algorithm>: or <algorithm>= prefix, or SRI entries none of which names the chosen algorithm. `sri_unsupported_algorithm`: digestEncoding is \"sri\" and algorithm is md5 or sha1, which SRI does not define. `invalid_input_encoding`: value is not valid for the declared inputEncoding (e.g. non-hex characters with inputEncoding \"hex\"). `invalid_secret_encoding`: secret is not valid for the declared secretEncoding (e.g. non-hex characters with secretEncoding \"hex\"). `sri_with_secret`: digestEncoding is \"sri\" on operation \"generate\" and a secret was supplied; SRI carries plain digests, not HMACs. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "missing_expected", - "expected_without_compare", - "expected_malformed", - "expected_length_mismatch", - "expected_algorithm_mismatch", - "sri_unsupported_algorithm", - "invalid_input_encoding" -]New value: +[ + "missing_expected", + "expected_without_compare", + "expected_malformed", + "expected_length_mismatch", + "expected_algorithm_mismatch", + "sri_unsupported_algorithm", + "invalid_input_encoding", + "invalid_secret_encoding", + "sri_with_secret" +] - added
Output schema / properties / hmacAdded value: +{ + "const": true, + "description": "Present (true) when the digest is an HMAC keyed by secret; absent for a plain digest.", + "type": "boolean" +} - changed
Output schema / properties / matches / descriptionPrevious value: -"Constant-time equality of the computed digest against expected. Present for operation \"compare\"."New value: +"Constant-time equality of the computed digest (the HMAC when hmac is true) against expected. Present for operation \"compare\"."
1 tool update
- Changed
toolkit_geolocate_ip10 fields changed- changed
Input schema / properties / target / anyOfPrevious value: -[ - { - "description": "A raw IPv4 address.", - "format": "ipv4", - "pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$", - "type": "string" - }, - { - "description": "A raw IPv6 address.", - "format": "ipv6", - "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$", - "type": "string" - }, - { - "description": "A dotted hostname, e.g. \"example.com\".", - "pattern": "^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$", - "type": "string" - } -]New value: +[ + { + "description": "Blank means unset.", + "pattern": "^\\s*$", + "type": "string" + }, + { + "description": "A raw IPv4 address.", + "format": "ipv4", + "pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$", + "type": "string" + }, + { + "description": "A raw IPv6 address.", + "format": "ipv6", + "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$", + "type": "string" + }, + { + "description": "A dotted hostname, e.g. \"example.com\".", + "pattern": "^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$", + "type": "string" + } +] - changed
Input schema / properties / target / descriptionPrevious value: -"A public IPv4/IPv6 address or a hostname (e.g. \"8.8.8.8\" or \"example.com\")."New value: +"One public IP or dotted hostname; mutually exclusive with nonempty targets." - added
Input schema / properties / targetsAdded value: +{ + "description": "Ordered public IPs or dotted hostnames; first 100 positions are served, every remainder is disclosed. Mutually exclusive with nonblank target.", + "items": { + "anyOf": [ + { + "description": "A raw IPv4 address.", + "format": "ipv4", + "pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$", + "type": "string" + }, + { + "description": "A raw IPv6 address.", + "format": "ipv6", + "pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$", + "type": "string" + }, + { + "description": "A dotted hostname, e.g. \"example.com\".", + "pattern": "^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$", + "type": "string" + } + ], + "description": "A public IPv4/IPv6 address or a hostname (e.g. \"8.8.8.8\" or \"example.com\")." + }, + "maxItems": 1000, + "type": "array" +} - removed
Input schema / requiredRemoved value: -[ - "target" -] - changed
Output schema / anyOfPrevious value: -[ - { - "not": { - "required": [ - "error" - ] - }, - "required": [ - "target", - "resolvedIp", - "source" - ] - }, - { - "required": [ - "error" - ] - } -]New value: +[ + { + "not": { + "required": [ + "error" + ] + } + }, + { + "required": [ + "error" + ] + } +] - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `unresolvable_host`: A hostname target failed DNS resolution. `private_target`: The target resolves to a private/reserved IP with no public geolocation. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `rate_limited`: The endpoint request quota or provider cooldown is exhausted. `unresolvable_host`: A hostname target failed DNS resolution. `private_target`: The target resolves to a private/reserved IP with no public geolocation. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "unresolvable_host", - "private_target" -]New value: +[ + "rate_limited", + "unresolvable_host", + "private_target" +] - added
Output schema / properties / failedCountAdded value: +{ + "description": "Number of failed processed targets.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - added
Output schema / properties / resultsAdded value: +{ + "description": "Ordered results or failures for the first 100 input positions.", + "items": { + "anyOf": [ + { + "additionalProperties": false, + "description": "Normalized geolocation metadata for one target.", + "properties": { + "asn": { + "description": "Autonomous System number, e.g. \"AS15169\". Absent on providers that omit it.", + "maxLength": 256, + "type": "string" + }, + "city": { + "description": "City name. Absent when unknown.", + "maxLength": 256, + "type": "string" + }, + "country": { + "description": "Country name. Absent when the provider does not report it.", + "maxLength": 256, + "type": "string" + }, + "countryCode": { + "description": "ISO 3166-1 alpha-2 country code. Absent when unknown.", + "maxLength": 256, + "type": "string" + }, + "hosting": { + "description": "True when the address belongs to a hosting or datacenter network, so the location is a facility rather than a person. Absent when unreported.", + "type": "boolean" + }, + "latitude": { + "description": "Latitude in decimal degrees. Absent when unknown.", + "type": "number" + }, + "longitude": { + "description": "Longitude in decimal degrees. Absent when unknown.", + "type": "number" + }, + "mobile": { + "description": "True when the address belongs to a mobile carrier network, where NAT can place the location far from the device. Absent when unreported.", + "type": "boolean" + }, + "org": { + "description": "Owning organization or ISP, e.g. \"Google LLC\". Absent when unknown.", + "maxLength": 256, + "type": "string" + }, + "proxy": { + "description": "True when the address is a known proxy, VPN, or Tor exit — the location describes the exit node, not the user. Absent when the provider does not report it.", + "type": "boolean" + }, + "region": { + "description": "Region or state name. Absent when unknown.", + "maxLength": 256, + "type": "string" + }, + "resolvedIp": { + "description": "The IP that was actually located (a supplied hostname is resolved to this first).", + "type": "string" + }, + "source": { + "description": "The provider that answered the lookup, e.g. \"ip-api\".", + "type": "string" + }, + "target": { + "description": "The target as supplied (IP or hostname).", + "type": "string" + }, + "timezone": { + "description": "IANA timezone, e.g. \"America/Los_Angeles\". Absent when unknown.", + "maxLength": 256, + "type": "string" + } + }, + "required": [ + "target", + "resolvedIp", + "source" + ], + "type": "object" + }, + { + "additionalProperties": false, + "description": "A failed batch target with recovery guidance.", + "properties": { + "error": { + "additionalProperties": false, + "description": "Failure for this input position.", + "properties": { + "message": { + "description": "Server-authored failure message.", + "type": "string" + }, + "reason": { + "description": "Why this target could not be located.", + "enum": [ + "unresolvable_host", + "private_target", + "rate_limited", + "provider_unavailable" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": false, + "description": "Recovery guidance for the failed target.", + "properties": { + "hint": { + "description": "How to recover this target lookup.", + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "waitTimeSeconds": { + "description": "Seconds to wait before retrying a rate-limited target.", + "type": "number" + } + }, + "required": [ + "reason", + "message", + "recovery" + ], + "type": "object" + }, + "target": { + "description": "The failed target as supplied.", + "type": "string" + } + }, + "required": [ + "target", + "error" + ], + "type": "object" + } + ], + "description": "Result or failure for one input position." + }, + "type": "array" +} - added
Output schema / properties / unprocessedTargetsAdded value: +{ + "description": "Every input position past the first 100; resubmit these targets in another batch.", + "items": { + "description": "One unprocessed target.", + "type": "string" + }, + "type": "array" +}
4 tool updates
- Changed
toolkit_encode_value7 fields changed- changed
Input schema / properties / operation / descriptionPrevious value: -"\"encode\" transforms text into the encoding; \"decode\" recovers text from an encoded value."New value: +"\"encode\" transforms text into the encoding; \"decode\" recovers the bytes from an encoded value." - added
Input schema / properties / outputEncodingAdded value: +{ + "description": "Decode only: how the recovered bytes are returned. utf8 (used when omitted) returns text and fails when the bytes are not valid UTF-8; hex and base64 return the raw bytes re-encoded, losslessly. Rejected when operation is \"encode\".", + "enum": [ + "utf8", + "hex", + "base64" + ], + "type": "string" +} - changed
Input schema / properties / value / descriptionPrevious value: -"The value to transform — raw text for encode, an encoded string for decode."New value: +"The value to transform — raw text for encode, an encoded string for decode. Whitespace is ignored when decoding hex, base64, or base64url; a url value is taken literally." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `decode_failed`: operation is \"decode\" but value is malformed for the chosen encoding. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `decode_failed`: operation is \"decode\" but value is malformed for the chosen encoding. `decode_not_utf8`: operation is \"decode\", outputEncoding is utf8 (or omitted), and the decoded bytes are not valid UTF-8 text. `output_encoding_not_applicable`: operation is \"encode\" and outputEncoding was supplied; it selects how decoded bytes are returned. Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "decode_failed" -]New value: +[ + "decode_failed", + "decode_not_utf8", + "output_encoding_not_applicable" +] - added
Output schema / properties / outputEncodingAdded value: +{ + "description": "How result renders the decoded bytes: utf8 text, hex, or base64. Present for operation \"decode\".", + "enum": [ + "utf8", + "hex", + "base64" + ], + "type": "string" +} - changed
Output schema / properties / result / descriptionPrevious value: -"The transformed value (encoded text, or the decoded original)."New value: +"The transformed value: encoded text for encode; for decode, the recovered bytes as UTF-8 text, hex, or base64 per outputEncoding."
- Changed
toolkit_generate_id1 field changed- changed
Output schema / properties / ids / descriptionPrevious value: -"The minted identifiers — exactly count of them, in mint order; for uuid_v7 and ulid that order is strictly increasing (sorted by creation)."New value: +"The minted identifiers — exactly count of them, in mint order; for uuid_v7 and ulid that order is strictly increasing (sorted by creation), with random gaps between ids minted in the same millisecond."
- Changed
toolkit_generate_qr4 fields changed- changed
Input schema / properties / data / descriptionPrevious value: -"The text or URL to encode. 2953 is the absolute ceiling (QR version 40, level L, byte mode); usable capacity drops at higher errorCorrection levels, so over-capacity data is rejected with a typed data_too_large error rather than a generic failure."New value: +"The text or URL to encode, stored as UTF-8. Capacity is counted in bytes: 2953 UTF-8 bytes is the absolute ceiling (QR version 40, level L, byte mode). The 2953-character limit here is only an upper bound, since a non-ASCII character takes 2–4 bytes. Usable capacity drops at higher errorCorrection levels, so over-capacity data is rejected with a typed data_too_large error rather than a generic failure." - changed
Input schema / properties / format / descriptionPrevious value: -"Output format: svg markup, png_base64 (raster bytes), or a terminal-renderable string."New value: +"Output format: svg markup, png_base64 (raster bytes), or terminal (plain Unicode half-blocks, drawn for a dark background)." - changed
Input schema / properties / scale / descriptionPrevious value: -"Pixels per module for raster (png_base64) output. Ignored for terminal. png_base64 also bounds the whole image at 2048 px per side, so a dense symbol or a wide margin admits a lower scale than 32."New value: +"Pixels per module for svg (its width and height) and png_base64. Ignored for terminal. png_base64 also bounds the whole image at 2048 px per side, so a dense symbol or a wide margin admits a lower scale than 32 there." - changed
Output schema / properties / content / descriptionPrevious value: -"The QR artifact: SVG markup, a terminal-renderable string, or base64 PNG bytes for png_base64."New value: +"The QR artifact: SVG markup, the terminal half-block grid (newline-separated rows), or base64 PNG bytes for png_base64."
- Changed
toolkit_hash_value13 fields changed- changed
Input schema / properties / algorithm / descriptionPrevious value: -"Digest algorithm. sha256 (default) or sha512 for security; md5/sha1 are checksum/compat only — not for security."New value: +"Digest algorithm. sha256 (default), sha384, or sha512 for security; md5/sha1 are checksum/compat only — not for security." - changed
Input schema / properties / algorithm / enumPrevious value: -[ - "sha256", - "sha512", - "sha1", - "md5" -]New value: +[ + "sha256", + "sha384", + "sha512", + "sha1", + "md5" +] - added
Input schema / properties / digestEncodingAdded value: +{ + "default": "hex", + "description": "Form of the generated digest: lowercase hex (default), standard base64, or sri (<algorithm>-<base64>, sha256/sha384/sha512 only). Applies to operation \"generate\".", + "enum": [ + "hex", + "base64", + "sri" + ], + "type": "string" +} - changed
Input schema / properties / expected / descriptionPrevious value: -"The expected lowercase-hex digest to compare against. Required when operation is \"compare\"."New value: +"The digest to compare against, as hex (any case), standard base64, or SRI (<algorithm>-<base64>); the form is recognized from its shape at the algorithm's digest length, and a string of only hex digits is always read as hex. An SRI value may carry several space-separated entries: entries for other algorithms are skipped, and it matches when any entry for algorithm matches. Supplying it with operation omitted runs a compare; it is rejected with operation \"generate\"." - changed
Input schema / properties / inputEncoding / descriptionPrevious value: -"How value (and expected's pre-image, when relevant) is decoded before hashing: utf8 text, hex, or base64."New value: +"How value is decoded before hashing: utf8 text, hex, or base64." - removed
Input schema / properties / operation / defaultRemoved value: -"generate" - changed
Input schema / properties / operation / descriptionPrevious value: -"\"generate\" produces a digest; \"compare\" constant-time-checks value against expected."New value: +"\"generate\" produces a digest; \"compare\" constant-time-checks value against expected. When omitted, resolves to \"compare\" if expected is supplied and \"generate\" otherwise." - changed
Output schema / properties / algorithm / enumPrevious value: -[ - "sha256", - "sha512", - "sha1", - "md5" -]New value: +[ + "sha256", + "sha384", + "sha512", + "sha1", + "md5" +] - changed
Output schema / properties / digest / descriptionPrevious value: -"Lowercase-hex digest of value. Present for operation \"generate\"."New value: +"Digest of value in the requested digestEncoding: lowercase hex, base64, or <algorithm>-<base64>. Present for operation \"generate\"." - changed
Output schema / properties / error / properties / data / properties / reason / descriptionPrevious value: -"Machine-readable failure mode. Declared by this tool: `missing_expected`: operation is \"compare\" but no expected digest was supplied. `expected_length_mismatch`: The expected digest length does not match the algorithm, so compare would always fail. `invalid_input_encoding`: value is not valid for the declared inputEncoding (e.g. non-hex characters with inputEncoding \"hex\"). Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `missing_expected`: operation is \"compare\" but no expected digest was supplied. `expected_without_compare`: operation is \"generate\" but an expected digest was also supplied, so it would be ignored. `expected_malformed`: expected is not a hex, standard base64, or sha256/sha384/sha512 SRI digest, or an SRI value holds a token that is not an SRI entry. `expected_length_mismatch`: expected is a recognized digest form but its length does not match the algorithm, so compare would always fail. `expected_algorithm_mismatch`: expected is SRI and none of its entries names the chosen algorithm. `sri_unsupported_algorithm`: digestEncoding is \"sri\" and algorithm is md5 or sha1, which SRI does not define. `invalid_input_encoding`: value is not valid for the declared inputEncoding (e.g. non-hex characters with inputEncoding \"hex\"). Other values are possible when a failure originates below the handler." - changed
Output schema / properties / error / properties / data / properties / reason / examplesPrevious value: -[ - "missing_expected", - "expected_length_mismatch", - "invalid_input_encoding" -]New value: +[ + "missing_expected", + "expected_without_compare", + "expected_malformed", + "expected_length_mismatch", + "expected_algorithm_mismatch", + "sri_unsupported_algorithm", + "invalid_input_encoding" +] - changed
Output schema / properties / lengthInBytes / descriptionPrevious value: -"Digest size in bytes (32 for sha256, 64 for sha512, 20 for sha1, 16 for md5). Present for \"generate\"."New value: +"Digest size in bytes (32 for sha256, 48 for sha384, 64 for sha512, 20 for sha1, 16 for md5). Present for \"generate\"." - changed
Output schema / properties / operation / descriptionPrevious value: -"The operation performed."New value: +"The operation performed, after resolving an omitted operation."
5 tool updates
- Changed
toolkit_encode_value6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "encoding", + "operation", + "result" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `decode_failed`: operation is \"decode\" but value is malformed for the chosen encoding. Other values are possible when a failure originates below the handler.", + "examples": [ + "decode_failed" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "encoding", - "operation", - "result" -]
- Changed
toolkit_generate_id6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "type", + "ids", + "count" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode.", + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "type", - "ids", - "count" -]
- Changed
toolkit_generate_qr6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "format", + "content", + "version" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `data_too_large`: data exceeds the QR capacity for the chosen errorCorrection level and encoding mode. `raster_too_large`: format is png_base64 and (modules + 2 × margin) × scale exceeds the pixel budget. Other values are possible when a failure originates below the handler.", + "examples": [ + "data_too_large", + "raster_too_large" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "format", - "content", - "version" -]
- Changed
toolkit_geolocate_ip6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "target", + "resolvedIp", + "source" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `unresolvable_host`: A hostname target failed DNS resolution. `private_target`: The target resolves to a private/reserved IP with no public geolocation. Other values are possible when a failure originates below the handler.", + "examples": [ + "unresolvable_host", + "private_target" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "target", - "resolvedIp", - "source" -]
- Changed
toolkit_hash_value6 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Input schema / additionalPropertiesAdded value: +false - changed
Output schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - added
Output schema / anyOfAdded value: +[ + { + "not": { + "required": [ + "error" + ] + }, + "required": [ + "algorithm", + "operation" + ] + }, + { + "required": [ + "error" + ] + } +] - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": {}, + "description": "Present when the call failed. Absent on success.", + "properties": { + "code": { + "description": "JSON-RPC error code for this failure.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "data": { + "additionalProperties": {}, + "properties": { + "reason": { + "description": "Machine-readable failure mode. Declared by this tool: `missing_expected`: operation is \"compare\" but no expected digest was supplied. `expected_length_mismatch`: The expected digest length does not match the algorithm, so compare would always fail. `invalid_input_encoding`: value is not valid for the declared inputEncoding (e.g. non-hex characters with inputEncoding \"hex\"). Other values are possible when a failure originates below the handler.", + "examples": [ + "missing_expected", + "expected_length_mismatch", + "invalid_input_encoding" + ], + "type": "string" + }, + "recovery": { + "additionalProperties": {}, + "description": "Actionable next step for the caller.", + "properties": { + "hint": { + "type": "string" + } + }, + "required": [ + "hint" + ], + "type": "object" + }, + "retryable": { + "description": "Whether retrying may succeed.", + "type": "boolean" + } + }, + "type": "object" + }, + "message": { + "description": "Human-readable description of what went wrong.", + "type": "string" + } + }, + "required": [ + "code", + "message" + ], + "type": "object" +} - removed
Output schema / requiredRemoved value: -[ - "algorithm", - "operation" -]
1 tool update
- Changed
toolkit_generate_qr1 field changed- changed
Input schema / properties / scale / descriptionPrevious value: -"Pixels per module for raster (png_base64) output. Ignored for terminal."New value: +"Pixels per module for raster (png_base64) output. Ignored for terminal. png_base64 also bounds the whole image at 2048 px per side, so a dense symbol or a wide margin admits a lower scale than 32."
5 tool updates
- First observed
toolkit_encode_value - First observed
toolkit_generate_id - First observed
toolkit_generate_qr - First observed
toolkit_geolocate_ip - First observed
toolkit_hash_value
Related MCP Connectors
Utility tools for AI agents: hashing, text stats, validation, DNS, currency, GEO audits.
Exact hashing, base64/hex/URL encoding, JWT decoding and UUIDs for AI agents. No auth required.
26 deterministic tools: PDF, image, QR, CSV/Excel, HTML to PDF, DNS/RDAP, FX rates, time zones.
26 deterministic tools: PDF, image, QR, CSV/Excel, HTML to PDF, DNS/RDAP, FX rates, time zones.
Related MCP Servers
- AlicenseAqualityDmaintenance14 utility tools via the PublicSoftTools API: QR code generation, PDF compress/merge/split/convert/unlock, cryptographic hashing (MD5/SHA-1/SHA-256/SHA-512), UUID generation, base64 encode/decode, secure password generation, IP geolocation, DNS records, SSL certificate check, and WHOIS lookup. Free tier: 1,500 calls/month.148 npmMIT
- AlicenseNot gradedqualityDmaintenanceProvides deterministic, stateless tools for common data work including JSON, CSV, text, encoding, hashing, IDs, date/time, and number statistics.MIT
- AlicenseBqualityCmaintenanceProvides deterministic system information and developer utilities including date/time operations, OS details, math calculations, random data generation, hashing, text formatting, data validation, encoding/decoding, and log analysis.20MIT
- AlicenseAqualityDmaintenanceProvides deterministic micro-utilities as an MCP server, including free tools for conversion, text processing, hashing, encoding, ID generation, and regex, plus paid per-call tools for timezone, cron, RRULE, currency, diff, JSON Schema validation, and date math.13MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.