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:
For the gateway (if not already installed):
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):
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)ΒΆ
Or via environment variable:
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
targetanduds- 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:
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ΒΆ
- Verify the server is running:
lsof -i :50051 - Check the server host binding (use
0.0.0.0for all interfaces) - Verify firewall rules allow the port
TLS Handshake FailedΒΆ
- Verify certificate paths are correct
- Check certificate expiration:
openssl x509 -in cert.pem -noout -dates - Ensure CA bundle matches between client and server
- For mTLS, verify client certificates are properly configured
Plugin Not DiscoveredΒΆ
- Check server logs for plugin loading errors
- Verify the
PLUGINS_CONFIG_PATHpoints to correct config file - Ensure plugin class paths are correct in the configuration
Performance Not as ExpectedΒΆ
- Verify gRPC transport is actually being used (check logs)
- Ensure persistent connections are being reused
- Check network latency between gateway and plugin server
- 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ΒΆ
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ΒΆ
- External Plugin mTLS Setup Guide - Detailed mTLS configuration for MCP transport
- Plugin Framework Guide - Overview of the plugin system
- Plugin Lifecycle Guide - Building and deploying external plugins
- Available Plugins - Catalog of available plugins