# AI desk Pro MCP Server (Preview)
# Overview
AI desk Pro exposes a Model Context Protocol (MCP) server for each agent. MCP is an open standard that allows AI applications, development tools, and orchestration platforms to interact with external tools in a standardized way.
When MCP is enabled on an agent, any MCP-compatible client (Claude Desktop, VS Code Copilot, custom orchestrators, and so on) can chat with the agent using its full knowledge base, documents, and configured data sources, just as a user would in Microsoft Teams or the webchat.
# Use cases
- AI-assisted development: Connect your agent to Claude Desktop or VS Code so developers can query internal documentation, HR policies, or IT procedures without leaving their IDE.
- Multi-agent orchestration: Use AI desk Pro agents as tools within a larger AI pipeline or agent framework.
- Internal system integration: Let internal platforms call the agent programmatically to answer user questions.
- Custom applications: Build your own chat interface or workflow that uses the agent's knowledge.
# How it works
The MCP server exposes the Streamable HTTP transport (the recommended transport, used by Claude Desktop and VS Code) at a single endpoint per agent (POST /mcp/{agent-id}), and also keeps the legacy HTTP + SSE (Server-Sent Events) transport for older clients. MCP clients connect to a dedicated endpoint for the agent and authenticate with a Microsoft Entra ID token. Once connected, the client can invoke three tools:
chat: send a question and receive a generated answer with citations.search: run a query against the knowledge base and get the matching passages back directly, with relevance scores and no generated answer.get_reference: turn any citation returned bychatorsearchinto something openable: a preview link for a local document, Microsoft Graph coordinates for a SharePoint document, or the full question/answer content for a QnA.
# Prerequisites
Before configuring MCP, ensure you have:
- Administrator access to the agent in AI desk Pro
- Access to the Microsoft Entra ID portal (to register or configure a client application)
- An MCP-compatible client application
# Enable MCP on an agent
MCP access is gated at two levels, and both must be satisfied, otherwise the server rejects connections:
- Subscription level: the MCP Server feature must be available on your plan/subscription. If it is not included in your subscription, the server returns
403regardless of the agent toggle. - Agent level: the MCP toggle must be turned on for the specific agent.
To turn on the agent toggle:
- Sign in to AI desk Pro
- Open the agent you want to expose via MCP
- Navigate to Configuration > Agent Customization
- Go to the Features tab
- Toggle MCP to On
- Save your changes
403 even though the agent toggle is On, confirm the MCP Server feature is included in your subscription plan.Once MCP is enabled, connection information appears on the agent's Information page:
| Field | Description |
|---|---|
| MCP Endpoint | The base URL for the MCP server (for example, https://admin.aidesk-pro.com/mcp/{agent-id}) |
| Application ID | The Microsoft Entra ID application ID used for authentication |
| Audience URI | The audience value to request in the OAuth token (for example, api://admin.aidesk-pro.com/botid-{application-id}) |
You will need these three values to configure both the Azure client application and the MCP client.
# Configure the Microsoft Entra ID client application
To authenticate with the MCP server, you need to register (or update) a client application in Microsoft Entra ID that has permission to request tokens for the agent's API.
# Step 1: Register a client application (or use an existing one)
- Go to the Azure Portal (opens new window) > Microsoft Entra ID > App registrations
- Click New registration (or select an existing application)
- Enter a name (for example,
MCP Client - AI desk Pro) - Set Supported account types to Accounts in this organizational directory only
- Click Register
- Note the Application (client) ID; you will need it for the MCP client configuration
# Step 2: Create a client secret
- In your client application, go to Certificates & secrets
- Click New client secret
- Enter a description and expiration period
- Click Add
- Copy the Value immediately; it will not be shown again
# Step 3: Add API permissions
You need to grant your client application permission to call the agent's API. The agent's API is exposed by the SSO application shown on the agent's Information page.
The MCP Server only supports the delegated (on-behalf-of-user) flow. Application permissions (service-to-service / client credentials) are not supported: every call must be made on behalf of a signed-in user so that the agent can enforce per-user permissions on the underlying knowledge sources.
- In your client application, go to API permissions
- Click Add a permission > APIs my organization uses
- Search for the Application ID shown on the agent's Information page
- Select Delegated permissions; the MCP client acts on behalf of a signed-in user
- Select the available permission scope and click Add permissions
# Step 4: Acquire a token
Your MCP client must obtain a JWT access token from Microsoft Entra ID before connecting, using the delegated (user) flow:
POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&client_id={your-client-app-id}
&scope={audience-uri}/.default
&code={authorization-code}
&redirect_uri={your-redirect-uri}
&client_secret={your-client-secret}
Replace {audience-uri} with the Audience URI from the agent's Information page.
The token's audience (
aud claim) must match one the server accepts, or the request is rejected with 401. The server validates against the host admin.aidesk-pro.com, so the audience must be the raw Application ID or api://admin.aidesk-pro.com/botid-{application-id}. A token issued for api://api.aidesk-pro.com/... (the old host) will be rejected. Always copy the exact Audience URI from the agent's Information page.# Connect an MCP client
# Connection settings
All MCP clients need the following information:
| Setting | Value |
|---|---|
| Server URL | The MCP Endpoint from the agent's Information page (https://admin.aidesk-pro.com/mcp/{agent-id}) |
| Transport | Streamable HTTP (recommended). Legacy HTTP + SSE is also supported for older clients |
| Authentication | Bearer token (Microsoft Entra ID JWT) |
# Claude Desktop
Add the following to your Claude Desktop MCP configuration file (claude_desktop_config.json). Use the Streamable HTTP endpoint (no /sse suffix):
{
"mcpServers": {
"aidesk-pro": {
"type": "http",
"url": "https://admin.aidesk-pro.com/mcp/{agent-id}",
"headers": {
"Authorization": "Bearer {your-access-token}"
}
}
}
}
# VS Code (GitHub Copilot)
In your VS Code settings.json, add an MCP server entry:
{
"mcp": {
"servers": {
"aidesk-pro": {
"type": "http",
"url": "https://admin.aidesk-pro.com/mcp/{agent-id}",
"headers": {
"Authorization": "Bearer {your-access-token}"
}
}
}
}
}
# Custom client (programmatic)
Any MCP SDK can connect to the server. Here is an example using the TypeScript MCP SDK:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
const transport = new StreamableHTTPClientTransport(
new URL("https://admin.aidesk-pro.com/mcp/{agent-id}"),
{
requestInit: {
headers: {
Authorization: "Bearer {your-access-token}",
},
},
}
);
const client = new Client({ name: "my-app", version: "1.0.0" });
await client.connect(transport);
// List available tools
const tools = await client.listTools();
console.log(tools);
// Chat with the agent
const result = await client.callTool("chat", {
message: "What is our company's remote work policy?",
});
console.log(result);
# Protocol reference (advanced)
This section describes the raw JSON-RPC flow for developers building a custom client without an MCP SDK. If you use an MCP SDK (TypeScript, Python, C#), these steps are handled automatically.
# Streamable HTTP (recommended)
Streamable HTTP uses a single endpoint (POST /mcp/{agent-id}) for every JSON-RPC message. There is no separate SSE channel to keep open: each request gets its response on the same HTTP call.
# 1: Initialize the session
POST the initialize request to the endpoint with the Bearer token:
POST /mcp/{agent-id} HTTP/1.1
Host: admin.aidesk-pro.com
Authorization: Bearer {access-token}
Content-Type: application/json
Accept: application/json, text/event-stream
{
"jsonrpc": "2.0",
"id": "init-1",
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": {
"name": "my-client",
"version": "1.0.0"
}
}
}
The server's response includes an Mcp-Session-Id response header. Send this header back on every subsequent request:
Mcp-Session-Id: {session-id-from-initialize-response}
# 2: List available tools
POST /mcp/{agent-id} HTTP/1.1
Host: admin.aidesk-pro.com
Authorization: Bearer {access-token}
Mcp-Session-Id: {session-id}
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": "tools-1",
"method": "tools/list",
"params": {}
}
The response includes the chat, search, and get_reference tools with their parameter schemas.
# 3: Call the chat tool
{
"jsonrpc": "2.0",
"id": "chat-1",
"method": "tools/call",
"params": {
"name": "chat",
"arguments": {
"message": "What is our remote work policy?",
"chatId": null
}
}
}
The JSON-RPC result contains the chat response (answer, citations, chatId, and so on).
# 4: Call the search tool
{
"jsonrpc": "2.0",
"id": "search-1",
"method": "tools/call",
"params": {
"name": "search",
"arguments": {
"query": "remote work eligibility",
"maxResults": 5
}
}
}
The JSON-RPC result contains the ranked passages (query and results) and no generated answer.
# HTTP + SSE (legacy)
# 1: Open the SSE connection
Connect to the SSE endpoint with the Bearer token:
GET /mcp/{agent-id}/sse HTTP/1.1
Host: admin.aidesk-pro.com
Authorization: Bearer {access-token}
Accept: text/event-stream
The server responds with a stream. Wait for the endpoint event:
event: endpoint
data: /mcp/message?sessionId=abc123
This gives you the message URL to send JSON-RPC requests to. Prepend the base URL and insert the agent ID:
POST https://admin.aidesk-pro.com/mcp/{agent-id}/message?sessionId=abc123
Keep the SSE connection open; all responses will arrive through it. The JSON-RPC initialize, tools/list, and tools/call payloads are identical to the Streamable HTTP flow above; only the transport differs.
# Available tools
The MCP server exposes three tools: chat, search, and get_reference.
Which tool to call: use search when you want the raw sources and intend to read them yourself, and chat when you want the agent to compose the answer for you. In both cases, get_reference turns a returned source into something you can open.
# chat
Chat with the AI desk Pro agent using its knowledge base, documents, and configured data sources.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
message | string | Yes | The user's question or query |
chatId | string | No | A chat session ID to continue an existing conversation |
Response (JSON):
| Field | Type | Description |
|---|---|---|
answer | string | The complete answer from the agent |
chatId | string | The chat session ID (use this to continue the conversation) |
chatMessageId | string | The unique ID of this response message |
citations | array | Sources and documents used to generate the answer (see below) |
error | object | Error details if the request failed (contains code and message) |
Citation shape:
Each item in citations carries the metadata you need to display the source and, if wanted, retrieve it via get_reference:
| Field | Type | Description |
|---|---|---|
referenceId | string | Identifier to pass back to get_reference. Empty when the source has no resolvable backing entity |
sourceType | string | The kind of source: Document or Qna. Pass it to get_reference alongside referenceId |
sourceName | string | Human-readable name: filename or QnA question |
snippet | string | The passage of text that supports the citation |
mimeType | string | MIME type of the source file (empty for QnAs) |
relevanceScore | number | Relevance of the citation against the query (higher is better) |
fileVersion | string | File version when known (empty for QnAs / unversioned sources) |
fileLastUpdate | string | Last-update timestamp of the source when known |
# search
Query the agent's knowledge base and get the matching passages back directly, with relevance scores and reference IDs, and without a generated answer. Use it for agentic retrieval: issue several short, focused queries, then read and combine the passages yourself.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | A short, focused, single-topic search query |
maxResults | integer | No | Maximum number of results to return. Default 10, maximum 50 |
chatId | string | No | An existing chat session ID to reuse. When omitted, a temporary session is created for the lookup |
Response (JSON):
| Field | Type | Description |
|---|---|---|
query | string | The query that was searched |
results | array | The matching passages, ordered by relevanceScore (highest first). Each item uses the same citation shape as the chat tool, so you can pass referenceId and sourceType straight to get_reference |
Good to know:
- A search is not a conversation turn: no chat message is stored and the passages are not added to the conversation history. Passing a
chatIdreuses that session for the lookup, nothing more. searchenforces the same access rules aschat: the agent must belong to your tenant, MCP must be available on the subscription, and the MCP toggle must be on. SharePoint permissions are re-checked for the signed-in user, exactly as in Microsoft Teams.- Passing a
chatIdthat does not exist returns400.
The
search call passes the agent's configured Document Match Threshold, the minimum match confidence a document passage must reach to be used. MCP results therefore respect the same relevance floor as answers in Microsoft Teams and the webchat: a passage that is too weak to be cited in Teams is not returned to your MCP client either. See Document Match Threshold.Example:
{
"query": "remote work eligibility",
"maxResults": 5
}
# get_reference
Resolve a citation returned by chat or search into an openable preview URL (local documents), Microsoft Graph coordinates (SharePoint documents), or the full QnA content. The agent re-checks that the reference belongs to it and re-validates the signed-in user's permissions before returning anything.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
referenceId | string | Yes | The referenceId from a citation returned by chat or a result returned by search |
sourceType | string | Yes | The citation's sourceType: Document or Qna |
Response (JSON): the same response shape is used for every kind of source; only the relevant fields are populated.
sourceTypeThe
sourceType you send is the citation's coarse type: Document or Qna. The sourceType the server returns is more specific: a Document resolves to Local, Sharepoint, or SharepointPage, while a Qna stays Qna. Branch your handling on the response value, not the input.Local document (sourceType = Local), a file stored by AI desk Pro:
| Field | Type | Description |
|---|---|---|
fileName | string | The document filename |
mimeType | string | MIME type of the file |
previewUrl | string | A ready-to-open, Office Online-compatible preview link. The link is signed and short-lived |
expiresAt | string | Expiry timestamp of previewUrl (default TTL: 1 hour) |
SharePoint document (sourceType = Sharepoint or SharepointPage), an indexed SharePoint file or page:
| Field | Type | Description |
|---|---|---|
fileName | string | The document filename |
mimeType | string | MIME type of the file |
webUrl | string | The SharePoint URL of the item |
driveId | string | Microsoft Graph drive ID (typically null for pages) |
driveItemId | string | Microsoft Graph drive item ID (typically null for pages) |
siteId | string | Microsoft Graph site ID |
pageId | string | Graph page ID (populated for SharePoint pages) |
For SharePoint sources, the MCP server returns coordinates only; it does not issue Microsoft Graph tokens. To open
webUrl or download via /drives/{driveId}/items/{driveItemId}/content, your client must obtain its own Graph access token (for example, through an interactive sign-in). The user's SharePoint permissions are re-checked server-side first, so a 403 is returned if the user is not allowed to read the document.QnA (sourceType = Qna):
| Field | Type | Description |
|---|---|---|
question | string | The QnA question |
answer | string | The QnA answer (see answerType for its format) |
answerType | string | Simple (plain text), Card (adaptive card JSON), or Dialog (serialized dialog flow) |
Error codes:
These apply to get_reference specifically; 401 and 403 can be returned by any MCP call (see the Error codes reference below).
| Code | Cause |
|---|---|
400 | Empty referenceId or sourceType, unknown sourceType, or a non-GUID QnA referenceId |
403 | Reference belongs to another agent, SharePoint permission denied, or tenant mismatch |
404 | Document or QnA not found within the agent's scope |
Example (Single question):
{
"message": "What are the steps to request a day off?"
}
Example (Continue a conversation):
{
"message": "And what about sick leave?",
"chatId": "abc123-def456-..."
}
# Error codes
The MCP server returns standard HTTP status codes. The most common ones across all calls:
| Code | Meaning | Typical cause |
|---|---|---|
400 | Bad request | Missing or invalid parameters (for example, empty referenceId/sourceType, unknown sourceType, non-GUID QnA referenceId, or a chatId that does not exist) |
401 | Unauthorized | Missing, expired, or invalid token, or a token whose audience (aud) does not match an accepted value (see Correct audience required) |
403 | Forbidden | MCP not available on the subscription, MCP toggle off on the agent, reference belongs to another agent, SharePoint permission denied, or tenant mismatch |
404 | Not found | The document or QnA does not exist within the agent's scope |
# Important information
- MCP is currently a Preview feature; it may evolve or change during this phase
- The MCP server version is 0.2.0
- Authentication requires a valid Microsoft Entra ID JWT token
- MCP must be available on the subscription and enabled on the agent (both levels are required)
- Each agent has its own dedicated MCP endpoint
- Chat sessions persist across calls when using the same
chatId - Document retrieval, for both
chatandsearch, respects the agent's Document Match Threshold - Content filtering is applied to all MCP interactions, just like in Teams or webchat