#
tokens: 16162/50000 18/18 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .gitignore
├── .mcpbignore
├── .npmignore
├── .vscode
│   └── settings.json
├── CODE_OF_CONDUCT.md
├── icon.png
├── LICENSE
├── manifest.json
├── package.json
├── README.md
├── SECURITY.md
├── src
│   ├── cli.ts
│   ├── constants.ts
│   ├── index.ts
│   ├── instructions.ts
│   ├── tools.ts
│   ├── types.ts
│   └── utils.ts
├── SUPPORT.md
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------

```
 1 | # Source files (as they'll be compiled)
 2 | src/
 3 | 
 4 | # Development files
 5 | node_modules/
 6 | .vscode/
 7 | .git/
 8 | .gitignore
 9 | 
10 | # Test files
11 | test/
12 | *.test.ts
13 | *.spec.ts
14 | 
15 | # Configuration files
16 | tsconfig.json
17 | .eslintrc*
18 | .prettierrc*
19 | 
20 | # Miscellaneous
21 | .DS_Store
22 | *.log
23 | npm-debug.log*
```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
 1 | # Dependency directories
 2 | node_modules/
 3 | 
 4 | # Build output
 5 | build/
 6 | dist/
 7 | *.dxt
 8 | *.mcpb
 9 | 
10 | # Logs
11 | logs/
12 | *.log
13 | npm-debug.log*
14 | yarn-debug.log*
15 | yarn-error.log*
16 | 
17 | # IDE specific files
18 | .idea/
19 | !.vscode/
20 | 
21 | # Environment variables
22 | .env
23 | 
24 | # OS specific files
25 | .DS_Store
26 | Thumbs.db
27 | 
```

--------------------------------------------------------------------------------
/.mcpbignore:
--------------------------------------------------------------------------------

```
 1 | # Development files
 2 | src/
 3 | types/
 4 | tests/
 5 | 
 6 | # Configuration files
 7 | .npmrc
 8 | tsconfig.json
 9 | 
