How MCP (Model Context Protocol) is Integrated with Maka for Secret Management

Maka integrates MCP through a dedicated McpClientManager class that automatically harvests secrets from OAuth flows and configuration, maintains a bounded secret inventory for each server, and scrubs every outbound message and error to ensure credentials never leak into logs or UI.

The Apache Maka project implements a secure, end-to-end secret-aware integration with the Model Context Protocol (MCP). This architecture treats secret management as a core concern of the MCP client lifecycle, ensuring that tokens, client secrets, and PKCE verifiers are detected, catalogued, and redacted before any data leaves the process.

The Secret Management Architecture

Maka’s MCP integration follows a five-stage pipeline that operates transparently during normal MCP operations. Each stage is implemented in specific source files and works collectively to prevent secret leakage.

Harvesting Secrets from OAuth and Configuration

When an MCP server connection is established, the McpClientManager immediately begins collecting sensitive values. The manager wraps the supplied OAuth storage with a harvesting proxy (harvestingStorage) that intercepts every token, refresh token, and PKCE code verifier written to storage.

This harvesting occurs in packages/mcp/src/index.ts around lines 306-338. The proxy records every newly observed secret into a per-server cache, ensuring that dynamically obtained credentials (such as OAuth tokens obtained during the session) are captured alongside static configuration secrets.

Building the Secret Inventory

For each connected server, Maka constructs a SecretInventory that aggregates secrets from two sources:

  • Configuration secrets: Static values like client_secret extracted via collectConfigSecrets
  • Harvested secrets: Dynamic values captured from OAuth storage (storedSecrets)

This logic resides in packages/core/src/mcp-secrets.ts. The inventory categorizes secrets into substitutable values (long enough to safely redact) and withheld values (short strings that could be revealed through partial replacement). Secrets shorter than MCP_SECRET_MIN_SUBSTITUTION_LENGTH are withheld rather than scrubbed to prevent information leakage through context clues.

Scrubbing Outbound Data

Every outbound MCP request passes through a scrubbing layer before transmission. The manager invokes scrubKnownMcpSecrets (which delegates to deepScrubMcpSecrets) to recursively scan tool arguments, results, and metadata for any substring matching the secret inventory.

In packages/mcp/src/index.ts (lines 2637-2652), this scrubber replaces known secrets with placeholders or removes them entirely. This guarantees that no secret appears in IPC messages, logging output, or UI tool call previews, even when an MCP server echoes back parameters in its response.

Error Handling with Secret Redaction

When MCP operations throw errors, the manager sanitizes the error chain before propagating exceptions to the rest of the application. The scrubbedError function (invoked around lines 2629-2630 and 2648-2652 in packages/mcp/src/index.ts) processes the error message through the secret inventory and constructs a sanitized cause chain (sanitizedCause).

This ensures that stack traces containing HTTP responses with embedded tokens, or error messages containing sensitive configuration values, are cleaned before reaching logs or crash reporters.

Credential Coordination

The McpCredentialCoordinator class in packages/mcp/src/credential-coordinator.ts mediates all writes to the OAuth storage. By centralizing credential updates, the coordinator ensures that secret harvesting and eviction happen atomically with token refreshes.

This prevents race conditions where a newly refreshed access token could be written to storage but not yet harvested before an error message containing the old token is logged.

Key Implementation Details

Several design decisions in the Maka codebase ensure the secret management system remains performant and safe:

  • Bounded Cache: Each server’s secret inventory is capped at MAX_HARVESTED_SECRETS_PER_SERVER (40 entries). This keeps scrubbing operations O(1) and prevents unbounded memory growth as servers issue new tokens over long-running sessions.

  • Minimum Substitution Length: The constant MCP_SECRET_MIN_SUBSTITUTION_LENGTH (exported from packages/core/src/mcp-secrets.ts) defines the minimum length for a secret to be eligible for substitution. Values shorter than this threshold are completely withheld from output rather than partially redacted.

  • Unified Scrubbing API: The scrubKnownSecrets function from @maka/core/mcp-secrets provides a single entry point used across the entire MCP stack. New code paths automatically inherit secret protection by using this shared utility.

Practical Implementation

The following examples demonstrate how to initialize the MCP client manager and verify that secret scrubbing is active.

Initializing with OAuth Storage

import { McpClientManager } from '@maka/mcp';
import { createMemoryMcpOAuthStorage } from '@maka/mcp';

// Create OAuth storage that automatically harvests secrets
const oauthStorage = createMemoryMcpOAuthStorage();
const mcp = new McpClientManager({ oauthStorage });

// Sync configuration containing a client secret
await mcp.sync({
  version: 1,
  mcpServers: {
    myServer: {
      url: 'https://example.com/mcp',
      clientInformation: {
        client_id: 'my-id',
        client_secret: 'super-secret-value-12345'
      }
    }
  }
});

Calling Tools with Automatic Scrubbing

try {
  // The manager automatically scrubs outbound arguments and inbound results
  const result = await mcp.callTool('mcpb1.myServer.0.xyz', { query: 'hello' });
  console.log(result.content);
} catch (err) {
  // Error messages are pre-scrubbed; no secrets will appear here
  console.error('Tool failed:', err.message);
}

Inspecting the Secret Inventory

For debugging purposes, you can inspect the internal secret inventory to verify what values are being tracked for a specific server:

const inventory = (mcp as any).secretsFor('myServer', {
  clientInformation: {
    client_secret: 'super-secret-value-12345'
  }
});

console.log(inventory);
// Output: { substitute: ['super-secret-value-12345'], withhold: [] }

Summary

  • McpClientManager orchestrates the entire secret lifecycle, from harvesting to scrubbing, in packages/mcp/src/index.ts.
  • SecretInventory aggregates configuration and OAuth secrets while distinguishing between substitutable and withheld values in packages/core/src/mcp-secrets.ts.
  • Automatic scrubbing applies to all outbound messages, tool results, and error objects, ensuring zero secret leakage through logs or IPC.
  • Credential coordination through McpCredentialCoordinator prevents race conditions during token refresh cycles.
  • Bounded caches and minimum length thresholds ensure the system remains performant and does not leak information through short secret fragments.

Frequently Asked Questions

How does Maka prevent short secrets from being leaked through partial redaction?

Maka defines a MCP_SECRET_MIN_SUBSTITUTION_LENGTH constant in the secrets module. Any harvested value shorter than this threshold is categorized as withheld rather than substitutable. The scrubber completely removes these short values from output rather than replacing them with placeholders, preventing attackers from inferring secrets from context or partial matches.

Where does the secret harvesting actually take place in the codebase?

The harvesting logic resides primarily in packages/mcp/src/index.ts, specifically where the McpClientManager wraps the OAuth storage with harvestingStorage (around lines 306-338). This wrapper intercepts all write operations to the OAuth storage, capturing tokens and PKCE verifiers as they are generated or refreshed during the MCP session.

What happens if an MCP server returns a secret in an error message?

When the McpClientManager catches an error from an MCP operation, it passes the error through scrubbedError before re-throwing. This function, implemented in packages/mcp/src/index.ts, scans the error message and cause chain against the current secret inventory. Any matching substrings are redacted or removed, ensuring that even server-generated error messages containing echoed parameters cannot leak credentials.

Is there a limit to how many secrets Maka tracks per server?

Yes. The system enforces a hard limit of MAX_HARVESTED_SECRETS_PER_SERVER (set to 40) to prevent memory exhaustion during long-running sessions with frequently rotating tokens. When this limit is reached, older secrets are evicted from the inventory to make room for newly harvested values, maintaining O(1) lookup performance for the scrubbing operations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →