toolkit-mcp-server

v2.0.1

Generate random IDs, QR codes, and hashes, encode and decode values, and geolocate IPs, plus gated network and system diagnostics, via MCP. STDIO or Streamable HTTP.

toolkit.caseyjhand.com/mcp
claude mcp add --transport http toolkit-mcp-server https://toolkit.caseyjhand.com/mcp
codex mcp add toolkit-mcp-server --url https://toolkit.caseyjhand.com/mcp
{
  "mcpServers": {
    "toolkit-mcp-server": {
      "url": "https://toolkit.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http toolkit-mcp-server https://toolkit.caseyjhand.com/mcp
{
  "mcpServers": {
    "toolkit-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://toolkit.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "toolkit-mcp-server": {
      "type": "http",
      "url": "https://toolkit.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://toolkit.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2025-11-25" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

5

read 4

toolkit_hash_value

Generate a cryptographic digest of a value, or verify a value against an expected digest. Set operation to "generate" for a lowercase-hex digest, or "compare" to constant-time-check value against the expected digest — compare is timing-safe and avoids manual string equality checks. Algorithm defaults to sha256; sha512 is also secure, while md5 and sha1 are exposed for checksum and file-integrity compatibility ONLY and must not be used for passwords, signatures, or any security purpose. inputEncoding controls how value and expected are 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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "toolkit_hash_value",
    "arguments": {
      "value": "<value>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "operation": {
      "default": "generate",
      "description": "\"generate\" produces a digest; \"compare\" constant-time-checks value against expected.",
      "type": "string",
      "enum": [
        "generate",
        "compare"
      ]
    },
    "value": {
      "type": "string",
      "description": "The data to hash, interpreted per inputEncoding (raw text by default)."
    },
    "algorithm": {
      "default": "sha256",
      "description": "Digest algorithm. sha256 (default) or sha512 for security; md5/sha1 are checksum/compat only — not for security.",
      "type": "string",
      "enum": [
        "sha256",
        "sha512",
        "sha1",
        "md5"
      ]
    },
    "expected": {
      "description": "The expected lowercase-hex digest to compare against. Required when operation is \"compare\".",
      "type": "string"
    },
    "inputEncoding": {
      "default": "utf8",
      "description": "How value (and expected's pre-image, when relevant) is decoded before hashing: utf8 text, hex, or base64.",
      "type": "string",
      "enum": [
        "utf8",
        "hex",
        "base64"
      ]
    }
  },
  "required": [
    "operation",
    "value",
    "algorithm",
    "inputEncoding"
  ],
  "additionalProperties": false
}
view source ↗

toolkit_generate_qr

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, png_base64 returns base64-encoded PNG bytes (with mimeType and byteLength), and terminal returns a block of Unicode block characters renderable in a monospace terminal. errorCorrection (L/M/Q/H) trades data capacity for damage tolerance, margin sets the quiet-zone width, and scale sets pixels per module for raster output. The returned version (1–40) reflects how dense the encoded data is.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "toolkit_generate_qr",
    "arguments": {
      "data": "<data>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "data": {
      "type": "string",
      "minLength": 1,
      "maxLength": 2953,
      "description": "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."
    },
    "format": {
      "default": "svg",
      "description": "Output format: svg markup, png_base64 (raster bytes), or a terminal-renderable string.",
      "type": "string",
      "enum": [
        "svg",
        "png_base64",
        "terminal"
      ]
    },
    "errorCorrection": {
      "default": "M",
      "description": "Error-correction level: L (~7% recoverable) to H (~30%). Higher tolerance lowers data capacity.",
      "type": "string",
      "enum": [
        "L",
        "M",
        "Q",
        "H"
      ]
    },
    "margin": {
      "default": 4,
      "description": "Quiet-zone width in modules around the symbol. The spec recommends 4.",
      "type": "integer",
      "minimum": 0,
      "maximum": 20
    },
    "scale": {
      "default": 4,
      "description": "Pixels per module for raster (png_base64) output. Ignored for terminal.",
      "type": "integer",
      "minimum": 1,
      "maximum": 32
    }
  },
  "required": [
    "data",
    "format",
    "errorCorrection",
    "margin",
    "scale"
  ],
  "additionalProperties": false
}
view source ↗

toolkit_encode_value

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 text from an encoded value. base64url uses the URL-safe alphabet (- and _ instead of + and /); url applies encodeURIComponent / decodeURIComponent. Decoding a value that is malformed for the chosen encoding is reported as a recoverable error, not a silent best-effort.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "toolkit_encode_value",
    "arguments": {
      "operation": "<operation>",
      "encoding": "<encoding>",
      "value": "<value>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "operation": {
      "type": "string",
      "enum": [
        "encode",
        "decode"
      ],
      "description": "\"encode\" transforms text into the encoding; \"decode\" recovers text from an encoded value."
    },
    "encoding": {
      "type": "string",
      "enum": [
        "base64",
        "base64url",
        "hex",
        "url"
      ],
      "description": "The encoding to apply: base64, URL-safe base64url, hex, or URL percent-encoding."
    },
    "value": {
      "type": "string",
      "description": "The value to transform — raw text for encode, an encoded string for decode."
    }
  },
  "required": [
    "operation",
    "encoding",
    "value"
  ],
  "additionalProperties": false
}
view source ↗

toolkit_geolocate_ip

open-world

Resolve a public IP address (or hostname) to geographic and network metadata: country, region, city, latitude/longitude, the owning ASN and organization, and timezone. target accepts an IPv4/IPv6 address or a hostname — a hostname is DNS-resolved first and the resolvedIp field echoes which IP was actually located. The provider is called directly (never the target), so this is SSRF-free and safe to expose anywhere. Results are best-effort and provider-bounded: VPNs, proxies, mobile NAT, and anycast all defeat IP-to-location, accuracy is city-level at best, and many fields can be absent for reserved or thinly-documented ranges — absent fields are reported as unknown, never invented. Private/reserved addresses have no public geolocation and are rejected. The source field names which provider answered.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "toolkit_geolocate_ip",
    "arguments": {
      "target": "<target>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "target": {
      "anyOf": [
        {
          "type": "string",
          "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])$",
          "description": "A raw IPv4 address."
        },
        {
          "type": "string",
          "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}|:))$",
          "description": "A raw IPv6 address."
        },
        {
          "type": "string",
          "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])?)+$",
          "description": "A dotted hostname, e.g. \"example.com\"."
        }
      ],
      "description": "A public IPv4/IPv6 address or a hostname (e.g. \"8.8.8.8\" or \"example.com\")."
    }
  },
  "required": [
    "target"
  ],
  "additionalProperties": false
}
view source ↗

write 1

toolkit_generate_id

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 from this tool feed into toolkit_generate_qr (pass ids[0] as data) to create a scannable code.

write
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "toolkit_generate_id",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "type": {
      "default": "uuid_v4",
      "description": "Identifier format: uuid_v4 (random), uuid_v7 (time-ordered), or ulid (sortable Crockford-base32).",
      "type": "string",
      "enum": [
        "uuid_v4",
        "uuid_v7",
        "ulid"
      ]
    },
    "count": {
      "default": 1,
      "description": "How many identifiers to mint (1–1000). The full batch is always returned.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    }
  },
  "required": [
    "type",
    "count"
  ],
  "additionalProperties": false
}
view source ↗