10 | # Documentation files
11 | docs/
12 | *.md
13 | 
14 | # Logs
15 | logs/
16 | *.log
17 | npm-debug.log*
18 | yarn-debug.log*
19 | yarn-error.log*
20 | 
21 | # IDE specific files
22 | .idea/
23 | .vscode/
24 | 
25 | # Environment variables
26 | .env
27 | 
28 | # OS specific files
29 | .DS_Store
30 | Thumbs.db
31 | 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Microsoft Clarity MCP Server
  2 | 
  3 | This is a Model Context Protocol (MCP) server for the Microsoft Clarity.
  4 | It allows you to access your session recordings, project analytics, and documentation from Clarity using Claude for Desktop or other MCP-compatible clients.
  5 | 
  6 | ## Key Features
  7 | 
  8 | - **Analytics Data Access**: Query your Microsoft Clarity analytics data including traffic metrics, user behavior insights, and performance statistics
  9 | - **Session Recording Retrieval**: Access and analyze session recordings to understand user interactions and identify optimization opportunities
 10 | - **Natural Language Querying**: Ask questions in plain English to get insights from your data - no need to learn complex query syntax or API endpoints
 11 | - **Flexible Data Filtering**: Filter results by various dimensions such as browser, device, country, and many more
 12 | - **Real-Time Data Access**: Fetch the latest analytics data and insights from your Clarity projects on-demand
 13 | - **Documentation Integration**: Get quick answers and guidance from Microsoft Clarity documentation directly within your workflow
 14 | - **Seamless MCP Integration**: Works natively with Claude for Desktop, Visual Studio Code, and other Model Context Protocol (MCP) compatible clients
 15 | 
 16 | ## Setup and Installation
 17 | 
 18 | ### Prerequisites
 19 | 
 20 | - Node.js v16 or higher
 21 | - A Microsoft Clarity account and API token
 22 | - Any MCP-compatible client (Claude for Desktop, etc.)
 23 | 
 24 | ### Installation
 25 | 
 26 | #### Option 1: Install via npm (recommended)
 27 | 
 28 | You can install and run this package directly using npm:
 29 | 
 30 | ```bash
 31 | # Install globally
 32 | npm install -g @microsoft/clarity-mcp-server
 33 | 
 34 | # Run the server
 35 | clarity-mcp-server
 36 | ```
 37 | 
 38 | #### Option 2: Run with npx without installing
 39 | 
 40 | You can run the server directly using npx without installing:
 41 | 
 42 | ```bash
 43 | npx @microsoft/clarity-mcp-server
 44 | ```
 45 | 
 46 | With either option, you can provide your Clarity API token using the `--clarity_api_token` parameter:
 47 | 
 48 | ```bash
 49 | npx @microsoft/clarity-mcp-server --clarity_api_token=your-token-here
 50 | ```
 51 | 
 52 | #### Option 3: Manual Installation
 53 | 
 54 | 1. Clone or download this repository
 55 | 2. Install dependencies:
 56 |    ```
 57 |    npm install
 58 |    ```
 59 | 3. Build the TypeScript code:
 60 |    ```
 61 |    npm run build
 62 |    ```
 63 | 4. Run the server:
 64 |    ```
 65 |    npm run start
 66 |    ```
 67 | 
 68 | ### Extension/Plugin Installation
 69 | 
 70 | #### Visual Studio Code Extension
 71 | 
 72 | [<img src="https://img.shields.io/badge/VS_Code-VS_Code?style=flat-square&label=Install+Server&color=0098FF" alt="Install in VS Code">](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522clarity-server%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540microsoft%252Fclarity-mcp-server%2522%255D%257D)
 73 | 
 74 | Click the button above to install the Microsoft Clarity MCP server directly in Visual Studio Code.
 75 | 
 76 | #### Claude Desktop Plugin
 77 | 
 78 | Install from Claude's extension gallery:
 79 | 
 80 | 1. Open **Claude Desktop**
 81 | 2. Navigate to **File → Settings → Extensions**
 82 | 3. Search for **Microsoft Clarity**
 83 | 4. Click **Install** to add the extension
 84 | 5. Configure your **API Token**:
 85 |    <br>
 86 |    Follow the instructions in the [API Token section](#api-token) to retrieve and set it up correctly.
 87 | 
 88 | ## Configuration
 89 | 
 90 | You can provide the [Clarity data export API](https://learn.microsoft.com/en-us/clarity/setup-and-installation/clarity-data-export-api) token in two ways:
 91 | 
 92 | 1. **Command Line Arguments**:
 93 |    ```bash
 94 |    npx @microsoft/clarity-mcp-server --clarity_api_token=your-token
 95 |    ```
 96 | 
 97 | 2. **Tool Parameters**:
 98 |    <br>
 99 |    Provide `token` as a parameter when calling the `get-clarity-data` tool
100 | 
101 | ## Configuring MCP Clients
102 | 
103 | ### Generic MCP Client Configuration
104 | 
105 | MCP clients typically require configuration to connect to the server. Here's a general example of how to configure an MCP client:
106 | 
107 | ```json
108 | {
109 |   "mcpServers": {
110 |     "@microsoft/clarity-mcp-server": {
111 |       "command": "npx",
112 |       "args": [
113 |         "@microsoft/clarity-mcp-server",
114 |         "--clarity_api_token=your-api-token-here"
115 |       ]
116 |     }
117 |   }
118 | }
119 | ```
120 | 
121 | The specifics of where and how to add this configuration will depend on your specific MCP client.
122 | 
123 | ### Claude for Desktop Configuration
124 | 
125 | To configure Claude for Desktop to use this server:
126 | 
127 | 1. Open your Claude for Desktop configuration file:
128 |    - **Windows**: `%AppData%\Claude\claude_desktop_config.json`
129 |    - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
130 | 2. Add the configuration shown in the generic example above
131 | 3. Save the configuration file and restart Claude for Desktop
132 | 
133 | ## Server Usage
134 | 
135 | The server exposes various tools that you can call from any MCP client.
136 | Just ask naturally and keep each request focused on one thing.
137 | 
138 | ### Query Analytics Dashboard
139 | - <b>Name:</b> `query-analytics-dashboard`
140 | - <b>Description:</b> Retrieves analytics data and metrics from your project's dashboard using a simplified natural language search query.
141 | - <b>Examples:</b>
142 |   - How many Clarity sessions did we get from Egypt in the past 3 days?
143 |   - What are the most used browsers in my Clarity project?
144 |   - Show me traffic metrics from my Clarity project for the last week
145 | 
146 | ### List Session Recordings
147 | - <b>Name:</b> `list-session-recordings`
148 | - <b>Description:</b> Lists your project's session recordings based on a specified filtering criteria. The filters allow you to narrow down the recordings by various fields such as URLs, device types, browser, OS, country, city, and more.
149 | - <b>Examples:</b>
150 |   - List the most recent Clarity sessions from mobile devices
151 |   - Show the top 5 Clarity sessions with the highest number of user clicks
152 |   - Get Clarity recordings where users encountered JavaScript errors
153 | 
154 | ### Query Documentation Resources
155 | - <b>Name:</b> `query-documentation-resources`
156 | - <b>Description:</b> Retrieves snippets from Microsoft Clarity documentation to find answers to user questions including step-by-step screenshots for setup guides, features, usage, troubleshooting, and integration instructions.
157 | - <b>Examples:</b>
158 |   - How to track custom events using Microsoft Clarity?
159 |   - How many labels can I add to a recording in Microsoft Clarity?
160 | 
161 | ## API Token
162 | 
163 | ### Getting Your API Token
164 | 
165 | To generate an API token:
166 | 
167 | 1. Go to your Clarity project
168 | 2. Select Settings → Data Export → Generate new API token
169 | 3. Provide a descriptive name for the token
170 | 4. Save the generated token securely
171 | 
172 | ## Privacy Policy
173 | 
174 | For information about data privacy and usage, please refer to the [Microsoft Clarity Privacy Policy](https://clarity.microsoft.com/privacy).
175 | 
176 | ## License
177 | 
178 | This project is licensed under the <b>MIT</b> License.
179 | 
```

--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------

```markdown
 1 | # Microsoft Open Source Code of Conduct
 2 | 
 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
 4 | 
 5 | Resources:
 6 | 
 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
 9 | - Contact [[email protected]](mailto:[email protected]) with questions or concerns
10 | 
```

--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------

```markdown
 1 | <!-- BEGIN MICROSOFT SECURITY.MD V0.0.9 BLOCK -->
 2 | 
 3 | ## Security
 4 | 
 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin).
 6 | 
 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below.
 8 | 
 9 | ## Reporting Security Issues
10 | 
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 | 
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report).
14 | 
15 | If you prefer to submit without logging in, send email to [[email protected]](mailto:[email protected]).  If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp).
16 | 
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 
18 | 
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 | 
21 |   * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 |   * Full paths of source file(s) related to the manifestation of the issue
23 |   * The location of the affected source code (tag/branch/commit or direct URL)
24 |   * Any special configuration required to reproduce the issue
25 |   * Step-by-step instructions to reproduce the issue
26 |   * Proof-of-concept or exploit code (if possible)
27 |   * Impact of the issue, including how an attacker might exploit the issue
28 | 
29 | This information will help us triage your report more quickly.
30 | 
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs.
32 | 
33 | ## Preferred Languages
34 | 
35 | We prefer all communications to be in English.
36 | 
37 | ## Policy
38 | 
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd).
40 | 
41 | <!-- END MICROSOFT SECURITY.MD BLOCK -->
42 | 
```

--------------------------------------------------------------------------------
/src/cli.ts:
--------------------------------------------------------------------------------

```typescript
1 | #!/usr/bin/env node
2 | 
3 | // This is the CLI entry point for the npx executable
4 | import './index.js';
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "@microsoft/clarity-mcp-server",
 3 |   "version": "2.0.1",
 4 |   "description": "MCP Server for Microsoft Clarity based on data export API",
 5 |   "author": "Microsoft",
 6 |   "license": "MIT",
 7 |   "type": "module",
 8 |   "main": "dist/index.js",
 9 |   "homepage": "https://clarity.microsoft.com/",
10 |   "repository": {
11 |     "type": "git",
12 |     "url": "https://github.com/microsoft/clarity-mcp-server"
13 |   },
14 |   "keywords": [
15 |     "clarity",
16 |     "behavior-analytics-tools",
17 |     "heatmaps",
18 |     "session-recordings",
19 |     "insights",
20 |     "analytics",
21 |     "mcp",
22 |     "model-context-protocol",
23 |     "ai",
24 |     "agents"
25 |   ],
26 |   "bin": {
27 |     "clarity-mcp-server": "./dist/cli.js"
28 |   },
29 |   "scripts": {
30 |     "build": "tsc",
31 |     "start": "node dist/index.js",
32 |     "dev": "tsc && node dist/index.js",
33 |     "prepublishOnly": "npm run build"
34 |   },
35 |   "dependencies": {
36 |     "@modelcontextprotocol/sdk": "^1.20.2",
37 |     "zod": "^3.25.76"
38 |   },
39 |   "devDependencies": {
40 |     "@types/node": "^20.19.23",
41 |     "typescript": "^5.9.3"
42 |   }
43 | }
44 | 
```

--------------------------------------------------------------------------------
/SUPPORT.md:
--------------------------------------------------------------------------------

```markdown
 1 | # TODO: The maintainer of this repo has not yet edited this file
 2 | 
 3 | **REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project?
 4 | 
 5 | - **No CSS support:** Fill out this template with information about how to file issues and get help.
 6 | - **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps.
 7 | - **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide.
 8 | 
 9 | *Then remove this first heading from this SUPPORT.MD file before publishing your repo.*
