MCP Tools

MCP tools expose Research Protocol to AI agents; 46 are documented below. All tools auto-discover via POST /mcp-server/mcp, and tools/list returns every one with its schema. Authentication is by API key (admin scope) for provider tools and by session for the rest.

Intelligence

4 tools

Cross-library research search and screening.

search_researchFree-text search across every connected provider's research notes, filtered by sector, ticker, or rating.
query (string, required)
Free-text search query.
sectors (string[], optional)
Filter by sector names.
tickers (string[], optional)
Filter by ticker symbols.
rating (string, optional)
Buy / Hold / Sell.
limit (int, default 20)
Max number of results.
search_research(query="UK banks Q1", rating="Buy", limit=10)
stock_intelligenceCross-street consensus for a single ticker: note count per provider, latest rating, and consensus distribution.
ticker (string, required)
Ticker symbol to look up.
stock_intelligence(ticker="SHEL")
screen_stocksMulti-factor screen across providers, filtered by sector, rating, and a minimum cross-street note count.
sectors (string[], optional)
Filter by sector names.
rating (string, optional)
Filter by analyst rating.
min_notes (int, optional)
Minimum cross-street note count.
limit (int, default 20)
Maximum results.
screen_stocks(sectors=["Energy"], rating="Buy", min_notes=3)
monitor_portfolioTracks a portfolio of tickers against recent research activity. Returns per-ticker note counts and rating changes inside the lookback window.
org_id (Guid, required)
Buy-side organisation identifier.
tickers (string[], required)
Tickers to monitor.
days_back (int, default 7)
Lookback window in days.
monitor_portfolio(org_id="...", tickers=["SHEL","BP."], days_back=14)

Buy-Side

6 tools

Activity, briefings, and watchlist monitoring for the buy-side.

research_feedFiltered feed of recent research notes across every provider you're entitled to.
limit (int, default 20)
Maximum number of notes.
sectors (string[], optional)
Sector filter.
note_type (string, optional)
e.g. initiation, update.
research_feed(sectors=["Banks"], limit=5)
morning_briefingOvernight research summary for an organisation: notes published since yesterday plus rating changes from the past week.
org_id (Guid, required)
Buy-side organisation identifier.
morning_briefing(org_id="...")
provider_valueProvider value scoring for an organisation: 30-day consumption, coverage breadth, and rating-change pace, ranked by usefulness.
org_id (Guid, required)
Buy-side organisation identifier.
provider_value(org_id="...")
watchlist_monitorMonitors a named watchlist for new research on tracked companies. Surfaces note count, latest published date, and any rating changes per ticker.
org_id (Guid, required)
Buy-side organisation identifier.
user_id (Guid, required)
User whose watchlist to monitor.
watchlist_name (string, default "Default")
Name of the watchlist.
days_back (int, default 7)
Lookback window.
watchlist_monitor(org_id="...", user_id="...", watchlist_name="Energy")
user_activityPer-user research consumption activity: purchase count and most recent purchase date.
org_id (Guid, required)
Buy-side organisation identifier.
user_id (Guid, optional)
Specific user, or omit for org-wide.
user_activity(org_id="...", user_id="...")
ticker_searchAutocomplete ticker search across the research index. Returns ticker, company name, and exchange.
query (string, required)
Company name or ticker fragment.
ticker_search(query="royal d")

Operations

6 tools

Provider listing, entitlement checks, and access to notes and their models.

list_providersLists every research provider on the protocol with portal status and current health.
list_providers()
check_entitlementChecks whether an organisation has active access to a specific provider. Returns access type and expiry.
org_id (Guid, required)
Buy-side organisation.
provider_id (Guid, required)
Provider to check.
check_entitlement(org_id="...", provider_id="...")
request_contentRequests access to a research note's content. Validates entitlement and returns a signed redirect URL.
note_id (Guid, required)
Research note identifier.
org_id (Guid, required)
Requesting organisation.
request_content(note_id="...", org_id="...")
get_note_modelsLists the models attached to a research note that you can download.
note_id (Guid, required)
Research note identifier.
get_note_models(note_id="...")
download_note_modelResolves one note model: returns its metadata and the download URL to fetch the file from.
note_id (Guid, required)
Research note identifier.
model_id (Guid, required)
The model (an attachment id), as get_note_models lists it.
download_note_model(note_id="...", model_id="...")
provider_dashboardDashboard summary for a single provider: note count, active entitlement count, latest publication date.
provider_id (Guid, required)
Provider identifier.
provider_dashboard(provider_id="...")

Support

1 tools

