"Measure Twice, Cut Once."
consent-mcp is an open-source Model Context Protocol (MCP) server that acts as an ethical gateway for proactive AI agents. It ensures that no autonomous agent initiates contact with a human target (neighbor, patient, or community member) without an explicit, verified consent handshake.
We are moving from "Chatbots" (reactive) to "Agents" (proactive).
- The Problem: A proactive agent checking on a neighbor can quickly become a nuisance or a privacy violation if it lacks social awareness.
- The Solution: This tool provides a Blocking Mechanism. Agents must call
check_consentbefore performing any task. If consent is notGRANTED, the agent is hard-blocked at the tool level.
- Double-Opt-In Workflow: Sends SMS (via Twilio) or email (via SendGrid) to the target requesting permission
- Blocking Tool:
check_consentreturnsFalseunless consent is valid and unexpired - Requester Tracking: Multiple users can request consent from the same target independently
- Consent Expiration: All consent has an expiration date for security
- Audit Logging: Every request, grant, and revocation is logged to PostgreSQL
- Pluggable Auth: API key or OAuth authentication out of the box
- Domain Driven Design: Clean architecture with swappable infrastructure
- Docker Ready: Deploy with a single
docker-compose up
# Clone the repository
git clone https://github.com/sairajm/consent-mcp.git
cd consent-mcp
# Copy environment template
cp .env.example .env
# Edit .env with your configuration
# At minimum, set API_KEYS for authentication
# Start the server
docker-compose up --buildThis workflow runs PostgreSQL in Docker but executes the Python server locally on your machine for fast iteration.
-
Windows:
.\scripts\start_local.ps1
-
Linux/Mac:
chmod +x scripts/start_local.sh ./scripts/start_local.sh
This script will:
- Check for
.env(copying from.env.exampleif needed). - Start a specific local Postgres container (
consent-mcp-postgres-dev). - Wait for the database to be ready.
- Run database migrations.
- Start the MCP server with the local environment configuration.
Note: For manual setup, see
.github/workflows/ci.yml.
All configuration is via environment variables:
| Variable | Required | Description |
|---|---|---|
ENV |
No | Environment: test, development, production (default: development) |
DATABASE_URL |
Yes | PostgreSQL connection URL |
AUTH_PROVIDER |
No | Auth method: api_key, oauth, none (default: api_key) |
API_KEYS |
For api_key auth | Comma-separated key:client_id pairs |
TWILIO_ACCOUNT_SID |
For SMS | Twilio Account SID |
TWILIO_AUTH_TOKEN |
For SMS | Twilio Auth Token |
TWILIO_PHONE_NUMBER |
For SMS | Twilio phone number (E.164 format) |
SENDGRID_API_KEY |
For email | SendGrid API key |
SENDGRID_FROM_EMAIL |
For email | Sender email address |
Request consent from a target via SMS.
{
"requester_phone": "+15551234567",
"requester_name": "Alice",
"target_phone": "+15559876543",
"target_name": "Bob",
"scope": "wellness_check",
"expires_in_days": 30
}BLOCKING: Check if requester has active consent to contact target.
{
"requester_phone": "+15551234567",
"target_phone": "+15559876543"
}Returns true ONLY if consent is GRANTED and not expired.
Request consent from a target via email.
{
"requester_email": "alice@example.com",
"requester_name": "Alice",
"target_email": "bob@example.com",
"target_name": "Bob",
"scope": "appointment_reminder",
"expires_in_days": 365
}BLOCKING: Check if requester has active consent to contact target via email.
Simulate a consent response for testing without real SMS/email.
{
"target_contact_type": "phone",
"target_contact_value": "+15559876543",
"requester_contact_value": "+15551234567",
"response": "YES"
}
β οΈ This tool is only available whenENV=test
The project follows Domain Driven Design:
src/consent_mcp/
βββ domain/ # Business logic (entities, services, interfaces)
βββ infrastructure/ # External integrations (database, providers, auth)
βββ mcp/v1/ # MCP layer (tools, request/response schemas)
Add a new messaging provider:
- Create a class implementing
IMessageProviderininfrastructure/providers/ - Register it in
infrastructure/providers/factory.py
Add a new auth provider:
- Create a class implementing
IAuthProviderininfrastructure/auth/ - Register it in
infrastructure/auth/factory.py
Switch databases:
- Create a new class implementing
IConsentRepository - No changes needed in domain or MCP layers
# Start test database
docker-compose -f docker-compose.test.yml up -d
# Run all tests
pytest tests/ -v
# Run with coverage
pytest tests/ --cov=consent_mcp --cov-report=html
# Run specific test file
pytest tests/domain/test_services.py -v# Create a new migration
alembic revision --autogenerate -m "description"
# Apply migrations
alembic upgrade head
# Rollback one migration
alembic downgrade -1- All MCP requests require authentication (API key or OAuth)
- Admin tools are disabled in production
- Secrets are never logged
- Docker runs as non-root user
- Pre-commit hooks detect secrets before commit
- Fork the repository
- Create a feature branch
- Install pre-commit hooks:
pre-commit install - Make your changes
- Run tests:
pytest - Submit a pull request
MIT License - see LICENSE for details.