10 | 
11 | # Support
12 | 
13 | ## How to file issues and get help  
14 | 
15 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 
16 | issues before filing new issues to avoid duplicates.  For new issues, file your bug or 
17 | feature request as a new Issue.
18 | 
19 | For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE 
20 | FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER
21 | CHANNEL. WHERE WILL YOU HELP PEOPLE?**.
22 | 
23 | ## Microsoft Support Policy  
24 | 
25 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above.
26 | 
```

--------------------------------------------------------------------------------
/src/tools.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import {
 2 |   ANALYTICS_DASHBOARD_URL,
 3 |   CLARITY_API_TOKEN,
 4 |   DOCUMENTATION_URL,
 5 |   SESSION_RECORDINGS_URL
 6 | } from "./constants.js";
 7 | import {
 8 |   type FiltersType,
 9 |   type SortOptionsType,
10 |   SortOptionsEnum
11 | } from "./types.js";
12 | import { tryAsync } from "./utils.js";
13 | 
14 | export async function queryAnalyticsDashboardAsync(
15 |   query: string,
16 |   timezone: string,
17 | ): Promise<any> {
18 |   return await tryAsync(ANALYTICS_DASHBOARD_URL, {
19 |     method: 'POST',
20 |     headers: {
21 |       'Content-Type': 'application/json',
22 |       ...(CLARITY_API_TOKEN ? { 'Authorization': `Bearer ${CLARITY_API_TOKEN}` } : {}),
23 |     },
24 |     body: JSON.stringify({
25 |       query: query,
26 |       timezone: timezone,
27 |     })
28 |   });
29 | }
30 | 
31 | export async function queryDocumentationAsync(query: string): Promise<any> {
32 |   return await tryAsync(DOCUMENTATION_URL, {
33 |     method: 'POST',
34 |     headers: {
35 |       'Content-Type': 'application/json',
36 |       ...(CLARITY_API_TOKEN ? { 'Authorization': `Bearer ${CLARITY_API_TOKEN}` } : {})
37 |     },
38 |     body: JSON.stringify({
39 |       query: query,
40 |     })
41 |   });
42 | }
43 | 
44 | export async function listSessionRecordingsAsync(
45 |   startDate: Date,
46 |   endDate: Date,
47 |   filters: FiltersType,
48 |   sortBy: SortOptionsType,
49 |   count: number
50 | ): Promise<any> {
51 |   return await tryAsync(SESSION_RECORDINGS_URL, {
52 |     method: 'POST',
53 |     headers: {
54 |       'Content-Type': 'application/json',
55 |       ...(CLARITY_API_TOKEN ? { 'Authorization': `Bearer ${CLARITY_API_TOKEN}` } : {})
56 |     },
57 |     body: JSON.stringify({
58 |       sortBy: SortOptionsEnum[sortBy],
59 |       start: startDate.toISOString(),
60 |       end: endDate.toISOString(),
61 |       filters: filters,
62 |       count: count
63 |     })
64 |   });
65 | }
66 | 
```

--------------------------------------------------------------------------------
/src/constants.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { getConfigValue } from "./utils.js";
 2 | 
 3 | export const CLARITY_API_TOKEN = getConfigValue('clarity_api_token');
 4 | 
 5 | // Endpoint URLs.
 6 | export const API_BASE_URL = `https://clarity.microsoft.com/mcp`;
 7 | export const SESSION_RECORDINGS_URL = `${API_BASE_URL}/recordings/sample`;
 8 | export const ANALYTICS_DASHBOARD_URL = `${API_BASE_URL}/dashboard/query`;
 9 | export const DOCUMENTATION_URL = `${API_BASE_URL}/documentation/query`;
10 | 
11 | // Tool names.
12 | export const ANALYTICS_DASHBOARD_TOOL = "query-analytics-dashboard";
13 | export const DOCUMENTATION_TOOL = "query-documentation-resources";
14 | export const SESSION_RECORDINGS_TOOL = "list-session-recordings";
15 | 
16 | // Tool descriptions.
17 | export const ANALYTICS_DASHBOARD_DESCRIPTION = "Fetch Microsoft Clarity analytics data using a simplified natural language search query. The query should be focused on one specific data retrieval or aggregation task. Avoid complex multi-purpose queries. Time ranges should be explicitly specified when possible. If no time range is provided, prompt the user to specify one.";
18 | export const DOCUMENTATION_DESCRIPTION = "Retrieve Microsoft Clarity documentation snippets for finding answers to user questions including step-by-step screenshots for setup guides, features, usage, troubleshooting, and integration instructions. The query should be focused on one specific documentation topic or question. Avoid complex multi-purpose queries.";
19 | export const SESSION_RECORDINGS_DESCRIPTION = "List Microsoft Clarity session recordings based on specified filters. The filters allow you to narrow down the recordings by various criteria such as URLs, device types, browser, OS, country, city, and more. The date filter is required and must be in UTC ISO 8601 format.";
20 | 
```

--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { CLARITY_API_TOKEN } from "./constants.js";
 2 | 
 3 | // Get configuration from environment variables or command-line arguments
 4 | export const getConfigValue = (name: string, fallback?: string): string | undefined => {
 5 |   // Check command line args first (format: --name=value)
 6 |   const commandArg = process.argv.find(arg => arg.startsWith(`--${name}=`));
 7 |   if (commandArg) {
 8 |     return commandArg.split('=')[1];
 9 |   }
10 | 
11 |   // Then check environment variables
12 |   if (process.env[name] || process.env[name.toUpperCase()]) {
13 |     return process.env[name] || process.env[name.toUpperCase()];
14 |   }
15 | 
16 |   return fallback;
17 | };
18 | 
19 | export const tryAsync = async (input: string | URL | Request, init?: RequestInit | undefined): Promise<any> => {
20 |   // Use provided token or fallback to environment/command-line variables
21 |   // Check if we have the necessary credentials
22 |   if (!CLARITY_API_TOKEN) {
23 |     return {
24 |       content: [
25 |         {
26 |           type: "text",
27 |           text: "No Clarity API token provided. Please provide a token via the 'token' parameter, CLARITY_API_TOKEN environment variable, or --clarity_api_token command-line argument.",
28 |         },
29 |       ],
30 |     };
31 |   }
32 | 
33 |   try {
34 |     const response = await fetch(input, init);
35 | 
36 |     if (!response.ok) {
37 |       throw new Error(`Endpoint request failed with status: ${input} ${response.status}`);
38 |     }
39 | 
40 |     const data = await response.json();
41 | 
42 |     return {
43 |       content: [
44 |         {
45 |           type: "text",
46 |           text: JSON.stringify(data, null, 2),
47 |         },
48 |       ],
49 |     };
50 |   } catch (error) {
51 |     console.error("Error during fetch:", error);
52 |     return {
53 |       content: [
54 |         {
55 |           type: "text",
56 |           text: "An error occurred while fetching the data.",
57 |         },
58 |       ],
59 |     };
60 |   }
61 | };
62 | 
```

--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   //
 3 |   // File Settings
 4 |   //
 5 | 
 6 |   "files.insertFinalNewline": true,
 7 |   "files.trimFinalNewlines": true,
 8 |   "files.trimTrailingWhitespace": true,
 9 |   "files.eol": "\r\n",
