Outlook Semantic MCP - Local Development
2 min read
Outlook Semantic MCP - Local Development
This guide walks through setting up the Outlook Semantic MCP Server for local development and testing.
Prerequisites
Requirement | Version | Purpose |
|---|---|---|
Node.js | 20+ | Runtime |
pnpm | 9+ | Package manager |
Docker | 24+ | Run PostgreSQL and RabbitMQ |
Azure CLI | Latest | Configure Entra app registration |
MCP Inspector | Latest | MCP Client for testing |
A public reverse proxy, recommended:
Azure Dev Tunnels for webhook testing
Quick Start
# Clone and install
git clone git@github.com:Unique-AG/connectors.git
cd services/outlook-semantic-mcp
pnpm install
# Configure environment (must come before docker compose — docker-compose.prod.yaml reads .env automatically)
cp .env.example .env
# Edit .env with your values (see below)
# Start infrastructure
docker compose -f docker-compose.prod.yaml up -d
# Run migrations
pnpm db:migrate
# Start development server
pnpm devThe server starts at the configured port (default: 9542).
Infrastructure Setup
Docker Compose
The included docker-compose.prod.yaml provides PostgreSQL and RabbitMQ:
docker compose -f docker-compose.prod.yaml up -dService | Credentials |
|---|---|
PostgreSQL | postgres:postgres |
RabbitMQ | rabbitmq:rabbitmq |
RabbitMQ Management | rabbitmq:rabbitmq |
Microsoft Entra App Registration
You need a Microsoft Entra ID app registration for OAuth. See Authentication Setup for detailed instructions.
For local development, configure:
Setting | Value |
|---|---|
Redirect URI |
|
Supported account types | Your organization only |
Environment Configuration
Create .env from the template:
cp .env.example .envRequired Variables
# Application
SELF_URL=http://localhost:9542
LOG_LEVEL=debug
# Database
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/outlook_semantic_mcp
# RabbitMQ
AMQP_URL=amqp://rabbitmq:rabbitmq@localhost:5672
# Microsoft (from Entra app registration)
MICROSOFT_CLIENT_ID=<your-client-id>
MICROSOFT_CLIENT_SECRET=<your-client-secret>
MICROSOFT_WEBHOOK_SECRET=<generate-128-char-hex>
MICROSOFT_PUBLIC_WEBHOOK_URL=<your-tunnel-url> # See webhook testing below
# Security (generate with: openssl rand -hex 32)
AUTH_HMAC_SECRET=<64-char-hex>
ENCRYPTION_KEY=<64-char-hex>
# Unique API (for local testing, use external mode)
UNIQUE_SERVICE_AUTH_MODE=external
UNIQUE_INGESTION_SERVICE_BASE_URL=http://localhost:8091
UNIQUE_SCOPE_MANAGEMENT_SERVICE_BASE_URL=http://localhost:8092
UNIQUE_ZITADEL_CLIENT_ID=<zitadel-client-id>
UNIQUE_ZITADEL_CLIENT_SECRET=<zitadel-client-secret>
UNIQUE_ZITADEL_OAUTH_TOKEN_URL=https://your-zitadel.zitadel.cloud/oauth/v2/token
UNIQUE_ZITADEL_PROJECT_ID=<zitadel-project-id>Note on Unique API URLs: The
http://localhost:8091andhttp://localhost:8092values assume a locally-running proxy that forwards to the Unique ingestion and scope management services. Replace these with your actualhttps://*.unique.appservice URLs when testing against a real Unique tenant.
Generating Secrets
See Configuration — Required Secrets for the full format reference. Quick generation:
# For MICROSOFT_WEBHOOK_SECRET (128 chars)
openssl rand -hex 64
# For AUTH_HMAC_SECRET and ENCRYPTION_KEY (64 chars each)
openssl rand -hex 32Webhook Testing
Microsoft Graph webhooks require a publicly accessible HTTPS endpoint. For local development, use Azure Dev Tunnels or any other HTTPS tunnel solution (e.g., ngrok, Cloudflare Tunnel):
Setup Dev Tunnel
# Install (macOS)
brew install azure-dev-tunnels
# Login
devtunnel user login
# Create persistent tunnel
devtunnel create outlook-semantic-mcp --allow-anonymous
# Start tunnel
devtunnel port create outlook-semantic-mcp -p 9542
devtunnel host outlook-semantic-mcpConfigure Environment
Set MICROSOFT_PUBLIC_WEBHOOK_URL to your tunnel URL:
MICROSOFT_PUBLIC_WEBHOOK_URL=https://abc123.devtunnels.msMicrosoft Graph appends /mail-subscription/notification and /mail-subscription/lifecycle to this URL when delivering webhook events. It must be publicly reachable by Microsoft, which is why you need a tunnel URL locally instead of http://localhost:9542.
Development Workflow
Available Scripts
Script | Description |
|---|---|
| Start with hot reload |
| Build for production |
| Start with Node.js debugger |
| Run unit tests |
| Run tests in watch mode |
| Run tests with coverage |
| Run end-to-end tests |
| Run end-to-end tests in watch mode |
| Generate migrations from schema changes |
| Apply pending migrations |
| Check migration consistency |
| Check code style (Biome) |
| Fix code style issues |
| TypeScript type checking |
Testing the OAuth Flow
Start the dev server:
pnpm devOpen
http://localhost:9542/.well-known/oauth-authorization-serverYou should see the OAuth metadata JSON
Connect with MCP Inspector or another MCP client that supports OAuth
After connecting, use
verify_inbox_connectionto check subscription status
Debugging
Common Issues
OAuth redirect mismatch:
Verify
SELF_URLmatches the redirect URI in your Entra app registrationThe redirect URI must be exactly:
http://localhost:9542/auth/callback
Webhook not received:
Check dev tunnel is running and accessible
Verify
MICROSOFT_PUBLIC_WEBHOOK_URLis set correctlyCheck logs for subscription creation errors
Database connection error:
Verify Docker Compose is running:
docker compose -f docker-compose.prod.yaml psCheck
DATABASE_URLmatches the credentials in the Docker Compose service
Emails not appearing in search:
Use the
sync_progresstool to check the sync stateIf the state is
not_configured, usereconnect_inboxfirst
Related Documentation
Configuration Reference - All environment variables
Authentication Setup - Entra app registration
FAQ - Frequently asked questions
Architecture - System design