mcpd

repository·main·Indexed 41 days ago

https://github.com/mozilla-ai/mcpd

A daemon that manages Model Context Protocol (MCP) servers via declarative configuration, exposing them as HTTP endpoints. It handles lifecycle management, secret injection, and environment promotion, bridging AI agents and infrastructure. It includes a CLI for managing .mcpd.toml projects and official SDKs for Python, JavaScript, Go, and .NET.

Tokens
33.2K
Snippets
143
Records
180
Agent score
51%

What's inside mcpd

  1. Overview of mcpd

    main
    mcpd is a toolchain and runtime designed to simplify the configuration, execution, and integration of Model Context Protocol (MCP) servers with agentic applications. It provides a unified experience across local development and production environments by handling cross-language server orchestration, secrets management, version pinning, and lifecycle control via a single daemon.
  2. What is an mcpd plugin?

    main

    An mcpd plugin is a standalone executable that the mcpd daemon launches as a child process. Communication occurs over gRPC using a Unix socket.

    Because plugins are not shared libraries loaded into the daemon, they can be written in any language that supports gRPC. The plugin's primary contract is to bind to the socket provided by mcpd and implement the Plugin service defined in mcpd-proto (mozilla.mcpd.plugins.v1).

  3. Mutate request or response payloads with content plugins

    main

    Only plugins in the content category are permitted to mutate (modify) requests or responses. Other categories (like authentication or validation) can only observe or reject the traffic. Modified content from a content plugin is passed sequentially to the next plugin in the chain.

    [[plugins.content]]
      name = "encryption"
      flows = ["request", "response"]
  4. Understand optional plugin behavior and rejections

    main

    When a plugin is not marked as required (or is explicitly set to false):

    1. Crashes/Exceptions: These are logged as warnings, and the pipeline continues.
    2. Rejections (returning Continue=false): The pipeline stops processing and respects the rejection, except for the observability category.

    Observability Exception: Because observability plugins run in parallel, the pipeline ignores their rejections to ensure the main request flow is not interrupted by monitoring issues.

  5. Understand plugin category constraints

    main

    The category assigned to a plugin in .mcpd.toml dictates its permissions regarding request/response mutation:

    CategoryConstraint
    contentThe only category permitted to mutate a request or response.
    observabilityRuns in parallel with other observability plugins; may not mutate.
    All othersMay observe or reject, but not mutate.

    If a plugin in a non-content category attempts to return modified content, those modifications will not be applied.

  6. How plugin categories and execution order work

    main

    The mcpd daemon uses a plugin subsystem organized into categories. Plugins execute in a specific order based on their category during both the request and response phases. Within a single category, plugins execute in the order they are defined in the configuration file.

    Category Execution Order:

    1. observability: Collect metrics/traces (runs in parallel, non-blocking).
    2. authentication: Validate client identity (sequential).
    3. authorization: Verify permissions (sequential).
    4. rate_limiting: Enforce rate limits (sequential).
    5. validation: Check structure and content (sequential).
    6. content: Transform payloads (sequential; only this category can mutate requests/responses).
    7. audit: Log compliance and security events (sequential).
  7. Handle required plugin failures

    main

    If a plugin is marked as required = true and fails, mcpd rejects the request with an HTTP 500 Internal Server Error.

    To identify where the failure occurred, check the Mcpd-Error-Type response header:

    • request-pipeline-failure: The plugin failed during request processing (before the upstream call).
    • response-pipeline-failure: The plugin failed during response processing (after the upstream call).

    Note on Response Pipeline: The response pipeline runs on all upstream responses, regardless of the status code (e.g., 200 OK or 500 error), ensuring security and audit plugins always execute.

  8. Environment variable visibility during hot reload

    main

    The mcpd process can only see environment variables that existed when it initially started.

    • Shell Expansion: When reloading a config, ${VAR} syntax will expand using the environment available to the running mcpd process.
    • New Variables: If you export a new variable in your shell (e.g., export NEW_VAR=val) after mcpd is already running, mcpd will not see it during a hot reload. You must restart the daemon for new system environment variables to be recognized.
  9. How hot reloading works in mcpd

    main

    The mcpd daemon supports hot-reloading of MCP server configurations (via --config-file) and execution contexts (via --runtime-file) without a full restart.

    Triggering a Reload

    To trigger a reload, send a SIGHUP signal to the running daemon process:

    # 1. Find the daemon process ID (PID)
    ps aux | grep mcpd
    
    # 2. Send the reload signal
    kill -HUP <PID>

    Reload Behavior Logic

    Change TypeActionDescription
    Unchanged serversPreserveKeeps existing connections, tools, and health status
    Removed serversStopGracefully shuts down servers no longer in config
    New serversStartInitializes and connects newly added servers
    'Tools-Only' changesUpdateUpdates allowed tools list in-place without restarting the process
    Configuration changesRestartStops and restarts servers if package, env vars, args, or context changed

    Limitations

    Hot reload does NOT apply to:

    • Daemon-level settings (timeouts, CORS, etc.)
    • New environment variables added to the system after mcpd started.
    # Example: Triggering reload
    kill -HUP $(pgrep mcpd)
  10. Manage plugin health and shutdown

    main

    Plugins must handle readiness, liveness, and graceful shutdown:

    • Readiness vs Health: CheckReady is used at startup to gate whether the plugin enters service. CheckHealth reports ongoing liveness.
    • Timeouts: Request and response RPCs have a default 5-second timeout. If a plugin blocks on a slow dependency, the call will fail.
    • Shutdown: On shutdown, mcpd calls Stop, closes the gRPC connection, and waits for the process to exit. The daemon allows 5 seconds for the Stop call to complete. If the process does not exit within a 2-second force-kill timeout, it is killed.
  11. Understand mcpd Cache Behavior and Storage

    main

    Cache Lifecycle (Enabled by Default)

    1. First Request: Downloads the manifest from the remote URL and saves it to the cache directory.
    2. Subsequent Requests: Uses the local file if it exists and the TTL has not expired.
    3. Expiration: If the TTL has expired, mcpd automatically downloads a fresh manifest.
    4. Cache Miss/Corruption: If the file is missing or corrupted, mcpd falls back to the remote URL.

    Storage Format

    Cache files are stored as .json files named using the SHA-256 hash of their corresponding registry URLs.

    Example structure:

    ~/.cache/mcpd/registries/
    ├── a1b2c3d4e5f6...1234.json  # mcpm registry manifest
    └── ...
  12. How the plugin startup handshake works

    main

    The mcpd daemon manages the plugin lifecycle. It executes the plugin binary with --address and --network unix flags. The plugin is responsible for creating and listening on the specified socket.

    Once the socket is available, mcpd performs the following RPC calls in order:

    1. Configure: Delivers the plugin configuration.
    2. CheckReady: Confirms the plugin is ready to serve requests.
    3. GetMetadata: Retrieves the plugin's name, version, and commit hash.

    Note: GetCapabilities is called lazily by mcpd only when a configured flow requires it, but the plugin must still implement it.

    Critical: You must listen on the socket before performing slow initialization work. If the socket does not accept a connection within the default 10-second timeout, mcpd will kill the process.