10 | 
11 |   //
12 |   // Editor Settings
13 |   //
14 | 
15 |   // Indentation.
16 |   "editor.detectIndentation": false,
17 |   "editor.insertSpaces": true,
18 |   "editor.tabSize": 2,
19 | 
20 |   // Wrapping.
21 |   "editor.rulers": [220],
22 |   "editor.wordWrap": "wordWrapColumn",
23 |   "editor.wordWrapColumn": 220,
24 |   "editor.wrappingIndent": "indent",
25 | 
26 |   // Formatting.
27 |   "editor.defaultFormatter": "vscode.typescript-language-features",
28 |   "editor.formatOnSave": true,
29 |   "editor.formatOnPaste": false,
30 | 
31 |   // Code actions.
32 |   "editor.codeActionsOnSave": {
33 |     "source.fixAll": "explicit",
34 |     "source.fixAll.eslint": "explicit",
35 |     "source.organizeImports": "explicit"
36 |   },
37 | 
38 |   //
39 |   // Typescript Settings
40 |   //
41 | 
42 |   // Preferences.
43 |   "typescript.preferences.importModuleSpecifier": "non-relative",
44 |   "typescript.preferences.organizeImports": {
45 |     "enabled": true,
46 |     "sortImports": true,
47 |     "sortAndCombineImports": true
48 |   },
49 |   "typescript.preferences.preferTypeOnlyAutoImports": true,
50 |   "typescript.preferences.quoteStyle": "double",
51 | 
52 |   // Formatting.
53 |   "typescript.format.enable": true,
54 |   "typescript.format.indentSwitchCase": true,
55 |   "typescript.format.insertSpaceAfterCommaDelimiter": true,
56 |   "typescript.format.insertSpaceAfterConstructor": false,
57 |   "typescript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,
58 |   "typescript.format.insertSpaceAfterKeywordsInControlFlowStatements": true,
59 |   "typescript.format.insertSpaceAfterOpeningAndBeforeClosingEmptyBraces": true,
60 |   "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true,
61 |   "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false,
62 |   "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false,
63 |   "typescript.format.insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false,
64 |   "typescript.format.insertSpaceAfterSemicolonInForStatements": true,
65 |   "typescript.format.insertSpaceBeforeAndAfterBinaryOperators": true,
66 |   "typescript.format.insertSpaceBeforeFunctionParenthesis": false,
67 |   "typescript.format.placeOpenBraceOnNewLineForControlBlocks": false,
68 |   "typescript.format.placeOpenBraceOnNewLineForFunctions": false,
69 |   "typescript.format.semicolons": "insert",
70 | 
71 |   // Code actions.
72 |   "typescript.updateImportsOnFileMove.enabled": "always",
73 |   "typescript.updateImportsOnPaste.enabled": true,
74 | }
75 | 
```

--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "manifest_version": "0.2",
 3 |   "name": "@microsoft/clarity-mcp-server",
 4 |   "display_name": "Microsoft Clarity",
 5 |   "version": "2.0.1",
 6 |   "description": "MCP Server for Microsoft Clarity",
 7 |   "long_description": "This extension enables integration between AI systems and Microsoft Clarity, providing access to project analytics, documentation, and session recordings.",
 8 |   "author": {
 9 |     "name": "Microsoft",
10 |     "url": "https://clarity.microsoft.com",
11 |     "email": "[email protected]"
12 |   },
13 |   "repository": {
14 |     "type": "git",
15 |     "url": "https://github.com/microsoft/clarity-mcp-server"
16 |   },
17 |   "homepage": "https://clarity.microsoft.com",
18 |   "documentation": "https://github.com/microsoft/clarity-mcp-server",
19 |   "support": "https://github.com/microsoft/clarity-mcp-server/issues",
20 |   "icon": "icon.png",
21 |   "server": {
22 |     "type": "node",
23 |     "entry_point": "dist/index.js",
24 |     "mcp_config": {
25 |       "command": "node",
26 |       "args": [
27 |         "${__dirname}/dist/index.js"
28 |       ],
29 |       "env": {
30 |         "CLARITY_API_TOKEN": "${user_config.api_token}"
31 |       }
32 |     }
33 |   },
34 |   "tools": [
35 |     {
36 |       "name": "list-session-recordings",
37 |       "description": "List Microsoft Clarity session recordings timeline information. Returns metadata including session link, duration, and a timeline of relevant user interactions."
38 |     },
39 |     {
40 |       "name": "query-documentation-data",
41 |       "description": "Fetch Microsoft Clarity documentation snippets for finding answers to user questions including step-by-step screenshots for setup guides, features, usage, troubleshooting, and integration instructions. The query should be focused on one specific documentation topic or question. Avoid complex multi-purpose queries."
42 |     },
43 |     {
44 |       "name": "query-analytics-data",
45 |       "description": "Fetch Microsoft Clarity analytics data using a simplified natural language search query. The query should be focused on one specific data retrieval or aggregation task. Avoid complex multi-purpose queries. Time ranges should be explicitly specified when possible. If no time range is provided, prompt the user to specify one."
46 |     }
47 |   ],
48 |   "tools_generated": false,
49 |   "keywords": [
50 |     "clarity",
51 |     "api",
52 |     "analytics",
53 |     "behavior-analytics-tools",
54 |     "heatmaps",
55 |     "session-recordings",
56 |     "mcp",
57 |     "data insights",
58 |     "insights",
59 |     "model-context-protocol",
60 |     "ai",
61 |     "agent"
62 |   ],
63 |   "license": "MIT",
64 |   "privacy_policies": [
65 |     "https://clarity.microsoft.com/privacy"
66 |   ],
67 |   "compatibility": {
68 |     "claude_desktop": ">=0.10.0",
69 |     "platforms": [
70 |       "darwin",
71 |       "win32",
72 |       "linux"
73 |     ],
74 |     "runtimes": {
75 |       "node": ">=16.0.0"
76 |     }
77 |   },
78 |   "user_config": {
79 |     "api_token": {
80 |       "type": "string",
81 |       "title": "Clarity API Token",
82 |       "description": "Provide your Clarity data export API token",
83 |       "required": true,
84 |       "sensitive": true
85 |     }
86 |   }
87 | }
88 | 
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | 
  4 | import pkg from "../package.json" with { type: "json" };
  5 | 
  6 | import {
  7 |   ANALYTICS_DASHBOARD_DESCRIPTION,
  8 |   ANALYTICS_DASHBOARD_TOOL,
  9 |   CLARITY_API_TOKEN,
 10 |   DOCUMENTATION_DESCRIPTION,
 11 |   DOCUMENTATION_TOOL,
 12 |   SESSION_RECORDINGS_DESCRIPTION,
 13 |   SESSION_RECORDINGS_TOOL
 14 | } from "./constants.js";
 15 | import {
 16 |   SYSTEM_INSTRUCTIONS_PROMPT
 17 | } from "./instructions.js";
 18 | import {
 19 |   listSessionRecordingsAsync,
 20 |   queryAnalyticsDashboardAsync,
 21 |   queryDocumentationAsync
 22 | } from "./tools.js";
 23 | import {
 24 |   ListRequest,
 25 |   SearchRequest,
 26 | } from "./types.js";
 27 | 
 28 | // Create server instance
 29 | const server = new McpServer(
 30 |   {
 31 |     name: pkg.name,
 32 |     version: pkg.version,
 33 |     capabilities: {
 34 |       resources: {},
 35 |       tools: {}
 36 |     },
 37 |   },
 38 |   {
 39 |     instructions: SYSTEM_INSTRUCTIONS_PROMPT,
 40 |   }
 41 | );
 42 | 
 43 | // Register the query-analytics-data tool
 44 | server.tool(
 45 |   ANALYTICS_DASHBOARD_TOOL,             /* Name */
 46 |   ANALYTICS_DASHBOARD_DESCRIPTION,      /* Description */
 47 |   SearchRequest,                        /* Parameter Schema */
 48 |   {                                     /* Metadata & Annotations */
 49 |     title: "Query Analytics Dashboard",
 50 |     readOnlyHint: true,
 51 |     destructiveHint: false,
 52 |     openWorldHint: false
 53 |   },
 54 |   async ({ query }) => {
 55 |     return await queryAnalyticsDashboardAsync(query, Intl.DateTimeFormat().resolvedOptions().timeZone);
 56 |   }
 57 | );
 58 | 
 59 | // Register the session-recordings tool
 60 | server.tool(
 61 |   SESSION_RECORDINGS_TOOL,              /* Name */
 62 |   SESSION_RECORDINGS_DESCRIPTION,       /* Description */
 63 |   ListRequest,                          /* Parameter Schema */
 64 |   {                                     /* Metadata & Annotations */
 65 |     title: "List Session Recordings",
 66 |     readOnlyHint: true,
 67 |     destructiveHint: false,
 68 |     openWorldHint: false
 69 |   },
 70 |   async ({ filters, sortBy, count }) => {
 71 |     const now = new Date().toISOString();
 72 | 
 73 |     // Calculate end as now, start as now - numOfDays
 74 |     const endDate = new Date(filters?.date?.end || now);
 75 |     const startDate = new Date(filters?.date?.start || now);
 76 | 
 77 |     if (!filters?.date?.start) {
 78 |       startDate.setDate(endDate.getDate() - 2);
 79 |     }
 80 | 
 81 |     return await listSessionRecordingsAsync(startDate, endDate, filters, sortBy, count);
 82 |   }
 83 | );
 84 | 
 85 | // Register the query-documentation-resources tool
 86 | server.tool(
 87 |   DOCUMENTATION_TOOL,                   /* Name */
 88 |   DOCUMENTATION_DESCRIPTION,            /* Description */
 89 |   SearchRequest,                        /* Parameter Schema */
 90 |   {                                     /* Metadata & Annotations */
 91 |     title: "Query Documentation Resources",
 92 |     readOnlyHint: true,
 93 |     destructiveHint: false,
 94 |     openWorldHint: false
 95 |   },
 96 |   async ({ query }) => {
 97 |     return await queryDocumentationAsync(query);
 98 |   }
 99 | );
100 | 
101 | // Main function
102 | async function main() {
103 |   // Log configuration status
104 |   if (CLARITY_API_TOKEN) {
105 |     console.error("Clarity API token configured via environment/command-line");
106 |   } else {
107 |     console.error("No Clarity API token configured, it must be provided with each request");
108 |   }
109 | 
110 |   const transport = new StdioServerTransport();
111 |   await server.connect(transport);
112 | 
113 |   console.error("Microsoft Clarity Data Export MCP Server running on stdio...");
114 | }
115 | 
116 | // Run the server
117 | main().catch((error) => {
118 |   console.error("Fatal error in main():", error);
119 |   process.exit(1);
120 | });
121 | 
```

