MCP STDIO Webhook Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP STDIO Webhook ServerSend a file.save event for /repo/file.py with token1"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP STDIO Webhook Server
A lightweight Python MCP (Model Context Protocol) server that accepts event envelopes and maps them to MCP tools. This server uses the STDIO transport and can be deployed with Docker Compose in a one-click style using a stdio-proxy (TCP bridge).
Overview
This project provides a robust MCP server that:
Communicates over STDIO internally with MCP clients
Exposes an easy-to-use TCP endpoint via a proxy/bridge for Docker deployments
Supports optional bearer-token authentication
Maps received event envelopes to registered MCP tools using configurable mappings
Supports both synchronous and asynchronous processing modes
Related MCP server: MCP Docker Demo
Features
Core Features (MVP)
✅ STDIO-based MCP server using
FastMCPand the MCP Python SDK✅ Envelope router with configurable event-to-tool mappings
✅ Optional bearer-token authentication (empty tokens = auth disabled)
✅ TCP bridge (stdio-proxy) for Docker deployment
✅ JSON structured logging
✅ Example tools:
ack_event,process_payload,list_recent_events
Additional Features (Implemented)
✅ In-memory recent event log (via
list_recent_eventstool)✅ In-process worker pool for async jobs (configurable via
ASYNC_PROCESSING)✅ Comprehensive testing (unit + integration)
✅ CI/CD pipeline with GitHub Actions
Optional/Future Features
✅ Redis-backed queue for high-throughput scenarios (use with
--profile async)🔜 Example stdio client script (see Task 150)
🔜 Prometheus metrics integration
Quick Start
Prerequisites
Docker and Docker Compose
(Optional) Python 3.11+ for local development
Docker Compose Deployment
Clone the repository:
git clone https://github.com/encoded-evolution/mcp_webhook_python_zed.git
cd mcp_webhook_python_zedCopy the example environment file:
cp .env.example .envConfigure your environment (optional):
# Edit .env to customize PORT, WEBHOOK_BEARER_TOKENS, etc.Create a mapping configuration:
cp config/mapping.yml.example config/mapping.ymlStart the server:
docker-compose up --buildThe server will be available at tcp://localhost:9000 (default port).
Testing the Connection
Quick TCP Test (netcat) Send a test envelope using netcat (for basic connectivity testing):
printf '%s\n' '{"type":"event","event_type":"file.save","payload":{"path":"/repo/file.py"},"meta":{"auth":"token1"}}' | nc localhost 9000Using the Example Client For proper MCP stdio framing, use the example client:
python examples/stdio_client.py --event file.save --path /repo/file.py --auth token1Note: The netcat test is for basic TCP connectivity only. Full MCP stdio framing is required for production usage. See examples/stdio_client.py for a complete client implementation.
MCP Client Configuration
This server can be used with any MCP-compatible client (Claude Desktop, VS Code MCP extension, etc.) by configuring the client to connect via Docker.
Prerequisites
Pull the Docker image:
docker pull encoded-evolution/mcp-webhook-stdio:0.1.0Create a local configuration directory:
mkdir -p ~/.config/mcp-webhook
cp config/mapping.yml.example ~/.config/mcp-webhook/mapping.ymlClaude Desktop Configuration
Add the following to your Claude Desktop configuration file (claude_desktop_config.json):
Minimal configuration (no auth, default settings):
{
"mcpServers": {
"mcp-webhook": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-p", "9000:9000",
"encoded-evolution/mcp-webhook-stdio:latest"
]
}
}
}Full configuration with all settings:
{
"mcpServers": {
"mcp-webhook": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "PORT=9000",
"-e", "MCP_NAME=My-Webhook-Server",
"-e", "WEBHOOK_BEARER_TOKENS=your-secret-token-1,another-token-2",
"-e", "ASYNC_PROCESSING=false",
"-e", "LOG_LEVEL=INFO",
"-e", "REDIS_URL=",
"-e", "MAPPING_FILE=/app/config/mapping.yml",
"-v", "${HOME}/.config/mcp-webhook:/app/config:ro",
"-p", "9000:9000",
"encoded-evolution/mcp-webhook-stdio:latest"
]
}
}
}VS Code MCP Extension Configuration
Claude Desktop Configuration
Add to your Claude Desktop config file (claude_desktop_config.json on macOS/Linux or claude_desktop_config.json in %APPDATA%\Claude\ on Windows):
Option 1: Using docker compose (recommended for multiple clients)
{
"mcpServers": {
"mcp-webhook": {
"transport": {
"type": "tcp",
"host": "localhost",
"port": 9000
}
}
}
}VS Code MCP Extension Configuration
Add to your VS Code settings (settings.json):
Option 1: Using docker compose (recommended for multiple clients)
{
"mcp.servers": {
"mcp-webhook": {
"transport": {
"type": "tcp",
"host": "localhost",
"port": 9000
}
}
}
}Option 2: Using individual container (one client per container)
{
"mcp.servers": {
"mcp-webhook": {
"transport": {
"type": "stdio",
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "PORT=9000",
"-e", "MCP_NAME=My-Webhook-Server",
"-e", "WEBHOOK_BEARER_TOKENS=your-secret-token-1,another-token-2",
"-e", "ASYNC_PROCESSING=false",
"-e", "LOG_LEVEL=INFO",
"-e", "REDIS_URL=",
"-e", "MAPPING_FILE=/app/config/mapping.yml",
"-v", "${env:HOME}/.config/mcp-webhook:/app/config:ro",
"-p", "9000:9000",
"encoded-evolution/mcp-webhook-stdio:latest"
]
}
}
}
}Zed Configuration
Configure Zed by adding to your settings.json:
Option 1: Using docker compose (recommended - server already running)
First, start the server:
cd mcp_webhook_python_zed
docker compose upThen configure Zed (open settings.json):
{
"context_servers": {
"mcp-webhook": {
"url": "tcp://localhost:9000"
}
}
}Option 2: Using individual container (server starts with Zed)
Configure Zed (open settings.json):
{
"context_servers": {
"mcp-webhook": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-p", "9000:9000",
"encoded-evolution/mcp-webhook-stdio:latest"
],
"env": {}
}
}
}Important: Do not use Option 2 if you already have docker compose up running, as it will cause a port conflict on 9000.
Note: When using "url" for remote connections, do not include a "command" field. The "command" field is only for starting local processes via STDIO transport.
TCP Transport (For Other Clients)
If your MCP client supports direct TCP connections, you can connect directly to the TCP proxy:
{
"mcpServers": {
"mcp-webhook-tcp": {
"transport": {
"type": "tcp",
"host": "localhost",
"port": 9000
}
}
}
}Environment Variables for Client Configuration
Variable | Purpose | Default | Example |
| Port for stdio-proxy listener |
|
|
| Human-readable server name |
|
|
| Comma-separated auth tokens (empty = no auth) | `` (disabled) |
|
| Enable async worker pool |
|
|
| Logging verbosity |
|
|
| Redis connection URL for async queue (optional) | `` (disabled) |
|
| Path to event mapping config |
|
|
Testing the Connection
After configuring your MCP client:
If using docker compose:
Verify the container is running:
docker ps | grep mcp-webhookCheck logs for startup:
docker logs mcp-webhook-serverTest TCP connection (optional):
nc -zv localhost 9000Look for successful client connection in logs:
docker logs -f mcp-webhook-serverIf using individual container:
Start your MCP client (Zed, Claude Desktop, etc.)
Client will automatically start the Docker container
Check logs from container:
docker ps | grep mcp-webhook-stdio
docker logs <container-id>Restart your MCP client if you make configuration changes
Common Issues
Port Already in Use
If using docker compose and seeing port conflicts, ensure you're not running multiple MCP clients configured for STDIO transport. Use TCP transport instead.
Connection Refused
Ensure the container is running before trying to connect with TCP transport. Check with docker ps.
Authentication Failures
Container not starting: Check Docker is running and the image is pulled correctly.
Port already in use: Change the port in your client configuration:
"-e", "PORT=9001",
"-p", "9001:9001",Authentication errors: Ensure the token in your envelope matches one of the configured WEBHOOK_BEARER_TOKENS.
Configuration file not found: Verify the volume mount path matches where your mapping file is located on the host.
Configuration
Environment Variables
Variable | Default | Description |
| 9000 | Port for stdio-proxy TCP listener |
| MCP-STDIO-Server | Human-friendly server name |
| (empty) | Comma-separated bearer tokens (empty = auth disabled) |
| false | Enable async processing mode |
| /app/config/mapping.yml | Path to event mapping configuration |
| INFO | Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) |
| (empty) | Redis connection URL (e.g., redis://redis:6379/0); empty uses in-memory queue |
Using Redis-Backed Async Queue
For higher throughput scenarios, you can enable a Redis-backed queue instead of the in-memory queue:
Start the services with the async profile:
docker-compose --profile async up --buildSet the
REDIS_URLenvironment variable in your.envfile:
REDIS_URL=redis://redis:6379/0
ASYNC_PROCESSING=trueThe server will automatically use Redis for task queuing when:
REDIS_URLis configured and non-emptyThe
aioredispackage is installed (included in[redis]optional dependency)
Benefits of Redis Queue:
Persistent queue that survives container restarts
Multiple worker processes can share the same queue
Better for high-throughput scenarios
Tasks are stored in a Redis list and processed by worker coroutines
Note: When Redis is unavailable, the server will fall back to the in-memory queue automatically and log a warning.
Event Mapping Configuration
Create a mapping.yml file to define how events map to tools:
mappings:
- event: "file.save"
tool: "process_payload"
args:
path: payload.path
user_id: payload.user.id
- event: "file.open"
tool: "ack_event"
args:
file: payload.pathEnvelope Format
Events are sent as JSON envelopes:
{
"type": "event",
"event_type": "file.save",
"payload": {
"path": "/repo/file.py",
"user": {
"id": "alice"
}
},
"meta": {
"auth": "token1",
"id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-01-06T12:00:00Z"
}
}Envelope Fields
Field | Type | Required | Description |
| string | Yes | Must be "event" |
| string | Yes | Event identifier for mapping |
| object | Yes | Event data (any structure) |
| string | Conditional | Bearer token (required if auth enabled) |
| string | No | Unique event identifier |
| string | No | ISO 8601 timestamp |
Architecture
┌─────────────┐ TCP ┌──────────────┐ STDIO ┌─────────────┐
│ Client │ ◄──────────► │ stdio-proxy │ ◄────────────► │ MCP Server │
│ │ Port: 9000 │ (TCP Bridge) │ Framing │ (FastMCP) │
└─────────────┘ └──────────────┘ └─────────────┘
│
▼
┌──────────────┐
│ Envelope │
│ Router │
└──────────────┘
│
▼
┌──────────────┐
│ Async Worker │
│ (in-memory │
│ or Redis) │
└──────────────┘
│
▼
┌──────────────┐
│ MCP Tools │
│ (ack_event, │
│ process_ │
│ payload, │
│ list_recent)│
└──────────────┘Components
Client: Connects via TCP to the stdio-proxy
stdio-proxy: TCP bridge that forwards data to/from server STDIO
MCP Server: FastMCP-based server handling MCP protocol
Envelope Router: Maps events to tools and validates auth
MCP Tools: Executable functions that process events
Available MCP Tools
ack_event
Acknowledges an event and returns a confirmation.
# Parameters: event_type: str, payload: dict
# Returns: {"status": "acknowledged", "event_type": "..."}process_payload
Processes a payload with path and user information.
# Parameters: path: str, user_id: str
# Returns: {"processed": true, "path": "...", "user_id": "..."}list_recent_events
Returns the list of recently processed events.
# Parameters: None
# Returns: {"events": [...]}Development
Local Development Setup
Create a virtual environment:
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate2. Install dependencies:
# For basic development
pip install -e ".[dev]"
# For Redis queue support (optional)
pip install -e ".[dev,redis]"Run tests:
pytestRun linting:
ruff check src/
black src/
isort src/Project Structure
mcp_webhook_python_zed/
├── src/
│ └── mcp_webhook/
│ ├── __init__.py
│ ├── config.py # Configuration management
│ ├── mapping.py # Event-to-tool mapping parser
│ ├── envelope.py # Envelope Pydantic models
│ ├── tools.py # MCP tool implementations
│ ├── router.py # Envelope routing logic
│ ├── worker.py # Async worker (optional)
│ ├── server.py # FastMCP server bootstrap
│ └── proxy.py # stdio-proxy (TCP bridge)
├── config/
│ ├── mapping.yml.example # Example mapping configuration
│ └── .env.example # Example environment variables
├── tests/
│ ├── unit/ # Unit tests
│ └── integration/ # Integration tests
├── examples/
│ └── stdio_client.py # Example client implementation
├── docker/
│ └── entrypoint.sh # Docker entrypoint script
├── docker-compose.yml # Docker Compose configuration
├── Dockerfile # Docker image definition
├── pyproject.toml # Python project configuration
├── README.md # This file
├── Planning.md # Project planning document
└── Task.md # Task trackingTesting
Unit Tests
# Run all unit tests
pytest tests/unit/
# Run specific test file
pytest tests/unit/test_config.py
# Run with coverage
pytest --cov=src --cov-report=htmlIntegration Tests
# Run all integration tests
pytest tests/integration/
# Run specific integration test
pytest tests/integration/test_stdio_proxy.pyEnd-to-End Test with Docker
# Build and start the service
docker-compose up --build
# Run the example client (from another terminal)
python examples/stdio_client.py
# Verify logs for processed events
docker-compose logs -f mcp-stdioSecurity
Authentication
Bearer tokens are stored in environment variables
When
WEBHOOK_BEARER_TOKENSis empty, authentication is disabledIn production, use proper secret management (e.g., Docker secrets, Vault)
Recommendations
Run behind a firewall or in a secure network
Use an external proxy (e.g., Traefik, Nginx) for TLS termination
Rotate bearer tokens regularly
Enable structured logging for audit trails
Troubleshooting
Port Already in Use
# Find process using port 9000
netstat -ano | findstr :9000 # Windows
lsof -i :9000 # macOS/Linux
# Change port in .env
PORT=9001Connection Refused
Verify the container is running:
docker-compose psCheck logs:
docker-compose logs mcp-stdioEnsure firewall allows connections to the configured port
Authentication Failures
Verify
WEBHOOK_BEARER_TOKENSmatches the token in envelope metaCheck that
meta.authfield is present in the envelopeReview logs for detailed error messages
Contributing
Fork the repository
Create a feature branch:
git checkout -b feature/my-featureMake your changes and write tests
Run tests:
pytestRun linting:
ruff check src/ && black src/ && isort src/Commit your changes:
git commit -m "Add my feature"Push to the branch:
git push origin feature/my-featureOpen a Pull Request
License
MIT License - see LICENSE file for details
Roadmap
See Planning.md for detailed project planning and Task.md for task tracking.
Upcoming Features
Enhanced admin tooling
Per-client token management
Multi-tenant support
Kubernetes manifests / Helm chart
OAuth or HMAC signing flows
Prometheus metrics integration
Example stdio client script
Support
For issues, questions, or contributions, please open an issue on the project repository.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/encoded-evolution/mcp_webhook_python_zed'
If you have feedback or need assistance with the MCP directory API, please join our Discord server