Blog

Secure defaults for MCP servers are concrete engineering choices

Loopback binding, mandatory authentication, bounded outputs, and narrow tool schemas prevent deployment mistakes from becoming incidents.

Armor12 min read

Your quick-start example is somebody else's production configuration next month.

Treat that copy-and-paste path as a supported deployment. The secure option should be visible in the example itself, because many operators will never reach the hardening appendix.

Before publishing the starter template

  • Choose the first transport deliberately. A local stdio server can rely on its process and operating-system context. A shared HTTP listener needs an explicit caller identity and authorization design.
  • Keep local listeners local. Require an intentional change to bind beyond loopback, and show the effective binding at startup.
  • Reject demonstration secrets. A known sample credential should make a protected deployment fail startup.
  • Separate discovery from sensitive actions. Public metadata, where intentionally allowed, should never imply anonymous access to reads, writes, execution, or administration.
  • Scope sessions. Use server-issued identifiers, bind state to the appropriate principal, and expire it.

These choices reduce the number of security decisions each downstream operator must rediscover.

Put limits in the SDK

Every tool author should inherit bounded request bodies, response streams, tasks, sessions, and concurrency. Set sensible ceilings and provide a documented way to change them.

Apply those limits while work is happening. A response-size check after buffering does not protect memory. A session limit that ignores rejected initialization does not bound retained state.

Pair the defaults with one cleanup path for completion, rejection, timeout, cancellation, and disconnect.

Prefer a small tool contract

A tool for exporting a report can accept a report identifier and an approved output location. It rarely needs a shell command, an arbitrary URL, and a caller-selected working directory.

Use enums and structured arguments to keep the action reviewable. Give read, write, delete, package installation, and server registration separate permissions.

When a powerful capability is necessary, make the enablement obvious in configuration and logs. Describe its required credential and network scope.

Test the exact copy path

Install from a clean environment using only the published instructions. Try an anonymous request, an unauthorized tool call, an oversized body, a stalled stream, and a repeated initialization failure.

Then place the service behind the reverse proxy your documentation recommends. Confirm it has not widened the listener, discarded identity, or bypassed resource limits.

Keep example dependencies pinned to reviewed revisions and maintain them with the release. A secure framework paired with an outdated starter can still teach the wrong behavior.

For a deeper look at the memory and lifecycle cases, see resource exhaustion in MCP. The best default is one that stays understandable when an operator has to debug it.

mcpsecure-defaultsdevelopment

See what your own fleet is running

Armor1 discovers and risk-scores every MCP server, skill and tool your developers have connected. Free for personal use, no credit card.

Start Free