Server data from the Official MCP Registry
MCP gateway with authorization, credential injection, audit logging, and output policies.
MCP gateway with authorization, credential injection, audit logging, and output policies.
Remote endpoints: streamable-http: https://{host}:8123/mcp
Valid MCP server (1 strong, 1 medium validity signals). No known CVEs in dependencies. Imported from the Official MCP Registry. 1 finding(s) downgraded by scanner intelligence.
Endpoint verified · Open access · 1 issue found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
This plugin requests these system permissions. Most are normal for its category.
Remote Plugin
No local installation needed. Your AI client connects to the remote endpoint directly.
Add this to your MCP configuration to connect:
{
"mcpServers": {
"io-github-dunkelcloud-toolmesh": {
"url": "https://{host}:8123/mcp"
}
}
}From the project's GitHub README.
The missing control layer between AI agents and enterprise systems. ToolMesh turns uncontrolled AI tool calls into a governed, auditable process — and connects any REST API or MCP server in minutes, not months.
In practice, MCP servers only expose a fraction of the REST API they wrap — and you'll hit the gaps fast. ToolMesh lets you replace the wrapper layer with .dadl files — a declarative YAML format that describes any REST API as MCP tools. No wrapper server to build, deploy, or maintain.
Current: Claude → ToolMesh → MCP Server → REST API
With DADL: Claude → ToolMesh → REST API (via .dadl file)
You don't write the YAML by hand. You ask an LLM. Claude, GPT, Gemini — any model that knows the DADL spec generates a working .dadl file in seconds. Describe what you need, drop the file into config/dadl/, done.
"Create a DADL for the GitHub API — list repos, open issues, and create pull requests."
10 seconds. Works with any LLM that knows the format.
And unlike MCP gateways that just pass tool calls through, ToolMesh adds what production deployments actually need:
| Pillar | What it does | Backed by |
|---|---|---|
| Any Backend | 30 lines of DADL replace a whole MCP server. Also proxies existing MCP servers. | Go MCP SDK + DADL (.dadl files) |
| Code Mode | 15 MCP servers at once? Without ToolMesh, impossible. Code Mode cuts 50,000+ tokens to ~1,000. | AST-parsed tool calls |
| Credential Store | Secrets injected at execution time — never in prompts, never in LLM client configs | Per-request injection via Executor pipeline |
| OpenFGA | Fine-grained authorization (user → plan → tool). Example: free users get read-only, pro gets everything. | OpenFGA |
| Gate | Block confidential data before execution, redact PII in responses | goja |
| Audit | Every tool call recorded and queryable — answer "what did that agent do?" with SQL | slog / SQLite |
Want to try ToolMesh before installing? Connect to our public demo instance — no Docker, no config, no API keys:
demo.toolmesh.io — Hacker News APIs via ToolMesh. Works with Claude Desktop, Claude Code, and ChatGPT. Login: dadl / toolmesh.
# Clone
git clone https://github.com/DunkelCloud/ToolMesh.git
cd ToolMesh
# Configure
cp .env.example .env
# IMPORTANT: Set a password — without it, all requests are rejected:
# TOOLMESH_AUTH_PASSWORD=my-secret-password
# Or set an API key for programmatic access:
# TOOLMESH_API_KEY=my-api-key
# Optional: local overrides (build locally, enable OpenFGA, HTTPS proxy, ...)
# cp docker-compose.override.yml.example docker-compose.override.yml
# # then edit docker-compose.override.yml — picked up automatically by Docker Compose
# Start (runs in bypass mode by default — no authz required)
docker compose up -d
# Verify it's running (default port: 8123)
curl http://localhost:8123/health
# MCP endpoint: http://localhost:8123/mcp
# Note: Most MCP clients require HTTPS — see TLS section below
ToolMesh itself serves plain HTTP. Most MCP clients — including Claude Desktop — require HTTPS and will reject http:// URLs. You need a TLS-terminating reverse proxy in front of ToolMesh:
| Option | When to use |
|---|---|
| Caddy | Self-hosted with a public domain — automatic Let's Encrypt certs |
| Cloudflare Tunnel | No open ports needed, zero-config TLS |
| nginx / Traefik | Already in your stack |
For local development only, you can bypass TLS by editing claude_desktop_config.json by hand (the GUI enforces https://).
Add to your Claude Desktop MCP config:
{
"mcpServers": {
"toolmesh": {
"url": "https://toolmesh.example.com/mcp"
}
}
}
For local development without TLS proxy:
{
"mcpServers": {
"toolmesh": {
"url": "http://localhost:8123/mcp"
}
}
}
ToolMesh supports OAuth 2.1 with PKCE S256 for remote access. Configure users in config/users.yaml and use the public HTTPS URL as the MCP endpoint.
ToolMesh supports two authentication methods that can be used independently or together. All OAuth state (tokens, auth codes, clients) is persisted in Redis and survives server restarts.
Define users in config/users.yaml with bcrypt-hashed passwords:
users:
- username: admin
password_hash: "$2a$10$..."
company: dunkelcloud
plan: pro
roles: [admin]
Generate password hashes with any bcrypt-capable utility:
htpasswd -nbBC 10 "" "my-password" | cut -d: -f2
For single-user setups, TOOLMESH_AUTH_PASSWORD still works as a fallback. Configure the identity with TOOLMESH_AUTH_USER, TOOLMESH_AUTH_PLAN, and TOOLMESH_AUTH_ROLES (defaults: owner, pro, admin).
Define API keys in config/apikeys.yaml with bcrypt-hashed keys:
keys:
- key_hash: "$2a$10$..."
user_id: claude-code-user
company_id: dunkelcloud
plan: pro
roles: [tool-executor]
Each key maps to a distinct user identity with its own plan and roles, which flow through to OpenFGA authorization.
For single-key setups, TOOLMESH_API_KEY still works as a fallback. The same TOOLMESH_AUTH_USER, TOOLMESH_AUTH_PLAN, and TOOLMESH_AUTH_ROLES variables control the identity.
Dynamic Client Registration is rate-limited to 5 registrations per hour per IP to prevent abuse.
OPENFGA_MODE controls whether OpenFGA authorization is enforced:
| Mode | Behavior |
|---|---|
bypass (default) | All tool calls are allowed without authz checks |
restrict | OpenFGA enforces user → plan → tool authorization (requires OPENFGA_STORE_ID) |
Start with bypass to get running quickly, then switch to restrict after bootstrapping OpenFGA.
See docs/configuration.md for all environment variables.
| Variable | Default | Description |
|---|---|---|
TOOLMESH_MCP_TIMEOUT | 120 | HTTP client timeout (seconds) for calls to downstream MCP servers |
TOOLMESH_EXEC_TIMEOUT | 120 | Tool execution timeout (seconds) — context deadline for backend calls |
Increase these for backends that need more time (e.g. browser-based web fetchers):
TOOLMESH_MCP_TIMEOUT=180
TOOLMESH_EXEC_TIMEOUT=180
ToolMesh uses structured logging via slog. The default level is debug for full MCP traceability out of the box — set LOG_LEVEL=info or higher for production since debug logs include complete request/response payloads. Per-backend debug files, log formats, and all logging variables are documented in docs/configuration.md.
See docs/architecture.md for the full architecture documentation.
┌─────────────────────────────────┐
│ ToolMesh │
│ │
│ Redis · OpenFGA · Audit │
│ Credential Store · JS Gate │
│ │
AI Agent ──MCP──────────▶ │ AuthZ ▸ Creds ▸ Gate ▸ Exec │
│ │
└──┬──────┬───────┬───────┬───────┘
│ │ │ │
MCP Client .dadl .dadl .dadl
│ │ │ │
▼ ▼ ▼ ▼
MCP Stripe GitHub Vikunja
Server API API API
Create or edit config/backends.yaml:
backends:
- name: memorizer
transport: http
url: "https://memorizer.example.com/mcp"
api_key_env: "MEMORIZER_API_KEY"
Set the credential as an environment variable:
CREDENTIAL_MEMORIZER_API_KEY=sk-mem-xxxxx
Tools from each backend are exposed with a prefix (e.g. memorizer_retrieve_knowledge). Credentials are injected by the Executor at runtime via the CredentialStore — the LLM never sees API keys.
When an MCP server doesn't expose an endpoint you need, describe it in a .dadl file and ToolMesh calls the REST API directly — no wrapper server needed. Both modes run in parallel.
Add a REST backend to config/backends.yaml:
backends:
- name: vikunja
transport: rest
dadl: /app/dadl/vikunja.dadl
url: "https://vikunja.example.com/api/v1"
For internal services with private IPs or self-signed certificates:
backends:
- name: internal-api
transport: rest
dadl: internal.dadl
url: "https://192.168.1.50:8443/api"
allow_private_url: true # allow private/loopback addresses (default: true)
tls_skip_verify: true # accept self-signed certificates (default: false)
Want Claude to list GitHub issues? Here's all it takes:
tools:
list_issues:
method: GET
path: /repos/{owner}/{repo}/issues
description: "List issues for a repository"
params:
owner: { type: string, in: path, required: true }
repo: { type: string, in: path, required: true }
state: { type: string, in: query }
ToolMesh handles auth, pagination, retries, and error mapping. DADL supports bearer tokens, OAuth2, session auth, API keys, automatic pagination, retry with backoff, response transformation, composite tools, and more.
For the full spec, examples, and the community registry, see dadl.ai. The fastest way to create a .dadl file is asking any LLM that knows the format.
Connect 15 MCP servers to a single AI agent? Without ToolMesh, that simply does not work — the context window fills up, the client chokes. Code Mode makes it possible.
Instead of exposing hundreds of individual tool definitions (50,000+ tokens), ToolMesh exposes two meta-tools: list_tools and execute_code. The LLM gets compact TypeScript interfaces (~1,000 tokens) and writes JavaScript against them:
const repos = await toolmesh.github_list_repos({ sort: "updated" });
const issues = await toolmesh.github_list_issues({
owner: repos[0].owner.login,
repo: repos[0].name,
state: "open"
});
Multiple API calls in a single round-trip. ToolMesh parses the code, extracts tool calls, and routes them through the full execution pipeline.
ToolMesh uses a registry-based extension model inspired by Go's database/sql driver pattern. Three component types are extensible via init() registration:
| Component | Built-in | Config |
|---|---|---|
| Credential Store | embedded | CREDENTIAL_STORE=<name> |
| Tool Backend | mcp, rest (DADL), echo | config/backends.yaml |
| Gate Evaluator | goja | GATE_EVALUATORS=<list> |
Enterprise extensions (InfisicalStore, VaultStore, Compliance-LLM, etc.) are planned and will be included via Go build tags: go build -tags enterprise ./cmd/toolmesh.
See docs/architecture.md for details.
See CONTRIBUTING.md.
Apache 2.0 — Copyright 2025–2026 Dunkel Cloud GmbH
Be the first to review this server!
by Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
by Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
by mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
by Microsoft · Content & Media
Convert files (PDF, Word, Excel, images, audio) to Markdown for LLM consumption
by mcp-marketplace · Developer Tools
Scaffold, build, and publish TypeScript MCP servers to npm — conversationally
by mcp-marketplace · Finance
Free stock data and market news for any MCP-compatible AI assistant.