BriefPanel is a remote MCP server. Connect it to Cursor, Claude Code, Windsurf, or anything that speaks the Model Context Protocol, and your agent can start monitoring pages and read back what changed.
This is the technical reference. For an overview of what the integration is for, see the MCP page.
Endpoint
https://actions.briefpanel.com/mcp
- Transport — Streamable HTTP, stateless: one JSON-RPC request per
POST, answered with a JSON response. Server-Sent Events are deprecated and not required. - Protocol version —
2024-11-05, advertised in theinitializehandshake.
A discovery document is published at https://briefpanel.com/.well-known/mcp.json, so MCP hosts that auto-discover servers by domain can find it without configuration.
Authentication
Send a personal API key as a Bearer token:
Authorization: Bearer YOUR_BRIEFPANEL_API_KEY
Create a key under Settings → API & integrations in the app (https://app.briefpanel.com/integrations).
Keys start with bp_mcp_ and the same key works for the REST API.
A missing or invalid key returns 401 with a WWW-Authenticate header.
Scopes
Each key carries scopes. Read tools need read; add_source, update_source, pause_source,
resume_source and relearn_source need write. Calling a tool your key lacks the scope for
fails rather than silently doing nothing.
OAuth
Clients that need OAuth — Claude.ai and Claude Desktop custom connectors, ChatGPT connectors — can connect without a pasted key. Point the client at the endpoint above and it discovers the rest:
/.well-known/oauth-protected-resource(RFC 9728) and/.well-known/oauth-authorization-serverpublish the metadata.- Clients register themselves at
/oauth/register(RFC 7591), so there is no client setup to do by hand. - The flow is OAuth 2.1 authorization code with PKCE (S256). You approve the connection on a consent screen in the BriefPanel app, signed in to the account being connected.
- Scopes are the same
readandwritean API key carries.
Access tokens (bp_oat_) last an hour. Refresh tokens last 30 days and rotate on every use.
Tokens are audience-bound to the MCP resource, so they authenticate MCP calls only. Sending one to
the REST API returns 401 with a message saying exactly that — the token is not
broken, REST takes a personal API key instead.
Client configuration
Most clients read the standard mcpServers block:
{
"mcpServers": {
"briefpanel": {
"url": "https://actions.briefpanel.com/mcp",
"headers": { "Authorization": "Bearer YOUR_BRIEFPANEL_API_KEY" }
}
}
}
Claude Code takes it as one command:
claude mcp add --transport http briefpanel https://actions.briefpanel.com/mcp \
--header "Authorization: Bearer YOUR_BRIEFPANEL_API_KEY"
Cursor has a one-click install link on the MCP page.
Tools
Fourteen tools, nine of them read-only.
For every paginated tool, keep following pagination.nextCursor while pagination.hasMore is
true. Filters can make a page empty or shorter than limit even when more results remain.
list_sources
List the web pages you monitor, including monitoring configuration and recent fetch health. It does
not carry a page's monitoring instructions or sensitivity — get_source does.
| Argument | Type | Notes |
|---|---|---|
limit |
number | Maximum sources to return, 1–100. Defaults to 25. |
cursor |
string | Opaque value from pagination.nextCursor on the previous response. |
Two fields there are derived rather than stored, and both exist so you are never told a check that is not coming:
| Field | Meaning |
|---|---|
nextCheckTime |
When the next check is expected, at the earliest. Absent when there is no next check to report — either no check is coming at all (a paused page, or one auto-paused after repeated failures), or the page has never been checked and its first one has not landed yet, which is what you read right after add_source. status tells the two apart: the second is active. |
effectiveMonitoringFrequency |
The cadence actually in effect. Checks are started by a scheduler on a fixed tick, so a page set faster than that tick is still read at the tick. |
get_source
One monitored page in full: everything list_sources returns, plus every setting add_source and
update_source can write. Read a setting through this before changing it, and call it again to
confirm the change landed.
| Argument | Type | Notes |
|---|---|---|
sourceId |
string | Required. The source ID to read. |
Beyond the list_sources fields, the response carries userPrompt, notificationsEnabled,
updateSensitivity and sensitivityLevel. updateSensitivity runs from 0 to 1 and decides how much
of a page's churn is worth reporting; sensitivityLevel names the band it falls in:
updateSensitivity |
sensitivityLevel |
What gets reported |
|---|---|---|
| 0–0.33 | low |
Material facts only — price, availability, dates, terms. A price must move 5% to alert. |
| 0.34–0.66 | medium |
The default when it was never set. Adds supporting detail; 2% on price. |
| 0.67–1 | high |
Adds small clarifications too; 0.5% on price. |
A source that never had one set reports the effective 0.5 / medium, which is what its checks
actually use.
list_source_entries
The items one monitored page currently holds — their IDs, titles, URLs, prices and tracked
attributes — most recently updated first. This is how you reach an entryId for get_entry_updates
and get_entry_changes: an item that has not changed lately appears in no change feed. An empty
first page means the page holds no items at all, which is a different answer from having no recent
changes.
| Argument | Type | Notes |
|---|---|---|
sourceId |
string | Required. The source ID whose items to list. |
limit |
number | Maximum entries to return, 1–100. Defaults to 25. |
cursor |
string | Opaque value from pagination.nextCursor on the previous response. |
get_source_changes
Typed item updates across your monitored pages. Every result includes the entry title, URL, kind,
updateType, importance, canonical field and valueChange; price updates also include a
convenience priceDelta. Pass sourceId to read one page's changes instead of the whole account's.
| Argument | Type | Notes |
|---|---|---|
sourceId |
string | Optional. Return only this page's updates. Omit for every page. |
limit |
number | Maximum updates to return, 1–100. Defaults to 25. |
cursor |
string | Opaque value from pagination.nextCursor on the previous response. |
since |
number or string | Epoch milliseconds, or an ISO-8601 timestamp. |
importance |
string | Optional critical, material, or minor filter. |
get_entry_updates
The typed history for one extracted entry. This has the same data contract as the REST API's entry updates endpoint, including filters and cursor pagination.
| Argument | Type | Notes |
|---|---|---|
entryId |
string | Required. The entry ID to inspect. |
limit |
number | Maximum updates to return, 1–100. Defaults to 25. |
cursor |
string | Opaque value from pagination.nextCursor on the previous response. |
importance |
string | Optional critical, material, or minor filter. |
field |
string | Optional tracked field filter, such as price or title. |
get_entry_changes
The fetch/change timeline for one entry, including whether structured diff evidence is available.
| Argument | Type | Notes |
|---|---|---|
entryId |
string | Required. The entry ID to inspect. |
limit |
number | Maximum timeline cards to return, 1–100. Defaults to 25. |
cursor |
string | Opaque value from pagination.nextCursor on the previous response. |
get_entry
One item in full — everything list_source_entries returns for it plus the prose the list omits:
summary (what the page says about the item — the article's text, the quote, the job posting) and
author. For every non-priced kind (quote, news article, blog post, job posting) these two fields
are the entry's content. Also carries language, the locale the prose was written in.
| Argument | Type | Notes |
|---|---|---|
entryId |
string | Required. The entry ID to read. |
get_credit_balance
Your remaining credits. A check spends one credit per page it reads — the source page, plus each item page it follows. No arguments.
whoami
The identity and scopes tied to the current API key — useful for confirming which account a key belongs to. No arguments.
add_source
Start monitoring a page. It needs the write scope. Each later check spends one credit per page it reads.
| Argument | Type | Notes |
|---|---|---|
url |
string | Required. The page URL to monitor. |
userPrompt |
string or null | What changes matter, in plain language. null clears it. |
monitoringFrequency |
number | Minutes between checks, from 30 to 10080 (7 days). Defaults to 60. A value outside that range is refused, not quietly changed. |
notificationsEnabled |
boolean | Whether to notify on changes. Defaults to false. |
One page per URL. An account never holds the same URL twice. Calling add_source for a page it
already monitors — under any userPrompt — does not start a second copy of it. The settings the
call carries are applied to the page that already exists, and only those: anything you leave out
keeps its current value.
The response says which case you got:
| Field | Meaning |
|---|---|
sourceId |
The page's id, new or existing. |
created |
true for a page that did not exist, false for one that did. |
updatedSettings |
The settings this call wrote onto an existing page. Empty when created is true, because everything passed was used to create it. |
Changing userPrompt this way re-learns how the page is read, exactly as update_source does,
for the same one credit.
The URL is normalized first, so https://www.example.com/a/ and https://example.com/a are the
same page, not two.
update_source
Update ordinary settings for a monitored page. It needs the write scope; use pause_source and
resume_source to stop and start monitoring.
| Argument | Type | Notes |
|---|---|---|
sourceId |
string | Required. The source ID to update. |
name |
string or null | Optional display name; pass null to clear it. |
userPrompt |
string or null | Optional monitoring instructions; pass null to clear them. |
monitoringFrequency |
number | Optional minutes between checks, from 30 to 10080 (7 days). A value outside that range is refused, not quietly changed. |
notificationsEnabled |
boolean | Optional notification toggle. |
updateSensitivity |
number | Optional change sensitivity from 0 through 1. |
Supply at least one setting besides sourceId.
A changed userPrompt re-learns how the page is read, which costs one credit when the re-learn
succeeds. With no credits left the prompt is still saved, but the re-learn does not run.
pause_source
Reversibly stop monitoring a page. It needs the write scope; it does not delete the source or its
history. Start it again with resume_source, or from the BriefPanel app.
| Argument | Type | Notes |
|---|---|---|
sourceId |
string | Required. The source ID to pause. |
resume_source
Start monitoring a paused page again — the counterpart to pause_source. It needs the write
scope.
| Argument | Type | Notes |
|---|---|---|
sourceId |
string | Required. The source ID to resume. |
Checks restart on the page's own frequency and spend credits again, one per page read. The answer
carries alreadyActive, status and nextFetchTime: resuming a page that is already monitored is
a no-op reported as alreadyActive: true, not an error, and it schedules no extra check — so a
retry is safe.
status is the page's stored state, not a forecast. On an account with no credits a resume still
answers active, and the scheduler re-parks the page as creditPaused on the next check it comes
due for — use get_credit_balance to tell whether checks will actually run.
Resuming does not rebaseline. The page is still compared against how it looked when it was paused, so the first check after a long pause can report everything that changed in between. Items collected before the pause are untouched and are not re-notified.
relearn_source
Re-analyze how a page is structured, so later checks extract it with freshly learned rules. Use it
when a page was redesigned, or when its items are coming out wrong. It needs the write scope, and
it changes extraction rules only — items already collected are untouched. Each call costs one
credit when the re-analysis succeeds, and nothing when it fails; with no credits left it fails with
noCredits and nothing runs.
| Argument | Type | Notes |
|---|---|---|
sourceId |
string | Required. The source ID to re-analyze. |
Reading history
MCP is built for conversation: use get_source_changes for a cross-source feed (or one page's,
with sourceId), list_source_entries to reach an item, get_entry to read one item's prose in
full, and the entry tools for typed history. The
REST API exposes most of the same reads for programmatic clients, plus
snapshot/blob retrieval and its OpenAPI contract — but get_source's settings and the sourceId
filter are MCP-only for now.