Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Description from the maker (original English)
Self-hosted MCP gateway. Turn any REST API into MCP tools via YAML (DADL). Authz, audit, policies.
These three are never merged into one score: opinions, measurements and popularity are different things.
We have not written a plain-language summary for this one yet. Below are the facts we read from the registry.
Pick the AI app you use, then copy the settings.
You need
Which app do you use?
Pick your app above. We remember it, so next time the button says “Install in …”.
Works in Claude on the web, desktop and mobile:
https://{host}:8123/mcpThe address contains {…} parts that only you know (such as your account), so copy it and fill them in.
Run this in your terminal
claude mcp add --transport http toolmesh 'https://{host}:8123/mcp'The address contains {…} parts that only you know (such as your account), so copy it and fill them in.
Paste into .cursor/mcp.json in your project, or ~/.cursor/mcp.json
{
"mcpServers": {
"toolmesh": {
"url": "https://{host}:8123/mcp"
}
}
}Your browser asks to open the app, then the app shows the settings and asks you to confirm. Key values are left empty for you to fill in.
The address contains {…} parts that only you know (such as your account), so copy it and fill them in.
Paste into .vscode/mcp.json in your project
{
"servers": {
"toolmesh": {
"type": "http",
"url": "https://{host}:8123/mcp"
}
}
}Your browser asks to open the app, then the app shows the settings and asks you to confirm. Key values are left empty for you to fill in.
ChatGPT connects only to servers on the internet:
https://{host}:8123/mcpThe address contains {…} parts that only you know (such as your account), so copy it and fill them in.
Menu names can differ slightly by plan and over time.
Your choice stays on this device in a cookie; no account needed.
These settings are generated from the maker’s registry entry. If the README says otherwise, follow the README.
We have not read this server’s tool list yet; we check endpoints in rotation.
We check information anyone can see; we have not read the code. Checks that do not apply are left out of the count. · Checked Nov 6, 2026
The registry name was verified with the GitHub account DunkelCloud, which owns the repo
We have not read this repo from GitHub yet
We have not read this repo from GitHub yet
The address needs your own account values, so we cannot check it for you
The address needs your own account values, so we cannot check it for you
Not checked yet; we read the tool list when we check the endpoint
Compared with every active server in this category in the registry. Stars count only when the publisher owns the repo.
It passed 1 of 1 applicable basic checks. We have not read the code. Before adding a key or token, see what access the server asks for and use a key with only the permissions you need.
The registry does not list a required key, though some servers ask you to sign in on first use.
It runs in the maker’s cloud. Connect over the internet with nothing to install, but what you send passes through the maker’s servers.
The GitHub repo last changed –, and the latest version (0.5.0) reached the registry 14 days ago.
Apps that support MCP, such as Claude Desktop, Claude Code, Cursor and VS Code. It connects by URL, so apps that accept remote MCP servers work too, such as ChatGPT in developer mode.
In the same category: Spec Driven Development, Remote Desktop Commander, FOGA node
Servers in the same category from other makers, sorted by stars.
Reading a card:★ GitHub starsiThree pillars: reviews · checks · usageiUpdated = latest version published to the registryi
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
A Finch OG Agent cell as an MCP server: read the world, dry-run and take ERC-8414 tenders by policy.
Copied from the maker’s repo as written. PopNx MCP has not reviewed or endorsed it. HTML, images and scripts are removed. Links lead off this site.
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, on by default with nothing to install (user → plan → tool). Example: free users get read-only, pro gets everything. | OpenFGA, embedded or external |
| 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](https://www.toolmesh.io/en/demo/) — 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
cp .env.example .env
docker compose up -d
curl http://localhost:8123/health
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:
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. Each entry names its key by the SHA-256 of the key:
keys:
Generate a key and its key_sha256:
KEY="tm_$(openssl rand -hex 32)"
printf '%s' "$KEY" | sha256sum | cut -d' ' -f1
Each key maps to a distinct user identity with its own plan and roles, which flow through to authorization.
Entries with a bcrypt key_hash, as files written for earlier versions have them, keep working without any change. Until its key has been used once after startup, such an entry costs a bcrypt comparison for every bearer credential that nothing else recognizes; key_sha256 is looked up directly and is meant for randomly generated keys. See docs/configuration.md for the details and for how the two forms differ.
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.
A request to /mcp without a valid credential is answered 401 with a WWW-Authenticate: Bearer challenge that carries resource_metadata, as the MCP authorization specification asks. MCP clients start the OAuth flow, or refresh an expired token, on that status. Such requests are logged at INFO and counted in toolmesh_logins_total{method="anonymous"}. See docs/configuration.md.
Dynamic Client Registration is rate-limited to 5 registrations per hour per IP to prevent abuse (with Redis; a Redis outage lets registrations through and is logged). A registered client that never obtains a token is forgotten after a day, and one that does after 90 days without a new token (TOOLMESH_DCR_CLIENT_TTL, TOOLMESH_DCR_CLIENT_IDLE_TTL). See docs/configuration.md.
The file broker (upload_file, POST /files/upload, download URLs under /blobs/) can be switched off with TOOLMESH_FILE_BROKER_ENABLED=false and bounded with a quota in bytes, in total and per user (TOOLMESH_FILE_BROKER_MAX_TOTAL_BYTES, TOOLMESH_FILE_BROKER_MAX_BYTES_PER_USER). It is on and unbounded by default. See docs/configuration.md.
Failed password logins are limited per account and per client address: by default 5 failures for one account from one address, 20 for one account from all addresses together, and 50 from one address across all accounts, each within 15 minutes. Beyond that the login answers 429 until the window has passed. Every failed login is logged at WARN and counted in toolmesh_logins_total{result="failure"}. Already issued tokens and API keys are not affected by a lockout. See docs/configuration.md for the variables and the reverse-proxy requirement of the per-address limits.
The number of bcrypt comparisons that run at the same time is bounded for the whole process (TOOLMESH_BCRYPT_MAX_CONCURRENT, default: half of the available CPUs), so that password logins cannot take the CPU away from everything else. See docs/configuration.md.
Every tool call is checked, and tool listings show each caller only the tools it may call. Nothing has to be set up: ToolMesh runs OpenFGA inside its own process and keeps its data in data/authz.db.
TOOLMESH_AUTHZ_MODE selects the engine:
| Mode | Behavior |
|---|---|
embedded (default) | Checks run inside ToolMesh. Grants come from a preset or from config/authz.yaml. |
external | Checks go to an OpenFGA server you operate (OPENFGA_API_URL, OPENFGA_STORE_ID). ToolMesh never writes to it. |
disabled | No checks. Reported at every start and recorded in the audit trail. |
Grants refer to the users, roles, plans and companies from users.yaml, apikeys.yaml or the single password/API key. Without a grants file a preset applies:
| Preset | Who may call what |
|---|---|
single-user | the owner (TOOLMESH_AUTH_USER) and role admin: every tool. Default without users.yaml/apikeys.yaml. |
team | as single-user, plus plan pro: every tool, plan free: every read tool. Default with users.yaml or apikeys.yaml. |
open | every authenticated caller: every tool |
For finer control, copy config/authz.yaml.example to config/authz.yaml; grants can name all tools, backends, single tools or DADL access classes (read, write, ...), denies block any of these and win over every grant, and changes take effect within seconds:
grants:
denies:
An installation upgraded from a version without authorization keeps every tool open to every authenticated caller (preset open) and says so at every start, until you pick a preset or write grants. OPENFGA_MODE is deprecated: restrict maps to external, bypass to embedded. See docs/configuration.md.
ToolMesh is secure-by-default: it ships with no individual default that relaxes a control silently. At boot it logs a single security-posture summary that lists every control still in a relaxed state (missing auth credential, authorization disabled or open to everyone, open CORS, debug tools, login limits switched off) together with how to harden it. In the default production posture these are log
Only the beginning is shown; read the rest in the repo