Skip to main content

Connect an MCP Server

Tasks

Register an upstream MCP server and choose how AIControls authenticates to it. For how MCP tool-call proxying and authorization work conceptually, see MCP Governance.

Register the server

  1. Go to Inventory → MCP Servers → Registration tab → Add MCP Server.
  2. Fill in the server fields:

    FieldDescription
    NameUsed as a tool prefix in agent calls, e.g. prometheus → tool prometheus__query
    Typehttp (remote server) or stdio (local command)
    TransportFor http servers: SSE (legacy, and what most MCP servers speak) or Streamable HTTP (FastMCP 3.x and any server built against the 2025-03-26 MCP spec). Use Detect settings from URL if you aren't sure.
    URL / CommandMCP server endpoint or shell command
    AuthenticationSee Choose an authentication method below
tip

Pick Streamable HTTP for servers with slow tools, and for any tool that isn't safe to run twice.

SSE holds one long-lived connection, so AIControls probes it with a short timeout to tell a stalled connection apart from a working one. A tool that takes longer than 15 seconds to reply is treated as a possibly-dead connection: the call is abandoned and retried on a fresh connection. If the server had in fact received the first call, the tool runs twice — which matters for anything that isn't idempotent, such as creating a ticket, sending a message, or committing a change.

Streamable HTTP sends each tool call as an independent request, so there is no connection to go stale, no probe, and no retry. A tool may take as long as the calling client's own request deadline allows, and it is invoked exactly once.

note

Developers don't configure MCP servers themselves — they're provisioned centrally and available to all agents automatically based on group membership policies.

Choose an authentication method

Each MCP server can be configured with one of seven authentication methods. The right choice depends on whether the upstream server has shared credentials, per-developer credentials, or an OAuth-capable identity layer.

No credentials are forwarded.

When to use: Internal servers on a private network that trust all proxy traffic implicitly.

Two more fields appear on the form for several of the methods above, regardless of which is selected:

FieldApplies toDescription
Discovery tokenPassthrough, Per-developer (credential store), OAuth 2.0, Cross-App AccessOptional. A one-time bearer token used only to list tools from the upstream during registration — not stored afterward. Leave blank to register with zero tools discovered; the count populates once a developer makes a real call
Connection instructionsAll per-developer methodsOptional guidance shown to developers in Connected Accounts before they connect their own credential or OAuth account. Most useful for Per-developer (credential store), where developers need to know how to generate the credential you expect

Test the connection while adding a server

Before saving, click Test connection in the Add/Edit MCP Server drawer to run the standard MCP discovery sequence (initialize, then tools/list, prompts/list, resources/list) against the form's current values, without registering or persisting anything. The result shows the tool/prompt/resource counts, or an error per category.

Discovery — whether run from Test connection, on save, or by a later Refresh — is bounded by a 30-second deadline. An upstream that accepts the connection but never responds fails with a clear scan timed out error instead of leaving the request hanging.

The same 30-second bound applies to the proxy's own connection handshake when a developer's first tool call opens a session to the upstream — the call fails with a clear connection-timeout error rather than hanging. Only the handshake is bounded: a healthy server's tool call may still run as long as it needs (streaming responses are never capped).

For a Cross-App Access server, Test connection uses your own linked enterprise identity (see Link your enterprise identity) to run the real two-leg ID-JAG exchange, if you've linked one — the same exchange a developer's tool call would trigger — rather than substituting a discovery token. The result tells you which happened:

ResultMeaning
✓ Real Cross-App Access exchange validatedYou have a linked identity; the test ran the actual leg-1 + leg-2 exchange against the IdP and Resource Authorization Server and reached the upstream with a real access token
Discovery only — link your identity to validate the real exchangeYou haven't linked an enterprise identity yet, so the test fell back to the Discovery token (or an unauthenticated connection) instead of a real exchange

Test your connection as a developer

For any per-developer authentication method (Passthrough, Per-developer credential store, OAuth 2.0, or Cross-App Access), once you've connected your own credential in Connected Accounts, click Scan next to the server to run a live check with that credential. AIControls calls the standard MCP discovery sequence — initialize, then tools/list, prompts/list, and resources/list — and shows you exactly what your credential can currently reach: the tools, prompts, and resources the upstream server returns, or an error for any category the credential can't access.

This is useful for confirming a new OAuth connection or stored credential actually grants the access you expect, without needing to make a real tool call from an agent first.

note

The Scan button only appears once you've connected a credential for that server — it reflects your access, not the server's discovery-token connection used at registration time.

Resolve a quarantined server

When AIControls sees tool-call traffic to a server that isn't configured as a datasource, it automatically creates a quarantined catalog entry and sends a one-time admin alert — see Shadow MCP traffic & quarantine for why this happens. Resolving it is one of two actions:

  1. Go to Inventory → MCP Servers → Registration tab and find the entry marked Quarantined — it shows the endpoint AIControls observed traffic to and when it was first seen.
  2. Choose how to resolve it:

    ActionEffect
    PromoteRuns the same flow as registering a server manually — confirm the endpoint, transport, and authentication. The entry then becomes a normal governed server: ownable, policy-able, and eligible for Access Bindings.
    DenyThe entry is kept for audit history with quarantine_state: denied; further tool calls to that endpoint are blocked by policy.
  3. Save. There's no third option — an unresolved quarantined entry stays audit-only (logged, but ungoverned) until an admin picks one.
note

Quarantine is a one-time alert per newly discovered server, not a repeating notification — if you miss it, find outstanding entries by filtering Inventory → MCP Servers → Registration tab for the Quarantined state.

Write a tool-authorization policy

Use object.mcp.tool to match tool calls. Arguments are available as object.mcp.arguments:

Block file writes outside the workspace

apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata:
name: restrict-write-file
spec:
matchConditions:
- expression: 'object.mcp.tool == "write_file"'
validations:
- expression: |
object.mcp.arguments.path.startsWith("/home/") ||
object.mcp.arguments.path.startsWith("/workspace/")
message: "write_file is only permitted inside /home/ or /workspace/"
validationActions: [Deny]

Audit all bash commands

apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata:
name: audit-bash
annotations:
proxy.nirmata.io/enforcement-mode: audit
spec:
matchConditions:
- expression: 'object.mcp.tool == "bash"'
validations:
- expression: 'true'
message: "bash call recorded"
validationActions: [Audit]

Block destructive commands

apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata:
name: block-destructive-bash
spec:
matchConditions:
- expression: 'object.mcp.tool == "bash"'
validations:
- expression: |
!object.mcp.command.matches("(rm -rf|DROP TABLE|truncate)")
message: "Destructive command blocked by policy"
validationActions: [Deny]

See also