Claude Code Internal MCP Servers: Connect Without Exposing Credentials

Claude Code Internal MCP Servers: Connect Without Exposing Credentials
Bifrost centralizes MCP authentication for Claude Code, keeping API keys, bearer tokens, and OAuth credentials out of developer configs and environment files while giving every consumer scoped access to exactly the tools they need.

Connecting Claude Code to internal MCP servers creates a credential exposure problem that most teams discover the hard way. The default approach, placing API keys and service tokens directly in settings.json or environment variables, means credentials travel with developer workstations, get committed to dotfiles repos, and proliferate across every machine that runs the agent. Bifrost, the open-source AI gateway built in Go by Maxim AI, solves this by sitting between Claude Code and every internal MCP server: credentials stay on the gateway, and Claude Code receives only a scoped virtual key.

Why Credential Exposure Is a Real Risk for MCP Deployments

Claude Code connects to MCP servers to read files, query databases, call internal APIs, and execute business logic. Each of those connections needs authentication. The straightforward path is to embed credentials in the developer's local config.

That approach has three structural problems:

  • Blast radius: a single leaked developer workstation exposes every service the developer was authorized to use
  • No rotation path: credentials baked into config files are rarely rotated because the rotation requires updating every developer's machine
  • No audit trail: when a shared static token is used, you cannot determine which developer (or which AI agent invocation) executed a given tool call

Security researchers analyzing MCP deployments in production have found that roughly 38% of MCP servers in enterprise environments are from unofficial sources, and a measurable fraction contain hardcoded credentials that function as traps for developers who connect real keys. The attack surface grows with every new MCP server added to a developer's config.

The correct architecture is to centralize credential storage on a gateway, issue developers short-lived scoped keys, and enforce access control per consumer. That is exactly what Bifrost's MCP gateway is designed to do.

How Bifrost Handles MCP Authentication Centrally

Bifrost sits between Claude Code and every upstream MCP server. It stores credentials, handles token refresh, and enforces access control. The developer's settings.json contains only a Bifrost virtual key, which carries no inherent permissions to any backend system.

Five Authentication Modes for Upstream MCP Servers

Bifrost supports five authentication types for connecting to external MCP servers:

  • None: for STDIO connections running local processes with no network auth required
  • Headers: static API keys, bearer tokens, or custom headers, stored in Bifrost and injected at tool execution time
  • OAuth 2.0: admin-level shared OAuth token with automatic refresh, PKCE support, and dynamic client registration
  • Per-User OAuth: each developer authenticates with their own credentials via a consent flow; Bifrost stores tokens per identity
  • Per-User Headers: each developer provides their own header values (tenant IDs, user tokens) through a Bifrost-hosted form

For most internal API use cases, headers auth is the right starting point. The credential is configured once on the gateway and never leaves it:

{
  "name": "internal_crm",
  "connection_type": "http",
  "connection_string": "<https://crm-mcp.internal.example.com/mcp>",
  "auth_type": "headers",
  "headers": {
    "Authorization": "Bearer your-service-token",
    "X-Tenant-ID": "production"
  },
  "tools_to_execute": ["get_customer", "list_accounts"]
}

The Authorization and X-Tenant-ID values are stored in Bifrost. Claude Code, configured to point at Bifrost, never sees them.

For sensitive values, Bifrost supports environment variable references in the connection string and header values using the env.VARIABLE_NAME syntax, so even the gateway config file does not contain plaintext credentials.

Referencing Secrets Without Storing Them in Config

When you deploy Bifrost with a secrets manager, you can inject credentials at runtime without writing them to disk:

{
  "name": "data_warehouse",
  "connection_type": "http",
  "connection_string": "env.DW_MCP_URL",
  "auth_type": "headers",
  "headers": {
    "Authorization": "env.DW_SERVICE_TOKEN"
  },
  "tools_to_execute": ["*"]
}

Bifrost resolves env.DW_MCP_URL and env.DW_SERVICE_TOKEN at startup, validates that all required variables are present, and redacts them from API responses and the management UI. The secrets manager, whether HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault, is the source of truth. Bifrost reads from it; Claude Code never touches it. Bifrost Enterprise includes native vault support for each of these providers.

Scoping Access with Virtual Keys

The second half of the credential isolation problem is ensuring that different developers, teams, or agent invocations access only the tools they are authorized to use.

Bifrost's virtual keys are the primary governance entity. Each virtual key can be configured with:

  • An explicit list of MCP servers it can access
  • Tool-level filtering within each server
  • Spend budgets and rate limits
  • Expiration dates for short-lived credentials

A developer running Claude Code connects to Bifrost using their virtual key. The gateway evaluates what that key is permitted to access and presents Claude Code with only those tools.

{
  "virtual_key": "sk-bf-dev-alice-xxxx",
  "mcp_servers": ["internal_crm", "knowledge_base"],
  "budget": { "daily_usd": 10 },
  "rate_limit": { "rpm": 60 }
}

Alice's Claude Code session can call internal_crm and knowledge_base tools. It cannot call data_warehouse tools even if that server is registered on the same Bifrost instance. The restriction is enforced at the gateway, not in Alice's client config. MCP tool filtering per virtual key gives you tool-level granularity within each server.

