SurveyMCP
FreeNot checkedProcesses PDF emails from Gmail, generates structured surveys using Gemini, and sends HTML replies automatically via a queued workflow.
About
Processes PDF emails from Gmail, generates structured surveys using Gemini, and sends HTML replies automatically via a queued workflow.
README
Project Scope
This repository implements a queued survey generation workflow for PDF documents received by Gmail. It uses ActiveMQ as the message broker, PostgreSQL and MongoDB for persistence, and Google Gemini for natural language processing. The workflow extracts text from incoming PDFs, generates a structured survey summary, produces HTML or PDF output, and sends the result back to the original sender.
What this project does
- Reads unread Gmail messages and downloads attached PDF files
- Extracts text from PDFs using PyMuPDF
- Queues document processing tasks with ActiveMQ / STOMP
- Consumes tasks in a worker process
- Generates report summaries using Google Gemini (
google.genaipreferred) - Converts generated summaries into HTML email content
- Sends HTML email replies via Gmail API
- Tracks metadata in PostgreSQL and task status in MongoDB
- Uses environment-based configuration via
.env
Libraries and Technologies Used
python-dotenv- load environment variables from.envstomp.py- STOMP client for ActiveMQpsycopg2-binary- PostgreSQL database adapterpymongo- MongoDB clientgoogle-genai/google-generativeai- Gemini text generationgoogle-api-python-client/google-auth-oauthlib/google-auth-httplib2- Gmail API integrationPyMuPDF- PDF text extractionreportlab- PDF generation from survey textmarkdown- Markdown-to-HTML conversionopentelemetry-api/opentelemetry-sdk/opentelemetry-exporter-otlp- telemetry and tracingdocker- project includes Docker Compose support for service orchestrationGrafana- dashboards and provisioning for monitoring and visualization
High-level Flow
Email ingestion
app/server.pypolls Gmail for unread messages and downloads PDF attachments viaapp/gmail_utils.py- Each valid PDF becomes a task message published to ActiveMQ
- Metadata is stored in PostgreSQL and MongoDB as
pending
Task queueing
app/queue_manager.pypublishes the task to the configured ActiveMQ queue- Each task includes
email_id,sender,pdf_path,document_uuid, anddocument_name
Worker consumption
app/worker.pysubscribes to the queue and receives tasks- When a task arrives, the worker:
- marks the task
in_progressin MongoDB - extracts PDF text via
app/pdf_utils.py - generates survey content with
app/gemini_utils.py - converts the survey into HTML via
app/survey_utils.py - sends the HTML email using
app/gmail_utils.py - updates document status in PostgreSQL and MongoDB
- marks the task
Output and persistence
- PDF text extraction, survey generation, emailing, and state updates are logged
uploads/stores downloaded email attachmentsoutputs/stores generated survey PDFs
Directory Structure
MCP/
├── .env # Local configuration values (private)
├── .env.example # Example environment variables
├── docker-compose.yml # Service orchestration template
├── otel-collector-config.yaml
├── requirements.txt # Python dependencies
├── app/
│ ├── config.py # dotenv loader
│ ├── gemini_utils.py # Gemini model invocation and text extraction
│ ├── gmail_utils.py # Gmail API helpers for download/send
│ ├── mongodb_db.py # MongoDB task status store
│ ├── pdf_utils.py # PDF text extraction via PyMuPDF
│ ├── postgres_db.py # PostgreSQL metadata store
│ ├── queue_manager.py# ActiveMQ STOMP connection, publish, subscribe
│ ├── server.py # Queue producer / FastMCP tool wrapper
│ ├── survey_utils.py # HTML/PDF generation from survey text
│ ├── telemetry.py # Logging and tracing helpers
│ ├── test_gmail.py # Gmail-related tests/examples
│ └── worker.py # Queue consumer and task processor
├── credentials/ # Gmail OAuth credentials
├── outputs/ # Generated survey output files
├── grafana/
│ ├── dashboards/
│ │ └── survey_dashboard.json
│ └── provisioning/
│ ├── dashboards/
│ │ └── dashboard.yml
│ └── datasources/
│ └── postgres.yml
└── uploads/ # Downloaded PDF attachments
Core Components
app/server.py
- Exposes FastMCP tools for document processing and inbox workflow
- Primary workflow is
process_inbox() - Reads unread Gmail messages
- Downloads PDF attachments and stores them locally
- Writes metadata to PostgreSQL
- Writes pending task status to MongoDB
- Publishes processing tasks to ActiveMQ
app/worker.py
- Runs the background consumer
- Connects to ActiveMQ, PostgreSQL, and MongoDB
- Subscribes to the configured queue
- Processes each message by:
- extracting PDF text
- generating survey text
- producing HTML content
- emailing the result
- updating both databases with final status
app/queue_manager.py
- Handles ActiveMQ connectivity via STOMP
- Validates broker protocol on startup
- Supports infinite connection timeout with
ACTIVEMQ_CONNECT_TIMEOUT=0 - Allows publish and subscribe operations
- Disabled STOMP heartbeats for long-running worker tasks
app/gemini_utils.py
- Uses
google.genaiwhen available - Falls back to
google.generativeaifor compatibility - Sends a structured prompt to Gemini
- Extracts text safely from the response
app/gmail_utils.py
- Uses the Gmail API for:
- fetching unread messages
- downloading attachment payloads
- parsing sender email addresses
- sending HTML-rich emails
- Stores attachments under
uploads/ - Builds clean email content with fallback text formatting
app/pdf_utils.py
- Extracts text from PDF documents using PyMuPDF
- Used as the first processing step in the worker
app/survey_utils.py
- Generates PDF output from survey text via ReportLab
- Converts survey text to styled HTML for email delivery
- Includes a fallback HTML generator for plain text
app/postgres_db.py
- Connects to PostgreSQL
- Creates a
documentstable if missing - Stores sender, document UUID, file name, and final status
- Tracks result status for each processed document
app/mongodb_db.py
- Connects to MongoDB
- Stores and updates task status documents
- Supports index creation for
document_uuid,sender, and timestamps
app/config.py
- Loads
.envvalues withpython-dotenv - Centralizes environment configuration for the whole app
app/telemetry.py
- Simple console logging helper
- Provides OpenTelemetry span support for tracing operations
Grafana provisioning & dashboards
- Dashboard JSON: grafana/dashboards/survey_dashboard.json contains pre-built panels for survey processing metrics and document status.
- Provisioning files: grafana/provisioning/dashboards/dashboard.yml and grafana/provisioning/datasources/postgres.yml allow Grafana to auto-provision the dashboard and a PostgreSQL datasource on startup.
- Ensure the datasource configuration matches your
POSTGRES_*settings so dashboard panels can query persisted metadata.
Setup
- Create and activate your Python virtual environment
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
- Copy environment example
cp .env.example .env
- Populate
.env
GEMINI_API_KEYorGOOGLE_API_KEYACTIVEMQ_HOST,ACTIVEMQ_PORT,ACTIVEMQ_USER,ACTIVEMQ_PASSWORDPOSTGRES_HOST,POSTGRES_PORT,POSTGRES_USER,POSTGRES_PASSWORD,POSTGRES_DBMONGODB_URI,MONGODB_DB,MONGODB_COLLECTION
- Provide Gmail OAuth credentials in
credentials/credentials.json - Start ActiveMQ, PostgreSQL, and MongoDB services
Running the project
Start the worker
python app/worker.py
Trigger inbox processing
- The inbox workflow is exposed via
app/server.pyas a FastMCP tool - In practice, run the tool path or call
process_inbox()from your FastMCP interface - Alternatively, you can add a small script to invoke
process_inbox()directly
Start Grafana (optional)
To preview processing metrics and the included dashboard locally you can run Grafana and mount the provisioning files. Example using docker run:
docker run -d -p 3000:3000 \
-v "$(pwd)/grafana/provisioning:/etc/grafana/provisioning" \
-v "$(pwd)/grafana/dashboards:/var/lib/grafana/dashboards" \
--name grafana grafana/grafana:latest
If you use docker-compose, mount the grafana/ directory into your Grafana service under /etc/grafana/provisioning so Grafana will auto-provision the dashboard on startup.
Important Notes
uploads/stores downloaded PDF attachments from Gmailoutputs/stores generated survey PDF filesACTIVEMQ_CONNECT_TIMEOUT=0disables the STOMP connection timeout for long-running workers- Gmail credentials and API tokens must remain private and should not be committed
Extended Notes
- The worker is designed to stay alive while processing long Gemini requests
- The queue consumer logs disconnects and reconnects if the broker drops connection
- PostgreSQL stores stable document metadata, while MongoDB stores live task status changes
- The project is structured to separate email ingestion, queue orchestration, NLP generation, and output delivery cleanly
Future Improvements
- Add a scheduler or webhook trigger for
process_inbox() - Add retry logic for failed tasks and emails
- Add unit tests around queue, DB, and Gemini flows
- Add a health-check endpoint or monitoring integration
Grafana dashboard
- A pre-built Grafana dashboard is included at grafana/dashboards/survey_dashboard.json.
- Grafana provisioning files are available in grafana/provisioning/dashboards/dashboard.yml and grafana/provisioning/datasources/postgres.yml.
- To enable the dashboard, mount the
grafana/directory into your Grafana container's provisioning path or copy the provisioning files into your Grafana server; Grafana will auto-provision the dashboard on startup when provisioning is enabled. - Ensure the datasource configuration points to your PostgreSQL instance used by this project so panels can query the stored metadata and metrics.
Installing SurveyMCP
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/murali-ftw/SurveyMCPFAQ
Is SurveyMCP MCP free?
Yes, SurveyMCP MCP is free — one-click install via Unyly at no cost.
Does SurveyMCP need an API key?
No, SurveyMCP runs without API keys or environment variables.
Is SurveyMCP hosted or self-hosted?
A hosted option is available: Unyly runs the server in the cloud, no local setup required.
How do I install SurveyMCP in Claude Desktop, Claude Code or Cursor?
Open SurveyMCP on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Gmail
Read, send and search emails from Claude
by GoogleSlack
Send, search and summarize Slack messages
by SlackRunbear
No-code MCP client for team chat platforms, such as Slack, Microsoft Teams, and Discord.
Discord Server
A community discord server dedicated to MCP by [Frank Fiegel](https://github.com/punkpeye)
Compare SurveyMCP with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All communication MCPs