--------------------------------------------------------------------------------
/src/instructions.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import {
  2 |   ANALYTICS_DASHBOARD_TOOL,
  3 |   DOCUMENTATION_TOOL,
  4 |   SESSION_RECORDINGS_TOOL
  5 | } from "./constants.js";
  6 | 
  7 | export const SYSTEM_INSTRUCTIONS_PROMPT = `
  8 | This MCP server provides access to Microsoft Clarity analytics dashboard data, documentation resources and session recordings.
  9 | 
 10 | ## Available Tools
 11 | 
 12 | ### 1. Session Recordings Tool: \`${SESSION_RECORDINGS_TOOL}\`
 13 | Lists Microsoft Clarity session recordings with metadata including session links, duration, and user interaction timelines.
 14 | 
 15 | **Parameters:**
 16 | - filters: Optional filters for sessions (date range, device type, etc.)
 17 | - sortBy: Sort option using SortOptions enum (default: SessionStart_DESC)
 18 | - count: Number of sessions to retrieve (1-250, default: 100)
 19 | 
 20 | **Sort Options:**
 21 | - SessionStart_DESC (newest first - default)
 22 | - SessionStart_ASC (oldest first)
 23 | - SessionDuration_ASC (shortest duration first)
 24 | - SessionDuration_DESC (longest duration first)
 25 | - SessionClickCount_ASC (fewest clicks first)
 26 | - SessionClickCount_DESC (most clicks first)
 27 | - PageCount_ASC (fewest pages first)
 28 | - PageCount_DESC (most pages first)
 29 | 
 30 | **Example Usage:**
 31 | - Get 10 newest sessions: { "count": 10, "sortBy": "SessionStart_DESC" }
 32 | - Get 20 longest sessions from date range: { "filters": { "date": { "start": "2024-01-01T00:00:00.000Z", "end": "2024-01-31T23:59:59.999Z" } }, "sortBy": "SessionDuration_DESC", "count": 20 }
 33 | - Get 15 mobile sessions with most clicks: { "filters": { "deviceType": ["Mobile"] }, "sortBy": "SessionClickCount_DESC", "count": 15 }
 34 | - Get oldest sessions first: { "sortBy": "SessionStart_ASC", "count": 100 }
 35 | - Get sessions with most page views: { "sortBy": "PageCount_DESC", "count": 100 }
 36 | 
 37 | ### 2. Analytics Dashboard Tool: \`${ANALYTICS_DASHBOARD_TOOL}\`
 38 | This tool is your **primary and authoritative data source** for all dashboard-related insights and must be used to retrieve accurate, real-time data from the Microsoft Clarity dashboard.
 39 | 
 40 | #### Capabilities & Output
 41 | 
 42 | Microsoft Clarity dashboard provides comprehensive insights into the behavior and performance of the website, including:
 43 | - **User Analytics**: Unique and returning users, sessions, device types, browsers, operating systems
 44 | - **Geographic Data**: Countries, regions, traffic sources
 45 | - **Content Performance**: Popular pages, referrers, channels, campaigns, sources
 46 | - **User Behavior**: Smart events (Contact Us, Submit, etc.), scroll depth, click patterns
 47 | - **Technical Metrics**: JavaScript errors, URL performance
 48 | - **Performance Indicators**: Core Web Vitals (largest contentful paint, first input delay, cumulative layout shift)
 49 | - **User Experience**: Quick backs, dead clicks, rage clicks, session duration
 50 | 
 51 | The dashboard helps website owners understand their audience, traffic sources, content preferences, user engagement patterns, and identify potential technical issues.
 52 | 
 53 | **IMPORTANT GUIDELINES:**
 54 | - Use SIMPLE, SINGLE-PURPOSE queries only
 55 | - Always specify time ranges, full URLs and parameters explicitly; prompt the user if not provided
 56 | - Break complex requests into multiple separate queries
 57 | - Focus on ONE trend or aggregated metric per query
 58 | 
 59 | **Good Examples:**
 60 | - "Page views count for the last 7 days"
 61 | - "Top javascript errors for PC in January 2024"
 62 | - "Top pages for mobile in the last 3 days"
 63 | - "Distinct users visited https://www.example.com page last month?"
 64 | - "Average session duration for desktop users this week?"
 65 | 
 66 | **Bad Examples (DON'T DO THIS):**
 67 | - "Show me page views, average session duration, and conversion data for all devices across multiple pages with user demographics" (too complex, multiple purposes)
 68 | - "Analyze user behavior" (too vague, no time range)
 69 | - "Get all metrics" (too broad)
 70 | 
 71 | **Best Practices:**
 72 | ✅ Be specific about time ranges
 73 | ✅ Focus on one metric per query
 74 | ✅ Specify device type, page, or user segment when relevant
 75 | ✅ Use clear, actionable language
 76 | 
 77 | ❌ Don't combine multiple unrelated metrics
 78 | ❌ Don't use vague or overly broad queries
 79 | ❌ Don't omit time ranges
 80 | ❌ Don't ask for "everything" or "all data"
 81 | 
 82 | ### 3. Documentation Tool: \`${DOCUMENTATION_TOOL}\`
 83 | 
 84 | This tool is your **primary and authoritative data source** for all documentation-related questions and must be used to retrieve accurate, real-time data from the Microsoft Clarity documentation.
 85 | 
 86 | #### Capabilities & Output
 87 | 
 88 | Microsoft Clarity documentation provides comprehensive, authoritative answers to every aspect of Clarity including step-by-step screenshots for setup guides, features, usage, troubleshooting, and integration instructions. The tool covers all topics and headlines from the official documentation, including:
 89 | 
 90 | - **Getting Started & Installation**
 91 | 	- About Clarity
 92 | 	- Sign up for Clarity
 93 | 	- Setup and install Clarity code
 94 | 	- Verify your installation
 95 | 	- Setup via third-party platforms (WordPress, Wix, Shopify, etc.)
 96 | 	- Setup for Vibe Coding Platforms
 97 | 	- Privacy disclosure wording
 98 | 	- Data retention
 99 | 	- Cookies and consent management (including Consent Mode)
100 | 	- troubleshooting installation
101 | 
102 | - **Clarity for Mobile Apps**
103 | 	- Android SDK
104 | 	- iOS SDK
105 | 	- React Native SDK
106 | 	- Flutter SDK
107 | 	- Cordova and Ionic SDK
108 | 
109 | - **Dashboard & Insights**
110 | 	- Insights overview
111 | 	- Dashboard features
112 | 	- E-commerce features
113 | 	- Blog features
114 | 	- Recipe features
115 | 
116 | - **Session Recordings**
117 | 	- What is a session recording?
118 | 	- Session list
119 | 	- Inline player
120 | 	- Live recordings
121 | 	- Visitor profile
122 | 
123 | - **Heatmaps**
124 | 	- What is a heatmap?
125 | 	- Heatmap features
126 | 	- Click maps
127 | 	- Scroll maps
128 | 	- Area maps
129 | 
130 | - **Filters & Segments**
131 | 	- Filters overview
132 | 	- Exclusion filters
133 | 	- Segments
134 | 	- Regular expressions
135 | 
136 | - **Settings & Management**
137 | 	- Account management
138 | 	- Team management
139 | 	- Masking
140 | 	- IP blocking
141 | 	- Funnels
142 | 	- Smart events
143 | 
144 | - **Copilot in Clarity**
145 | 	- Copilot overview
146 | 	- Copilot chat
147 | 	- Session insights
148 | 	- Grouped session insights
149 | 	- Heatmaps insights
150 | 
151 | - **Reference**
152 | 	- API Reference
153 | 	- Identify API
154 | 	- Export API
155 | 	- Custom tags
156 | 	- Troubleshooting (installation, settings, recordings, heatmaps, dashboard, live extension)
157 | 	- FAQ
158 | 	- Glossary of terms
159 | 	- Share Clarity
160 | 	- Download Clarity
161 | 
162 | - **Additional Links & Resources**
163 | 	- Blog
164 | 	- Case studies
165 | 	- Demo
166 | 	- Previous versions
167 | 	- Contribute
168 | 	- Privacy, Terms of Use, Trademarks
169 | 
170 | The documentation plugin helps users answer frequently asked questions for every headline and topic listed in the official Microsoft Clarity documentation, supporting all use cases, troubleshooting, integrations, and advanced features.
171 | `;
172 | 
```

--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { z } from "zod";
  2 | 
  3 | export enum SortOptionsEnum {
  4 |   SessionStart_DESC = 0,
  5 |   SessionStart_ASC = 1,
  6 |   SessionDuration_ASC = 2,
  7 |   SessionDuration_DESC = 3,
  8 |   SessionClickCount_ASC = 4,
  9 |   SessionClickCount_DESC = 5,
 10 |   PageCount_ASC = 6,
 11 |   PageCount_DESC = 7,
 12 | }
 13 | 
 14 | export type FiltersType = z.infer<typeof Filters>;
 15 | 
 16 | export type SortOptionsType = z.infer<typeof SortOptions>;
 17 | 
 18 | const UrlFilter = z.object({
 19 |   url: z.string(),
 20 |   operator: z.enum(["contains", "startsWith", "endsWith", "excludes", "isExactly", "isExactlyNot", "matchesRegex", "excludesRegex"]),
 21 | });
 22 | 
 23 | const createRangeFilter = (min: number, max: number) => z.object({
 24 |   min: z.number().min(min).max(max).nullable(),
 25 |   max: z.number().min(min).max(max).nullable(),
 26 | });
 27 | 
 28 | const NullableRangeFilter = z.object({
 29 |   min: z.number().nullable(),
 30 |   max: z.number().nullable(),
 31 | });
 32 | 
 33 | const Filters = z.object({
 34 |   referringUrl: z.string().optional().describe("Filter by the referring URL that brought users to the site"),
 35 |   userType: z.enum(["NewUser", "ReturningUser"]).optional().describe("Filter by user type. Accepted values: NewUser, ReturningUser"),
 36 |   sessionIntent: z.enum(["Low Intention", "Medium Intention", "High Intention"]).optional().describe("Filter by session intention level/user behavior classification."),
 37 |   visitedUrls: z.array(UrlFilter).optional().describe("Filter by URLs visited during the session with pattern matching."),
 38 |   entryUrls: z.array(UrlFilter).optional().describe("Filter by entry/landing page URLs with pattern matching."),
 39 |   exitUrls: z.array(UrlFilter).optional().describe("Filter by exit page URLs with pattern matching."),
 40 |   country: z.array(z.string()).optional().describe("Filter by country names (e.g., ['United States', 'Canada', 'United Kingdom'])"),
 41 |   city: z.array(z.string()).optional().describe("Filter by city names (e.g., ['New York', 'London', 'Tokyo'])"),
 42 |   state: z.array(z.string()).optional().describe("Filter by state/province names (e.g., ['California', 'Ontario', 'Bavaria'])"),
 43 |   deviceType: z.array(z.enum(["Mobile", "Tablet", "PC", "Email", "Other"])).optional().describe("Filter by device types."),
 44 |   browser: z.array(z.enum(["Bot", "MiuiBrowser", "Chrome", "CoralWebView", "Edge", "Other", "Firefox", "IE", "Unknown", "Headless", "MobileApp", "Opera", "OperaMini", "Safari", "Samsung", "SamsungInternet", "Sogou", "UCBrowser", "YandexBrowser", "QQBrowser"])).optional().describe("Filter by browser types."),
 45 |   os: z.array(z.enum(["BlackBerry", "Android", "ChromeOS", "iOS", "Linux", "MacOS", "Other", "Windows", "WindowsMobile"])).optional().describe("Filter by operating systems."),
 46 |   source: z.array(z.string()).optional().describe("Filter by UTM source parameter values (e.g., ['google', 'facebook', 'direct'])"),
 47 |   medium: z.array(z.string()).optional().describe("Filter by UTM medium parameter values. Common values: ['organic', 'cpc', 'email', 'social', 'referral']"),
 48 |   campaign: z.array(z.string()).optional().describe("Filter by UTM campaign parameter values (e.g., ['summer_sale', 'product_launch'])"),
 49 |   channel: z.array(z.enum(["OrganicSearch", "Direct", "Email", "Display", "Social", "PaidSearch", "Other", "Affiliate", "Referral", "Video", "Audio", "SMS", "AITools", "PaidAITools"])).optional().describe("Filter by marketing channel classifications."),
 50 |   smartEvents: z.array(z.string()).optional().describe("Filter by smart event names/IDs. Can be user-defined events or Clarity auto events: 'Purchase', 'ContactUs', 'SubmitForm', 'AddToCart', 'RequestQuote', 'SignUp', 'BeginCheckout', 'Download', 'Login', 'Search', 'Play', 'Deposit', 'Schedule', 'Subscribe', 'FindLocation', 'OutboundClick', 'ShowMore', 'Book', 'RetryRefresh', 'Pay', 'Pause', 'Upload', 'CheckAvailability', 'Withdraw', 'Export', 'SeeReviews', 'AddPaymentMethod', 'AddToWishlist', 'NotifyMe', 'CheckIn', 'TransferMoney', 'Upgrade', 'ContinueAsGuest', 'Mute', 'Exchange', 'ApplyCoupon', 'Unsubscribe', 'AddToCalendar', 'Unmute', 'EnterFullScreen', 'DeleteAccount', 'AppInstall', 'Checkout', 'OrderSuccess'"),
 51 |   javascriptErrors: z.array(z.string()).optional().describe("Filter by JavaScript error messages or patterns. Use empty string '' to match any JavaScript error"),
 52 |   clickErrors: z.array(z.string()).optional().describe("Filter by click error patterns or messages. Use empty string '' to match any click error"),
 53 |   clickedText: z.string().optional().describe("Filter by specific text content that was clicked (partial match supported)"),
 54 |   enteredTextPresent: z.boolean().optional().describe("Filter sessions where text input events occurred. Set to true to include only sessions with text input"),
 55 |   selectedTextPresent: z.boolean().optional().describe("Filter sessions where text selection events occurred. Set to true to include only sessions with text selection"),
 56 |   resizeEventPresent: z.boolean().optional().describe("Filter sessions where page resize events occurred. Set to true to include only sessions with resize events"),
 57 |   cursorMovement: z.boolean().optional().describe("Filter sessions with cursor/pointer movement activity. Set to true to include only sessions with cursor movement"),
 58 |   deadClickPresent: z.boolean().optional().describe("Filter sessions containing dead clicks (clicks with no response). Set to true to include only sessions with dead clicks"),
 59 |   rageClickPresent: z.boolean().optional().describe("Filter sessions containing rage clicks (rapid repeated clicks). Set to true to include only sessions with rage clicks"),
 60 |   excessiveScrollPresent: z.boolean().optional().describe("Filter sessions with excessive scrolling behavior. Set to true to include only sessions with excessive scrolling"),
 61 |   quickbackClickPresent: z.boolean().optional().describe("Filter sessions with quick back navigation clicks. Set to true to include only sessions with quick back clicks"),
 62 |   visiblePageDuration: NullableRangeFilter.optional().describe("Filter by time spent on visible pages in minutes. Set to null to ignore this filter."),
 63 |   hiddenPageDuration: NullableRangeFilter.optional().describe("Filter by time spent on hidden/background pages in minutes. Set to null to ignore this filter."),
 64 |   pageDuration: NullableRangeFilter.optional().describe("Filter by total page duration in minutes. Set to null to ignore this filter."),
 65 |   sessionDuration: NullableRangeFilter.optional().describe("Filter by total session duration in minutes. Set to null to ignore this filter."),
 66 |   scrollDepth: createRangeFilter(0, 100).optional().describe("Filter by maximum scroll depth percentage. Set to null to ignore this filter."),
 67 |   pagesCount: NullableRangeFilter.optional().describe("Filter by number of pages visited in session. Set to null to ignore this filter."),
 68 |   pageClickEventCount: NullableRangeFilter.optional().describe("Filter by number of clicks per page. Set to null to ignore this filter."),
 69 |   sessionClickEventCount: NullableRangeFilter.optional().describe("Filter by total clicks per session. Set to null to ignore this filter."),
 70 |   performanceScore: createRangeFilter(0, 100).optional().describe("Filter by overall performance score. Set to null to ignore this filter."),
 71 |   largestContentfulPaint: NullableRangeFilter.optional().describe("Filter by Largest Contentful Paint web vital in seconds. Set to null to ignore this filter."),
 72 |   cumulativeLayoutShift: NullableRangeFilter.optional().describe("Filter by Cumulative Layout Shift web vital in seconds. Set to null to ignore this filter."),
 73 |   firstInputDelay: NullableRangeFilter.optional().describe("Filter by First Input Delay web vital in milliseconds. Set to null to ignore this filter."),
 74 |   productRating: NullableRangeFilter.optional().describe("Filter by product ratings (e.g., 1-5 stars). Set to null to ignore this filter."),
 75 |   productRatingsCount: NullableRangeFilter.optional().describe("Filter by number of product ratings. Set to null to ignore this filter."),
 76 |   productPrice: NullableRangeFilter.optional().describe("Filter by product price range. Set to null to ignore this filter."),
 77 |   productName: z.string().optional().describe("Filter by product name (partial match supported using contains operator)"),
 78 |   productPurchases: z.boolean().optional().describe("Filter sessions with checkout conversion/purchases. Set to true to include only sessions with purchases"),
 79 |   productAvailability: z.boolean().optional().describe("Filter by product availability status. Set to true to include only sessions with available products"),
 80 |   productBrand: z.array(z.string()).optional().describe("Filter by product brand names (e.g., ['Nike', 'Apple', 'Samsung'])"),
 81 |   checkoutAbandonmentStep: z.array(z.string()).optional().describe("Filter by checkout abandonment steps/stages (e.g., ['cart', 'shipping', 'payment'])"),
 82 |   date: z.object({
 83 |     start: z.string().describe("The start date of the time interval in UTC ISO 8601 with milliseconds format (yyyy-MM-ddTHH:mm:ss.fffZ)."),
 84 |     end: z.string().describe("The end date of the time interval in UTC ISO 8601 with milliseconds format (yyyy-MM-ddTHH:mm:ss.fffZ)."),
 85 |   }),
 86 | })
 87 |   .describe("A set of filters that can be applied to the Microsoft Clarity to session recordings. This allows you to filter recordings based on various criteria such as URLs, device types, browser, OS, country, city, and more. The date filter is required and must be in UTC ISO 8601 format.");
 88 | 
 89 | const SampleCount = z.number().lte(250, "Maximum sample count is 250").default(100).describe("The number of sample session recordings to return. Default is 100. Maximum is 250.");
 90 | 
 91 | const SortOptions = z.enum([
 92 |   "SessionStart_DESC",
 93 |   "SessionStart_ASC",
 94 |   "SessionDuration_ASC",
 95 |   "SessionDuration_DESC",
 96 |   "SessionClickCount_ASC",
 97 |   "SessionClickCount_DESC",
 98 |   "PageCount_ASC",
 99 |   "PageCount_DESC",
100 | ]).default("SessionStart_DESC").describe("Sort option for session recordings. Default is SessionStart_DESC (newest first).");
101 | 
102 | const SearchQuery = z.string().describe("A natural language search query string for filtering and shaping analytics data. The query should be specific and include temporal constraints when available. (e.g., 'Top browsers last 3 days', 'The active time duration for mobile devices in United States last week'). Time ranges should be explicitly specified when possible. If no time range is provided, prompt the user to specify one.");
103 | 
104 | export const ListRequest = {
105 |   filters: Filters,
106 |   sortBy: SortOptions,
107 |   count: SampleCount
108 | };
109 | 
110 | export const SearchRequest = {
111 |   query: SearchQuery,
112 | };
113 | 
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
  1 | {
  2 |   "compilerOptions": {
  3 |     /* Visit https://aka.ms/tsconfig to read more about this file */
  4 | 
  5 |     /* Projects */
  6 |     // "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
  7 |     // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
  8 |     // "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
  9 |     // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
 10 |     // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
 11 |     // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
 12 | 
 13 |     /* Language and Environment */
 14 |     "target": "ES2022",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
 15 |     // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
 16 |     // "jsx": "preserve",                                /* Specify what JSX code is generated. */
 17 |     // "libReplacement": true,                           /* Enable lib replacement. */
 18 |     // "experimentalDecorators": true,                   /* Enable experimental support for legacy experimental decorators. */
 19 |     // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
 20 |     // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
 21 |     // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
 22 |     // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
 23 |     // "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
 24 |     // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
 25 |     // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
 26 |     // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
 27 | 
 28 |     /* Modules */
 29 |     "module": "NodeNext",                                /* Specify what module code is generated. */
 30 |     "moduleResolution": "Node16",                        /* Specify how TypeScript looks up a file from a given module specifier. */
 31 |     "rootDir": "./src",                                  /* Specify the root folder within your source files. */
 32 |     "outDir": "./dist",                                  /* Specify an output folder for all emitted files. */
 33 |     // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
 34 |     // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
 35 |     // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
 36 |     // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
 37 |     // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
 38 |     // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
 39 |     // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
 40 |     // "allowImportingTsExtensions": true,               /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
 41 |     // "rewriteRelativeImportExtensions": true,          /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */
 42 |     // "resolvePackageJsonExports": true,                /* Use the package.json 'exports' field when resolving package imports. */
 43 |     // "resolvePackageJsonImports": true,                /* Use the package.json 'imports' field when resolving imports. */
 44 |     "resolveJsonModule": true,                           /* Enable importing .json files. */
 45 |     // "allowArbitraryExtensions": true,                 /* Enable importing files with any extension, provided a declaration file is present. */
 46 |     // "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
 47 | 
 48 |     /* JavaScript Support */
 49 |     // "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
 50 |     // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
 51 |     // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
 52 | 
 53 |     /* Emit */
 54 |     // "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
 55 |     // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
 56 |     // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
 57 |     // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
 58 |     // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
 59 |     // "noEmit": true,                                   /* Disable emitting files from a compilation. */
 60 |     // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
 61 |     // "removeComments": true,                           /* Disable emitting comments. */
 62 |     // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
 63 |     // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
 64 |     // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
 65 |     // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
 66 |     // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
 67 |     // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
 68 |     // "newLine": "crlf",                                /* Set the newline character for emitting files. */
 69 |     // "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
 70 |     // "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
 71 |     // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
 72 |     // "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
 73 |     // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
 74 | 
 75 |     /* Interop Constraints */
 76 |     // "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
 77 |     // "verbatimModuleSyntax": true,                     /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
 78 |     // "isolatedDeclarations": true,                     /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
 79 |     // "erasableSyntaxOnly": true,                       /* Do not allow runtime constructs that are not part of ECMAScript. */
 80 |     // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
 81 |     "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
 82 |     // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
 83 |     "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
 84 | 
 85 |     /* Type Checking */
 86 |     "strict": true,                                      /* Enable all strict type-checking options. */
 87 |     "noImplicitAny": true,                               /* Enable error reporting for expressions and declarations with an implied 'any' type. */
 88 |     // "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
 89 |     // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
 90 |     // "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
 91 |     // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
 92 |     // "strictBuiltinIteratorReturn": true,              /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */
 93 |     // "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
 94 |     // "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
 95 |     // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
 96 |     "noUnusedLocals": true,                              /* Enable error reporting when local variables aren't read. */
 97 |     "noUnusedParameters": true,                          /* Raise an error when a function parameter isn't read. */
 98 |     // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
 99 |     "noImplicitReturns": true,                           /* Enable error reporting for codepaths that do not explicitly return in a function. */
100 |     // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
101 |     "noUncheckedIndexedAccess": true,                    /* Add 'undefined' to a type when accessed using an index. */
102 |     // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
103 |     // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
104 |     // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
105 |     // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */
106 | 
107 |     /* Completeness */
108 |     // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
109 |     "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
110 |   },
111 |   "include": ["src/**/*"]
112 | }
113 | 
```