---
title: "MCP"
description: "How to connect Primary Portal MCP to your AI assistant and query Primary Portal ECM deal data."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.primaryportal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP

## Overview

Primary Portal MCP lets you query Primary Portal's ECM deal data directly from your own AI assistant (Claude, ChatGPT, or any other MCP-compatible tool) using natural language instead of the web UI. It exposes deal search, filtering, aggregated metrics, deal lookups, lock-up expiries and bookbuild messages over the Model Context Protocol, scoped to whatever your account and organisation are entitled to see.

> **Terms of use**
>
> Use of the Primary Portal MCP is subject to the [Data MCP Terms of Use](/mcp/terms-and-conditions/).

## Before you start

You'll need:

- An existing Primary Portal **investor** account. This surface is investor-only.
- A **Priced** or **Live** entitlement on your organisation. Live includes everything Priced does, plus announced/live deals and bookbuild messages (see [Entitlements](#entitlements)). If you're not sure which you hold, ask your Primary Portal account team.
- For announced or in-flight (not yet priced) deals from a specific bank, an active **connection** to that bank. Without one, you'll only see the priced-deal universe your entitlement covers.

<Banner variant="tip" content='<p><strong>Not on Primary Portal yet?</strong> Investors can <a href="https://live.primaryportal.com/auth/buy-side-sign-up">sign up for free</a>.</p>' />

<Banner variant="tip" content='<p><strong>On a banker or sell-side sales account?</strong> This surface is for investors. Email <a href="mailto:experience@primaryportal.com">experience@primaryportal.com</a> and we&rsquo;ll help.</p>' />

## Connecting your AI assistant

**Endpoint.** Primary Portal MCP is reached at:

```
https://mcp.live.ai.primaryportal.com/mcp
```

**Authentication.** OAuth 2.1, with no API key or personal access token to generate or store. When you add Primary Portal MCP as a remote server in your AI assistant, it will redirect you to sign in with your existing Primary Portal investor credentials and ask you to authorise access.

**Steps** (exact menus vary by client):

1. Open your AI assistant's connector or integrations settings.
2. Add a new MCP server and paste the endpoint URL above.
3. Sign in with your Primary Portal credentials when prompted.
4. Approve the permissions request.

Once connected, the tools your assistant can see are filtered live to your organisation's entitlements, so what you're offered may differ from a colleague's, even at the same firm.

## Entitlements

Access comes in two tiers, and **Live is a superset of Priced**:

| Entitlement | What it covers |
| --- | --- |
| **Priced** | All priced and withdrawn deals, plus lock-ups. |
| **Live** | Everything in Priced, **plus** announced and in-flight (live) deals and bookbuild messages. |

Your entitlement decides both the deal universe you can query and which tools your assistant is offered. The catalogue is filtered live at connection time, so a Live user sees more tools than a Priced user, and what you're offered may differ from a colleague's, even at the same firm.

## Available tools

Every tool Primary Portal MCP can expose is listed below. The **Access** column shows the minimum entitlement. A Priced tool is also available to Live users, since Live includes Priced.

| Tool | What it does | Access |
| --- | --- | --- |
| `get_deals_data_coverage` | Dataset metadata: pricing-date and withdrawal-date spans, deal count by state, and every available field with a plain-language description | Priced |
| `get_available_deals_filters` | Valid filter values for deal searches: regions, offering types, sectors, market-cap bands, states, countries and the pricing-date range. Pass `includePublishingBanks=true` for the full list of bank names | Priced |
| `search_deals` | Search deals by region, offering type, sector, market-cap band, state, pricing-date or withdrawal-date range, issuers, countries, publishing banks or minimum deal size (at least one filter required) | Priced |
| `get_aggregated_deals_metrics` | Deal count, total volume or average performance, grouped by sector, region, offering type, market-cap band, state, country or publishing bank | Priced |
| `get_deal` | Full detail on up to 50 deals at once, by deal ID | Priced |
| `search_lockups` | Search the upcoming lock-up expiries calendar | Priced |
| `search_bookbuild_messages` | Search bookbuild messages by deal, issuer or bank | **Live** |
| `get_available_bookbuild_filters` | Valid issuer, bank and country values for bookbuild search | **Live** |

All tools are read-only. Rather than treating this table as fixed, ask your assistant to list its available tools after connecting, or call `get_deals_data_coverage`.

## Deal tools

Five tools cover the deals dataset. Most questions follow the same path:

1. **`get_available_deals_filters`** to find valid filter values.
2. **`search_deals`** to find deals, or **`get_aggregated_deals_metrics`** to summarise them.
3. **`get_deal`** for the full record of specific deals.

**`get_deals_data_coverage`** explains what each field means and how often it's filled.

### Filters

`search_deals` and `get_aggregated_deals_metrics` take the same filters. All are optional, and they combine with AND.

| Filter | Values | Matching |
| --- | --- | --- |
| `region` | `EMEA`, `APAC` or `AMRS` | Exact, any case |
| `offeringType` | `IPO`, `ABO`, `EQL`, `RI`, `SPAC` or `OTH` | Exact, any case |
| `sector` | A sector name | Partial, any case |
| `marketCapBand` | `micro`, `small`, `mid`, `large` or `mega` | Exact, any case |
| `state` | `PRICED`, `ANNOUNCED`, `LIVE` or `WITHDRAWN`. Omit it for every state | Exact, any case |
| `pricingDateFrom` / `pricingDateTo` | Dates as `YYYY-MM-DD` | Inclusive. Only priced deals have a pricing date |
| `withdrawnDateFrom` / `withdrawnDateTo` | Dates as `YYYY-MM-DD` | Inclusive. Only withdrawn deals have a withdrawal date |
| `issuers` | Up to 50 issuer names | Partial, any case; any name matches |
| `countries` | Up to 50 country codes (see [Countries](#countries)) | Exact; any code matches |
| `publishingBanks` | Up to 50 bank names (see [Publishing banks](#publishing-banks)) | Partial, ignoring case, punctuation and spacing; any name matches |
| `minDealSizeUSD` | A deal size in US dollars | Deal size at or above this |

### `search_deals`

Finds deals that match your filters, most recently priced first. Withdrawn deals are ordered by withdrawal date.

- **Needs at least one filter.** `state=PRICED` on its own doesn't count, but `ANNOUNCED`, `LIVE` or `WITHDRAWN` does.
- **Returns** 20 deals per page by default and up to 50, with the total count, whether there are more, and the offset of the next page.
- **Each deal** carries every field in [What a deal contains](#what-a-deal-contains) except `state` and `marketCapBand`. Use `get_deal` for those.

Examples: `offeringType` `IPO`, `countries` `["IND"]` and `pricingDateFrom` `2026-01-01` lists IPOs listed in India and priced in 2026. `state` `WITHDRAWN` and `withdrawnDateFrom` `2026-01-01` lists deals withdrawn this year.

### `get_aggregated_deals_metrics`

Groups deals by one dimension and returns one metric for each group.

- **`groupBy`**: `sector`, `region`, `offeringType`, `marketCapBand`, `state`, `country` or `publishingBank`.
- **`metric`**: one of the following.

  | Metric | What it returns |
  | --- | --- |
  | `dealCount` | Number of deals |
  | `totalVolumeUSD` | Total deal size, in US dollars |
  | `avgPerf1d` / `avgPerf1w` / `avgPerf1m` | Average share price move one day, one week or one month after pricing, in percentage points |

- **Filters**: the same as `search_deals`. For dates, use one of the pricing-date range, `lookbackDays` (days back from the latest pricing date in the data) or the withdrawal-date range.
- **States**: without a `state` or date filter, groups include announced, live and withdrawn deals as well as priced ones. Set `state` `PRICED`, or a pricing-date range, to count completed deals only.
- **Returns** one row per group: the group value, its deal count and the metric. Check the deal count before trusting an average.

Example: `groupBy` `country`, `metric` `totalVolumeUSD`, `offeringType` `IPO` and `lookbackDays` `90` gives IPO volume by listing country over the last 90 days.

> **Some groupings count a deal more than once**
>
> Grouping by `country` counts a dual-listed deal in each of its countries, and
> grouping by `publishingBank` counts a deal once for every bank on it. Group
> totals can then add up to more than the number of deals. Deals with no
> country or no bank form a group of their own. Average performance for
> announced, live and withdrawn groups comes back empty, because those deals
> haven't traded.

### `get_deal`

Returns the full record for up to 50 deals at once.

- **`dealIds`**: an array of 1 to 50 deal IDs. IDs from `search_deals`, `search_lockups` and `search_bookbuild_messages` all work.
- **Returns** the deals in the order you asked for, every field in [What a deal contains](#what-a-deal-contains), plus a list of any IDs that matched no deal.

### `get_available_deals_filters`

Returns the valid values for every filter above, worked out from the data, plus the earliest and latest pricing dates. Pass values to the filters exactly as returned. Bank names are a long list, so they're only included when you pass `includePublishingBanks=true`.

### `get_deals_data_coverage`

Describes the dataset: the pricing-date and withdrawal-date ranges, deal counts by state, and every field the deal tools return, with what it means, its possible values and how often it's filled. It also lists the dataset's limits. Ask your assistant to call it when you need to know how far an answer can be trusted.

### Publishing banks

You can filter and group deals by the banks on them, in any role: bookrunners and coordinators, but also sponsors, co-managers, placing agents and advisers.

- Any bank name containing your term counts, so "Morgan Stanley" also matches "MUFG Morgan Stanley", and a broad term such as "Bank" pulls in several banks.
- If a name matches no bank, you get no deals back, plus a list of similar bank names to try instead.
- Grouping by `publishingBank` uses the bank names as they appear on each deal, so one bank can show up under several name variants. Check the groups before comparing two banks.

### Countries

`countries` filters on the country of the **listing exchange**, not the issuer's home country. Values are three-letter ISO 3166 codes, for example `IND`, `JPN` or `GBR`. A dual-listed deal matches each of its countries.

## What a deal contains

`get_deal` returns every field below. `search_deals` returns all of them except `state` and `marketCapBand`. Not every field is filled for every deal: announced and live deals have no pricing date, prices or performance yet, withdrawn deals never get them, and EQL deals have no prices, performance or market cap.

| Field | What it is |
| --- | --- |
| `dealId` | Primary Portal's ID for the deal. |
| `issuer` | The issuer's name. |
| `ticker` | The ticker, with its exchange code, for example `658A JP`. |
| `state` | `PRICED`, `ANNOUNCED`, `LIVE` or `WITHDRAWN`. |
| `offeringType` | `IPO`, `ABO`, `EQL`, `RI`, `SPAC` or `OTH`. |
| `region` | `EMEA`, `APAC` or `AMRS`. |
| `sector` | The issuer's sector. |
| `dealSizeUSD` | The deal size, in US dollars. |
| `marketCapBand` | The issuer's market cap at the time of the deal, as a band: `micro` (under USD 250m), `small` (250m to 2bn), `mid` (2bn to 10bn), `large` (10bn to 200bn) or `mega` (200bn and above). Filled only when `marketCapUSD` is. |
| `marketCapUSD` | The issuer's market cap at the time of the deal, in US dollars. It's fixed then and never refreshed, so it isn't today's market cap. For IPOs it's the low end of the implied range. Often empty outside IPOs. |
| `announcementDate` | The date the deal was announced. Filled on almost every deal, including announced and live ones. |
| `pricingDate` | The date the deal priced. |
| `withdrawnDate` | The date the deal was withdrawn. Filled only on withdrawn deals. |
| `offeringCurrency` | The currency the deal was offered in, as a three-letter ISO 4217 code, for example `JPY`. Both prices below are in this currency. Often empty on announced and live deals. |
| `finalPriceLocal` | The final offer price per share, in the offering currency. |
| `latestPriceLocal` | The latest daily closing price per share, in the offering currency. It's refreshed once a day, not a live quote, and isn't adjusted for splits or rights issues. |
| `timeToBooksCoveredMin` | Minutes from books opening to books covered. Filled on only a minority of deals. An ABO usually covers in minutes and an IPO over a day or more, so only compare it within one offering type. |
| `performance` | The share price move in percentage points: `oneDay`, `oneWeek`, `oneMonth` and `sincePricing`. `sincePricing` compares the latest price with the final price. |
| `publishingBanks` | Every bank on the deal, with its role. |
| `url` | A link to the deal in Primary Portal (see [What data you'll see](#what-data-youll-see)). |

## Sample prompts

- "What deal data do I have access to?"
- "Show me IPOs priced in the technology sector in EMEA over the last 6 months."
- "What's the average one-week aftermarket performance for healthcare IPOs this year, by region?"
- "Show me the deals Nomura was on in the last six months."
- "Compare Goldman Sachs and Morgan Stanley on healthcare IPOs this year by deal count."
- "List IPOs listed in India in 2026."
- "Which country had the highest total ECM volume in APAC this year?"
- "Which IPOs were withdrawn in EMEA this year?"
- "Give me full details on these three deals: [deal IDs]."
- "What filters can I use to narrow a deal search?"
- "Which IPO lock-ups are expiring in the next month in EMEA?"
- "Which lock-ups expire in Japan in the next two weeks?"
- "Show me the bookbuild messages from JP Morgan for [issuer name]."

## Lock-ups

`search_lockups` queries an upcoming **lock-up expiries calendar**: a forward-looking view of when share lock-ups on recent deals are due to expire. It's available on the **Priced** entitlement, and therefore to Live users too.

> **You must name at least one deal type**
>
> `search_lockups` never returns the whole dataset unfiltered. The `dealTypes`
> filter is required. Every query has to name one or more offering types (for
> example, IPO). The remaining filters are optional.

Filters:

- **`dealTypes`** (required): one or more offering types.
- **`issuer`** (optional): partial and case-insensitive; matches on both the issuer name and the ticker.
- **`region`** (optional): a specific deal region.
- **`countries`** (optional): one or more listing countries (see [Countries](#countries)).
- **`expiryFrom` / `expiryTo`** (optional): bound the results to a lock-up expiry date range.
- Results are ordered by expiry date, nearest first, and paginated.

Each row also lists the deal's bookrunners and a link to the deal in Primary Portal.

> **One row per selling shareholder**
>
> A deal appears once per selling shareholder, so the same deal can span several
> rows. The USD value on each row is that shareholder's own holding (in USD
> millions, not the deal size), so summing it across a deal's rows gives the
> deal's total locked-up value. Performance is a deal-level figure repeated on
> every row, so don't sum or average it across a deal's rows, or you'll
> double-count.

The dataset is a rolling snapshot of upcoming expiries (currently around a month ahead), not a full history. Depending on when it was last loaded, it can also include expiries from the past few days. Every response reports the expiry window it currently holds, so an empty result tells you whether nothing matched your filters or you simply queried outside the loaded window.

## Bookbuild messages

If your organisation holds the **Live** entitlement, two additional tools let you search bookbuild messages.

> **Requires the Live entitlement**
>
> The bookbuild tools are the one part of Primary Portal MCP that Priced doesn't reach. A
> Priced-only account won't see them at all. They simply won't appear in your
> assistant's tool list. Everything else, including lock-ups, is available on
> both tiers.

- **`search_bookbuild_messages`**: filter by `dealIds` (exact match), `issuers` (partial, case-insensitive) or `bankNames` (partial, case-insensitive). At least one of these is required. Each takes up to 50 values: values within a filter are combined with OR, and different filters with AND. You can narrow further with `countries`, but it doesn't count as the required filter on its own. Results are paginated (up to 50 per page), ordered most recent first, and message bodies are returned in full. Each message carries its deal's state, including withdrawn, and a link to the deal.
- **`get_available_bookbuild_filters`**: takes no input and returns the issuer names, bank names and listing countries present in the messages you can see, so you can discover valid filter values instead of guessing (the bookbuild equivalent of `get_available_deals_filters`).

You only see messages for deals you can see through the deal tools. A deal ID you can't see returns an empty list rather than an error, as does a search with no matches.

## What data you'll see

**Announced and live deals.** Priced users see the priced-deal universe. Live users additionally see announced and in-flight deals, but only where there's an active [connection](#before-you-start) to the relevant bank, and further filtered by country and regulatory-status rules (REG_S vs QIBS). If a connection is revoked, it takes effect on your very next query.

**Deal states.** Deals are `PRICED`, `ANNOUNCED`, `LIVE` or `WITHDRAWN`. Withdrawn deals were cancelled before pricing. They're included on the Priced entitlement, and `get_deals_data_coverage` reports the span of withdrawal dates available.

> **Empty fields on in-flight deals are expected**
>
> In-flight deals may show empty performance or pricing fields rather than a
> fabricated placeholder. That's expected, not a data error.

**Links to Primary Portal.** Every deal, lock-up and bookbuild result includes a link to the deal in Primary Portal: the termsheet for announced and live deals, and the deal page otherwise. Your assistant should pass the link on unchanged rather than build its own.

**Input rules.**

- Fixed values such as region, offering type, market-cap band, state and deal type are accepted in any case, so `ipo` works as well as `IPO`.
- Filters that take a list (issuers, countries, banks, deal IDs) accept up to 50 values. More than that is rejected with an input error.

## Fair use thresholds

Primary Portal MCP isn't charged by volume, but use must stay within these thresholds, under clause [5.2](/mcp/terms-and-conditions/#clause-5-2) of the [Data MCP Terms of Use](/mcp/terms-and-conditions/).

| Term | Meaning |
| --- | --- |
| Data object | A single deal, bookbuild message or lock-up record |
| Tool call | A single call to one of the MCP tools |

| Threshold | Limit |
| --- | --- |
| Data objects per minute per authorised user | 2,000 |
| Data objects per month per authorised user | 100,000 |
| Tool calls per minute per authorised user | 30 |

Use above any threshold is presumed to be outside interactive sessions, unless you can show otherwise.

> **Need bulk or automated access?**
>
> Primary Portal MCP is for interactive questions only. Bulk, automated or system-to-system access to deal data is available through Dealfeed. Contact [experience@primaryportal.com](mailto:experience@primaryportal.com) to find out more.

## Security and data handling

- No API keys or personal access tokens: you sign in with your existing Primary Portal account (OAuth), and access ends as soon as your account, connection or entitlement changes.
- Every query is checked against your current entitlements and connections, so a change applies from your next query.
- You only ever see the deals your organisation is entitled to.
- Every tool is read-only: none can create, change or delete anything.
- Access is logged for usage and audit purposes.

## Getting help

> **Need help?**
>
> For help with Primary Portal MCP, or if something isn't behaving as this guide describes, email [experience@primaryportal.com](mailto:experience@primaryportal.com).

Source: https://docs.primaryportal.com/mcp/index.mdx
