Skip to content

Deploy the MCP Server

Choose your deployment method below. Each section includes optional OAuth (Microsoft Login) setup at the end.

Important: Retrain Before Export

If you have connections trained before MCP was added, retrain them first. Export a new mcp_export.zip after retraining, or the MCP server won't start.

Jump to Section


Zip Setup

Access required

  • SSH or terminal access to the Linux machine where the MCP server will run
  • sudo privileges
  • Python 3.10+ installed

Use this method if you received a mcp_export.zip file and don't have Docker.

This guide is for Linux only (Ubuntu 20.04 or later recommended). Windows users without Docker should contact Tursio support.

Before You Start

From Tursio, you need:

  • mcp_export.zip — your server package with API credentials

On your Linux machine, you need:

  • Ubuntu 20.04 or later (or another Debian-based distro)
  • Python 3.10 or higher. Check your version:
python3 --version

Look for something like Python 3.11.2. If the number after "Python 3." is 10 or higher, you're set.

If Python is missing or too old:

sudo apt-get install -y python3.11 python3.11-venv
  • unzip. Check if it's installed:
unzip -v

If not, install it:

sudo apt-get install -y unzip
  • sudo access — you need this to create /opt/tursio-mcp

Step 1 — Unzip the File

Open a terminal and run:

sudo mkdir -p /opt/tursio-mcp
sudo chown $USER /opt/tursio-mcp
unzip mcp_export.zip -d /opt/tursio-mcp

If you saved the file to your Downloads folder:

unzip ~/Downloads/mcp_export.zip -d /opt/tursio-mcp

Navigate to the folder:

cd /opt/tursio-mcp

Step 2 — Edit Your Config File

Open the config file. First, find available config files:

