> For the complete documentation index, see [llms.txt](https://docs.salescaling.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.salescaling.com/en/api/mcp-server.md).

# MCP Server (Model Context Protocol)

The Salescaling MCP server allows AI agents like Claude, Cursor, and other MCP-compatible clients to access your meeting data, transcripts, and summaries in a structured and secure way.

## What is MCP?

Model Context Protocol (MCP) is a standard protocol that allows language models (LLMs) to interact with external systems in a structured way. The Salescaling MCP server implements this protocol to expose your meeting data through tools that AI agents can use.

## Features

* ✅ **Spec-Compliant**: Full implementation of the official MCP protocol
* ✅ **11 Available Tools**: Meetings (video call and in person), phone calls, search, listings, transcription, summary with action items, details, statistics, and more
* ✅ **Advanced Search**: Full Text Search with PostgreSQL for semantic searches with optimized GIN indexes
* ✅ **Payload Control**: Configurable limits to avoid context overflow
* ✅ **Secure Authentication**: Salescaling API key or **OAuth Clients** (Authorization Code + PKCE)
* ✅ **Multi-tenant**: Automatic isolation by organization
* ✅ **High Performance**: Optimized for millions of rows with GIN indexes and concurrency control

## MCP Endpoints

The MCP server exposes two main endpoints:

### GET `/api/v1/mcp` - List Tools

Returns the list of available tools with their input schemas.

**Example:**

```bash
curl -X GET https://api.salescaling.com/api/v1/mcp \\
  -H "X-API-Key: sk_xxx"
```

### POST `/api/v1/mcp` - Execute Tool

Executes a specific tool with the provided arguments.

**Example:**

```bash
curl -X POST https://api.salescaling.com/api/v1/mcp \\
  -H "X-API-Key: sk_xxx" \\
  -H "Content-Type: application/json" \\
  -d '{
    "name": "search_meetings",
    "arguments": {
      "query": "performance",
      "limit": 10
    }
  }'
```

## MCP Connection via OAuth Clients

In addition to the API key, you can connect MCP clients that support **OAuth 2.0** (flow *Authorization Code* with **PKCE**). OAuth clients are registered **explicitly** in Salescaling (there is no dynamic client registration in the authorization server).

### Requirements

* An account with permissions to manage **OAuth Clients** (usually organization administrators).
* The MCP client must be able to complete the OAuth flow in the browser and send `Authorization: Bearer <access_token>` to the MCP server.

### Configure the client in Salescaling

1. In the platform, go to **Settings → OAuth Clients** (or **Settings → OAuth Clients**).
2. Create a new OAuth client.
3. Add the allowed **Redirect URIs** . For **Claude (Anthropic)** use exactly:

   `https://claude.ai/api/mcp/auth_callback`
4. Assign the **scopes** scopes the MCP needs (at minimum `meetings:read` for the current meeting tools).
5. Save the client and copy the **`client_id`** (and the secret only if you created a confidential client; many MCP clients use a public client with PKCE).

### Authorization server metadata

Salescaling exposes metadata compatible with OpenID discovery on the MCP endpoint itself:

* `GET https://api.salescaling.com/api/v1/mcp/.well-known/openid-configuration`

There you will find `issuer`, `authorization_endpoint`, `token_endpoint`, `revocation_endpoint` and supported scopes (replace the host if you use another environment).

### Example: MCP for Claude with OAuth

After creating the OAuth Client with the redirect above, configure the MCP client with the MCP server URL and OAuth endpoints (adjust domains if your tenant uses another app URL):

```json
{
  "mcpServers": {
    "salescaling": {
      "url": "https://api.salescaling.com/api/v1/mcp",
      "oauth": {
        "authorizationUrl": "https://app.salescaling.com/oauth/authorize",
        "tokenUrl": "https://api.salescaling.com/v1/oauth/token",
        "clientId": "<client_id_created_in_oauth_clients>",
        "scopes": ["meetings:read"]
      }
    }
  }
}
```

**Summary of typical URLs**

| Use                                    | URL                                           |
| -------------------------------------- | --------------------------------------------- |
| MCP Server                             | `https://api.salescaling.com/api/v1/mcp`      |
| Authorization (user login)             | `https://app.salescaling.com/oauth/authorize` |
| Token (code exchange / refresh)        | `https://api.salescaling.com/v1/oauth/token`  |
| Redirect URI in Salescaling for Claude | `https://claude.ai/api/mcp/auth_callback`     |

Requests to the MCP will use the access token in the header `Authorization: Bearer …` instead of `X-API-Key`.

## Meetings vs phone calls

Salescaling stores **video calls**, **in-person meetings** and **phone calls** in the same meeting entity. To keep the MCP API clear:

* The tools whose name includes **`meetings`** (`search_meetings`, `list_meetings`, `find_meetings_by_participant`) only include **video calls and in-person meetings** (they do not return phone calls).
* The tools **`list_calls`**, **`search_calls`** and **`find_calls_by_participant`** are dedicated to **phone calls** and support filters such as direction (`INBOUND` / `OUTBOUND`) and phone numbers.
* **`get_meeting_transcript`**, **`get_meeting_summary`**, **`get_meeting_details`** and **`get_meeting_action_items`** work with **any** meeting or call ID (the same identifier).

## Available Tools

### 1. `search_meetings` - Advanced Search

Searches **video calls and in-person meetings** by text in titles and/or transcripts (Full Text Search). **Does not include phone calls**; for that use `search_calls`.

**Parameters:**

| Parameter  | Type   | Required | Description                                    |
| ---------- | ------ | -------- | ---------------------------------------------- |
| `query`    | string | Yes      | Search term                                    |
| `scope`    | string | No       | `title`, `sentences` or `all` (default: `all`) |
| `fromDate` | string | No       | Start date (YYYY-MM-DD)                        |
| `toDate`   | string | No       | End date (YYYY-MM-DD)                          |
| `limit`    | number | No       | Maximum 50 (default: 20)                       |

**Note:** Only video call or in-person activities.

**Example:**

```json
{
  "name": "search_meetings",
  "arguments": {
    "query": "performance review",
    "scope": "all",
    "fromDate": "2024-12-01",
    "limit": 10
  }
}
```

### 2. `list_meetings` - List Meetings

Lists **video calls and in-person meetings** with structured filters (excludes phone calls).

**Parameters:**

| Parameter      | Type      | Required | Description                                            |
| -------------- | --------- | -------- | ------------------------------------------------------ |
| `keyword`      | string    | No       | Search in names / title                                |
| `fromDate`     | string    | No       | Start date                                             |
| `toDate`       | string    | No       | End date                                               |
| `limit`        | number    | No       | Maximum 50 (default: 20)                               |
| `skip`         | number    | No       | Pagination (default: 0)                                |
| `sortOrder`    | string    | No       | `asc` or `desc` — sort by start date (default: `desc`) |
| `participants` | string\[] | No       | Participant emails                                     |
| `organizers`   | string\[] | No       | Organizer emails                                       |

**Example:**

```json
{
  "name": "list_meetings",
  "arguments": {
    "fromDate": "2024-12-01",
    "toDate": "2024-12-31",
    "participants": ["cliente@empresa.com"],
    "limit": 20
  }
}
```

### 3. `get_meeting_transcript` - Get Transcript

Gets the detailed transcript with speaker attribution (meeting or call).

**Parameters:**

| Parameter      | Type   | Required | Description                      |
| -------------- | ------ | -------- | -------------------------------- |
| `transcriptId` | string | Yes      | Meeting or call ID               |
| `language`     | string | No       | Language code (e.g., "es", "en") |
| `maxSentences` | number | No       | Sentence limit (payload control) |

**Payload Control:**

* Auto-truncates at 10,000 sentences if not specified `maxSentences`
* Indicates in the response if the content was truncated

**Example:**

```json
{
  "name": "get_meeting_transcript",
  "arguments": {
    "transcriptId": "meeting-uuid-here",
    "language": "es",
    "maxSentences": 100
  }
}
```

### 4. `get_meeting_summary` - Get Summary

Gets the AI-generated summary: text (`summaryText`), **action items** (`actionItems` / `next_steps`), and depending on the type, **topics/highlights** (meetings) or **call insights** (calls).

**Parameters:**

| Parameter      | Type   | Required | Description        |
| -------------- | ------ | -------- | ------------------ |
| `transcriptId` | string | Yes      | Meeting or call ID |
| `language`     | string | No       | Language code      |

**Example:**

```json
{
  "name": "get_meeting_summary",
  "arguments": {
    "transcriptId": "meeting-uuid-here",
    "language": "es"
  }
}
```

### 5. `get_meeting_details` - Full Details

Gets complete details of a meeting (metadata + transcript + summary).

**Parameters:**

| Parameter           | Type    | Required | Description                        |
| ------------------- | ------- | -------- | ---------------------------------- |
| `id`                | string  | Yes      | Meeting ID                         |
| `includeTranscript` | boolean | No       | Include transcript (default: true) |
| `includeSummary`    | boolean | No       | Include summary (default: true)    |
| `maxSentences`      | number  | No       | Sentence limit in transcript       |

**Example:**

```json
{
  "name": "get_meeting_details",
  "arguments": {
    "id": "meeting-uuid-here",
    "includeTranscript": true,
    "includeSummary": true,
    "maxSentences": 500
  }
}
```

### 6. `find_meetings_by_participant` - Search Meetings by Participant

Finds meetings where a specific person participated. Searches by name (partial match) or email (exact match).

**Parameters:**

| Parameter     | Type   | Required | Description                                          |
| ------------- | ------ | -------- | ---------------------------------------------------- |
| `participant` | string | Yes      | Participant name or email                            |
| `fromDate`    | string | No       | Start date (YYYY-MM-DD)                              |
| `toDate`      | string | No       | End date (YYYY-MM-DD)                                |
| `limit`       | number | No       | Maximum 50 (default: 20)                             |
| `skip`        | number | No       | Pagination (default: 0)                              |
| `sortOrder`   | string | No       | `asc` or `desc` by start date (default: `desc`)      |
| `titleFilter` | string | No       | Optional filter on the meeting title (partial match) |

**Features:**

* Only **video calls and in-person meetings** (no phone calls).
* **Email search**: Exact match (case-insensitive)
  * Example: `jon@empresa.com` will find only that exact email
* **Name search**: Partial match
  * Example: `Jon` will find "Jon Smith", "Jonathan", "Jon Doe", etc.
* Returns full participant and organizer information
* Configurable order with `sortOrder`

**Examples:**

Search by email:

```json
{
  "name": "find_meetings_by_participant",
  "arguments": {
    "participant": "jon@empresa.com",
    "fromDate": "2024-12-01",
    "limit": 20
  }
}
```

Search by name:

```json
{
  "name": "find_meetings_by_participant",
  "arguments": {
    "participant": "Jon",
    "fromDate": "2024-01-01",
    "toDate": "2024-12-31",
    "limit": 50
  }
}
```

### 7. `list_calls` - List phone calls

Lists only **phone calls** (`phonecall`), with filters by dates, title, participants, direction, and numbers.

| Parameter                 | Type      | Required | Description                                    |
| ------------------------- | --------- | -------- | ---------------------------------------------- |
| `titleFilter`             | string    | No       | Partial match in the name/title                |
| `fromDate` / `toDate`     | string    | No       | Date range (YYYY-MM-DD)                        |
| `limit`                   | number    | No       | Maximum 50 (default: 20)                       |
| `skip`                    | number    | No       | Pagination                                     |
| `sortOrder`               | string    | No       | `asc` or `desc` (default: `desc`)              |
| `direction`               | string    | No       | `INBOUND` or `OUTBOUND`                        |
| `participants`            | string\[] | No       | Participant emails                             |
| `fromNumber` / `toNumber` | string    | No       | Partial filter by caller or destination number |

### 8. `search_calls` - Search in calls

Search in titles and/or transcripts **for phone calls only**. Similar parameters to `search_meetings`, plus `direction`, `fromNumber`, `toNumber` optional ones.

### 9. `find_calls_by_participant` - Calls by participant

Same as `find_meetings_by_participant` but only for **phone calls**, with the same extra filters as `list_calls` (`titleFilter`, `sortOrder`, `direction`, numbers).

### 10. `get_meeting_action_items` - Summary action items

Returns the **next steps** structured from the AI summary for a meeting or call ID.

| Parameter   | Type   | Required |
| ----------- | ------ | -------- |
| `meetingId` | string | Yes      |
| `language`  | string | No       |

### 11. `get_meetings_statistics` - Aggregated statistics

Totals, average durations by activity type, and **top participants** (limited sample). Configurable scope:

| Parameter             | Type   | Description                                                            |
| --------------------- | ------ | ---------------------------------------------------------------------- |
| `fromDate` / `toDate` | string | Optional range                                                         |
| `type`                | string | `meetings` (video+in-person), `calls` (phone only), or `all` (default) |

## Configuration in MCP Clients

For **OAuth** (including Claude with redirect `https://claude.ai/api/mcp/auth_callback`), follow the section [MCP Connection via OAuth Clients](#mcp-oauth-clients).

### Claude Desktop (API Key)

1. Locate your configuration file:
   * **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
   * **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
2. Add the MCP server configuration:

```json
{
  "mcpServers": {
    "salescaling": {
      "url": "https://api.salescaling.com/api/v1/mcp",
      "headers": {
        "X-API-Key": "sk_your_api_key_here"
      }
    }
  }
}
```

3. Restart Claude Desktop
4. Verify that the server is connected:
   * Look for the tools icon in the interface
   * You should see "salescaling" as an available server
   * The 11 tools should appear listed

### Cursor IDE

1. Open Cursor settings (`Cmd/Ctrl + ,`)
2. Search for "MCP Servers" in settings
3. Add the Salescaling server:

```json
{
  "mcp.servers": {
    "salescaling": {
      "url": "https://api.salescaling.com/api/v1/mcp",
      "headers": {
        "X-API-Key": "sk_your_api_key_here"
      }
    }
  }
}
```

4. Restart Cursor
5. Use the server from Cursor chat:
   * Mention "@salescaling" in chat
   * Or ask directly: "Search meetings about performance"

### Other MCP Clients

For any MCP-compatible client:

1. **Server URL**: `https://api.salescaling.com/api/v1/mcp`
2. **Authentication**: Header `X-API-Key` with your API key
3. **Protocol**: Standard HTTP/HTTPS
4. **Format**: JSON

## Usage Examples

### Example 1: Search Meetings with Claude

```
User: "Search meetings about pricing from last month"

Claude → POST /api/v1/mcp
{
  "name": "search_meetings",
  "arguments": {
    "query": "pricing",
    "scope": "all",
    "fromDate": "2024-12-01",
    "limit": 20
  }
}

Claude: "I found 5 meetings about pricing:
1. Pricing meeting with Acme Corp - Dec 15, 2024
2. Pricing strategy review - Dec 10, 2024
..."
```

### Example 2: Get Full Transcript

```
User: "Give me the full transcript of the meeting with ID abc-123"

Claude → POST /api/v1/mcp
{
  "name": "get_meeting_transcript",
  "arguments": {
    "transcriptId": "abc-123",
    "language": "es"
  }
}

Claude: "Here is the meeting transcript:
[00:00 - 00:15] Juan Pérez: Good morning everyone..."
```

### Example 3: Analysis of Multiple Meetings

```
User: "Analyze the sales meetings from December and give me insights"

Claude:
1. List meetings → list_meetings (December)
2. For each meeting → get_meeting_summary
3. Analyze patterns and generate insights

Claude: "I analyzed 15 meetings in December:
- Most discussed topics: pricing (8), implementation (6)
- Common objections: implementation time (5)
- Identified opportunities: 3 enterprise accounts..."
```

## Response Format

All tools return responses in standard MCP format:

```json
{
  "content": [
    {
      "type": "text",
      "text": "Human-readable description of the result"
    },
    {
      "type": "resource",
      "resource": {
        "uri": "salescaling://meeting/xxx",
        "mimeType": "application/json",
        "text": "{...structured JSON data...}"
      }
    }
  ]
}
```

## Security and Privacy

### Authentication

* Requests require **API key** (`X-API-Key`) **or** an **OAuth access token** (`Authorization: Bearer`) issued for an authorized OAuth Client
* API keys are managed from **Settings > API Keys**; OAuth clients from **Settings > OAuth Clients**
* Each credential is linked to your organization (tenant)

### Data Isolation

* The MCP server respects multi-tenant isolation
* You can only access meetings from your organization
* OpenFGA permissions are applied automatically

### Best Practices

1. **Never share your API key**: Treat it like a password
2. **Use environment variables**: Do not hardcode the key in files
3. **Rotate keys periodically**: Create new keys and delete the old ones
4. **Set expiration dates**: For temporary or test keys
5. **Monitor usage**: Review access logs regularly

## Limits and Quotas

### Rate Limiting

The MCP server shares the same limits as the public API:

* **Short term**: 35 requests per second
* **Medium term**: 200 requests every 10 seconds
* **Long term**: 1000 requests per minute

### Payload Limits

* **Transcripts**: Auto-truncates at 10,000 sentences
* **Searches**: Maximum 50 results per request
* **Listings**: Maximum 50 meetings per request

Use the parameter `maxSentences` to control transcript size.

## Troubleshooting

### Error: "Unauthorized - missing or invalid API key"

**Cause**: Invalid or missing API key

**Solution**:

1. Verify that the header `X-API-Key` is present
2. Confirm that the key is valid in **Settings > API Keys**
3. Verify that the key has not expired

### Error: "Unknown tool: xxx"

**Cause**: Incorrect tool name

**Solution**:

1. Verify the tool name (case-sensitive)
2. Use `GET /api/v1/mcp` to see the available tools
3. Valid names (among others): `search_meetings`, `list_meetings`, `get_meeting_transcript`, `get_meeting_summary`, `get_meeting_details`, `find_meetings_by_participant`, `list_calls`, `search_calls`, `find_calls_by_participant`, `get_meeting_action_items`, `get_meetings_statistics`

### Error: "Meeting not found"

**Cause**: Meeting ID does not exist or you do not have access

**Solution**:

1. Verify that the ID is correct
2. Confirm that the meeting belongs to your organization
3. Use `list_meetings` to obtain valid IDs

### The server does not appear in Claude Desktop

**Solution**:

1. Check that the configuration file is in the correct location
2. Check that the JSON is valid (no syntax errors)
3. Restart Claude Desktop completely
4. Check the Claude Desktop logs for errors

### Very long responses or timeouts

**Solution**:

1. Use `maxSentences` to limit transcripts
2. Reduce the `limit` in searches and listings
3. Use `includeTranscript: false` if you only need the summary
4. Filter by dates to reduce the dataset

## Support

Need help with the MCP server?

* **Email**: <support@salescaling.com>
* **API Documentation**: <https://api.salescaling.com/api/docs>
* **Community Slack**: [Join here](https://salescaling.com/slack)

## Additional Resources

* [Official MCP Specification](https://modelcontextprotocol.io)
* [Salescaling Public API](/en/api/introduction.md)
* [API Key Management](https://github.com/salescaling/web-platform/blob/main/apps/docs/configuraciones-de-la-plataforma/configuraciones-tecnicas/api-keys.md)
* [Webhooks](/en/api/webhooks.md)

***

**Last updated**: April 2026


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.salescaling.com/en/api/mcp-server.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