For enterprise teams provisioning access at scale, access profiles let you define reusable permission templates that automatically allocate virtual keys with the correct MCP server lists, budgets, and rate limits when a new user is provisioned.

Connecting Claude Code to the Bifrost MCP Gateway

Once your upstream MCP servers are registered in Bifrost with their credentials, Claude Code connects to a single Bifrost endpoint. All tool discovery, execution, and authentication flow through that endpoint.

Claude Code's settings.json configuration is minimal:

{
  "env": {
    "ANTHROPIC_BASE_URL": "<http://your-bifrost-instance:8080/anthropic>",
    "ANTHROPIC_AUTH_TOKEN": "sk-bf-dev-alice-xxxx"
  }
}

The ANTHROPIC_AUTH_TOKEN is Alice's virtual key. It authenticates her to Bifrost; Bifrost handles authentication to every upstream MCP server on her behalf.

When Claude Code is configured to use Bifrost as an MCP gateway endpoint, it can also be pointed at Bifrost's /mcp endpoint directly, which exposes all registered tools through a single aggregated MCP server:

{
  "mcpServers": {
    "bifrost": {
      "url": "<http://your-bifrost-instance:8080/mcp>",
      "headers": {
        "Authorization": "Bearer sk-bf-dev-alice-xxxx"
      }
    }
  }
}

Claude Code connects once, discovers all tools Alice is authorized to use, and has no visibility into which upstream servers back each tool or what credentials those servers require.

Forwarding Per-Request Context Without Exposing Service Credentials

Some internal APIs require per-request context that varies by caller: a user token for data-plane authorization, a tenant ID for multi-tenant services, or a trace ID for observability. Bifrost's allowed_extra_headers feature handles this without requiring developers to know the upstream credentials.

You configure which headers a given MCP client will accept from callers:

{
  "name": "internal_crm",
  "connection_type": "http",
  "connection_string": "<https://crm-mcp.internal.example.com/mcp>",
  "auth_type": "headers",
  "headers": {
    "Authorization": "Bearer service-level-token"
  },
  "allowed_extra_headers": ["x-user-token", "x-tenant-id"],
  "tools_to_execute": ["*"]
}

The static Authorization header (the service-level credential) is managed by Bifrost and injected on every tool call. The x-user-token and x-tenant-id values are forwarded only when the caller provides them, and only if they appear in that client's allowlist. Each client enforces its own allowlist at execution time, so a header allowed for the CRM server is not automatically forwarded to the data warehouse server.

The developer's Claude Code session passes these headers in the inference request. The service-level credential is never visible to the developer.

Per-User OAuth for Personal Integrations

When internal tools require developers to authenticate with their own identity (for audit trail purposes, or because the backing API enforces per-user authorization), Bifrost's per-user OAuth flow handles the consent and token storage without requiring developers to manage tokens themselves.

On the first tool call to a per-user OAuth server, Bifrost returns an mcp_auth_required URL. The developer opens that URL, completes the OAuth consent flow with the upstream provider, and Bifrost stores the resulting token against their identity. Subsequent tool calls execute normally. Token refresh is automatic.

This means developers authenticate with their own credentials once, through a governed flow, and Bifrost enforces that each developer can only act within the scope they were granted by the upstream system.

Audit Trails and Observability

With credentials centralized on the gateway, every tool call passes through a single point where it can be logged with full context. Bifrost captures which virtual key made the request, which tool was called, what parameters were passed, and what the upstream returned.

For regulated environments, audit logs produce immutable trails that support SOC 2 Type II, GDPR, HIPAA, and ISO 27001 requirements. Log exports can deliver this data to S3, GCS, BigQuery, or your existing data lake.

Secrets detection guardrails can scan prompts and completions for API keys, tokens, and credentials before they reach upstream systems, providing a second layer of protection against accidental credential leakage in agent outputs.

Enterprise Deployment: Keeping Everything Inside the Network Boundary

For teams with strict network segmentation requirements, Bifrost supports in-VPC deployment so the gateway runs inside your private cloud infrastructure. Claude Code connects to a Bifrost instance that has no public internet exposure. Internal MCP servers are reachable from Bifrost by private DNS, and no credentials or tool traffic cross the public internet.

The Bifrost Enterprise page covers deployment options including air-gapped configurations and on-premises infrastructure for teams that cannot use cloud-hosted gateways.

Centralize Credentials Once, Govern Access Everywhere

The correct model for Claude Code and internal MCP servers is not to distribute credentials to every developer's machine. It is to register each internal server once on Bifrost, configure the right authentication type, and issue developers virtual keys that carry exactly the access they need.

The MCP gateway documentation covers the full set of authentication modes, virtual key configuration, and tool filtering options. For teams running multiple Claude Code users against a shared set of internal tools, the governance and audit capabilities in Bifrost Enterprise remove the operational overhead of per-machine credential management.

To see how Bifrost can centralize MCP authentication for your Claude Code deployments, book a demo with the Bifrost team.