Skip to content

gRPC Transport for External PluginsΒΆ

This guide covers how to run external plugins using gRPC transport and configure the gateway to connect to them. gRPC provides significantly higher performance than the default MCP/HTTP transport.

Performance ComparisonΒΆ

Transport Throughput Use Case
MCP/HTTP ~600 calls/sec Default, broad compatibility
MCP/STDIO ~600 calls/sec Subprocess-based plugins
gRPC ~4,700 calls/sec High-performance remote plugins
Unix Socket ~9,000 calls/sec High-performance local IPC

gRPC provides approximately 8x better performance than MCP/HTTP transport due to: - Binary protocol (Protocol Buffers) vs JSON - HTTP/2 multiplexing and header compression - Persistent connections with lower overhead - Explicit message schemas reducing serialization costs

Architecture OverviewΒΆ

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           gRPC            β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   MCP Gateway       │◄────────────────────────►│  External Plugin    β”‚
β”‚   (Client)          β”‚      (HTTP/2 + Proto)     β”‚  Server (gRPC)      β”‚
β”‚                     β”‚                           β”‚                     β”‚
β”‚  GrpcExternalPlugin β”‚                           β”‚  GrpcPluginServicer β”‚
β”‚        β–Ό            β”‚                           β”‚        β–Ό            β”‚
β”‚  grpc.aio.Channel   β”‚                           β”‚  ExternalPluginServerβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Quick StartΒΆ

1. Install gRPC DependenciesΒΆ

For the plugin server:

# In your external plugin directory
pip install ".[grpc]"

# Or using make target
make install-grpc

For the gateway (if not already installed):

pip install "mcp-contextforge-gateway[grpc]"

2. Start the gRPC Plugin ServerΒΆ

# Set the plugin config path
export PLUGINS_CONFIG_PATH=./resources/plugins/config.yaml

# Start the gRPC server (default port: 50051)
python -m mcpgateway.plugins.framework.external.grpc.server.runtime

# Or with custom port
python -m mcpgateway.plugins.framework.external.grpc.server.runtime --port 50052

# Or with Unix domain socket (highest local performance)
PLUGINS_GRPC_SERVER_UDS=/var/run/grpc-plugin.sock \
  python -m mcpgateway.plugins.framework.external.grpc.server.runtime

Using the convenience script (if using plugin templates):

PLUGINS_TRANSPORT=grpc ./run-server.sh

3. Configure the Gateway ClientΒΆ

In your gateway's plugins/config.yaml:

plugins:
  # TCP connection
  - name: "MyGrpcPlugin"
    kind: "external"
    hooks: ["tool_pre_invoke", "tool_post_invoke"]
    mode: "enforce"
    priority: 50
    grpc:
      target: "localhost:50051"

  # Unix domain socket connection (for local high-performance)
  - name: "MyLocalGrpcPlugin"
    kind: "external"
    hooks: ["tool_pre_invoke"]
    mode: "enforce"
    priority: 50
    grpc:
      uds: /var/run/grpc-plugin.sock

Server ConfigurationΒΆ

Plugin Server Configuration FileΒΆ

The plugin server reads its configuration from a YAML file. Configure the gRPC server settings in the same file:

# resources/plugins/config.yaml (on the plugin server)
plugins:
  - name: "PIIFilterPlugin"
    kind: "plugins.pii_filter.pii_filter.PIIFilterPlugin"
    hooks: ["tool_pre_invoke", "tool_post_invoke"]
    mode: "enforce"
    priority: 50
    config:
      detect_ssn: true
      detect_credit_card: true

# gRPC server settings (TCP)
grpc_server_settings:
  host: "0.0.0.0"
  port: 50051
  # tls:                                    # Uncomment for TLS/mTLS
  #   certfile: /path/to/server.pem
  #   keyfile: /path/to/server-key.pem
  #   ca_bundle: /path/to/ca.pem           # Required for mTLS
  #   client_auth: "require"               # none, optional, require

# OR use Unix domain socket (alternative to TCP, higher performance for local)
# grpc_server_settings:
#   uds: /var/run/grpc-plugin.sock

Environment Variables (Server)ΒΆ

You can also configure the server via environment variables:

