SimplaixSimplaix Gateway
Concepts

MCP Access Control

Provider-level ACL and tool-level policies that govern which agents and users can access MCP tools through the Gateway.

The Gateway enforces a two-tier access control model for every MCP tool call:

  1. Provider-level ACL -- can this subject (agent or user) access the provider at all?
  2. Tool-level policy -- which specific tools within that provider can they call, and under what conditions?

Subjects

Access rules are scoped to a subject -- the entity making the request:

Subject typeDescriptionDefault behavior
userAn individual end-user (by user ID)Deny (whitelist model)
agentA registered agent (by agent ID)Deny (whitelist model)

All subjects are denied access to all providers by default. An admin must explicitly grant access to each provider by creating allow (or require_confirmation) rules. This whitelist model ensures no provider is accidentally exposed without deliberate configuration.

Provider-Level ACL

Each rule grants or denies a subject access to a provider:

{
  "subjectType": "agent",
  "subjectId": "agent-abc123",
  "providerId": "slack-provider-id",
  "action": "allow",
  "toolPattern": "*"
}

Evaluation Order

When multiple rules match, the Gateway evaluates in this order (first match wins):

  1. Explicit user deny → denied
  2. Explicit user allow/require_confirmation → allowed
  3. Explicit agent deny → denied
  4. Explicit agent allow/require_confirmation → allowed
  5. Wildcard (*) provider rules
  6. Default → deny for all subjects (whitelist model)

Tool-Level Policies

Each access rule includes a toolPattern (glob syntax) and an action that controls what happens when a matching tool is called:

ActionBehavior
allowTool call goes through immediately
denyTool call is rejected with 403
require_confirmationTool call is paused until a human confirms or rejects it (see Confirmations)

Glob Patterns

Tool patterns use glob syntax to match tool names:

PatternMatches
*All tools in the provider
slack_send_*slack_send_message, slack_send_file, etc.
github_read_*github_read_repo, github_read_issue, etc.
transfer_moneyExactly transfer_money

Risk Levels

Each rule can optionally specify a riskLevel for categorization and audit:

Risk LevelDescription
lowRead-only operations
mediumWrite operations
highFinancial or sensitive operations
criticalDestructive operations

Policy Specificity

When multiple tool-level rules match the same tool call, the most specific rule wins. Specificity is scored by:

  1. Tool specificity -- exact name beats glob pattern beats wildcard (*)
  2. Subject specificity -- user beats agent
  3. Action severity -- deny beats require_confirmation beats allow

Configuration

Via the Dashboard

  1. Go to the Agents tab and click an agent card to open the Agent Detail Panel
  2. Each provider shows a toggle and a tool selector:
    • Toggle a provider to enabled to grant access
    • Select all tools or pick specific ones
  3. Click Save Changes

Changes take effect immediately -- the tool aggregation cache refreshes within 60 seconds.

Via the API

List rules for an agent:

GET /api/v1/admin/provider-access?subject_type=agent&subject_id={agentId}

Bulk upsert rules for an agent:

curl -X PUT https://<your-gateway-url>/api/v1/admin/provider-access/agent/<agent-id> \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "rules": [
      { "providerId": "slack-id", "action": "allow", "toolPattern": "*" },
      { "providerId": "github-id", "action": "allow", "toolPattern": "github_read_*" },
      { "providerId": "stripe-id", "action": "require_confirmation", "toolPattern": "stripe_charge_*", "riskLevel": "high" }
    ]
  }'

Create a single rule:

curl -X POST https://<your-gateway-url>/api/v1/admin/provider-access \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "subjectType": "agent",
    "subjectId": "<agent-id>",
    "providerId": "<provider-id>",
    "action": "allow",
    "toolPattern": "slack_read_*",
    "riskLevel": "low"
  }'

Test policy evaluation (dry run):

curl -X POST https://<your-gateway-url>/api/v1/admin/provider-access/evaluate \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-id",
    "providerId": "slack-id",
    "toolName": "slack_send_message",
    "agentId": "agent-id"
  }'
# Response: { "action": "require_confirmation", "risk": "high", "matchedRule": { ... } }

If there are zero DB rules available for evaluate, the gateway falls back to src/config.ts policy rules. If DB rules exist but none match the tool pattern, the result is deny. In normal MCP proxy/unified flows, provider-level ACL still gates access first (default deny).

Examples

Read-only agent

Allow an agent to list and read from all providers, but deny any write operations:

[
  { "providerId": "slack-id", "action": "allow", "toolPattern": "slack_list_*" },
  { "providerId": "slack-id", "action": "allow", "toolPattern": "slack_get_*" },
  { "providerId": "slack-id", "action": "deny", "toolPattern": "*" },
  { "providerId": "github-id", "action": "allow", "toolPattern": "github_read_*" },
  { "providerId": "github-id", "action": "deny", "toolPattern": "*" }
]

Because more specific patterns win over wildcards, slack_list_* (allow) takes priority over * (deny).

Confirmation-gated agent

Allow an agent full read access but require human confirmation for writes:

[
  { "providerId": "slack-id", "action": "allow", "toolPattern": "slack_list_*" },
  { "providerId": "slack-id", "action": "require_confirmation", "toolPattern": "slack_send_*", "riskLevel": "medium" },
  { "providerId": "stripe-id", "action": "require_confirmation", "toolPattern": "*", "riskLevel": "high" }
]

On this page