io.github.cyanheads/toolkit-mcp-server icon

toolkit-mcp-server

by Cyanheads

io.github.cyanheads/toolkit-mcp-server

Generate IDs, QR codes, and hashes, encode values, geolocate IPs, plus gated host diagnostics.

Version 2.0.0 · latest
Other
Local
View source

toolkit-mcp-server · v2.0.0 (latest)

by Cyanheads

61

@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.

7 Tools

Install in Cursor


Tools

Seven tools. Five are always on and need no configuration — pure-compute utilities plus an SSRF-free IP lookup. Two probe the server host and stay absent from tools/list until you opt in, fail-closed.

Tool Description
toolkit_hash_value Generate a cryptographic digest (sha256/sha512/sha1/md5), or constant-time-compare a value against an expected digest.
toolkit_generate_id Mint cryptographically-random identifiers — UUIDv4, UUIDv7, or ULID — singly or in batches up to 1000.
toolkit_generate_qr Encode text or a URL into a QR code as SVG markup, base64 PNG, or a terminal-renderable string.
toolkit_encode_value Encode or decode a value across base64, base64url, hex, or URL percent-encoding, in either direction.
toolkit_geolocate_ip Resolve a public IP or hostname to geographic and network metadata — country, city, coordinates, ASN, timezone.
toolkit_check_network Gated, off by default. Read-only network diagnostics from the server host — ping, traceroute, TCP connectivity, or egress-IP detection.
toolkit_check_system Gated, off by default. Report a facet of the server host's system state — OS, CPU, memory, load average, or network interfaces.

toolkit_hash_value

Generate a digest, or constant-time-verify a value against an expected one.

  • operation: generate (lowercase-hex digest) or compare (timing-safe check via timingSafeEqual)
  • Algorithms: sha256 (default) and sha512 for security; sha1 and md5 are exposed for checksum and file-integrity compatibility only — never for passwords or signatures
  • inputEncoding reads value as utf8 (default), hex, or base64, so binary blobs skip a decode round-trip
  • Canonical use: match a download against a vendor-published checksum

toolkit_generate_id

Mint cryptographically-random identifiers from the platform CSPRNG — the correct source for IDs that must be unpredictable, unlike model-invented values.

  • type: uuid_v4 (random, default), uuid_v7 (time-ordered, sortable by creation), or ulid (26-char Crockford base32, lexicographically sortable)
  • count mints a batch up to 1000 in one call; the returned ids array always holds exactly count values
  • Not read-only — each call is fresh entropy, so a client won't cache it or auto-approve it as side-effect-free

toolkit_generate_qr

Encode text or a URL into a QR code.

  • format: svg (inline markup), png_base64 (raster bytes with mimeType and byteLength), or terminal (Unicode block string)
  • errorCorrection (L/M/Q/H) trades data capacity for damage tolerance; margin sets the quiet-zone width; scale sets pixels per module for raster output
  • The returned version (1–40) reflects how dense the encoded data is
  • data is capped at 2953 bytes — the absolute QR capacity (version 40, level L)

toolkit_encode_value

Encode or decode a value, in either direction.

  • encoding: base64, base64url (URL-safe alphabet), hex, or url (percent-encoding)
  • operation: encode (raw UTF-8 → encoding) or decode (encoded value → text)
  • Malformed decode input returns a typed decode_failed error with a recovery hint, not a silent best-effort

toolkit_geolocate_ip

Resolve a public IP or hostname to geographic and network metadata.

  • Returns country, region, city, latitude/longitude, ASN, owning organization, and timezone
  • A hostname is DNS-resolved first; resolvedIp echoes the IP actually located, and source names the answering provider
  • SSRF-free — the server calls the provider, never the target; the resolved IP is re-checked against private ranges, and private/reserved addresses are rejected (they have no public geolocation)
  • Best-effort and provider-bounded: VPNs, proxies, mobile NAT, and anycast all defeat IP-to-location, accuracy is city-level at best, and absent fields are reported as unknown rather than invented
  • Keyless by default (ip-api free tier); results are cached in memory by resolved IP

toolkit_check_network