Read-only diagnosis of your own readers and notes. Needs a provider admin's session, or an API key of the provider's organisation holding the support scope, which only Research Protocol can set. The provider is always the caller's own.

explain_accessExplains why a person can or cannot open one of your notes: runs the real access check as them for each organisation they belong to, and reports the facts behind each step (note status, the grant and its template, user scoping, each rule, the portal compliance check). facts_and_gate_disagree=true means a bug, not a setup question. An address outside your clients and staff answers exactly as an unknown one.
email (string, required)
The reader's email address.
note_id (Guid, required)
The research note.
explain_access(email="[email protected]", note_id="...")

Forecasts

5 tools

Broker forecasts and cross-broker consensus. Headline consensus figures come back for any caller; a signed-in caller also gets the spread and rating distribution, and per-provider rows, revisions and models are limited to the providers you own or are entitled to.

get_consensusCross-broker consensus for a ticker: median, mean, min, max, count and currency, plus the interquartile range and rating distribution when you are signed in. Per-provider rows are on compare_brokers.
exchange (string, required)
Listing exchange, e.g. LSE, NASDAQ.
ticker (string, required)
Ticker symbol, e.g. SHEL.
get_consensus(exchange="LSE", ticker="SHEL")
get_consensus_historyThe history view for a ticker. snapshots is the current consensus per metric and period (there is no consensus time series yet). For entitled callers, provider_revisions is each entitled provider's full revision history; superseded_at null marks the current revision.
exchange (string, required)
Listing exchange, e.g. LSE, NASDAQ.
ticker (string, required)
Ticker symbol, e.g. SHEL.
get_consensus_history(exchange="LSE", ticker="SHEL")
compare_brokersPer-provider forecast rows for a ticker, side by side, limited to the providers you are entitled to (empty when you have no entitlements). The period filters narrow the rows.
exchange (string, required)
Listing exchange, e.g. LSE, NASDAQ.
ticker (string, required)
Ticker symbol, e.g. SHEL.
fiscal_year (int, optional)
Fiscal-year filter.
period_type (string, optional)
annual, half, quarter or month.
period_index (int, optional)
1-based period index; omit for annual.
compare_brokers(exchange="LSE", ticker="SHEL", fiscal_year=2027, period_type="annual")
get_provider_forecast_modelOne provider's rendered forecast model for a company: the assigned template's views, line items and active values. You must own the provider (the sell-side view) or hold an entitlement on it (the buy-side view).
provider_id (Guid, required)
The provider.
exchange (string, required)
Listing exchange, e.g. LSE, NASDAQ.
ticker (string, required)
Ticker symbol, e.g. SHEL.
get_provider_forecast_model(provider_id="...", exchange="LSE", ticker="SHEL")
list_provider_templatesLists every active forecast template a provider owns, with id, code, display name and version. You must own the provider or hold an entitlement on it.
provider_id (Guid, required)
The provider.
list_provider_templates(provider_id="...")

Forecast Authoring

8 tools

Sell-side tools for building a forecast model and publishing numbers: define line items and views, assemble them into templates, map line items to consensus metrics, assign a template to a company and push forecast rows. The provider is always the caller's own, so a caller whose organisation is not a provider is refused. Every write is an upsert on a code or a placement, so repeating a call is safe.