Variable Default Description
PLUGINS_CONFIG_PATH ./resources/plugins/config.yaml Path to plugin configuration file
PLUGINS_GRPC_SERVER_HOST 0.0.0.0 Server bind address
PLUGINS_GRPC_SERVER_PORT 50051 Server bind port
PLUGINS_GRPC_SERVER_UDS - Unix domain socket path (alternative to host:port)
PLUGINS_GRPC_SERVER_SSL_ENABLED false Enable TLS/mTLS (not supported with UDS)
PLUGINS_GRPC_SERVER_SSL_CERTFILE - Path to server certificate
PLUGINS_GRPC_SERVER_SSL_KEYFILE - Path to server private key
PLUGINS_GRPC_SERVER_SSL_CA_CERTS - Path to CA bundle (enables mTLS)
PLUGINS_GRPC_SERVER_SSL_CLIENT_AUTH require Client auth mode (none/optional/require)

Server Command Line OptionsΒΆ

python -m mcpgateway.plugins.framework.external.grpc.server.runtime \
    --config plugins/config.yaml \
    --host 0.0.0.0 \
    --port 50051 \
    --log-level INFO \
    --tls  # Enable TLS (configure certs via env vars)

Gateway Client ConfigurationΒΆ

YAML ConfigurationΒΆ

Configure external plugins to use gRPC in the gateway's plugin configuration:

plugins:
  # gRPC external plugin
  - name: "HighPerformanceFilter"
    kind: "external"
    hooks: ["tool_pre_invoke", "prompt_pre_fetch"]
    mode: "enforce"
    priority: 10
    grpc:
      target: "plugin-server:50051"
      # tls:                                # Uncomment for TLS/mTLS
      #   verify: true
      #   ca_bundle: /path/to/ca.pem
      #   certfile: /path/to/client.pem    # For mTLS
      #   keyfile: /path/to/client-key.pem # For mTLS

  # MCP external plugin (for comparison)
  - name: "LegacyPlugin"
    kind: "external"
    hooks: ["tool_post_invoke"]
    mode: "permissive"
    priority: 100
    mcp:
      proto: STREAMABLEHTTP
      url: http://localhost:8000/mcp

Environment Variables (Client)ΒΆ

Client-side TLS can be configured via environment variables:

Variable Default Description
PLUGINS_GRPC_CLIENT_MTLS_VERIFY true Verify server certificate
PLUGINS_GRPC_CLIENT_MTLS_CA_BUNDLE - Path to CA bundle
PLUGINS_GRPC_CLIENT_MTLS_CERTFILE - Path to client certificate (mTLS)
PLUGINS_GRPC_CLIENT_MTLS_KEYFILE - Path to client private key (mTLS)
PLUGINS_GRPC_CLIENT_MTLS_KEYFILE_PASSWORD - Password for encrypted private key

Unix Domain Socket ConfigurationΒΆ

For local deployments where both the gateway and plugin server run on the same machine, Unix domain sockets provide the best performance by avoiding TCP overhead.

Server Configuration (UDS)ΒΆ

grpc_server_settings:
  uds: /var/run/grpc-plugin.sock

Or via environment variable:

export PLUGINS_GRPC_SERVER_UDS=/var/run/grpc-plugin.sock

Client Configuration (UDS)ΒΆ

plugins:
  - name: "LocalGrpcPlugin"
    kind: "external"
    hooks: ["tool_pre_invoke"]
    mode: "enforce"
    priority: 50
    grpc:
      uds: /var/run/grpc-plugin.sock

Important Notes for UDSΒΆ

  • TLS is not supported with Unix domain sockets (communication is local and inherently secure)
  • File permissions on the socket control access - ensure appropriate permissions on the socket directory
  • Cannot use both target and uds - choose one or the other
  • Performance: UDS eliminates TCP handshake overhead, providing lower latency for local IPC

TLS/mTLS ConfigurationΒΆ

TLS Only (Server Certificate Verification)ΒΆ

Server configuration:

grpc_server_settings:
  host: "0.0.0.0"
  port: 50051
  tls:
    certfile: /certs/server.pem
    keyfile: /certs/server-key.pem
    client_auth: "none"  # Don't require client certificates

Client configuration:

grpc:
  target: "plugin-server:50051"
  tls:
    verify: true
    ca_bundle: /certs/ca.pem

mTLS (Mutual TLS)ΒΆ

Server configuration:

grpc_server_settings:
  host: "0.0.0.0"
  port: 50051
  tls:
    certfile: /certs/server.pem
    keyfile: /certs/server-key.pem
    ca_bundle: /certs/ca.pem      # Verify client certs against this CA
    client_auth: "require"         # Require client certificates

Client configuration:

grpc:
  target: "plugin-server:50051"
  tls:
    verify: true
    ca_bundle: /certs/ca.pem
    certfile: /certs/client.pem    # Client certificate for mTLS
    keyfile: /certs/client-key.pem

Client Auth ModesΒΆ

Mode Description
none Standard TLS, no client certificate required
optional Client certificate validated if provided
require Client certificate required (full mTLS)

