MCP Forge

6 common MCP server mistakes and how to fix them

A practical guide. Updated 2026.

MCP servers are easy to stand up and easy to misconfigure. A server that wraps a real API, touches the filesystem, or listens on a port is a piece of production software, but most get shipped with the security posture of a weekend script. Below are six mistakes that show up again and again in real MCP servers, each with the concrete fix. If you only read one section, make it the first one.

1. A remote server with no authentication

The single most dangerous pattern: an HTTP or SSE transport bound to a public interface with no auth in front of it. Anyone who finds the URL can call every tool you exposed. If one of those tools runs a query, writes a file, or hits an internal API, you have handed that capability to the open internet. A stdio server launched by the client is fine because only the local client can talk to it, but the moment you switch to a network transport you own the access control.

// minimal bearer check on an HTTP MCP transport
app.use((req, res, next) => {
  const token = (req.headers.authorization || "").replace("Bearer ", "");
  if (token !== process.env.MCP_TOKEN) return res.sendStatus(401);
  next();
});

See Authentication for the full flow.

2. Cleartext HTTP for a remote transport

Even with a token, serving over plain http:// means the token and every tool argument and result travel unencrypted. On any shared or untrusted network that is a free credential and a free transcript for whoever is listening. A bearer token sent over cleartext is a bearer token you have already leaked.

# Caddy: HTTPS in front, plain HTTP to the MCP process behind it
mcp.example.com {
  reverse_proxy 127.0.0.1:8080
}

3. Over-broad filesystem roots

Filesystem servers take a set of allowed directories. The lazy choice is the home directory or, worse, /. Now a single tool call can read your SSH keys, your .env files, and your browser data. The model does not need that reach, and a prompt-injected instruction will happily use it.

import { resolve, sep } from "node:path";
const ROOT = resolve("/srv/project");
function safe(p) {
  const full = resolve(ROOT, p);
  if (full !== ROOT && !full.startsWith(ROOT + sep)) {
    throw new Error("path escapes root");
  }
  return full;
}

4. Unpinned runners in client config

Running a server with npx some-mcp-server or uvx against a floating package name means you fetch and execute whatever the latest published version is, every launch. A compromised or hijacked release runs with your full local privileges the next time the client starts. This is supply-chain exposure hiding in a one-line config.

{
  "mcpServers": {
    "fetch": {
      "command": "npx",
      "args": ["-y", "some-mcp-server@1.4.2"]
    }
  }
}

5. Exposing too many tools

Every tool you register costs tokens in the system prompt on every single turn, and each one widens the surface a confused or hijacked model can act through. Servers that dump forty tools into the context make the client slower, more expensive, and easier to misdirect. More tools is not more capable, it is more noise.

Cutting the tool list is also one of the cheapest ways to lower per-turn cost. More on that in Cut token usage.

6. Secrets sitting in config and code

The fast way to give a server its API key is to paste the literal value into the client config or hard-code it next to the fetch call. Both places leak: client config files get synced and backed up, and hard-coded keys get committed. Secrets belong in the environment, injected at launch, never in your source tree.

{
  "mcpServers": {
    "billing": {
      "command": "node",
      "args": ["/opt/billing-mcp/server.js"],
      "env": { "STRIPE_API_KEY": "${STRIPE_API_KEY}" }
    }
  }
}

Catch these before you ship

Every one of these is easy to introduce under deadline and invisible in a quick demo, because the server still works. The free mcp-audit tool scans an MCP project for exactly this list (missing auth, cleartext transports, broad filesystem roots, unpinned runners, and plaintext secrets) so the problem shows up in review instead of in an incident. Run it in CI.

Ship MCP servers without these six mistakes

MCP Forge Kit gives you a server scaffold that is secure by default: token-gated HTTP transport over TLS, scoped filesystem roots, pinned runners, lean tool sets, environment-based secrets, and a CI step running mcp-audit.

Get MCP Forge Kit, €39

Related: Authentication · Write a secure tool · Security checklist