upsert_line_itemCreates a line item by code, or patches the supplied fields onto your active one with that code. Returns the line item id and whether it was revised.
code (string, required)
Stable code you control, snake_case, at most 80 characters.
display_name (string, required)
Name shown in tables and charts.
unit_type (string, required)
currency, per_share, percent, multiple, ratio or count.
description (string, optional)
Analyst description.
currency_code (string, optional)
ISO 4217 code; required for currency and per_share.
magnitude (string, optional)
units, thousands, millions or billions.
display_suffix (string, optional)
Suffix override for the renderer, at most 10 characters.
upsert_line_item(code="revenue", display_name="Revenue", unit_type="currency", currency_code="GBP", magnitude="millions")
upsert_forecast_viewCreates a view by code, or updates the display name, view type and description of your active one with that code.
code (string, required)
Stable code you control, snake_case.
display_name (string, required)
Name shown in the builder and render headers.
view_type (string, required)
table, line_chart, bar_chart, summary_card or combo_chart.
description (string, optional)
Analyst notes about the view.
upsert_forecast_view(code="income_statement", display_name="Income statement", view_type="table")
place_line_item_in_viewPlaces a line item in a view at a sort order, or updates the sort order, row style and group label of an existing placement. Both must be your provider's.
view_id (Guid, required)
The view.
line_item_id (Guid, required)
The line item to place.
sort_order (int, required)
Ascending order within the view, by convention 10, 20, 30.
row_style (string, optional)
standard, sub_total, grand_total, header or separator.
group_label (string, optional)
Section label grouping consecutive rows.
place_line_item_in_view(view_id="...", line_item_id="...", sort_order=10)
upsert_forecast_templateCreates a template by code, or updates the display name and description of your active one with that code. Returns the template id and its current version.
code (string, required)
Stable code you control, snake_case.
display_name (string, required)
Name shown on assignment dropdowns.
description (string, optional)
Analyst description.
upsert_forecast_template(code="oil_major", display_name="Oil major")
add_view_to_templatePlaces a view in a template at a position, or updates the position and title override of an existing placement. Both must be your provider's.
template_id (Guid, required)
The template.
view_id (Guid, required)
The view to place.
position (int, required)
Ascending position within the template, by convention 10, 20, 30.
title_override (string, optional)
Title for the view in this template only.
add_view_to_template(template_id="...", view_id="...", position=10)
map_line_item_to_canonicalMaps a line item on a template to a Research Protocol canonical metric (revenue, ebitda, eps_adjusted and so on), which is what feeds consensus. Updates the scale factor and sign flip when the mapping already exists.
template_id (Guid, required)
The template.
line_item_id (Guid, required)
The source line item.
rpt_canonical_metric (string, required)
e.g. revenue, ebitda, eps_adjusted.
scale_factor (number, default 1.0)
Multiplier applied before the value contributes to consensus.
sign_flip (bool, default false)
Negate the value before aggregation, e.g. net cash to net_debt.
map_line_item_to_canonical(template_id="...", line_item_id="...", rpt_canonical_metric="revenue")
assign_template_to_companyAssigns one of your templates to a company. Reassigning replaces the template without removing the company's forecast rows. Provider admin only.
template_id (Guid, required)
The template.
exchange (string, required)
Listing exchange, e.g. LSE, NASDAQ.
ticker (string, required)
Ticker symbol, e.g. SHEL.
assign_template_to_company(template_id="...", exchange="LSE", ticker="SHEL")
push_forecast_rowsPushes a batch of forecast rows, each resolving its line item by id or code, and returns ingested, unchanged or rejected per row. An analyst may push only for tickers they cover; provider and platform admins are not limited. An API key must hold the admin scope and name analyst_user_id; pushing on behalf of another user needs admin.
rows (object[], required)
Each row: exchange, ticker, fiscal_year, period_type and as_of_date; line_item_id or line_item_code; value_numeric or value_text; optionally period_index, period_end_date, period_kind (actual, estimate or preliminary; default estimate), currency and note_id.
analyst_user_id (Guid, optional)
Whose forecast this is. Defaults to you in a session; required for an API key.
push_forecast_rows(rows=[{"line_item_code": "revenue", "exchange": "LSE", "ticker": "SHEL", "fiscal_year": 2027, "period_type": "annual", "value_numeric": 312000, "as_of_date": "2026-10-22"}])

Forecast Delegation

4 tools

Provider admins hand forecast work to analysts: coverage of a ticker lets an analyst push rows for it, and template-editor rights let them change one template's structure. Provider admin only, and the analyst must belong to your own organisation.

grant_coverageGrants an analyst coverage of one company, so their pushed rows for that ticker pass the coverage check without a provider admin.
user_id (Guid, required)
The analyst.
exchange (string, required)
Listing exchange, e.g. LSE, NASDAQ.
ticker (string, required)
Ticker symbol, e.g. SHEL.
role (string, default "owner")
owner or backup.
grant_coverage(user_id="...", exchange="LSE", ticker="SHEL")
revoke_coverageRevokes a coverage assignment by id.
user_id (Guid, required)
The analyst who holds the assignment.
coverage_id (Guid, required)
The coverage assignment.
revoke_coverage(user_id="...", coverage_id="...")
grant_template_editorGrants an analyst rights to edit one forecast template's structure. The template must be your provider's.
user_id (Guid, required)
The analyst.
template_id (Guid, required)
The template.
grant_template_editor(user_id="...", template_id="...")
revoke_template_editorRevokes a template-editor grant by id.
user_id (Guid, required)
The analyst who holds the grant.
grant_id (Guid, required)
The template-editor grant.
revoke_template_editor(user_id="...", grant_id="...")

Provider Admin

12 tools