ls /opt/tursio-mcp/mcp/server/configs/*.yaml
nano /opt/tursio-mcp/mcp/server/configs/<your-config>.yaml

You'll see these fields at the top:

search_url: ...
context_url: ...
api_key: ...

Update all three:

Field Value
search_url https://<your-tursio-hostname>/nlp-search
context_url https://<your-tursio-hostname>/nlp-context
api_key Your API key from Tursio portal → Settings

Replace <your-tursio-hostname> with your company's Tursio portal address. Example: If your portal is at https://yourcompany.tursio.ai, set search_url to https://yourcompany.tursio.ai/nlp-search.

For Cassandra-backed datasets:

  • search_url: https://<your-tursio-hostname>/cassandra-search
  • context_url: https://<your-tursio-hostname>/cassandra-context

For DynamoDB-backed datasets:

  • search_url: https://<your-tursio-hostname>/dynamodb-search
  • context_url: https://<your-tursio-hostname>/dynamodb-context

Save the file.

Step 3 — Make the Startup Script Executable

chmod +x mcp/run.sh

You only need to do this once.

Step 4 — Start the Server

./mcp/run.sh

The first run takes a minute or two because it installs Python packages automatically. You'll see output like:

Log file: /opt/tursio-mcp/mcp/run.log
Auto-detected config: your-dataset-name
Using Python: Python 3.11.x
Creating virtual environment...
Virtualenv activated: /opt/tursio-mcp/mcp/.venv
Upgrading pip...
Installing dependencies...
Dependencies installed.
Starting server without OAuth...
Config: your-dataset-name
Port: 8000
INFO:root:Starting semantic context warmup
INFO:root:Semantic context warmup completed
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

When you see "Uvicorn running on http://0.0.0.0:8000", the server is up.

Later runs are faster because the virtual environment is already set up.

Step 5 — Keep the Server Running

Using systemd (recommended for servers)

Create a service file:

sudo tee /etc/systemd/system/tursio-mcp.service > /dev/null <<EOF
[Unit]
Description=Tursio MCP Server
After=network.target

[Service]
Type=simple
User=$USER
WorkingDirectory=/opt/tursio-mcp
ExecStart=/opt/tursio-mcp/mcp/run.sh
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable tursio-mcp
sudo systemctl start tursio-mcp

Check the status:

sudo systemctl status tursio-mcp

To stop the server:

sudo systemctl stop tursio-mcp

With systemd, the server restarts automatically if it crashes and starts when your machine boots.

Without systemd (quick background start)

nohup ./mcp/run.sh > /opt/tursio-mcp/startup.log 2>&1 &

The shell shows the process ID (PID). Save it so you can stop the server later:

[1] 12345

To stop the server:

kill 12345

Replace "12345" with your actual PID. Note: this method doesn't survive reboots.

Step 6 — Connect to Your AI Tool

Your server URL is http://your-server-address:8000/mcp. Replace your-server-address with your Linux machine's IP or hostname (use localhost if Claude Desktop is on the same machine).

Jump to Connect AI Tools for step-by-step instructions.

Troubleshooting

"Permission denied" when running ./mcp/run.sh

You skipped Step 3. Run this first:

chmod +x mcp/run.sh

Then try Step 4 again.

Server starts but immediately stops with an api_key error

Check your config file (Step 2). Make sure api_key is your real API key from Tursio portal → Settings, not placeholder text.

"Port 8000 already in use"

Another process is using port 8000. Start on a different port:

./mcp/run.sh --port 8001

Then use port 8001 in your AI tool configuration.

Server stopped after closing the terminal

You didn't use the background command from Step 5. Restart the server:

cd /opt/tursio-mcp
nohup ./mcp/run.sh > /opt/tursio-mcp/startup.log 2>&1 &

Something else went wrong

Check the log file for the full error:

cat /opt/tursio-mcp/mcp/run.log

Send this file to Tursio support.

Microsoft Login (OAuth) — Optional

Skip this section unless your IT team asked you to set up Microsoft login.

You need four values from your Azure App Registration:

What Where to find it in Azure Portal
Server's public URL The URL users will access, e.g. https://mcp.yourcompany.com
Client ID App registrations → your app → Application (client) ID
Client Secret App registrations → your app → Certificates & secrets → your secret's Value
Tenant ID App registrations → your app → Directory (tenant) ID

Run the server with these extra flags:

./mcp/run.sh \
  --port 8000 \
  --oauth \
  --url https://mcp.yourcompany.com \
  --client-id paste-your-client-id-here \
  --client-secret "paste-your-client-secret-here" \
  --tenant-id paste-your-tenant-id-here

Important: --url must have no trailing slash.

Set the Azure redirect URI to: https://mcp.yourcompany.com/auth/ms-callback

With OAuth enabled, users must sign in with their Microsoft account — this is expected.

Update your AI tool URL

With OAuth, the server needs a public URL. Localhost won't work.

Claude Desktop — update the config file:

{
  "mcpServers": {
    "tursio": {
      "url": "https://mcp.yourcompany.com/mcp"
    }
  }
}

Save and restart Claude Desktop.

Claude.ai (web):

  1. Go to Org / Admin Settings → Connectors → find your Tursio connector → Edit
  2. Change the Remote MCP server URL to https://mcp.yourcompany.com/mcp
  3. Click Save

In both cases, use your --url value with /mcp appended.


Docker Compose Setup

Access required

  • SSH or terminal access to the machine where the MCP server will run
  • Docker installed and running on that machine
  • The .tar image file and mcp_export.zip accessible on that machine

Use this method if you received a Docker image (.tar file) and an mcp_export.zip.

Before You Start

From Tursio, you need:

  • tursio-mcp-<version>.tar.gz — the Docker image
  • mcp_export.zip — your server package (connection ID is pre-configured)

You also need Docker installed. Check:

docker --version

If Docker isn't installed, get Docker Desktop from https://docs.docker.com/get-docker.

Step 1 — Load the Docker Image

Open a terminal in the folder with your .tar file and run:

docker load -i tursio-mcp-<version>.tar.gz

Replace with your actual filename. Example:

docker load -i tursio-mcp-v1.2.tar.gz

You'll see output like:

Loaded image: tursio.azurecr.io/tursio-mcp:v1.2

Save the image name for the next step.

Step 2 — Place Your mcp_export.zip

Copy the file to a permanent location:

Linux / Mac:

mkdir -p /opt/tursio
cp mcp_export.zip /opt/tursio/mcp_export.zip

Windows (PowerShell):

New-Item -ItemType Directory -Force -Path C:\tursio
Copy-Item mcp_export.zip C:\tursio\mcp_export.zip

Don't rename or unzip it. The Docker container reads it as-is.

Step 3 — Get Your Configuration Values

Before starting the server, get these from your Tursio portal:

  1. API key — Go to Tursio portal → Settings and copy your API key.
  2. Hostname — Your company's Tursio portal address, like https://yourcompany.tursio.ai.

Your URLs will be:

URL Value
Search https://<your-tursio-hostname>/nlp-search
Context https://<your-tursio-hostname>/nlp-context

For Cassandra-backed datasets:

  • Search: https://<your-tursio-hostname>/cassandra-search
  • Context: https://<your-tursio-hostname>/cassandra-context

For DynamoDB-backed datasets:

  • Search: https://<your-tursio-hostname>/dynamodb-search
  • Context: https://<your-tursio-hostname>/dynamodb-context

Keep these handy for the next step.

Step 4 — Start the Server

Using Docker Compose (Recommended)

Tursio provides a compose.yaml and env.example file.

  1. Copy the env template:

    cp env.example .env
    
  2. Edit .env with your values:

    VERSION=v1.2              - image tag
    ZIP_PATH=/opt/tursio/mcp_export.zip  - from Step 2
    MCP_PORT=8000
    API_KEY=paste-your-api-key-here      - from Step 3
    SEARCH_URL=https://yourcompany.tursio.ai/nlp-search  - from Step 3
    CONTEXT_URL=https://yourcompany.tursio.ai/nlp-context  - from Step 3
    
  3. Start the server:

    docker compose up -d
    
  4. Check the status:

    docker compose logs tursio-mcp
    

You should see the startup output (see Step 5 below for details).

Upgrading to a New Version

When Tursio sends a new .tar file:

docker load -i tursio-mcp-<new-version>.tar.gz

Update .env:

VERSION=<new-version>

Restart:

docker compose up -d

Your configuration stays the same.

Useful Commands

Task Command
View live logs docker compose logs -f tursio-mcp
Stop the server docker compose stop
Start the server docker compose start
Restart the server docker compose restart
Remove everything docker compose down

Without Docker Compose

If you don't have Docker Compose, run this command instead.

Linux / Mac:

docker run -d \
  --name tursio-mcp \
  --restart unless-stopped \
  -p 8000:8000 \
  -v /opt/tursio/mcp_export.zip:/app/server.zip:ro \
  -e MCP_PORT=8000 \
  -e API_KEY=paste-your-api-key-here \
  -e SEARCH_URL=https://<your-tursio-hostname>/nlp-search \
  -e CONTEXT_URL=https://<your-tursio-hostname>/nlp-context \
  tursio.azurecr.io/tursio-mcp:<version>

Windows (PowerShell):

docker run -d `
  --name tursio-mcp `
  --restart unless-stopped `
  -p 8000:8000 `
  -v C:\tursio\mcp_export.zip:/app/server.zip:ro `
  -e MCP_PORT=8000 `
  -e API_KEY=paste-your-api-key-here `
  -e SEARCH_URL=https://<your-tursio-hostname>/nlp-search `
  -e CONTEXT_URL=https://<your-tursio-hostname>/nlp-context `
  tursio.azurecr.io/tursio-mcp:<version>

Replace the image name with yours from Step 1.

Step 5 — Check the Server Status

docker compose logs tursio-mcp

You should see:

Extracting config from /app/server.zip...
Extracted: your-dataset-name.yaml
Extraction complete.
Auto-detected config: your-dataset-name
Starting server without OAuth on port 8000...
INFO:root:Starting semantic context warmup
INFO:root:Semantic context warmup completed
INFO:     Started server process [1]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

If you see "Uvicorn running on http://0.0.0.0:8000", the server is up.

The warmup messages are normal — the server pre-loads your Tursio context on startup.

Step 6 — Connect to Your AI Tool

Your server URL is http://your-server-address:8000/mcp. Replace your-server-address with your machine's IP or hostname (use localhost if on the same machine).

The server restarts automatically after reboots thanks to restart: unless-stopped.

Jump to Connect AI Tools for step-by-step instructions.

Troubleshooting

"Cannot connect to the Docker daemon"

Docker isn't running. Open Docker Desktop, wait for it to fully start, then try again.

"No such file or directory" when loading the image

You're in the wrong folder. Navigate to where your .tar file is saved, then try again.

Logs show: ERROR: No server.zip found at /app/server.zip

Your ZIP_PATH in .env is wrong. Check that it points to the correct location and the file exists there.

Logs show: ERROR: api_key ... is still a placeholder

Set API_KEY in .env to your real API key from Tursio portal → Settings.

Logs show: port is already allocated

Another process is using port 8000. Change MCP_PORT=8001 in .env and run docker compose up -d. Use port 8001 in your AI tool config.

Server stopped after closing the terminal

This shouldn't happen with restart: unless-stopped, but if it does, run:

docker compose start

Microsoft Login (OAuth) — Optional

Skip this section unless your IT team asked you to set up Microsoft login.

In your .env file, add:

OAUTH_ENABLED=true
PUBLIC_URL=https://mcp.yourcompany.com
MICROSOFT_CLIENT_ID=paste-your-client-id-here
MICROSOFT_CLIENT_SECRET=paste-your-client-secret-here
MICROSOFT_TENANT_ID=paste-your-tenant-id-here

The server needs a public HTTPS URL. Register this as the redirect URI in your Azure App Registration:

https://mcp.yourcompany.com/auth/ms-callback

Restart the server:

docker compose up -d

Kubernetes Setup

Access required

  • kubectl configured and pointing at the target cluster
  • Docker on a machine that can reach the cluster's image registry
  • Permissions to create namespaces, apply manifests, exec into pods, and tail logs

Use this method if you're deploying to a Kubernetes cluster.

This guide covers only the MCP server. It assumes the Tursio portal is already deployed and accessible.

No dedicated public IP or running multiple tenants? See Customization for path-based routing with NGINX, Traefik, or Azure Application Gateway. Want to keep secrets out of your manifest? See Secret Management Options for alternatives to putting credentials in mcp-server.yaml.

Before You Start

From Tursio, you need:

  • tursio-mcp-<version>.tar.gz — the MCP server image
  • mcp_export.zip — your server package (connection ID is pre-configured)

You also need:

  • A running Kubernetes cluster with kubectl access
  • Docker on a machine that can reach the cluster

Verify kubectl is connected:

kubectl cluster-info

Step 1 — Load the MCP Image

On a machine with Docker access to your cluster's registry:

docker load -i tursio-mcp-<version>.tar.gz

You'll see:

Loaded image: tursio.azurecr.io/tursio-mcp:<version>

Save this image name for Step 3.

Now make the image available to your cluster. Choose one option:

Option A — Push to your private registry (recommended for multi-node clusters):

docker tag tursio.azurecr.io/tursio-mcp:<version> \
  registry.yourcompany.com/tursio-mcp:<version>
docker push registry.yourcompany.com/tursio-mcp:<version>

Then update the image: field in mcp-server.yaml to use your registry path.

Option B — Load directly on a single node:

Copy the .tar file to the target node and run:

docker load -i tursio-mcp-<version>.tar.gz

Then uncomment nodeName in mcp-server.yaml and set it to that node's name.

Step 2 — Create the Namespace and Load Your Package

Create the namespace:

kubectl create namespace tursio-mcp

Load your mcp_export.zip as a Secret:

kubectl create secret generic tursio-mcp-zip \
  --from-file=server.zip=mcp_export.zip \
  -n tursio-mcp --dry-run=client -o yaml | kubectl apply -f -

Run this command again whenever you get an updated mcp_export.zip, then restart the deployment (see the Upgrading section below).

Step 3 — Configure the Manifest

Open mcp-server.yaml and fill in these values:

Location Field Value
Secret API_KEY Your Tursio API key from Tursio portal → Settings
ConfigMap SEARCH_URL https://<your-tursio-hostname>/nlp-search
ConfigMap CONTEXT_URL https://<your-tursio-hostname>/nlp-context
Deployment image Your image from Step 1

Replace <your-tursio-hostname> with your company's Tursio portal address.

For Cassandra-backed datasets:

  • SEARCH_URL: https://<your-tursio-hostname>/cassandra-search
  • CONTEXT_URL: https://<your-tursio-hostname>/cassandra-context

For DynamoDB-backed datasets:

  • SEARCH_URL: https://<your-tursio-hostname>/dynamodb-search
  • CONTEXT_URL: https://<your-tursio-hostname>/dynamodb-context

Secret Management Options

By default, credentials go directly into mcp-server.yaml. This is fine for testing, but don't commit real values to git.

Option A — Separate secrets file (recommended for teams)

Extract the Secret to a separate file mcp-secrets.yaml, fill in real values there, and add it to .gitignore. Apply both files:

kubectl apply -f mcp-server.yaml -f mcp-secrets.yaml

Leave the Secret block in mcp-server.yaml with placeholder values so it's safe to commit.

Option B — Azure Key Vault (AKS, production)

Store API_KEY and MICROSOFT_CLIENT_SECRET in Azure Key Vault and mount them using the Secrets Store CSI Driver. No Kubernetes Secret object is needed. See: https://learn.microsoft.com/en-us/azure/aks/csi-secrets-store-driver

Step 4 — Deploy

kubectl apply -f mcp-server.yaml

Check the pod status:

kubectl get pods -n tursio-mcp

You should see STATUS: Running and READY: 1/1.

Check the logs:

kubectl logs deployment/tursio-mcp -n tursio-mcp

Look for:

INFO:    Uvicorn running on http://0.0.0.0:8000

Step 5 — Expose the Server

The manifest creates a Service on port 8000 and exposes it as a LoadBalancer. Your cloud provider assigns an external IP.

Get the external IP:

kubectl get svc tursio-mcp -n tursio-mcp

Access the server at:

http://<external-ip>:8000/mcp

For Microsoft OAuth or AI tools that need HTTPS, configure TLS at your load balancer or reverse proxy. The MCP server itself runs on plain HTTP internally.

If the Tursio portal is in the same cluster and you are not using OAuth, you don't need to expose the MCP server externally. Connect directly using the internal cluster DNS:

http://tursio-mcp.tursio-mcp.svc.cluster.local:8000/mcp

This does not work with OAuth — the OAuth redirect callback requires a public HTTPS URL. If OAuth is enabled, expose the server externally and set PUBLIC_URL accordingly.

Step 6 — Connect to Your AI Tool

Your server URL is http://<your-mcp-endpoint>/mcp from Step 5.

Jump to Connect AI Tools for step-by-step instructions.

Upgrading

New mcp_export.zip:

kubectl create secret generic tursio-mcp-zip \
  --from-file=server.zip=mcp_export.zip \
  -n tursio-mcp --dry-run=client -o yaml | kubectl apply -f -
kubectl rollout restart deployment/tursio-mcp -n tursio-mcp

New image version:

Load and push the new image (as in Step 1), update the image: tag in mcp-server.yaml, then:

kubectl apply -f mcp-server.yaml
kubectl rollout status deployment/tursio-mcp -n tursio-mcp

Microsoft Login (OAuth) — Optional

Skip this section unless your IT team asked you to set up Microsoft login.

In mcp-server.yaml, uncomment the OAuth fields in the ConfigMap and Secret:

ConfigMap
OAUTH_ENABLED: "true"
PUBLIC_URL: "https://mcp.yourcompany.com"
MICROSOFT_CLIENT_ID: "paste-your-client-id-here"
MICROSOFT_TENANT_ID: "paste-your-tenant-id-here"
Secret
MICROSOFT_CLIENT_SECRET: "paste-your-client-secret-here"

The server needs a public HTTPS URL. Register this as the redirect URI in your Azure App Registration:

https://mcp.yourcompany.com/auth/ms-callback

Apply the changes:

kubectl apply -f mcp-server.yaml

Troubleshooting

Pod is in CrashLoopBackOff

Check the logs:

kubectl logs deployment/tursio-mcp -n tursio-mcp
Log message Fix
ERROR: Missing required env vars A required value is missing from the ConfigMap or Secret in mcp-server.yaml
ERROR: API_KEY looks like a placeholder Set API_KEY to your real Tursio API key from Tursio portal → Settings
ERROR: No server.zip found The zip Secret wasn't created — run the kubectl create secret command from Step 2
ERROR: No .yaml config files found in zip The mcp_export.zip is invalid or corrupt — re-export from the Tursio portal

Pod is Running but AI tool cannot connect

  • Make sure the service is reachable from outside the cluster
  • Check your ingress or load balancer configuration
  • If using a LoadBalancer, allow port 8000 in your firewall / security group

Connect AI Tools

Once your Tursio MCP server is running, connect your AI client using the server URL from Step 6 of your deployment method.

For web-based AI tools (Claude.ai, ChatGPT, Copilot), the MCP server must be accessible via a public HTTPS URL. Claude Desktop can connect to a local server on localhost.

Claude

Availability: Custom connectors using remote MCP are free on Claude.

Claude Desktop

Open the Claude Desktop config file:

  • Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add this, replacing the URL with your server address:

{
  "mcpServers": {
    "tursio": {
      "url": "http://your-server-address:8000/mcp"
    }
  }
}

Save the file and restart Claude Desktop.

Cursor

Go to Settings → MCP and add a new server with your server URL.

Claude.ai (web)

  1. Go to Org / Admin Settings → Connectors (sidebar) → Add custom connector
  2. Select MCP
  3. Enter a Name (e.g., Tursio) and your Remote MCP server URL
  4. Click Add

Follow Anthropic's official MCP instructions to add a custom connector.

Screenshot

ChatGPT

Availability:

  • MCP is available in developer mode beta for Pro, Plus, Business, Enterprise, and Education accounts on the web.

ChatGPT developer mode is a beta feature that enables full MCP client support. Follow these steps to create an app that connects to your Tursio MCP server:

  1. Enable developer mode: Click your profile → Settings

    Screenshot

  2. Go to Apps → Advanced settings

    Screenshot

  3. Find Developer mode and enable it

    Screenshot

  4. Go back and click Create app

    Screenshot

  5. Fill in the details. If dynamic discovery is enabled on your MCP server, you only need a name and URL. Otherwise, you may also need the client ID and secret

    Screenshot

  6. Click Create. It will log in and refresh the page, then you'll see your tool ready

    Screenshot

  7. Select the tool and use it as shown below

    Screenshot

    Screenshot

Microsoft Copilot

Availability

  • Requires a Copilot Studio License. Trial or developer accounts are available.

Microsoft offers MCP support across Copilot products, with Copilot Studio providing the smoothest integration.

  1. Open Copilot Studio and log in. Select Agents from the sidebar, then click Create blank agent

    Screenshot

  2. Wait a moment for the setup to complete. When the screen loads, click Add tool

    Screenshot

  3. From the model options, choose Model Context Protocol

    Screenshot

  4. Fill in the details. Select OAuth 2.0 and Dynamic Discovery if enabled

    Screenshot

  5. Once done, click Create new connection to add a connection

    Screenshot

  6. Click Create on the next screen. It will sign in using the URL you provided

    Screenshot

  7. Click Add and Configure

    Screenshot

  8. Type "hi" in the test chatbox. If prompted to configure the connection, click Open connection manager

    Screenshot

  9. Click Connect, then click Submit in the modal. A popup will appear for Microsoft OAuth login

    Screenshot

  10. Once connected, go back to the test agent tab and try another query

    Screenshot

    Screenshot


Microsoft Teams

This document outlines the high-level architecture, data flows, and security model for the Tursio agent in Microsoft Teams.

System Architecture

The diagram below illustrates the high-level components and the flow of information among the user platform (Microsoft Teams), the Teams Agent, and the Tursio Backend.

Screenshot

Security & Authentication

The architecture enforces multiple layers of security and authentication to ensure data privacy and appropriate access control across services.

Teams Users and Client

Admins control which users have access to Tursio’s Teams Agent. Once they have access, users can use the agent in three ways:

Screenshot

  1. Direct conversation: From the Apps sidebar in Teams, go to “Built for your org” and install the “Tursio” app. Once installed, choose “Open” to start a direct conversation.
  2. Group conversation / Channel / Meeting: People who have access to the Tursio Agent can also add it to a group chat or a channel, and only they can trigger the agent to respond. Note that anyone present in that conversation can see the responses.
  3. Copilot tooling: Once the “Tursio” app is installed, it can also be added as a tool in your Copilot conversation.

Teams Client to Teams Agent

All interactions originating from Microsoft Teams are securely authenticated via the Microsoft Bot Framework. This layer utilizes Entra ID (Azure Active Directory) validation. The Teams Agent verifies the cryptographic tokens attached to each incoming message to confirm user identity and tenant origin before processing the request.

Teams Agent to LLM Service

The Teams Agent communicates with the LLM Service over an encrypted TLS connection. Access is governed via OpenAI API key authorization, ensuring the reasoning engine is accessible only from approved infrastructure. Note that this LLM service is the same instance already used by the Tursio Backend.

Teams Agent to Tursio MCP Server

When the AI determines that answers must be retrieved from the Tursio backend, the Teams Agent initiates a query via the Tursio MCP Server. This connection implements OAuth 2.0 / Bearer Token authentication. The Teams Agent must hold a valid, non-expired access token, obtained through a secure authentication flow (e.g., Client Credentials), to successfully query the MCP Server.

Tursio MCP Server to Tursio Backend

The Tursio MCP Server routes the query into the core Tursio Search API. This layer uses restrictive API key authentication or license tokens tied directly to specific datasets. This ensures that even authenticated MCP Server instances can only query data repositories for which they hold explicit configuration licenses.

Note

Admins can create multiple database connections in the Tursio portal and expose one with limited data access to a MCP Server. For example, users may request a limited set of aggregated information directly within Teams, but will need to visit the Tursio portal for more details. Multiple database connections can each be exposed through a different MCP server and Teams agent, enabling proper isolation and access control.

Deployment

Deploying the Tursio Teams agent leverages the official Microsoft 365 Agents Toolkit to configure and provision the resources for hosting the Teams agent in your Azure environment.

Prerequisites

  1. Ensure you hold a Microsoft 365 Tenant with permissions to upload custom Teams apps.
  2. Have an Azure account to provide the resources and host the Teams agent online.
  3. Have an OpenAI API key (or Azure OpenAI setup) ready.

Required Configuration Variables

The application relies on specific environment variables. These are mapped into the execution context (maintained in a .env file locally and within the App Service configuration remotely).

Key variables (setup in environment config):

  • OPENAI_API_KEY: Your OpenAI or Azure AI API key.
  • OPENAI_MODEL_NAME: e.g., gpt-5.2 or your specific deployment model name.
  • MCP_SERVER_URL: The public HTTPS endpoint of your Tursio MCP Server (e.g., https://demo.tursio.ai/mcp).

Deployment Process

Tursio provides a packaged Teams agent solution, and a script will automatically deploy the agent using your M365 and Azure accounts. The script internally uses the official Microsoft Teams toolkit teamsapp-cli and executes the following steps in the command line to guide the deployment process:

  1. Log in to your Microsoft 365 (Teams) account
  2. Log in to your Azure account (to create the infrastructure)
  3. Provision the Azure resources for the Tursio Teams agent
  4. Deploy the agent to the newly created Azure App Service
  5. Submit to publish the agent app to your Teams admin portal

After the agent is deployed, you can navigate to the Teams admin portal to approve the app and publish it to your org. Once published, organization members can install the Tursio Teams Agent as an app within their Teams client, while administrators can configure policies to control app access for specific user groups.

Audit Logs

The Teams logs are available for the admins in the Teams admin panel. For direct or copilot conversation, the respective activities are logged. For group conversation, the activity for adding and triggering the agent is also logged.

All requests by the Tursio Agent to the Tursio Backend are logged into the Tursio portal.

Customization

Path-Based Routing — Multiple Tenants on a Single Public IP

Use this setup when you need to run multiple MCP server instances behind a single public endpoint, each serving a different tenant or dataset.

Each instance runs as a separate MCP server instance or service and is assigned a unique path prefix. A reverse proxy (e.g. Azure Application Gateway) routes requests to the correct instance based on the path — with no URL rewriting.

Tenant Path Prefix Connector URL
Tenant A /tenant-a https://<host>/tenant-a/mcp
Tenant B /tenant-b https://<host>/tenant-b/mcp

Each MCP server instance must be configured with:

  • PATH_PREFIX — the path prefix assigned to that instance (e.g. /tenant-a)
  • PUBLIC_URL — the full public base URL including the prefix (e.g. https://<host>/tenant-a)

Configuration by Deployment Mode

Deploy one mcp-server.yaml per tenant, each with its own namespace or a distinct deployment name. In the ConfigMap, set:

PATH_PREFIX: "/tenant-a"
PUBLIC_URL: "https://<host>/tenant-a"
OAUTH_ENABLED: "true"
MICROSOFT_CLIENT_ID: "paste-your-client-id-here"
MICROSOFT_TENANT_ID: "paste-your-tenant-id-here"

And in the Secret:

MICROSOFT_CLIENT_SECRET: "paste-your-client-secret-here"

Repeat with /tenant-b and https://<host>/tenant-b for the second tenant.

Run a separate compose.yaml per tenant in its own directory, each with its own .env file:

# Tenant A — .env
PATH_PREFIX=/tenant-a
PUBLIC_URL=https://<host>/tenant-a
OAUTH_ENABLED=true
MICROSOFT_CLIENT_ID=paste-your-client-id-here
MICROSOFT_CLIENT_SECRET=paste-your-client-secret-here
MICROSOFT_TENANT_ID=paste-your-tenant-id-here
# Tenant B — .env
PATH_PREFIX=/tenant-b
PUBLIC_URL=https://<host>/tenant-b
OAUTH_ENABLED=true
MICROSOFT_CLIENT_ID=paste-your-client-id-here
MICROSOFT_CLIENT_SECRET=paste-your-client-secret-here
MICROSOFT_TENANT_ID=paste-your-tenant-id-here

Each tenant's compose stack must use a different host port (e.g. 8001 and 8002). The reverse proxy routes to those ports based on path.

Edit each instance's config file at /opt/tursio-mcp/mcp/server/configs/<your-config>.yaml and set:

path_prefix: /tenant-a
public_url: https://<host>/tenant-a
oauth_enabled: true
microsoft_client_id: paste-your-client-id-here
microsoft_client_secret: paste-your-client-secret-here
microsoft_tenant_id: paste-your-tenant-id-here

Run each instance on a different port and configure your reverse proxy to forward to the correct port based on path.


How PATH_PREFIX Works

Each MCP pod uses PATH_PREFIX to know which requests belong to it. The gateway forwards the full path unchanged — the pod reads the prefix, registers its routes under it, and strips it internally before processing.

Request: GET /tenant-a/mcp
Gateway matches /tenant-a/* → forwards to Pod A (no URL rewrite)
Pod A reads PATH_PREFIX=/tenant-a → handles /mcp
Response: 200 OK

The same instance also registers tenant-specific OAuth discovery endpoints with the tenant identifier as a path segment after /.well-known/oauth-authorization-server/ (e.g. /.well-known/oauth-authorization-server/tenant-a), which is why the gateway needs explicit rules for those paths — they don't fall under the /* catch-all.

Reverse Proxy Routing Rules

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tursio-mcp
  namespace: tursio-mcp
  annotations:
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
spec:
  ingressClassName: nginx
  rules:
    - host: <your-host>
      http:
        paths:
          - path: /tenant-a
            pathType: Prefix
            backend:
              service:
                name: tursio-mcp-tenant-a
                port:
                  number: 8000
          - path: /tenant-b
            pathType: Prefix
            backend:
              service:
                name: tursio-mcp-tenant-b
                port:
                  number: 8000

No URL rewriting — paths are forwarded as-is. Set PATH_PREFIX=/tenant-a and PATH_PREFIX=/tenant-b on each pod respectively.

OAuth: Also add explicit rules for /.well-known/oauth-authorization-server/tenant-a and /.well-known/oauth-authorization-server/tenant-b pointing to the correct backend — these paths don't start with /tenant-* so they won't be matched by the Prefix rules above.

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: tursio-mcp
  namespace: tursio-mcp
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`<your-host>`) && PathPrefix(`/tenant-a`)
      kind: Rule
      services:
        - name: tursio-mcp-tenant-a
          port: 8000
    - match: Host(`<your-host>`) && PathPrefix(`/tenant-b`)
      kind: Rule
      services:
        - name: tursio-mcp-tenant-b
          port: 8000

Traefik forwards the full path unchanged. Set PATH_PREFIX=/tenant-a and PATH_PREFIX=/tenant-b on each pod respectively.

OAuth: Also add PathPrefix(`/.well-known/oauth-authorization-server/tenant-a`) and the equivalent for tenant-b as separate routes pointing to the correct service — these won't be matched by the /tenant-* rules.

Configure path-based routing rules in your Application Gateway HTTP listener. No URL rewriting — paths are forwarded as-is.

Path(s) Backend pool
/tenant-a/* tenant-a pod
/tenant-b/* tenant-b pod
/.well-known/oauth-authorization-server/tenant-a
/.well-known/openid-configuration/tenant-a
/.well-known/oauth-protected-resource/tenant-a
tenant-a pod
/.well-known/oauth-authorization-server/tenant-b
/.well-known/openid-configuration/tenant-b
/.well-known/oauth-protected-resource/tenant-b
tenant-b pod

In the Azure Portal: Application Gateway → Rules → Path-based routing — add one rule per tenant pointing to separate backend pools. Ensure URL rewrite is disabled on all rules.

Set PATH_PREFIX=/tenant-a and PATH_PREFIX=/tenant-b on each pod respectively.

The /.well-known/ rules are required for OAuth

When Claude connects, it fetches /.well-known/oauth-authorization-server/<path-prefix> for OAuth discovery. Without a gateway rule routing this to the correct pod, OAuth fails with a 404.


Azure App Registration

Register one redirect URI per tenant under Authentication in your Azure App Registration:

https://<host>/tenant-a/auth/ms-callback
https://<host>/tenant-b/auth/ms-callback

Connector URLs

Give these URLs to users when adding the connector in their AI tool:

https://<host>/tenant-a/mcp
https://<host>/tenant-b/mcp