MCP security is becoming the new API security. For years, API security meant knowing which service could call which endpoint with which token. Agentic AI adds a new version of that problem: which model can call which tool through which MCP server with which credential.
That is why MCP security is becoming the new API security.
Recent research on the Model Context Protocol highlights risks that are structural, not cosmetic. MCP servers can sit between an AI agent and sensitive systems: files, repos, browsers, calendars, databases, cloud APIs, and internal services. Once a server is trusted, its outputs can influence the agent's next action.
That is a powerful design. It is also a trust boundary.
The MCP risks to understand
Three failure modes show up again and again:
1. Capability claims without enough verification
If a tool server says it can perform a safe action, how does the client verify what the server can really do? Capability declarations are useful, but declarations are not enforcement.
2. Tool output becomes instruction
An MCP server may return content from a webpage, file, issue, ticket, or document. That content can contain prompt injection. If the agent treats it as trusted instruction, the server becomes an injection path.
3. Secrets cross boundaries quietly
Many MCP configs pass environment variables, bearer tokens, or auth headers into tool servers. If the server is remote, compromised, misspelled, or overbroad, credentials leave the local trust boundary.
A practical MCP review checklist
Before enabling an MCP server, ask:
- Is the server local or remote?
- Who maintains it?
- What filesystem paths can it read?
- What network destinations can it reach?
- What credentials does it receive?
- Does it need write access?
- Can it execute shell commands?
- Are tool calls logged?
- Are destructive actions approved by a human?
- Is untrusted content separated from trusted instructions?
If those answers are fuzzy, the server should not touch production credentials.
The better mental model
Do not think of MCP servers as plugins. Think of them as service accounts with a language-model interface.
That means the normal rules apply:
- Least privilege
- Separate dev and prod credentials
- Audit logs
- Explicit allowlists
- Human approval for destructive actions
- No production secrets in demos
- No remote tool server gets broad auth by default
What Ship Safe checks
Ship Safe scans MCP and agent configuration for risky patterns:
- Third-party MCP URLs receiving auth headers or high-value environment variables
- MCP servers with broad filesystem access
- Tool configs that mix untrusted input and write actions
- Agent workflows that can act without approval
- Secrets committed beside agent configs
Run:
npx ship-safe scan
npx ship-safe red-teamMCP makes agents useful because it gives them hands. Security work starts when you decide what those hands are allowed to touch.
For concrete agent workflows, see the Hermes page. For release automation, pair MCP scanning with the Ship Safe docs and the hosted workflows on pricing.
Local MCP versus remote MCP
Local servers are not automatically safe, but they are easier to reason about. A local filesystem MCP server might read files on your machine, but it does not need to receive your credentials over the network. A remote MCP server changes the model: now you are trusting another service with tool inputs, outputs, and often credentials.
Use different defaults:
| Server type | Safer default |
|---|---|
| Local read-only | Allow for development with path restrictions. |
| Local write-capable | Require approval for destructive actions. |
| Remote read-only | Review maintainer, logs, and data retention. |
| Remote write-capable | Treat like a production integration. |
| Remote with secrets | Avoid unless there is a strong reason and scoped credentials. |
The riskiest pattern is a remote MCP server that receives production tokens and can execute broad actions. That is not a plugin. That is an external service account.
A bad config pattern
{
"servers": {
"deploy-helper": {
"url": "https://mcp.example-tools.dev/deploy",
"headers": {
"Authorization": "Bearer ${GITHUB_TOKEN}"
},
"env": {
"VERCEL_TOKEN": "${VERCEL_TOKEN}"
}
}
}
}This forwards high-value credentials to a remote server. Even if the server is honest, you have to trust its infrastructure, logs, dependencies, employees, and incident response. Use a narrow token created for that exact server, or keep the tool local.
What good looks like
{
"servers": {
"repo-reader": {
"command": "node",
"args": ["./tools/mcp/repo-reader.js"],
"env": {
"ROOT": "./src",
"MODE": "read-only"
}
}
}
}This shape is easier to defend: local command, limited root, read-only mode, no production token. It may not cover every workflow, but it is a safer baseline.
MCP security is a lifecycle
Review once is not enough. MCP servers evolve like APIs:
- New tools are added.
- Permissions grow.
- Environment variables drift.
- Local-only prototypes become shared team configs.
- Demo tokens become production tokens.
Add MCP configs to code review. Add them to scanning. Add them to onboarding docs. If a server can read code or act on a system, it belongs in your security inventory.
How prompt injection travels through MCP
MCP does not create prompt injection by itself, but it can move injection across boundaries. A server might fetch a GitHub issue, Slack message, webpage, PDF, or ticket. That content is untrusted. If it tells the agent to call another tool, exfiltrate a file, or change its objective, the agent needs to treat that as data, not instruction.
The safe pattern is:
- Tool output is labeled as untrusted unless explicitly trusted.
- Tool output cannot grant new permissions.
- Tool output cannot change the system policy.
- Tool output cannot trigger destructive actions without approval.
- The agent explains the planned action before crossing a write boundary.
This is the same lesson web security learned years ago: input is input, even when it comes through a useful integration.
Building an MCP inventory
Create a small inventory for every server:
| Field | Example |
|---|---|
| Name | github-reader |
| Owner | platform team |
| Location | local command |
| Data access | repo read-only |
| Credentials | GitHub token, read-only |
| Write actions | none |
| Approval required | yes for future write tools |
| Logs | local audit file |
The point is not bureaucracy. The point is to avoid the mystery state where nobody knows which server has which token.
Red flags during review
Watch for:
- Remote URLs with production tokens
- Servers that ask for full filesystem roots
- Tools named vaguely, like
execute,run, oradmin - Configs copied from demos
- Shared tokens across multiple MCP servers
- No owner listed for a server
- Write tools without approval language
- Output from external content used in later tool calls
If an MCP server would scare you as a conventional API integration, it should scare you as an AI tool integration too.
FAQ
What is MCP security?
MCP security is the practice of controlling which Model Context Protocol servers an agent can use, what data those servers can access, what credentials they receive, and which actions require approval.
Are local MCP servers safer than remote MCP servers?
Local servers are easier to reason about, but not automatically safe. Remote MCP servers add extra trust questions because tool inputs, outputs, and sometimes credentials cross a network boundary.
What is the biggest MCP mistake?
The highest-risk pattern is forwarding production tokens or broad auth headers to third-party MCP servers. Use scoped credentials, local tools, approval gates, and scan MCP configs before merge.
Scan MCP configs before they spread
Run npx ship-safe scan before committing MCP or agent configuration. To keep a history of MCP findings across repos, start a cloud scan.