Sell-side client administration: set up a client firm, grant it access, add its people, remove a leaver, and manage templates and per-user access. Needs a provider admin's session, or an API key of the provider's organisation created with the admin scope (only an organisation admin can grant it); other keys and members are refused. The provider is always the caller's own. The older api_key argument is optional: if sent, it must be a key of your own organisation.

create_client_orgCreates a client organisation (a firm whose people read your research), or attaches to the existing one its email domain identifies when that firm is already one of yours. A domain registered to a firm outside your reach is refused without naming it.
name (string, required)
Legal or trading name.
domain (string, optional)
Email domain, e.g. "examplefunds.com". Public email domains are ignored.
org_type (string, optional)
buy_side or sell_side.
institution_type (string, optional)
e.g. asset_manager, hedge_fund, wealth_manager.
regions (string[], optional)
Regions the firm covers.
asset_classes (string[], optional)
Asset classes the firm covers.
create_client_org(name="Example Fund Managers", domain="examplefunds.com")
grant_entitlementGrants a client organisation access to your research. Re-granting updates your one entitlement to it, re-activating a revoked one. Optionally applies one of your access templates. Refuses an organisation that owns another research provider.
buy_side_org_id (Guid, required)
The client organisation.
access_type (string, default "retainer")
e.g. retainer, trial, occasional.
expires_at (date, optional)
When the access lapses, read as UTC.
template_id (Guid, optional)
One of your access templates to apply.
grant_entitlement(buy_side_org_id="...", access_type="trial", expires_at="2027-03-31")
invite_contactsAdds people to your client organisations, or updates their names, with one outcome per row (created, updated, or skipped with the reason). At most 500 rows. No email is sent: people sign in with a magic link from your portal. Supports preview mode.
contacts (object[], required)
Rows of buy_side_org_id, email, display_name (optional) and role (optional: member or viewer at a client; admin only in your own organisation).
preview (bool, default false)
true to report each row's outcome without writing.
invite_contacts(contacts=[{"buy_side_org_id": "...", "email": "[email protected]", "display_name": "Pat Example"}], preview=true)
remove_contactRemoves a person who has left a client firm: archives their account, so they can no longer sign in, and drops their per-user access. Refused with org_shared_with_other_providers when other research providers also serve their firm, because removing the account would cut those providers off too; deny them on your own entitlement with bulk_user_access instead. Never removes a peer broker's staff or a firm's last admin.
user_id (Guid, required)
The person, as the Contacts directory or invite_contacts reports them.
remove_contact(user_id="...")
list_clientsLists the buy-side organisations entitled to your research, with access type, user scoping and expiry.
list_clients()
list_user_accessPer-user access records for a user-scoped entitlement.
entitlement_id (Guid, required)
The entitlement.
list_user_access(entitlement_id="...")
update_entitlement_scopeToggles user-level scoping on an entitlement (org-wide vs. specific allow/deny list).
entitlement_id (Guid, required)
The entitlement.
user_scoping (bool, required)
true to enable per-user gating.
update_entitlement_scope(entitlement_id="...", user_scoping=true)
bulk_user_accessBulk allow/deny/clear user access on a user-scoped entitlement. Supports preview mode.
entitlement_id (Guid, required)
The entitlement.
emails (string[], required)
User emails to update.
state (string, required)
allow, deny, or not_set.
preview (bool, default false)
true to compute changes without persisting.
bulk_user_access(entitlement_id="...", emails=[...], state="deny")
bulk_list_recipientsAdds email addresses to, or revokes them from, the distribution list behind one of your entitlement codes (the list that admits investors to a pre-IPO note). Add is idempotent; revoke is soft. Malformed addresses are reported by row. Supports preview mode.
code (string, required)
The entitlement code (case-insensitive).
emails (string[], required)
Addresses to add or revoke.
action (string, required)
"add" or "revoke".
preview (bool, default false)
true to compute changes without persisting.
bulk_list_recipients(code="RUTHERFORD", emails=[...], action="add")
apply_template_to_entitlementCopies an access template's rules onto an entitlement and stamps the template version.
entitlement_id (Guid, required)
Target entitlement.
template_id (Guid, required)
Template to apply.
apply_template_to_entitlement(entitlement_id="...", template_id="...")
detach_template_from_entitlementDetaches the template binding from an entitlement. Copied rules remain.
entitlement_id (Guid, required)
Target entitlement.
detach_template_from_entitlement(entitlement_id="...")
sync_templateRe-applies the latest template rules to every entitlement linked to it.
template_id (Guid, required)
Template to sync.
force (bool, default false)
Re-apply even if entitlement already at current version.
sync_template(template_id="...")