Pure-Python MCP server for encoding, hashing, and crypto-primitives — computed for real, locally.
mcp-bytesmith demonstrates strong schema quality and parameter documentation across all 5 tools. All tools have complete JSON Schema definitions with proper type annotations and parameter descriptions. Tool descriptions are comprehensive (194-400 chars average), exceeding baseline minimums. Naming is generally clear (verb_noun pattern: info, num_convert, byte_order, eth_hash, serialize_codec). Primary gaps: (1) no tool annotations (readOnlyHint/destructiveHint/idempotentHint) despite all tools being read-only, which would improve protocol readiness; (2) no output schemas explicitly documented in function signatures, requiring the LLM to infer response structure; (3) error handling descriptions are minimal, no recovery guidance or error classification. The server follows a clean single-responsibility pattern (each tool does one encoding/hashing task) and accepts human-friendly inputs (hex/text strings with flexible formats). Overall, definitions are production-grade for a utility library, though slightly weaker on error messaging and LLM affordances.
Convert a value between host and network byte order (htons/htonl/ntohs/ntohl). `data` is decoded via `input_format` (hex default). `from_order`/`to_order` are little|big|network|host: network is big-endian, host resolves to the platform's sys.byteorder — so on a little-endian box from_order=host to_order=network is htonl/htons. `width` (bytes) sets a fixed field size: a shorter buffer is left zero-padded up to `width`, a longer one is split into `width`-byte groups each swapped independently (array semantics); omit it to swap the whole buffer as one field. Differing orders reverse each field; equal orders only apply the width normalization. Returns {result, from_order, to_order, width, output_format}; `result` is rendered via `output_format`. Example: byte_order("0x12345678", "little", "big") -> result "78563412"
Compute an Ethereum-family hash: keccak-256 (raw), EIP-191 (personal_sign), EIP-712 (typed-data), or EIP-7702 (delegation authorization).
Discovery / health-check entrypoint: report availability and enabled toolsets. Returns six keys: `status` ("available"), `name`, `version` (package version), `python` (runtime version), `mcp_sdk` (MCP SDK version, or "unknown"), and `toolsets` (sorted list of live optional toolsets). Example: {"status":"available","name":"mcp-bytesmith","version":"0.1.0", "python":"3.12.3","mcp_sdk":"1.2.0","toolsets":["ethereum","serialize"]}
Convert a big-integer between bases (hex/dec/bin/oct). Parses `value` as a `from_base` integer (a leading 0x/0b/0o and a `-` sign are accepted) and renders it in `to_base`, prefixed for non-decimal output. `pad_bytes` zero-fills the output to that byte width (a minimum, never truncating); it is bit-aligned, so it is rejected for decimal output. Arbitrary precision — a 32-byte RPC value converts losslessly. Returns {value, from_base, to_base, result}. Example: num_convert("255", "dec", "hex") -> result "0xff"
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite all 5 tools being read-only deterministic operations. These annotations enable clients to optimize caching, retry logic, and UI presentation.
Output schemas not documented in tool definitions. Users/LLMs must infer response structure from examples only. The `info()` function returns a dict with specific keys (status, name, version, python, mcp_sdk, toolsets), but this is never declared as a schema.
eth_hash description lacks specificity. It states 'Compute an Ethereum-family hash' but does not explain when to use keccak256 vs eip191 vs eip712 vs eip7702, their use cases, or what the input 'data' format should be for each kind. The description should be 150-250 chars with clear guidance.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | 2026-07-28+ | v2 |
Encode or decode structured data (CBOR, MessagePack, bencode, protobuf, ASN.1, SSZ).
serialize_codec description too generic. It lists 6 formats but does not explain when to pick CBOR vs MessagePack vs bencode vs protobuf vs ASN.1 vs SSZ. LLMs cannot infer the use case from the name alone. Should state: 'For structured binary encoding. Pick: CBOR (config/RPC), MessagePack (compact msgpack), bencode (torrent), protobuf (cross-lang), ASN.1 (certs/X.509), SSZ (Ethereum consensus).'
No error recovery guidance. When num_convert fails (e.g. invalid value for from_base), there is no suggestion for the LLM to retry with a valid format or example. Error messages should follow the pattern: 'Invalid <field>: <value>, must be <constraint>. Example: <valid-example>.'