Teams MCP - Configuration
3 min read
Environment Variables
All configuration is done via environment variables, either directly or through Helm values.
Required Secrets
These must be provided via Kubernetes secrets:
Variable | Description | Format |
|---|---|---|
| PostgreSQL connection string |
|
| RabbitMQ connection string |
|
| Entra app client secret | String from Azure portal |
| Webhook validation secret | 128-character random string |
| JWT signing key | 64-character hex string |
| Token encryption key | 64-character hex string |
Application Configuration
Set via mcpConfig.app in Helm values:
Variable | Helm Path | Default | Description |
|---|---|---|---|
|
| (required) | Public URL of the MCP server |
Microsoft Configuration
Set via mcpConfig.microsoft in Helm values:
Variable | Helm Path | Default | Description |
|---|---|---|---|
|
| (required) | Entra app client ID |
|
|
| Webhook URL if different from SELF_URL |
Unique API Configuration
Set via mcpConfig.unique in Helm values:
Variable | Helm Path | Default | Description |
|---|---|---|---|
|
|
| Auth mode: |
|
| (required) | Unique API endpoint |
|
|
| API version |
|
| (required) | Root scope ID for uploads |
|
|
| Parallel user lookups |
|
| (required) | Ingestion service endpoint |
Authentication Configuration
Set via mcpConfig.auth in Helm values:
Variable | Helm Path | Default | Description |
|---|---|---|---|
|
|
| MCP access token TTL |
|
|
| MCP refresh token TTL (30 days) |
Runtime Configuration
Set via server.env in Helm values:
Variable | Default | Description |
|---|---|---|
|
| Log level: |
|
| Node.js max heap size |
|
| Node environment |
Helm Values Reference
Full Example
server:
# Environment variables from secrets
envVars:
- secretRef:
name: teams-mcp-secrets
# Static environment variables
env:
LOG_LEVEL: info
MAX_HEAP_MB: 1920
NODE_ENV: production
# Resource limits
resources:
limits:
memory: 2048Mi
requests:
cpu: 1
memory: 1984Mi
# Temporary storage for processing
volumes:
- name: tmp
emptyDir:
sizeLimit: 20Gi
volumeMounts:
- name: tmp
mountPath: /tmp
# Application configuration
mcpConfig:
enabled: true
app:
selfUrl: https://teams.mcp.example.com
microsoft:
clientId: "12345678-1234-1234-1234-123456789012"
# publicWebhookUrl: https://teams.mcp.example.com # optional
unique:
serviceAuthMode: cluster_local
apiBaseUrl: http://api-gateway.unique:8080
apiVersion: "2023-12-06"
rootScopeId: folder_abc123 # Your root scope ID from Unique
userFetchConcurrency: 5
ingestionServiceBaseUrl: http://node-ingestion.unique:8091
auth:
accessTokenExpiresInSeconds: 60
refreshTokenExpiresInSeconds: 2592000
# Ingress is disabled by default - traffic routed via Kong Gateway
ingress:
enabled: false
# Monitoring
grafana:
dashboard:
enabled: true
folder: mcp-servers
alerts:
enabled: true
defaultAlerts:
graphql:
enabled: true
uniqueApi:
enabled: trueService Auth Modes
cluster_local (Default)
For deployments within the same Kubernetes cluster as Unique:
mcpConfig:
unique:
serviceAuthMode: cluster_local
apiBaseUrl: http://api-gateway.unique:8080
ingestionServiceBaseUrl: http://node-ingestion.unique:8091
serviceExtraHeaders:
x-company-id: "company-id"
x-user-id: "service-user-id"external
For deployments outside the Unique cluster:
mcpConfig:
unique:
serviceAuthMode: external
apiBaseUrl: https://api.unique.app
serviceExtraHeaders:
authorization: "Bearer <api-key>"
x-app-id: "app-id"
x-user-id: "user-id"
x-company-id: "company-id"Zitadel Service Account
Why a Zitadel Service Account is Required
The Teams MCP Server requires a Zitadel service account to authenticate with the Unique Public API. This service account is used to:
Retrieve matching user information - Look up users in Unique by email or username to resolve meeting participants
Create scopes (folders) - Create organizational folders in Unique for storing meeting transcripts and recordings
Set access permissions - Grant appropriate read/write permissions to meeting organizers and participants
Upload transcript and recording data - Ingest transcript content and recordings into the Unique knowledge base
The service account credentials are passed via the x-company-id and x-user-id headers in all API requests to ensure proper access control and authorization.
Creating a Zitadel Service Account
Navigate to Zitadel
Log in to your Zitadel instance
Select the organization where you want to ingest transcripts
Create Service Account
Go to Service Accounts in the organization settings
Click New Service Account
Provide a descriptive name (e.g., "Teams MCP Server Service Account")
Set appropriate permissions for the service account
Note the Service Account Details
Company ID: The organization ID where the service account was created
User ID: The service account user ID
Configure in Helm Values
yamlmcpConfig: unique: serviceAuthMode: cluster_local # or external serviceExtraHeaders: x-company-id: "<your-company-id>" x-user-id: "<your-service-account-user-id>"
Service Account Permissions
The service account must have permissions to:
Read user information (to resolve meeting participants)
Create scopes/folders in the organization
Create and modify access permissions
Upload content to the knowledge base
Ensure the service account has sufficient permissions in the target organization to perform these operations.
Root Scope
Why a Root Scope is Required
The Teams MCP Server requires a root scope (folder) in the Unique platform. All meeting transcripts and recordings are ingested as child scopes under this root, providing a single organizational entry point and making it easy to manage permissions and visibility for Teams content.
Creating the Root Scope
The root scope must be created manually in the Unique platform before deploying the Teams MCP Server. There is no automated provisioning for this step.
Log in to the Unique platform as an administrator
Create a new scope (folder)
Navigate to the scope/folder management area
Create a new top-level scope with a descriptive name (e.g., "Teams MCP")
Note the scope ID — it starts with
scope_(e.g.,scope_abc123xyz)
Grant the service account access
Ensure the Zitadel service account (see above) has read/write permissions on the root scope
Configure in Helm Values
yamlmcpConfig: unique: rootScopeId: "scope_abc123xyz"
One Scope Per Environment
Each environment (QA, prod, etc.) requires its own root scope. Do not reuse the same scope ID across environments.
Database Configuration
Connection String Format
postgresql://username:password@hostname:port/database?sslmode=requireRequired Extensions
The PostgreSQL database requires no special extensions. Migrations create all necessary tables and indexes.
RabbitMQ Configuration
Connection String Format
amqp://username:password@hostname:5672/vhostAlternative: Individual Fields
Instead of AMQP_URL, you can set individual fields:
Variable | Description |
|---|---|
| RabbitMQ username |
| RabbitMQ password |
| RabbitMQ hostname |
| RabbitMQ port (default: 5672) |
| Virtual host |
Security Best Practices
Rotate secrets regularly (especially
MICROSOFT_CLIENT_SECRET)Use managed identities where possible (Azure, AWS, GCP)
Encrypt secrets at rest (Kubernetes secrets encryption or external secret managers)
Limit network access (enable network policies)
Monitor for anomalies (use provided Grafana dashboards and alerts)
See Security Documentation for details.