Skip to content

MCP Gateway

Use any MCP server. We secure the boundary.

The Model Context Protocol (MCP) is the emerging standard for agent-to-tool communication. Triggerfish provides a secure MCP Gateway that lets you connect to any MCP-compatible server while enforcing classification controls, tool-level permissions, taint tracking, and full audit logging.

You bring the MCP servers. Triggerfish secures every request and response that crosses the boundary.

How It Works

The MCP Gateway sits between your agent and any MCP server. Every tool call passes through the policy enforcement layer before reaching the external server, and every response is classified before it enters the agent context.

Agent  -->  MCP Gateway  -->  Policy Layer  -->  MCP Server (any)
                                    |
                              Classification
                              Taint tracking
                              Schema validation
                              Audit logging

The gateway provides five core functions:

  1. Server authentication and classification -- MCP servers must be reviewed and classified before use
  2. Tool-level permission enforcement -- Individual tools can be permitted, restricted, or blocked
  3. Request/response taint tracking -- Session taint escalates based on server classification
  4. Schema validation -- All requests and responses validated against declared schemas
  5. Audit logging -- Every tool call, decision, and taint change is recorded

MCP Server States

All MCP servers default to UNTRUSTED. They must be explicitly classified before the agent can invoke them.

StateDescriptionAgent Can Invoke?
UNTRUSTEDDefault for new servers. Pending review.No
CLASSIFIEDReviewed and assigned a classification level with per-tool permissions.Yes (within policy)
BLOCKEDExplicitly prohibited by admin.No
UNTRUSTED  -->  CLASSIFIED  (admin/user reviews and assigns level)
UNTRUSTED  -->  BLOCKED     (admin determines server is not permitted)
CLASSIFIED -->  BLOCKED     (admin revokes access)

SECURITY

An UNTRUSTED MCP server cannot be invoked by the agent under any circumstances. The LLM cannot request, convince, or trick the system into using an unclassified server. Classification is a code-level gate, not an LLM decision.

Configuration

MCP servers are configured in triggerfish.yaml with classification levels and per-tool permissions:

yaml
mcp_servers:
  - uri: "mcp://salesforce.mcp.example.com"
    name: "Salesforce MCP"
    classification: CONFIDENTIAL
    status: CLASSIFIED
    tools:
      - name: "query_opportunities"
        permitted: true
        requires_user_auth: true
      - name: "delete_record"
        permitted: false  # Blocked by policy
      - name: "export_all"
        permitted: false

  - uri: "mcp://weather-api.mcp.example.com"
    name: "Weather API"
    classification: PUBLIC
    status: CLASSIFIED
    tools:
      - name: "*"  # All tools permitted
        permitted: true

  - uri: "mcp://unknown-server.example.com"
    status: UNTRUSTED  # Pending review

Each server entry specifies:

  • uri -- The MCP server endpoint
  • classification -- The data sensitivity level assigned to this server
  • status -- The current server state (CLASSIFIED, UNTRUSTED, or BLOCKED)
  • tools -- Per-tool permission configuration (use "*" for all tools)
  • requires_user_auth -- Whether the tool requires user credential passthrough

Tool Call Flow

When the agent requests an MCP tool call, the gateway executes a deterministic sequence of checks before forwarding the request.

1. Pre-Flight Checks

All checks are deterministic -- no LLM calls, no randomness.

CheckFailure Result
Server status is CLASSIFIED?Block: "Server not approved"
Tool is permitted for this server?Block: "Tool not permitted"
User has required permissions?Block: "Permission denied"
Session taint compatible with server classification?Block: "Would violate write-down"
Schema validation passes?Block: "Invalid parameters"

INFO

If the session taint is higher than the server classification, the call is blocked to prevent write-down. A session tainted at CONFIDENTIAL cannot send data to a PUBLIC MCP server.

2. Execute

If all pre-flight checks pass, the gateway forwards the request to the MCP server.

3. Response Processing

When the MCP server returns a response:

  • Validate the response against the declared schema
  • Classify the response data at the server's classification level
  • Update session taint: taint = max(current_taint, server_classification)
  • Create a lineage record tracking the data origin

4. Audit

Every tool call is logged with: server identity, tool name, user identity, policy decision, taint change, and timestamp.

Response Taint Rules

MCP server responses inherit the server's classification level. Session taint can only escalate.

Server ClassificationResponse TaintSession Impact
PUBLICPUBLICNo taint change
INTERNALINTERNALTaint escalates to at least INTERNAL
CONFIDENTIALCONFIDENTIALTaint escalates to at least CONFIDENTIAL
RESTRICTEDRESTRICTEDTaint escalates to RESTRICTED

Once a session is tainted at a given level, it stays at that level or higher for the remainder of the session. A full session reset (which clears conversation history) is required to reduce taint.

User Authentication Passthrough

For MCP servers that support user-level authentication, the gateway passes through the user's delegated credentials rather than system credentials.

When a tool is configured with requires_user_auth: true:

  1. The gateway checks whether the user has connected this MCP server
  2. Retrieves the user's delegated credential from the secure credential store
  3. Adds user authentication to the MCP request headers
  4. The MCP server enforces user-level permissions

The result: the MCP server sees the user's identity, not a system identity. Permission inheritance works through the MCP boundary -- the agent can only access what the user can access.

TIP

User auth passthrough is the preferred pattern for any MCP server that manages access control. It means the agent inherits the user's permissions rather than having blanket system access.

Schema Validation

The gateway validates all MCP requests and responses against declared schemas before forwarding:

typescript
// Request validation (simplified)
function validateMcpRequest(
  serverConfig: McpServerConfig,
  toolName: string,
  params: Record<string, unknown>,
): Result<void, McpError> {
  const toolSchema = serverConfig.getToolSchema(toolName);

  if (!toolSchema) {
    return err(new McpError("Unknown tool"));
  }

  // Validate params against JSON schema
  if (!validateJsonSchema(params, toolSchema.inputSchema)) {
    return err(new McpError("Invalid parameters"));
  }

  // Check for injection patterns in string params
  for (const [, value] of Object.entries(params)) {
    if (typeof value === "string" && containsInjectionPattern(value)) {
      return err(new McpError("Potential injection detected"));
    }
  }

  return ok(undefined);
}

Schema validation catches malformed requests before they reach the external server and flags potential injection patterns in string parameters.

Enterprise Controls

Enterprise deployments have additional controls for MCP server management:

  • Admin-managed server registry -- Only admin-approved MCP servers can be classified
  • Per-department tool permissions -- Different teams can have different tool access
  • Compliance logging -- All MCP interactions available in compliance dashboards
  • Rate limiting -- Per-server and per-tool rate limits
  • Server health monitoring -- Gateway tracks server availability and response times

Released under the MIT License.