Back to blog
GuideMarch 202610 min read

How to Secure Your MCP Server Against
Prompt Injection and Tool Abuse

MCP (Model Context Protocol) is becoming the standard for connecting AI agents to external tools. But MCP servers expose powerful capabilities — file access, database queries, API calls — to any agent that connects. Without runtime security, a prompt-injected agent can abuse your MCP tools to exfiltrate data, modify files, or escalate privileges.

Why MCP servers need security

MCP tools are "execute" primitives. An MCP server that exposes a run_sql tool trusts the agent to send legitimate queries. But agents process untrusted input — user messages, RAG context, other agents' outputs. A single prompt injection can hijack tool calls.

Consider this attack chain: an agent retrieves a poisoned document via RAG. The injection payload tells the agent to call read_file on /etc/passwd. The data gets sent to an attacker via the send_http_request tool. Every step uses legitimate MCP tools. No individual call looks malicious. But the sequence is a full data exfiltration attack.

The attack surface

MCP servers have three primary attack vectors that traditional security tools miss entirely.

01Tool parameter injection

Malicious SQL, file paths, or shell commands embedded in tool arguments. The agent passes user-controlled input directly into tool parameters without sanitization. A query like "SELECT * FROM users; DROP TABLE users;" gets forwarded verbatim to your run_sql tool.

02Cross-tool chaining

A sequence of individually benign tool calls that constitute an attack when combined. Read a file, encode the contents, send an HTTP request to an external server. Each call passes validation on its own. The attack only becomes visible at the session level.

03Schema exploitation

Agents discover and call tools the developer didn't intend to expose. MCP servers advertise their full tool catalog to connecting agents. An injected agent can enumerate available tools and find privileged operations — admin endpoints, write operations, or debug tools left in production.

Adding Rune to your MCP server

Rune's Shield wraps your MCP tool handlers with runtime scanning. Every tool input is scanned before execution, and every output is scanned before it returns to the agent. Here's a Python MCP server with Rune integrated:

server.py — MCP server with Rune Shield
from rune import Shield
from mcp.server import Server

shield = Shield(api_key="rune_live_...")
server = Server("my-secure-server")

@server.tool()
async def run_sql(query: str) -> str:
    """Run a read-only SQL query."""
    # Scan the tool input before execution
    scan = shield.scan_input(query, context={"tool": "run_sql"})
    if scan.blocked:
        return f"Blocked: {scan.threat_type}"

    result = await db.execute(query)

    # Scan the output before returning to the agent
    output_scan = shield.scan_output(str(result))
    if output_scan.blocked:
        return "Output contained sensitive data — blocked"

    return str(result)

The scan_input call runs the query through Rune's scanning pipeline before it touches your database. The scan_output call checks the result for sensitive data before it returns to the agent. Both calls add less than 10ms of latency.

Policy enforcement for MCP

Beyond scanning individual inputs, you can define explicit security policies that restrict which tools can be called, block SQL injection patterns, and prevent file path traversal. Create a rune-policy.yaml file:

rune-policy.yaml
version: "1.0"
rules:
  - name: block-prompt-injection
    scanner: prompt_injection
    action: block
    severity: critical
  - name: block-sql-injection
    scanner: sql_injection
    action: block
    severity: critical
  - name: restrict-file-access
    scanner: path_traversal
    action: block
    severity: high
    config:
      allowed_paths:
        - /data/public/
        - /tmp/reports/
  - name: block-data-exfiltration
    scanner: data_exfiltration
    action: block
    severity: high

Then load the policy when you initialize the Shield:

server.py — with policy
shield = Shield(
    api_key="rune_live_...",
    policy="rune-policy.yaml"
)

Now every tool call is validated against your policy. SQL injection patterns are caught before they reach your database. Path traversal attempts like ../../etc/passwd are blocked at the boundary. And any attempt to exfiltrate data through tool outputs is stopped before it reaches the agent.

Monitoring MCP tool calls

Every tool call that passes through the Shield is logged to your Rune dashboard in real time. You get full visibility into what agents are doing with your MCP tools:

Events

Every tool call with full input/output payloads, timestamps, and the agent session that triggered it.

Blocked threats

Prompt injections, SQL injection attempts, path traversals, and data exfiltration — with the exact payload that was caught.

Session analysis

Behavioral analysis across entire agent sessions. Detects multi-step attack sequences that individual tool scans miss.

The dashboard gives you an audit trail for every MCP tool invocation — essential for compliance and incident response. Sign up to see it in action.

Best practices checklist

Scan every tool input before execution
Scan tool outputs before returning to the agent
Restrict file system access to specific directories
Use parameterized queries, never raw SQL from agent input
Log all tool calls for audit trails
Set explicit tool allow-lists in your security policy
Monitor for cross-tool attack sequences
Review MCP tool descriptions — agents use these to decide what to call

Secure your MCP servers in production

Runtime scanning for every MCP tool call. Prompt injection, SQL injection, path traversal, and data exfiltration caught before they cause damage. Free plan includes 10K events/mo.

How to Secure Your MCP Server Against Prompt Injection and Tool Abuse | Rune