KRAKEN TOOLS
Self-Hosted MCP Tool Server
Version 1.0 · March 2026
1. Overview
Kraken Tools is a self-hosted, production-ready MCP (Model Context Protocol) tool server that exposes a library of 36+ utility tools to AI assistants via the standard MCP Streamable HTTP transport. It also provides a REST API, a full-featured web dashboard, and the ability to proxy tools from remote MCP servers.
Features
- 36 Built-in Tools — Web, data, utilities, network, and math tools ready to use
- MCP Protocol — Full compliance with MCP Streamable HTTP transport (initialize, tools/list, tools/call, SSE notifications)
- REST API — Simple JSON interface at
/v1/toolsfor direct integration - Web Dashboard — Manage tools, API keys, remote servers, logs, and test tools live
- Tool Store — Install tools from a built-in catalog, URL, or MCP registries
- Remote Server Proxy — Connect to external MCP servers and proxy their tools as local
- API Key Management — Multiple keys with per-key rate limits and toolset scoping
- Hot-Reload — Create, edit, and delete tools without restarting the server
- SSRF Protection — Comprehensive URL validation with DNS resolution checks
- Container Hardening — Non-root, dropped capabilities, memory/CPU/PID limits
Architecture
Clients
┌──────────┬──────────┬──────────┐
│ Claude │ REST API │ Dashboard│
│ Desktop │ Client │ Browser │
└────┬─────┴─────┬────┴────┬─────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────┐
│ Express.js (:3204) │
│ │
│ POST /mcp ── MCP Transport │
│ /v1/tools ── REST API │
│ /dashboard ── Dashboard API │
│ / ── Frontend SPA │
└──────┬──────────────┬────────────┘
│ │
┌──────▼──────┐ ┌────▼────────────┐
│ Tool │ │ Remote MCP │
│ Registry │ │ Server Proxy │
│ (36 tools) │ │ (client pool) │
└──────┬──────┘ └────┬────────────┘
│ │
┌──────▼──────┐ ┌────▼────────────┐
│ tools/*.js │ │ External MCP │
│ (on disk) │ │ Servers │
└─────────────┘ └─────────────────┘
2. Quick Start
Installation
# Clone or copy project
cd /home/ubuntu/kraken-tools
# Configure environment
cp .env.example .env
nano .env
# Build and start
docker compose up -d --build
# Verify
curl http://localhost:3204/health
Configuration
| Variable | Default | Description |
|---|---|---|
PORT | 3204 | Server listen port |
NODE_ENV | production | Enables HSTS, optimized builds |
DASHBOARD_USER | admin | Dashboard login username |
DASHBOARD_PASS | admin | Dashboard login password |
API_KEY | (empty) | Optional bootstrap API key for MCP/REST access |
API_KEY is optional — managed keys created in the dashboard are recommended instead.
Creating Your First API Key
- Open the dashboard at
http://localhost:3204 - Log in with your configured credentials
- Navigate to API Keys in the sidebar
- Click Create API Key
- Set a name, rate limit, and optional toolset scope
- Copy the generated key — it is only shown once
# Test with your new key
curl http://localhost:3204/v1/tools \
-H "Authorization: Bearer YOUR_KEY"
3. Dashboard
The web dashboard is a single-page application served at the root URL. It provides full management of all server features without any external dependencies.
Overview Page
Displays real-time statistics:
- Total Tools — number of registered tools (local + remote)
- Enabled / Disabled — per-tool toggle counts
- Categories — active tool categories
- 24h Calls — successful and failed calls in the last 24 hours
- Top Tools — 5 most-called tools by volume
Tools Management
Lists all registered tools with their name, description, category, and status. Each tool can be:
- Enabled/Disabled — toggle switch, disabled tools are hidden from API and MCP
- Edited — opens the built-in code editor with the tool source
- Deleted — permanently removes the tool file (with confirmation)
Tools are organized by category and show remote or disabled badges as appropriate.
Code Editor
A built-in code editor with syntax highlighting for JavaScript. Supports:
- Keyword, string, comment, and function highlighting
- Line numbers
- Create new tools or edit existing ones
- Save triggers hot-reload — no restart needed
- Validation on save: checks for
name,description, andhandlerexports
Tool Store
Three ways to add tools:
| Method | Description |
|---|---|
| Built-in Catalog | 19 pre-built tools (web, data, utilities) — one-click install |
| From URL | Fetch a .js tool file from any URL (SSRF-protected) |
| MCP Registry | Browse the official MCP registry and mcpservers.org |
Built-in Catalog Tools
The catalog reads directly from the on-disk tool files, ensuring installed tools always include the latest security fixes:
url_screenshot ip_lookup dns_lookup whois_lookup
qrcode url_redirect weather currency_convert
regex_extract url_parse http_headers json_schema
ssl_check random_data cron_parse markdown_to_text
epoch_convert color_convert user_agent_parse
Test Panel
Select any enabled tool from a dropdown, fill in parameters via a dynamic form builder, execute it, and see the result with execution time. Useful for verifying tool behavior before deploying API keys to clients.
Logs
Request log showing recent tool calls with:
- Timestamp — when the call was made
- Tool Name — which tool was called
- Status — success or error
- Duration — execution time in milliseconds
- Key Name — which API key made the call
A Clear Logs button allows manual purge. Logs older than 7 days are automatically purged every hour. The log buffer holds up to 500 entries in a circular buffer (in-memory only, not persisted across restarts).
API Keys
Create, edit, and delete API keys. Each key has:
- Name — human-readable label
- Rate Limit — maximum requests per minute (1–10,000)
- Toolset — optional list of allowed tools (or "all tools")
- Usage Stats — last used timestamp and total request count
Remote Servers
Connect to external MCP servers. Their tools appear as local tools with a prefixed name (serverName__toolName). Supports custom headers for authentication, auto-connect on startup, and manual connect/disconnect.
4. MCP Protocol
Kraken Tools implements the MCP Streamable HTTP transport, the standard protocol for exposing tools to AI assistants like Claude Desktop, Cursor, and other MCP-compatible clients.
Transport
| Method | Endpoint | Purpose |
|---|---|---|
POST | /mcp | JSON-RPC 2.0 request handler (initialize, tools/list, tools/call) |
GET | /mcp | SSE stream for server-to-client notifications |
DELETE | /mcp | Terminate a session |
Required headers:
Content-Type: application/json
Accept: application/json, text/event-stream
Authorization: Bearer YOUR_API_KEY
Sessions
- A session is created on the first
initializecall - The server returns a
Mcp-Session-Idheader - All subsequent requests must include this header
- Sessions idle-timeout after 30 minutes
- Maximum 500 concurrent sessions (LRU eviction)
- Cleanup runs every 5 minutes
Supported Methods
initialize
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": { "name": "my-app", "version": "1.0" }
}
}
notifications/initialized
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
tools/list
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
Returns all enabled tools with their JSON Schema (converted from Zod). If the API key has a toolset scope, only those tools are returned.
tools/call
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "hash",
"arguments": {
"operation": "sha256",
"input": "hello world"
}
}
}
Connecting from Claude Desktop
Add to your Claude Desktop claude_desktop_config.json:
{
"mcpServers": {
"kraken-tools": {
"url": "http://YOUR_HOST:3204/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
5. REST API
A simpler alternative to MCP for programmatic tool access. All endpoints require API key authentication.
Authentication
Authorization: Bearer YOUR_API_KEY
Use a managed API key created in the dashboard, or the bootstrap API_KEY from the environment.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /v1/tools | List enabled tools (filtered by key's toolset) |
POST | /v1/tools/call | Execute a tool |
GET | /health | Health check (no auth required) |
Examples
List Tools
curl http://localhost:3204/v1/tools \
-H "Authorization: Bearer YOUR_KEY"
# Response
{
"tools": [
{ "name": "hash", "description": "Generate hashes...", "category": "utilities" },
{ "name": "http_fetch", "description": "Fetch a URL...", "category": "web" },
...
]
}
Call a Tool
curl http://localhost:3204/v1/tools/call \
-X POST \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"tool": "hash",
"args": {
"operation": "hash",
"input": "hello world",
"algorithm": "sha256"
}
}'
# Response
{
"tool": "hash",
"content": [{
"type": "text",
"text": "{\"algorithm\":\"sha256\",\"encoding\":\"hex\",\"hash\":\"b94d27b...\"}"
}],
"ms": 1
}
Health Check
curl http://localhost:3204/health
# Response
{
"status": "ok",
"totalTools": 36,
"enabledTools": 36
}
6. Tools Reference
All 36 built-in tools organized by category.
Web 11 tools
| Tool | Description | Key Parameters |
|---|---|---|
http_fetch | Fetch a URL and return content (text, JSON, headers) | url, method, headers, body, timeout |
http_status | Look up HTTP status code meaning or list by category | code, category |
http_headers | Inspect HTTP response headers (security, server info) | url |
dns_lookup | DNS lookup (A, AAAA, MX, TXT, NS, CNAME, SOA) via Cloudflare DoH | domain, type |
ip_lookup | Geolocation and ISP info via ip-api.com | ip |
ssl_check | Check SSL/TLS certificate details for a domain | domain |
port_check | Check if a TCP port is open on a host | host, port, timeout |
url_parse | Parse a URL into components (protocol, host, path, query) | url |
url_redirect | Follow URL redirects and return final destination | url, max_redirects |
url_screenshot | Generate URL screenshot via thum.io | url, width |
whois_lookup | WHOIS/RDAP domain lookup | domain |
Data 7 tools
| Tool | Description | Key Parameters |
|---|---|---|
csv_parse | Convert CSV to JSON or JSON to CSV | data, mode, delimiter, headers |
json_diff | Deep JSON comparison showing additions, removals, changes | a, b |
json_schema | Validate JSON against a schema or infer schema from data | data, mode, schema |
json_transform | Parse, query, flatten, pick/omit fields from JSON | data, operation, fields |
diff_text | Line-by-line text comparison (unified diff format) | a, b |
html_strip | Remove HTML tags, optional link extraction | html, extract_links |
regex_extract | Extract matches from text using regular expressions | text, pattern, flags |
Utilities 14 tools
| Tool | Description | Key Parameters |
|---|---|---|
base64 | Encode or decode Base64 strings | operation, input, urlSafe |
hash | Generate hashes (MD5, SHA-1, SHA-256, SHA-512) or UUIDs | operation, input, algorithm, encoding |
string_encode | Encode/decode: URL, HTML entities, hex, Unicode escapes | input, operation |
text_utils | Word/char count, case conversion, slugify, truncate | input, operation |
random_data | Generate passwords, UUIDs, tokens, numbers, lorem ipsum | type, length, min, max, count |
epoch_convert | Convert between Unix timestamps and human-readable dates | value, direction |
datetime | Date/time operations, format conversion, diff calculation | operation, date, timezone, format |
markdown_to_text | Strip markdown formatting, return plain text | markdown |
cron_parse | Parse and explain cron expressions | expression |
user_agent_parse | Parse User-Agent string (browser, OS, device) | ua |
color_convert | Convert colors between HEX, RGB, and HSL | color |
qrcode | Generate QR code image URL | text, size |
weather | Current weather conditions via Open-Meteo | latitude, longitude |
currency_convert | Currency conversion via frankfurter.app | amount, from, to |
Network & Math 4 tools
| Tool | Description | Key Parameters |
|---|---|---|
cidr_calc | CIDR subnet calculator (network, broadcast, host range) | cidr |
math_eval | Safe mathematical expression evaluation | expression |
jwt_decode | Decode JWT tokens (no verification) | token |
ping | Health check echo tool | message |
7. Tool Development
Tools are standard ES module .js files in the tools/ directory. The server discovers, validates, and hot-reloads them automatically.
File Structure
// tools/my-tool.js
import { z } from 'zod';
export const name = 'my_tool';
export const description = 'What this tool does';
export const category = 'utilities';
export const inputSchema = {
query: z.string().describe('Search query'),
limit: z.number().min(1).max(100).optional()
.default(10).describe('Max results'),
};
export const annotations = {
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
openWorldHint: false,
};
export async function handler({ query, limit = 10 }) {
// Your logic here
const results = doSomething(query, limit);
return {
content: [{
type: 'text',
text: JSON.stringify(results, null, 2)
}]
};
}
Input Schema (Zod)
The inputSchema is defined using Zod validators. The MCP SDK automatically converts them to JSON Schema for clients. Common patterns:
// Required string
name: z.string().describe('User name')
// Optional with default
limit: z.number().optional().default(10).describe('Max items')
// Enum
format: z.enum(['json', 'csv', 'xml']).describe('Output format')
// Bounded number
port: z.number().min(1).max(65535).describe('TCP port')
// Boolean
verbose: z.boolean().optional().describe('Show details')
Handler Return Format
// Success
return {
content: [{ type: 'text', text: 'result string' }]
};
// Error
return {
isError: true,
content: [{ type: 'text', text: 'Error: something failed' }]
};
// Multiple content blocks
return {
content: [
{ type: 'text', text: 'Analysis complete' },
{ type: 'text', text: JSON.stringify(data) }
]
};
Annotations
| Annotation | Meaning |
|---|---|
readOnlyHint | Tool does not modify any state |
destructiveHint | Tool performs a dangerous/irreversible operation |
idempotentHint | Same input always produces same output |
openWorldHint | Tool makes external network requests |
Hot-Reload
When a tool is saved (via dashboard or API), the server:
- Writes the new source to
tools/{filename}.js - Creates a backup of the previous version
- Imports the new module with cache-busting
- Validates exports:
name(string),handler(function),description(string) - Checks for name collisions with other tools
- Registers the tool in the in-memory registry
- On failure: restores the backup file and rolls back
8. Remote Servers
Concept
Kraken Tools can act as an MCP client, connecting to external MCP servers and proxying their tools as local tools. This lets you aggregate tools from multiple sources into a single endpoint.
Configuration
Each remote server has:
| Field | Description |
|---|---|
name | Identifier (used as tool name prefix) |
url | MCP endpoint URL (SSRF-validated) |
headers | Custom headers (e.g., Authorization) |
autoConnect | Connect automatically on server startup |
Tool Proxying
When a remote server is connected, its tools are discovered via tools/list and registered locally with a prefixed name:
# Remote server "github" with tool "search_repos"
# becomes local tool:
github__search_repos
Remote tools appear in the dashboard with a remote badge. They are callable via MCP, REST API, and the dashboard test panel just like local tools.
Connection timeout is 15 seconds. If the remote server is unreachable, the tools are not registered and the error is shown in the dashboard.
9. API Keys
Creation & Storage
API keys are generated as 32-byte random hex strings. Only a SHA-256 hash is stored — the raw key is returned only at creation time and cannot be recovered.
# Key format example
a7f3c8d2e1b4f5a6c9d0e3f2a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9
# Stored as
{
"id": "uuid",
"name": "my-app",
"prefix": "a7f3c8d2e1b4f5..",
"hash": "sha256hex...",
"rateLimit": 60,
"toolset": null,
"createdAt": "2026-03-13T...",
"lastUsed": "2026-03-13T...",
"requestCount": 142
}
Toolset Scoping
Each key can optionally restrict which tools are accessible:
- All tools (default) —
toolset: null— every enabled tool is available - Custom toolset —
toolset: ["hash", "dns_lookup", ...]— only listed tools are visible and callable
Toolset scoping is enforced at both the MCP and REST API layers. In MCP, the tool list returned by tools/list is filtered to only include the key's allowed tools.
Rate Limiting
- Each key has a configurable rate limit (default: 60 requests/minute)
- Uses a 60-second sliding window per key
- Returns
429 Too Many Requestswith aretryAfterfield when exceeded - Rate limit windows are cleaned up every 5 minutes
10. Security
Authentication
| Layer | Method | Details |
|---|---|---|
| MCP & REST API | Bearer token | HMAC-SHA256 (bootstrap) or SHA-256 hash (managed keys), timing-safe comparison |
| Dashboard | Username/Password | SHA-256 hashed, timing-safe comparison, session tokens (24h TTL) |
| Login Protection | Rate limit | Max 10 attempts per IP per 5 minutes |
SSRF Protection
All tools and endpoints that make outbound HTTP requests validate URLs through a centralized SSRF protection layer (lib/url-safety.js):
- Protocol whitelist — only
http:andhttps:allowed - Hostname blocklist — localhost, [::1], [::ffff:127.0.0.1], etc.
- IPv4 private ranges — 127.x, 10.x, 172.16-31.x, 192.168.x, 169.254.x, 0.x, CGNAT
- IPv6 private ranges — ::1, fc00::/7, fe80::, ::ffff:*
- IPv4-mapped IPv6 unwrapping —
::ffff:127.0.0.1correctly blocked - DNS resolution check — all A and AAAA records verified against private ranges
- Redirect blocking —
http_fetchusesredirect: 'manual'to prevent redirect-based SSRF
Protected endpoints: http_fetch, url_screenshot, install-url, remote server URLs, remote server PUT updates.
Header Injection Prevention
The http_fetch tool validates all custom headers for \r, \n, and \0 control characters before use, preventing HTTP header injection attacks.
Security Headers
All responses include:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Cache-Control: no-store
Permissions-Policy: camera=(), microphone=(), geolocation=()
Referrer-Policy: strict-origin-when-cross-origin
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'
Strict-Transport-Security: max-age=31536000; includeSubDomains (production only)
Container Hardening
| Measure | Configuration |
|---|---|
| Non-root user | Runs as node:node (UID 1000) |
| Privilege escalation | no-new-privileges: true |
| Linux capabilities | All dropped (cap_drop: ALL) |
| Memory limit | 512 MB (Node heap: 384 MB) |
| CPU limit | 1 core |
| PID limit | 256 processes |
| Tmpfs | /tmp mounted as tmpfs (ephemeral) |
| Init system | tini (proper signal handling) |
| Code generation | --disallow-code-generation-from-strings |
11. Operations
Docker Deployment
# Build and start
docker compose up -d --build
# View logs
docker compose logs -f
# Restart
docker compose restart
# Stop
docker compose down
# Rebuild after code changes
docker compose up -d --build
Volume Mounts
| Container Path | Host Path | Mode | Purpose |
|---|---|---|---|
/app/data | ./data | RW | Config persistence (tools.json) |
/app/tools | ./tools | RW | Tool source files |
/app/lib | ./lib | RO | Core libraries |
/app/routes | ./routes | RO | Route handlers |
/app/server.js | ./server.js | RO | Entry point |
/app/frontend | ./frontend | RO | Dashboard SPA |
Health Checks
# Docker health check (built-in)
# Runs every 30s, 5s timeout, 3 retries, 10s start period
# Manual check
curl http://localhost:3204/health
# {"status":"ok","totalTools":36,"enabledTools":36}
Log Management
- Request logs — 500-entry circular buffer (in-memory)
- Auto-purge — entries older than 7 days removed hourly
- Manual clear — via dashboard button or
DELETE /dashboard/logs - Not persisted — logs reset on container restart
- Application logs — console output, view with
docker compose logs
Data Persistence
Configuration is stored in data/tools.json with atomic writes (write to .tmp, then rename). The file is written with mode 0600 and uses deferred flushing (batched every 30 seconds) to minimize disk I/O.
Persisted data:
- API keys (hashed, never raw)
- Tool enable/disable settings
- Remote server configurations
Not persisted:
- Request logs (in-memory circular buffer)
- MCP sessions (in-memory)
- Rate limit windows (in-memory)
Limits & Timeouts
| Limit | Value |
|---|---|
| Tool execution timeout | 30 seconds |
| URL fetch timeout (http_fetch) | 10 seconds (max 30s) |
| Remote server connection timeout | 15 seconds |
| URL install timeout | 15 seconds |
| MCP registry fetch timeout | 12 seconds |
| Request body size | 1 MB |
| Tool source file size | 100 KB |
| HTTP response size (http_fetch) | 1 MB (max 5 MB) |
| Request log buffer | 500 entries |
| Log retention | 7 days (auto-purge) |
| MCP concurrent sessions | 500 |
| MCP session idle timeout | 30 minutes |
| Dashboard session TTL | 24 hours |
| Rate limit (API keys) | 1–10,000 req/min |
| Login attempts | 10 per 5 minutes per IP |
| Docker memory | 512 MB |
| Docker CPU | 1 core |
| Docker PIDs | 256 |
Directory Structure
kraken-tools/
├── server.js # Express entry point
├── package.json # Dependencies (MCP SDK, Express, Zod)
├── Dockerfile # Alpine + Node 22, non-root, tini
├── docker-compose.yml # Production orchestration
├── .env # Runtime configuration
├── lib/
│ ├── tool-registry.js # Tool discovery, loading, execution
│ ├── config.js # Atomic config persistence
│ ├── auth.js # API key + dashboard auth + rate limiting
│ ├── mcp-transport.js # MCP Streamable HTTP transport
│ ├── url-safety.js # SSRF protection (DNS resolve + IP check)
│ └── remote-servers.js # Remote MCP server proxy client
├── routes/
│ ├── dashboard.js # Dashboard API (tools, keys, logs, remote)
│ └── tools-api.js # REST API (/v1/tools)
├── tools/
│ ├── base64.js # 36 tool files...
│ ├── hash.js
│ ├── http-fetch.js
│ └── ...
├── frontend/
│ ├── index.html # Dashboard SPA
│ └── docs.html # This documentation
└── data/
└── tools.json # Persisted config (API keys, settings)
KRAKEN TOOLS · Documentation · v1.0 · March 2026