Gated — registered only when TOOLKIT_ENABLE_NET_DIAGNOSTICS=true. Read-only network diagnostics from the server host.

  • mode: ping (ICMP round-trip), traceroute (hop path to the target), connectivity (raw TCP connect to target on port), or public_ip (the host's own egress IP)
  • A host that does not respond is reported as reachable: false — a valid result, not an error
  • Diagnoses the server's own network, so it is useful on a local or self-hosted deployment; reaching a private/reserved/internal target additionally requires TOOLKIT_ALLOW_PRIVATE_NETWORK=true, which keeps the cloud-metadata endpoint blocked by default

toolkit_check_system

Gated — registered only when TOOLKIT_ENABLE_SYSTEM_INFO=true. Report a facet of the server host's system state, read-only.

  • what: os, cpu, memory, load, or interfaces
  • Exactly one facet object is populated per call, matching what
  • Describes the host this server runs on, not the calling client — meaningful on a local or self-hosted deployment; gated off by default because os and interfaces disclose host topology and version details

Features

Built on @cyanheads/mcp-ts-core:

  • Declarative tool definitions — single file per tool, framework handles registration and validation
  • Unified error handling — handlers throw, framework catches, classifies, and formats
  • Typed error contracts — each fallible tool declares its failure reasons with recovery hints the agent can act on
  • Pluggable auth: none, jwt, oauth
  • Structured logging with optional OpenTelemetry tracing
  • STDIO and Streamable HTTP transports

Toolkit-specific:

  • Fail-closed gating — the two host-probing tools are absent from tools/list unless explicitly enabled, so a hosted instance exposes no SSRF or info-disclosure surface
  • Two-tier network gate — even with diagnostics enabled, private/reserved/loopback/link-local targets (including the cloud-metadata endpoint) stay blocked until a second flag permits them
  • CSPRNG-backed primitives — identifiers and digests come from the platform crypto source, and hash comparison is constant-time via timingSafeEqual
  • SSRF-free geolocation — the server calls the provider, then re-checks the DNS-resolved IP against private ranges before the lookup, so a hostname cannot smuggle a request to an internal address

Agent-friendly output:

  • Provenance — geolocation echoes the resolved IP and names the answering provider; absent upstream fields are reported as unknown, never invented
  • Down-but-valid results — an unreachable host returns reachable: false instead of an error, so callers branch on data, not exception text
  • Typed failure reasons — decode failures, missing digests, and blocked private targets each carry a structured reason plus a next-step recovery hint

Getting started

Add the following to your MCP client configuration file. No API key is required — the five always-on tools and the default keyless geolocation tier work out of the box.

{
  "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.3.2 or higher (or Node.js v24+).
  • No API key needed — geolocation uses the keyless ip-api free tier by default.

Installation

  1. Clone the repository:
git clone https://github.com/cyanheads/toolkit-mcp-server.git
  1. Navigate into the directory:
cd toolkit-mcp-server
  1. Install dependencies:
bun install

Configuration

Every variable is optional. Server-specific options are validated at startup via the Zod schema in src/config/server-config.ts.

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. Meaningful only on a local or self-hosted deployment. false
TOOLKIT_ALLOW_PRIVATE_NETWORK With network diagnostics on, permit private/reserved/loopback targets. The second explicit gate. false
TOOLKIT_GEO_PROVIDER IP-geolocation provider id. The default ip-api tier is keyless. ip-api
TOOLKIT_GEO_API_KEY API key for the geolocation provider, if it requires one. none
TOOLKIT_GEO_BASE_URL Base URL for the geolocation provider. 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. 45
MCP_TRANSPORT_TYPE Transport: stdio or http. stdio
MCP_HTTP_PORT Port for the HTTP server. 3010
MCP_AUTH_MODE Auth mode: none, jwt, or oauth. none
MCP_LOG_LEVEL Log level (RFC 5424). info
OTEL_ENABLED Enable OpenTelemetry instrumentation (spans, metrics, completion logs). 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 -e MCP_TRANSPORT_TYPE=http -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 tools and inits services, with fail-closed gating for the two host-probing tools.
src/config Server-specific environment variable parsing and validation with Zod.
src/mcp-server/tools Tool definitions (*.tool.ts). Seven tools — five always-on, two gated.
src/services/geo Geolocation service — DNS resolution, provider call with retry/backoff, normalization, in-memory cache.
src/services/network Network-diagnostic service plus the shared target validator and private-range classifier.
tests/ Unit and integration tests mirroring the src/ structure.

Development guide

See CLAUDE.md / AGENTS.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage
  • Register new tools in the createApp() arrays in src/index.ts
  • The two host-probing tools register behind their enable-flags; the network target gate validates after DNS resolution — never fabricate a result for an unlocatable or unreachable target

Contributing

Issues and pull requests are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.