Generating CertificatesΒΆ

Use the gateway's certificate generation tools:

# Generate complete mTLS infrastructure
make certs-mcp-all

# Or generate individual components
make certs-mcp-ca                          # Generate CA
make certs-mcp-gateway                     # Generate gateway client cert
make certs-mcp-plugin PLUGIN_NAME=MyPlugin # Generate plugin server cert

Container DeploymentΒΆ

Building with gRPC SupportΒΆ

# Build container with gRPC support
make build-grpc

# Or using docker directly
docker build --build-arg INSTALL_GRPC=true -t my-plugin .

Docker Compose ExampleΒΆ

version: '3.8'

services:
  gateway:
    image: mcpgateway:latest
    ports:
      - "4444:4444"
    environment:
      - PLUGINS_ENABLED=true
      - PLUGIN_CONFIG_FILE=/app/plugins/config.yaml
    volumes:
      - ./plugins/config.yaml:/app/plugins/config.yaml
      - ./certs:/app/certs

  grpc-plugin:
    image: my-plugin:latest
    ports:
      - "50051:50051"
    environment:
      - PLUGINS_TRANSPORT=grpc
      - PLUGINS_CONFIG_PATH=/app/resources/plugins/config.yaml
      - PLUGINS_GRPC_SERVER_HOST=0.0.0.0
      - PLUGINS_GRPC_SERVER_PORT=50051
    volumes:
      - ./resources:/app/resources
      - ./certs:/app/certs

Health ChecksΒΆ

The gRPC server implements the standard gRPC Health Checking Protocol:

# Using grpcurl
grpcurl -plaintext localhost:50051 grpc.health.v1.Health/Check

# With TLS
grpcurl -cacert ca.pem localhost:50051 grpc.health.v1.Health/Check

Switching Between TransportsΒΆ

You can run the same plugin server with different transports:

# MCP/HTTP (default)
PLUGINS_TRANSPORT=http ./run-server.sh

# gRPC
PLUGINS_TRANSPORT=grpc ./run-server.sh

# Unix socket (highest performance for local deployment)
PLUGINS_TRANSPORT=unix ./run-server.sh

TroubleshootingΒΆ

Connection RefusedΒΆ

  1. Verify the server is running: lsof -i :50051
  2. Check the server host binding (use 0.0.0.0 for all interfaces)
  3. Verify firewall rules allow the port

TLS Handshake FailedΒΆ

  1. Verify certificate paths are correct
  2. Check certificate expiration: openssl x509 -in cert.pem -noout -dates
  3. Ensure CA bundle matches between client and server
  4. For mTLS, verify client certificates are properly configured

Plugin Not DiscoveredΒΆ

  1. Check server logs for plugin loading errors
  2. Verify the PLUGINS_CONFIG_PATH points to correct config file
  3. Ensure plugin class paths are correct in the configuration

Performance Not as ExpectedΒΆ

  1. Verify gRPC transport is actually being used (check logs)
  2. Ensure persistent connections are being reused
  3. Check network latency between gateway and plugin server
  4. Consider Unix socket transport for local deployments

Example: End-to-End SetupΒΆ

1. Create Plugin Server ConfigurationΒΆ

# plugin-server/resources/plugins/config.yaml
plugins:
  - name: "SecurityFilterPlugin"
    kind: "plugins.security.filter.SecurityFilterPlugin"
    hooks: ["tool_pre_invoke", "tool_post_invoke"]
    mode: "enforce"
    priority: 10
    config:
      block_dangerous_ops: true

grpc_server_settings:
  host: "0.0.0.0"
  port: 50051

2. Start the Plugin ServerΒΆ

cd plugin-server
pip install -e ".[grpc]"
PLUGINS_CONFIG_PATH=./resources/plugins/config.yaml \
  python -m mcpgateway.plugins.framework.external.grpc.server.runtime

3. Configure GatewayΒΆ

# gateway/plugins/config.yaml
plugins:
  - name: "SecurityFilterPlugin"
    kind: "external"
    hooks: ["tool_pre_invoke", "tool_post_invoke"]
    mode: "enforce"
    priority: 10
    grpc:
      target: "localhost:50051"

4. Start GatewayΒΆ

cd gateway
PLUGINS_ENABLED=true \
  PLUGIN_CONFIG_FILE=plugins/config.yaml \
  make dev

5. Verify ConnectionΒΆ

Check gateway logs for:

INFO - Loaded external plugin 'SecurityFilterPlugin' via gRPC transport
INFO - Connected to gRPC plugin server at localhost:50051

See AlsoΒΆ