About toolkit-mcp-server
toolkit-mcp-server provides everyday developer utilities through local tools, with public-IP geolocation handled by an external provider. It is for developers and agents needing IDs, hashes, QR codes, encoding, or optionally enabled host diagnostics.
Key features
- 01Generate UUIDs and ULIDs
- 02Create QR codes in multiple formats
- 03Hash and compare digests
- 04Encode and decode common formats
- 05Geolocate public IPs and hostnames
- 06Gated network and system diagnostics
Use cases
- 01Mint identifiers for test data
- 02Create QR codes from URLs
- 03Check file or value digests
- 04Inspect public IP location or host connectivity
MCP support
It exposes seven utility tools to MCP clients over stdio or Streamable HTTP. Network and system diagnostic tools are omitted unless explicitly enabled.
Configuration
Remote servers need no local install. Pick your client, then copy the config or install in one click.
https://toolkit.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-toolkit https://toolkit.caseyjhand.com/mcp{"mcpServers":{"cyanheads-toolkit":{"type":"http","url":"https://toolkit.caseyjhand.com/mcp"}}}Open in Cursor{"servers":{"cyanheads-toolkit":{"type":"http","url":"https://toolkit.caseyjhand.com/mcp"}}}Open in VS Code{"mcpServers":{"cyanheads-toolkit":{"type":"http","url":"https://toolkit.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-toolkit":{"serverUrl":"https://toolkit.caseyjhand.com/mcp"}}}Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.
Tools
5| Parameter | Type | Required | Description |
|---|---|---|---|
| value | string | Yes | The data to hash, interpreted per inputEncoding (raw text by default). |
| expected | string | No | 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". |
| algorithm | enum | No | Digest algorithm. sha256 (default), sha384, or sha512 for security; md5/sha1 are checksum/compat only — not for security.sha256 | sha384 | sha512 | sha1 | md5 |
| operation | enum | No | "generate" produces a digest; "compare" constant-time-checks value against expected. When omitted, resolves to "compare" if expected is supplied and "generate" otherwise.generate | compare |
| inputEncoding | enum | No | How value is decoded before hashing: utf8 text, hex, or base64.utf8 | hex | base64 |
| digestEncoding | enum | No | Form of the generated digest: lowercase hex (default), standard base64, or sri (<algorithm>-<base64>, sha256/sha384/sha512 only). Applies to operation "generate".hex | base64 | sri |
Details
From the project README@cyanheads/toolkit-mcp-server
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.
Public Hosted Server: https://toolkit.caseyjhand.com/mcp
Overview
Everyday developer utilities: generate IDs, QR codes, and hashes, encode and decode values, and geolocate a public IP or hostname. Everything but the geolocation lookup runs locally.
Tools
| Tool | Description |
|---|---|
toolkit_hash_value | Generate a digest (sha256/sha384/sha512/sha1/md5) as hex, base64, or SRI, or constant-time-compare a value against an expected digest |
toolkit_generate_id | Mint cryptographically random UUIDv4, UUIDv7, or ULID identifiers, up to 1000 per call |
toolkit_generate_qr | Encode text or a URL as a QR code in SVG, base64 PNG, or terminal half-blocks |
toolkit_encode_value | Encode or decode base64, base64url, hex, or URL percent-encoding |
toolkit_geolocate_ip | Resolve a public IP or hostname to country, city, coordinates, ASN, and timezone |
toolkit_check_network | Gated, off by default. Ping, traceroute, TCP connectivity, or egress-IP check from the server host |
toolkit_check_system | Gated, off by default. OS, CPU, memory, load average, or network interfaces of the server host |
Capability reference
toolkit_hash_value tool
valueread perinputEncoding(utf8default,hex,base64);algorithmissha256(default),sha384, orsha512, withsha1andmd5for checksum compatibility only;operationisgenerateorcompare, and when omitted it compares ifexpectedis sentgeneratereturnsdigestindigestEncoding(hexdefault,base64, orsrifor the SHA-2 algorithms) pluslengthInBytes;comparereturnsmatchesagainstexpected, given as hex, base64, or SRI, including a multi-entry npmintegrityvalue- A bad
expectedfails asexpected_malformed,expected_length_mismatch(the hint names the algorithm that length fits), orexpected_algorithm_mismatch
toolkit_generate_id tool
typeisuuid_v4(default),uuid_v7, orulid;countis 1–1000 (default 1)idsalways holds exactlycountvalues;uuid_v7andulidbatches are strictly increasing even within one millisecond, with random gaps so no id is derivable from another
toolkit_generate_qr tool
dataup to 2953 UTF-8 bytes aterrorCorrectionL, less atM(default),Q, andH;formatissvg(default),png_base64, orterminal;margin0–20 modules (default 4),scale1–32 px per module (default 4)- Returns
content, the symbolversion(1–40),mimeTypefor image formats, andbyteLengthfor PNG;png_base64also arrives as an MCP image block, andterminalis plain Unicode half-blocks drawn for a dark background - Over-capacity input fails as
data_too_largewith its byte count; a PNG over 2048 px per side fails asraster_too_largewith a scale that fits, whilesvgandterminalhave no pixel cap
toolkit_encode_value tool
operation(encodeordecode) andencoding(base64,base64url,hex,url) are required; whitespace inhex,base64, andbase64urlinput is ignored, so wrapped MIME and PEM bodies decode as-is- Decode returns
resultasutf8text unlessoutputEncodingasks forhexorbase64, which returns the bytes losslessly and transcodes between encodings; malformed input fails asdecode_failed, and binary bytes asdecode_not_utf8rather than with replacement characters
toolkit_geolocate_ip tool
targetis an IPv4/IPv6 address or a dotted hostname, DNS-resolved first; private or reserved addresses fail asprivate_target, unresolvable hostnames asunresolvable_host- Or send
targets(up to 1000) instead, never both: the first 100 return orderedresultswith per-target errors,failedCountcounts failures, andunprocessedTargetslists the rest to resubmit - Returns
country,countryCode,region,city,latitude/longitude,asn,org, andtimezonewithresolvedIpandsource; atrueinproxy,hosting, ormobilemeans the location describes infrastructure, not a person - Uses the keyless ip-api free tier over plaintext HTTP by default (
TOOLKIT_GEO_BASE_URL,TOOLKIT_GEO_API_KEY); results are cached per resolved IP - Single and batch lookups have separate rate limits (
TOOLKIT_GEO_RATE_LIMIT_PER_MIN=45,TOOLKIT_GEO_BATCH_RATE_LIMIT_PER_MIN=15); refusals reportrate_limitedwith seconds to wait, and cache hits stay free
toolkit_check_network tool
modeisping,traceroute,connectivity, orpublic_ip;targetis required except forpublic_ip, andport(1–65535) forconnectivity;count1–10 pings (default 3),timeoutMs100–30000 (default 3000)- A silent host is
reachable: false, not an error;pingaddsrttMs,sent,received, andpacketLossPercent,connectivityaddsoutcome(open,refused,timeout,unreachable), andtraceroutereturnshops; an unresolvable host or a ping/traceroute binary that can't run fails asunreachable - Registered only when
TOOLKIT_ENABLE_NET_DIAGNOSTICS=true; private and reserved targets fail asprivate_target_blockedunlessTOOLKIT_ALLOW_PRIVATE_NETWORK=true
toolkit_check_system tool
whatisos,cpu,memory,load, orinterfaces; exactly one matching facet object is populatedmemory.availableBytesis the allocation headroom andlimitBytesappears under a container memory limit;totalBytes,freeBytes, andusedBytesare raw OS figures that count reclaimable cache as used- Registered only when
TOOLKIT_ENABLE_SYSTEM_INFO=true, sinceosandinterfacesdisclose host topology and version details
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
Toolkit-specific:
- Hashing, ID minting, QR encoding, and encode/decode run in-process on
node:cryptoand theqrcodelibrary, with no upstream calls - Geolocation calls the provider, never the target, and checks the DNS-resolved IP against private ranges, so a hostname can't reach an internal address
- Fail-closed gating:
toolkit_check_networkandtoolkit_check_systemare absent fromtools/listunless enabled. Both report on the server's host, not the caller's, so they belong on local or self-hosted deployments - Two-tier network gate: with diagnostics on, private, loopback, link-local, and reserved targets (the cloud-metadata endpoint included) stay blocked until
TOOLKIT_ALLOW_PRIVATE_NETWORK=true
Agent-friendly output:
- Provenance: geolocation echoes
resolvedIpandsource, and omits fields the provider didn't report instead of inventing them - Response shaping: provider strings are capped at 256 characters and stripped of control characters, so registry-controlled text like
orgcan't flood or format a model's context - Discriminated outputs:
operation,format,mode, andwhatecho what ran, and only that branch's fields are populated - Typed failures: every declared failure carries a
reasonand a recovery hint, and conflicting inputs (expectedwithgenerate,outputEncodingwithencode) are rejected by name, not ignored
Getting started
Public Hosted Instance
A public instance is available at https://toolkit.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"toolkit-mcp-server": {
"type": "streamable-http",
"url": "https://toolkit.caseyjhand.com/mcp"
}
}
}
Self-Hosted / Local
Add the following to your MCP client configuration file. No API key is required.
{
"mcpServers": {
"toolkit-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/toolkit-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"toolkit-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/toolkit-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"toolkit-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/toolkit-mcp-server:latest"]
}
}
}
To enable the gated host-probing tools, add their flags to env (or -e for Docker):
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"TOOLKIT_ENABLE_NET_DIAGNOSTICS": "true",
"TOOLKIT_ENABLE_SYSTEM_INFO": "true"
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- No API key needed — geolocation uses the keyless ip-api free tier by default.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/toolkit-mcp-server.git
- Navigate into the directory:
cd toolkit-mcp-server
- Install dependencies:
bun install
Configuration
All variables are optional.
| Variable | Description | Default |
|---|---|---|
TOOLKIT_ENABLE_NET_DIAGNOSTICS | Register the gated toolkit_check_network tool. Leave off for hosted or shared deployments. | false |
TOOLKIT_ENABLE_SYSTEM_INFO | Register the gated toolkit_check_system tool. | false |
TOOLKIT_ALLOW_PRIVATE_NETWORK | With network diagnostics on, permit private, reserved, loopback, and link-local targets. | false |
TOOLKIT_GEO_API_KEY | API key for the geolocation endpoint, if it requires one. | none |
TOOLKIT_GEO_BASE_URL | Base URL for an ip-api-compatible endpoint. The keyless default is plaintext HTTP; ip-api's HTTPS endpoint needs a paid key. | http://ip-api.com |
TOOLKIT_GEO_CACHE_TTL_SECONDS | In-memory geolocation cache TTL in seconds. | 3600 |
TOOLKIT_GEO_RATE_LIMIT_PER_MIN | Max geolocation requests per minute; cache hits don't count. | 45 |
TOOLKIT_GEO_BATCH_RATE_LIMIT_PER_MIN | Max batch geolocation requests per minute, counted separately. | 15 |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | Port for the HTTP server. | 3010 |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto. | stateless |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (RFC 5424). | info |
OTEL_ENABLED | Enable OpenTelemetry. | false |
See .env.example for the full list of optional overrides.
Running the server
Local development
-
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:http -
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security, changelog sync bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t toolkit-mcp-server .
docker run --rm -p 3010:3010 toolkit-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/toolkit-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers the five always-on tools, and the two gated tools only behind their flags. |
src/config | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts). Seven tools, five always-on and two gated. |
src/services/geo | Geolocation service — DNS resolution, provider call with retry, normalization, in-memory cache. |
src/services/network | Network-diagnostic service plus the shared target schema and private-range classifier. |
tests/ | Vitest suites for tools (tests/tools) and services (tests/services). |
Development guide
See CLAUDE.md / AGENTS.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storage - Register new tools in the
createApp()arrays insrc/index.ts; a host-probing tool registers only behind an enable flag - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
Apache-2.0 — see LICENSE for details.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.