You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 938ee1f
Browse filesBrowse the repository at this point in the historyBrowse files
feat(mcp): native-app redirect URIs, and every tool spells out its hints
Registration accepts a private-use scheme in scheme://... authority form
(RFC 8252 §7.1), which is what a desktop MCP client registers; PKCE stays
mandatory, so a scheme squatter can catch a code and still not exchange it.
Read tools now carry destructiveHint and idempotentHint explicitly rather
than leaning on the spec's defaults.
'List the analytics sites this credential may read, with their slug, name, status and the caller’s role. Call this first: every other tool needs a site id from here.',
'Revenue totals for one site over a date range: gross charges, refunds, withdrawn and reinstated disputes, provider fees and net, plus charge, refund and dispute counts. Every amount is an integer in the minor unit of the site’s reporting currency (`totals.currency`) — 91000 in USD is $910.00, never divide before you have said which currency. Owner-only: any other role is refused with FORBIDDEN, which you must report rather than work around. Read `meta.revenue.connection_status` before calling a zero "no sales": `not_connected` means no payment provider was ever connected.',
'The same revenue measures bucketed over time, one point per hour or per day, for trends. Same currency, minor-unit and owner-only rules as revenue_summary, and the same `meta.revenue.connection_status` caveat. It returns no customer, order or transaction identifiers; individual transactions are not readable from any tool.',
'The tracking snippet and site key for one site — the public token that ships in page source. Read it to drop the tracker into a site’s HTML so it starts reporting. It is public by design; the private read key is never returned here.',
'The members of one site’s team — user id, role and email address. Needs the team:read scope, which is named on the consent screen because it carries emails.',
'The dashboard-defined custom events on one site — each with its name, status and currently published version number. Read this before writing a definition: the version number is what publish and rollback need to state which change they expect to replace. Include archived ones with include_archived=true.',
// not read-only prompts the human for confirmation before each of these.
462
497
{
463
498
name: 'create_site',
499
+
title: 'Create Site',
464
500
description:
465
501
'Create a new analytics site. Returns its id and its tracking key, so the snippet can be installed in the same flow. There is deliberately no domain field: a new site accepts events from any origin until its owner sets an origin allowlist, and that allowlist is a dashboard-only setting, never writable over MCP. Rename or restyle later with update_site.',
// definition stops its rules being served site-wide.
561
601
{
562
602
name: 'create_event_definition',
603
+
title: 'Create Event Definition',
563
604
description:
564
605
'Define a new custom event on one site, with its first version’s content. The definition starts unpublished: nothing reaches a visitor’s browser until publish_event_definition names a version. The event name is permanent — it is the key every chart and funnel will refer to.',
'Save a new draft version of an existing event definition. The whole content is restated, not patched — a version is immutable and complete. A draft is in nobody’s browser until it is published, so this is the safe half of editing an event.',
'Make one version of an event definition live — from this call on, visitors’ browsers evaluate its rules. Reversible with rollback_event_definition, which is why publishing is on this surface at all. `expected_published_version` is not optional bookkeeping: state the version you read from list_event_definitions (or null if nothing is published yet), and a concurrent publish by someone else comes back as a conflict naming what is actually live instead of silently overwriting it.',
'Republish an older version’s content as a new version — the undo for publish_event_definition. It rewinds nothing: calling it twice produces two versions, and the response says which one is now live. Same `expected_published_version` rule as publishing.',
'Edit a widget, or enable/disable it. Disabling is the reversible way to take a widget down — there is no delete over MCP, because a widget id is never reissued.',
'Change which surfaces a site’s public dashboard shows, and optionally rotate its public link. Rotating the link revokes the old one — the safe direction.',
686
733
path: '/sites/{site_id}/public-dashboard',
@@ -998,6 +1045,18 @@ export function createMcpRoutes(deps: McpRoutesDeps): Hono<Env> {
998
1045
},
999
1046
)
1000
1047
1048
+
// The transport is POST-only (no SSE stream, no sessions), which streamable
1049
+
// HTTP permits; what it does not permit is a `404` for the other verbs on a
1050
+
// URL that plainly exists. `405` plus `Allow` tells a probing client "right
1051
+
// door, wrong verb" instead of "no such door". `GET` is the optional
1052
+
// server-to-client stream, `DELETE` the optional session teardown; refusing
0 commit comments