# Fictura

> Paywalls, onboarding, subscription analytics, A/B tests, attribution and errors for mobile apps.

- name: co.fictura/mcp
- version: 0.1.2
- connection class: R0 (autonomous)
- trust: 96/100
- quality: 77/100 (good)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/co.fictura%2Fmcp
- tools: https://api.protogrid.dev/v1/servers/co.fictura%2Fmcp/tools

**An agent can connect right now, no human step.** Remote endpoint, no authentication, reachable on the last probe.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "fictura": {
      "type": "http",
      "url": "https://mcp.fictura.co/mcp",
      "headers": {
        "X-API-Key": "${X_API_KEY}"
      }
    }
  }
}
```

Placeholders to fill: `${X_API_KEY}`.

## Trust

- hygiene: 100
- liveness: 100
- freshness: 100
- provenance: 85
- drivers: +repository +dns-namespace +website +reachable +uptime-100% +updated-16d-ago
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 77/100 (good)

### protocol: 88 (weight 25)

- pass `protocol.modern`: supports 2026-07-28 (server/discover)
- pass `protocol.stateless`: answers without a session
- pass `protocol.transport`: streamable HTTP
- warn `protocol.list_ttl`: tools/list declares ttlMs 0, so clients re-fetch it on every use

### authorization: n/a (weight 15)

- n/a `auth.prm`, `auth.as_metadata`, `auth.cimd`: no remote uses OAuth
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 81 (weight 30)

- pass `tools.descriptions`: every tool has a description
- pass `tools.description_length`: descriptions are concise
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 87 of 87 tools declare readOnlyHint or destructiveHint
- warn `tools.directory_hints`: 19 of 87 tools declare all four hints; missing: get_tracking_plan (idempotentHint); list_campaigns (idempotentHint); get_issue_activity (idempotentHint); …
- warn `tools.token_cost`: about 20,288 tokens to load every tool
- warn `tools.api_dump`: 87 tools, 74% named like REST operations: looks like an API mapped one endpoint per tool
- pass `tools.hidden_text`: no hidden text in tool names, descriptions, schemas or annotations

### stability: 50 (weight 15)

- warn `stability.changes`: 96 tool changes in 30 days
- fail `stability.rug_pull`: 3 tools kept their name but changed most of their description in 30 days; review before trusting them
- pass `stability.new_links`: no tool change named a new site

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: deps.dev does not know @fictura/mcp@0.1.2

- tools: 87, about 20,288 tokens to load them all
- tool set hash: f15e137aac7c9cb7b641311095ac92c5
- tools last changed: 2026-11-12T23:12:56.841Z
- badge: [![protogrid quality](https://protogrid.dev/badge/co.fictura/mcp.svg)](https://protogrid.dev/servers/co.fictura/mcp)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

- 2026-11-12 `stop_experiment` added
  - Stop a running or paused test for good without rolling anything out: everyone gets the live config again. It can't be restarted. Rolling out a winner is done by a person in the dashboard. Only works when the app allows MCP writes.
- 2026-11-12 `resume_experiment` added
  - Resume a paused test so new users enroll again. Refused when another test now holds its surface and placement. Only works when the app allows MCP writes.
- 2026-11-12 `pause_experiment` added
  - Pause a running test: nobody new enrolls, and users already in it keep their arm. resume_experiment picks it up again. Only works when the app allows MCP writes.
- 2026-11-12 `start_experiment` added
  - Start a draft: from now on its arms are served to the users who pass its targeting. Refused when another test is running or paused on the same surface and placement. Only works when the app allows MCP writes.
- 2026-11-12 `create_experiment` added
  - Create an A/B test as a DRAFT: nobody sees it until start_experiment. 2 to 4 arms, each pointing at a paywall or onboarding flow of this app on the experiment's surface (ids from list_surfaces); one arm may be a holdout with no target (it keeps the live config). Exactly one control; the first arm when none is marked. Defaults: mode notify (report the winner, don't ship it), new users only, the default placement, trial_started as the metric. Only works when the app allows MCP writes.
- 2026-11-12 `create_tracking_link` changed (description, inputSchema)
  - before: Creates a tracking link and returns its shareable URL. A tap is logged as a click, then redirected to destination_url with the click's id, which is how an install is credited to the link. Use the store address for a real campaign, or the app's own scheme (myapp://) for a link that opens the app in a test. Creates a new link each time; nothing existing changes. Needs read and edit access.
  - after: Creates a tracking link and returns its shareable URL. A tap is logged as a click, then redirected to destination_url with the click's id, which is how an install is credited to the link. A tap from a computer goes to desktop_url instead, or to the app's website when destination_url is a store page. Use the store address for a real campaign, or the app's own scheme (myapp://) for a link that opens the app in a test. Creates a new link each time; nothing existing changes. Needs read and edit access.
- 2026-11-12 `get_fix_run` added
  - A fix run's status, root cause, plan, files, tests, cost so far, and its pull request.
- 2026-11-12 `start_fix_run` added
  - Start a hosted fix run: Fictura's AI finds the root cause and, if allowed, opens a draft PR. It spends the app's own Anthropic money, capped per run and per day. Poll get_fix_run. Needs MCP writes and AI fixes on.
- 2026-11-12 `get_pull_request_status` added
  - The PRs tied to an issue (opened by Fictura or linked), with state, draft, CI checks, merge and the release that shipped it.
- 2026-11-12 `create_pull_request` added
  - Open any change as a draft PR on a new branch in one of the repos connected to Fictura. Optionally tie it to an issue. Nothing under .github/. Needs "Let MCP keys open pull requests".

Full history: https://api.protogrid.dev/v1/servers/co.fictura%2Fmcp/changes

## Dependencies

- npm @fictura/mcp@0.1.2: unknown

Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0.

## Remotes

- https://mcp.fictura.co/mcp (streamable-http, auth none, reachable true, uptime30d 1)

## Packages

- npm @fictura/mcp@0.1.2 secrets: FICTURA_MCP_KEY

## Tools (87)

- `check_entitlement`: The authoritative paid/not-paid verdict for one user, unified across Stripe, RevenueCat, App Store and Play — the same answer GET /api/v1/entitlements/{user_id} returns to a server. Note: `environment` is SANDBOX when the verdict rests on test purchases, so always check it before granting production access; a cancellation only flips will_renew (access runs to expires_at); and an unknown user is a valid 'none' answer, not an error.
- `compare_releases`: Every route, screen and page seen in both releases, with count, p50, p95 and error rate in each, sorted by the extra time per minute release b spends against a: what got slower or faster. Also what appears in only one of them. Take release names from list_releases or get_tracing_health.
- `create_experiment`: Create an A/B test as a DRAFT: nobody sees it until start_experiment. 2 to 4 arms, each pointing at a paywall or onboarding flow of this app on the experiment's surface (ids from list_surfaces); one arm may be a holdout with no target (it keeps the live config). Exactly one control; the first arm when none is marked. Defaults: mode notify (report the winner, don't ship it), new users only, the default placement, trial_started as the metric. Only works when the app allows MCP writes.
- `create_fix_pr`: Open your fix for an issue as a draft PR in the app's repo, with `Fixes <short id>` so the issue resolves when it ships. Send patches (git diff) per file. No build, CI or .github changes. Needs "Let MCP keys open pull requests".
- `create_inbound_filter`: Drop matching errors at ingest from now on (within 30 seconds): counted, never stored, grouped or alerted on. Use it for noise nobody will fix. Kinds as in list_inbound_filters; environment `simulator` drops events from simulators and emulators. Refuses an exact duplicate. Only works when the app allows MCP writes.
- `create_onboarding_draft`: Creates a draft onboarding flow from a document you wrote (see get_onboarding_doc's reference). It is never made live: going live is done in the dashboard. Needs an MCP key that can edit.
- `create_paywall_draft`: Creates a draft paywall from a Studio template (template_key, from list_templates — the webview ones) or from a document you wrote. It is never made live: going live is done in the dashboard. Needs an MCP key that can edit.
- `create_pull_request`: Open any change as a draft PR on a new branch in one of the repos connected to Fictura. Optionally tie it to an issue. Nothing under .github/. Needs "Let MCP keys open pull requests".
- `create_ticket`: Create a ticket for an error issue in GitHub Issues, Linear or Jira (connected on the Tools tab). The body is short and redacted. One GitHub issue per error issue. Only works when the app allows MCP writes.
- `create_tracking_link`: Creates a tracking link and returns its shareable URL. A tap is logged as a click, then redirected to destination_url with the click's id, which is how an install is credited to the link. A tap from a computer goes to desktop_url instead, or to the app's website when destination_url is a store page. Use the store address for a real campaign, or the app's own scheme (myapp://) for a link that opens the app in a test. Creates a new link each time; nothing existing changes. Needs read and edit access.
- `delete_inbound_filter`: Stop dropping what one inbound filter matches; new events land again within 30 seconds. Events it already dropped are not recovered. Take the id from list_inbound_filters. Only works when the app allows MCP writes.
- `editor_get_doc`: The document exactly as it is on the person's screen (unsaved changes included), which paywall it is, the screen they are on and the node they have selected, plus the document model reference. Read this before editor_set_doc and edit what you got — keep node ids, change only what was asked.
- `editor_set_doc`: Replaces the document in the person's open editor with the one given. It is NOT saved: the person sees the change, can undo it, and saves it themselves. The document is validated first and refused with the problems if it does not parse. Needs an MCP key that can edit.
- `get_acquisition_report`: `roas` gives per-campaign spend, attributed installs/trials/paying users, revenue, CPI, CAC and ROAS, plus blended totals and explicitly-unattributed revenue — always keep attributed and blended figures apart when reporting these. `spend` gives raw daily ad-spend rows. `links` lists this app's tracking links.
- `get_ai_usage`: Model calls by model (gen_ai spans): calls, per minute, error rate, p50 to p99, total time, input and output tokens; and MCP tool calls by tool (mcp.server spans). Prompt and completion text is never stored, so it is never here.
- `get_analytics`: This app's real numbers. `overview` gives headline metrics (users, trials, trial→paid rate, events by name, cancel reasons, 14-day activity). `funnel` gives the ordered conversion funnel with per-step drop-off. `cohorts` compares behaviour across billing outcomes — what converted users did that cancelled users didn't. Below ~100 users in a step the sample is too small to read. `stores` splits paying users, purchases and revenue by App Store / Google Play / web and by storefront country (last 28 days).
- `get_app_setup`: The real values needed to wire the Fictura SDK into a codebase: the API base URL, this app's publishable SDK key (gk_…), and the RevenueCat webhook URL. ALWAYS call this before generating integration code — never leave a placeholder API key in what you write. The SDK key is publishable and safe to commit in app source; it identifies the app, not a person.
- `get_appsflyer_attribution_summary`: What the AppsFlyer import brought in about where people came from: people with an imported attribution, split by media source (organic included) and acquisition vs retargeting, plus the top campaigns. Filters on the install date. Imported verdicts never overwrite an attribution Fictura's own SDK resolved. For revenue and ROAS by source, use get_attribution_report with view=kpis.
- `get_appsflyer_import_status`: Whether AppsFlyer is connected, the latest import run (status, progress, rows imported, duplicates skipped, people created, date range covered, error if it stopped), and whether an import has ever finished. Call before start_appsflyer_import so a finished import is not offered again as though nothing had happened.
- `get_attribution_report`: Where installs and revenue actually came from. `summary` is the headline attribution picture (installs, organic vs non-organic, revenue). `kpis` breaks the same window down by source, campaign, link or day. `installs` lists individual installs with their attribution. Defaults to the trailing 28 days.
- `get_endpoint_summary`: Everything about one row of the Performance page, to answer 'why is this slow?': count, error rate, p50 to p99 and the change against the window before; where the time goes inside each request (database, HTTP and model calls, and the backend routes a screen waited on); what the slowest 10% have that the rest don't (release, status, device…) and which inner spans grow most in them; who calls a dependency; per-release numbers; sample traces (slowest, typical, fastest, failed: open them with get_trace); and the open issues on that route. op is like http.server, ui.load, ui.pageload, http.client, db, gen_ai, task; route is the route, screen, page, host or table as get_performance_overview lists it.
- `get_error_event`: One occurrence: frames with source lines and variables, request, tags, contexts, breadcrumbs, causes and trace id. Pass issue_id for its latest event, or event_id. Use it to see why one error happened. Long events give up variables, then library frames, then breadcrumbs, and `truncated` says what went: call again with section to read that part whole.
- `get_error_issue`: One issue with its status, history, 30 days of daily counts and recent occurrences. The newest occurrence has its stack and frames, the older ones are one-line summaries. Use it to see how an issue behaves over time. For a fix, get_error_issue_brief is shorter; for source lines and variables, use get_error_event.
- `get_error_issue_brief`: Use this first when asked to fix an error. One issue condensed: in-app frames with their source lines, the request, tags, breadcrumbs before it, log lines from the same trace, facets (release, OS, device, route), cause chain, and a ready-to-use fix prompt.
- `get_error_settings`: This app's error settings (auto-resolve days, built-in noise rules, crash-free threshold, digest, code links, retention, whether MCP may write) and tracing settings (sample rate, hosts that get trace headers). connection_can_write says whether this connection's write tools will work.
- `get_experiment`: One experiment with its variants and full Bayesian results.
- `get_fix_run`: A fix run's status, root cause, plan, files, tests, cost so far, and its pull request.
- `get_issue_activity`: What people and Fictura did to one issue, newest first: status changes, assignments, priority, notes with their text, tickets, regressions. Use it before changing an issue, to see who already looked at it.
- `get_issue_tag_values`: How often each value of one tag or facet appears on one issue in the last 30 days. Use it to see where an issue concentrates: which release, route, device, logger or person. Leave out key to list the keys there are.
- `get_jobs`: Work done outside requests: background tasks, queue publish and process, and cron runs, with counts, failures and timings; each cron with its last run, its usual gap, and late: true when it has not run for twice that gap.
- `get_link_infrastructure`: How links reach the app. `app_links` is the most important for integration work: it returns the iOS team id, bundle id, Android package and SHA-256 fingerprints that Fictura serves in the Universal Links / App Links association files, plus ios_ready and android_ready. Get these wrong and BOTH files fail SILENTLY — they parse, associate nothing, report no error, and links simply keep opening the browser instead of the app, so verify the ready flags rather than assuming. `domains` lists branded link domains and their DNS verification state, `web_config` the web-to-app smart banner, `esp` the email provider link setup.
- `get_mobile_vitals`: The mobile app's vitals from real devices: cold (and warm) app start, time to initial display (ttid) and full display (ttfd), slow and frozen frame percentages, and JS stall time; overall, per screen (busiest first) and per release. Each with p50, p75, p95 and the sample count. platform ios, android or both (default).
- `get_onboarding_doc`: The JSON document a builder-made onboarding flow is made of, with its status and version, plus the reference to the document model. Read this before save_onboarding_doc, and edit the document you got rather than writing one from scratch — keep step keys and node ids, change only what was asked.
- `get_paywall_doc`: The JSON document a Studio (visual editor) paywall is made of, with its status and version, plus the reference to the document model. Read this before save_paywall_doc, and edit the document you got rather than writing one from scratch — keep node ids, change only what was asked. Prices are never typed: use {{ products.<slot>.price }} and the other product variables.
- `get_performance_overview`: How fast the app is right now, backend and frontend: backend requests per minute, p95 and error rate against the window before; screen and page load times; then the routes that take the most total time, the slowest screens and pages, and the slowest dependencies (HTTP hosts, database tables). Start here, then open one with get_endpoint_summary.
- `get_pull_request_status`: The PRs tied to an issue (opened by Fictura or linked), with state, draft, CI checks, merge and the release that shipped it.
- `get_push_config`: Whether push is set up and who could receive it: registered-device counts per billing cohort (all / paid / trial / free) and whether OneSignal is configured. Returns counts and configuration only — never device tokens or individual recipients.
- `get_setup_status`: Where this app has got to: the six setup steps and which are really done, worked out from data that has arrived, then the billing state, every Fictura feature toggle and whether it is on, and which third-party integrations (Stripe, RevenueCat, Slack, App Store Connect, …) are connected. Use it to check a setup step worked, and to check a feature is enabled before writing code that depends on it — a disabled tool is a server-side kill switch the SDK obeys.
- `get_setup_step`: What to do for one of Fictura's six setup steps, ready to follow: the instructions, this app's real values (so there is nothing to fill in), the full text of that step's docs pages, and how to check it worked. Call this when a person pastes a setup prompt, and follow what it returns rather than recalling the SDK from memory. Steps in order: install, connect, events, attribution, errors, performance.
- `get_span`: One span in full: name, op, service, timing, status, every attribute, the errors that happened in it, and the log lines written while it ran. Take the trace_id and span_id from get_trace.
- `get_store_analytics`: Store-reported numbers synced from Appfigures: downloads, re-downloads, updates, uninstalls, store revenue after the store's cut (subscriptions, in-app purchases, ads), top countries, the ratings snapshot, recent reviews with text, and category chart positions. Money is in micros of `currency`. Store revenue is a separate figure from RevenueCat revenue; never add the two. Returns connected: false when Appfigures is not set up.
- `get_surface`: The full configuration of one paywall or onboarding flow, plus its version history. Note that configs never contain price strings — prices resolve at render time from the PurchasesAdapter's packages, so never copy a price literal out of (or into) a config.
- `get_trace`: One trace (app → backend → dependencies) as a tree: names, services, start offsets, durations, HTTP status and errors, plus the error events linked to it. Take the trace_id from an event or from search_traces. Use it to see where the time went or what failed first. Long traces page with next_cursor.
- `get_tracing_health`: Who is sending traces in the last 24 hours: each service with its SDK and version, frontend or backend, last span, span count, average sample rate and environments; how many of the app's traces reached a backend (joined traces: zero means the app is not sending traceparent to the API, or the backend is not traced); what ingest refused per day this week (invalid, rate limited, over the daily quota). The first tool to call when performance data looks missing.
- `get_tracking_plan`: Every event this app has ever sent, with volume, last-seen, and whether capture is switched off. Use it before adding instrumentation so you reuse the existing event name instead of introducing a near-duplicate — the name chosen here is the same string an experiment later names as its primary metric.
- `get_uptime_monitor`: The URL Fictura pings every minute for this app, whether it is up or down, the last check, consecutive failures, when the current downtime started, and availability over 24 hours and 7 days. monitor is null when none is set.
- `get_user`: One user's identity (every stitched device / account / RevenueCat id), event breakdown, churn state and recent activity. Accepts the Fictura master user id, or any identifier the app knows them by — a device id, account id or RevenueCat id.
- `get_web_vitals`: The web app's Core Web Vitals from real browsers: a 0 to 100 performance score (LCP 30%, INP 30%, CLS 15%, FCP 15%, TTFB 10%, Google's thresholds), each vital's p75 with its good / needs improvement / poor counts, and pages ranked by opportunity (how much the score would rise if that page scored 100).
- `link_pull_request`: Tie an existing GitHub PR (by URL) to an issue. When it merges, Fictura resolves the issue in the release that ships it. Only works when the app allows MCP writes.
- `list_alert_rules`: This app's alert rules with their triggers, conditions, channels and throttles. defaults_active means no rule is enabled, so the built-in defaults listed there apply. Use it to see what will and won't alert.
- `list_campaigns`: Campaigns read live from a connected ad platform: status, daily budget and ad sets. Returns a not_connected result rather than failing when the provider is not set up. This calls the provider's API, so prefer get_acquisition_report for historical numbers.
- `list_creators`: Creator records with a 28-day funnel per creator (clicks, installs, trials, paying users) and the tracking links tagged to each.
- `list_dependencies`: The HTTP hosts and database tables the app's services call, by total time spent: calls, calls per minute, error rate, p50 to p99, 4xx and 5xx. kind http, db or all (default). Open one with get_endpoint_summary (op http.client or db).
- `list_docs`: The full documentation index — every page path, grouped by section, with a one-line description. Use it to find the right page when a search term is hard to guess. No API key required.
- `list_error_alerts`: Every error alert Fictura fired, newest first: when, which trigger, the issue and its source, the channels, and whether it was delivered. Use it to check an alert went out, or what paged someone.
- `list_error_issues`: Start here to see what is broken: grouped issues from the backend and the app together, each with its source, level, status, event and user counts. Newest activity first, unresolved only. Console lines from the app are hidden unless include_console is true. Pass next_cursor to read on.
- `list_experiments`: Every experiment with status and, for running or finished ones, full Bayesian results — exposures, conversions, and the probability each variant is best.
- `list_inbound_filters`: This app's inbound filters: rules that drop a matching error at ingest, counted but never stored or alerted on. exc_type and release match exactly, message is a glob (* = anything, any case), environment is exact and `simulator` also drops simulator events. discarded_7d counts drops per reason.
- `list_monitors`: Every performance monitor: what it watches (metric, ops, route), its threshold and window, and its state (ok, firing, no_data) with the last value read. A firing monitor has an open issue: issue_id opens with get_error_issue.
- `list_releases`: Releases from the app and the backend, newest first. App rows have crash-free sessions and users and adoption; backend rows have crash-free and error-free requests. Each row states its source. Use it to tell whether a release made things worse.
- `list_store_products`: This app's auto-renewable subscriptions in App Store Connect: product id, billing period and Apple review state. Use it to check that a paywall references a product that actually exists. Pass subscription_id to also fetch Apple's price ladder for that one product (Apple scopes price points per subscription, so there is no global list).
- `list_surfaces`: Every paywall and onboarding flow, what is actually being served at each placement (running experiment > live > none), and the valid placement names. IMPORTANT: read `placements` before writing a placement string into code. The list is configured ∪ observed, so a name that appears only under `observed` is usually a typo in the app — and a placement that does not exist renders nothing at all, with no error.
- `list_templates`: The one-click starter templates available for paywalls or onboarding flows, with the template key and what each looks like. Use this when asked to add a paywall so you pick a real template key rather than inventing one.
- `list_users`: The app's users, most recently active first — each with an identity label, event count, last seen, and derived churn state (in_trial, converted, cancelled, expired, billing_issue, grace_period, paused, refunded, none). Capped so a large app does not flood the context; `total` reports how many matched before the cap.
- `pair_editor`: Connects to the paywall editor a person has open, using the 6-character code shown under “Pair an agent” in the Studio. Returns a pairing_id for the editor_* tools. The code works once and for 10 minutes; a pairing lasts 24 hours or until either side stops it.
- `pause_experiment`: Pause a running test: nobody new enrolls, and users already in it keep their arm. resume_experiment picks it up again. Only works when the app allows MCP writes.
- `read_doc`: The complete markdown of one documentation page. Accepts a site-relative path such as '/implementation/welcome/sdk-quickstart' (a full docs.fictura.co URL works too). If the path is wrong, the closest real paths come back as suggestions. No API key required.
- `resume_experiment`: Resume a paused test so new users enroll again. Refused when another test now holds its surface and placement. Only works when the app allows MCP writes.
- `save_onboarding_doc`: Replaces a draft flow's document with the one given, as a new version (the dashboard's history shows it as `mcp: <note>` and can roll it back). Refused for a live flow. Needs an MCP key that can edit. Translations, overrides and the exit setting are kept.
- `save_paywall_doc`: Replaces a draft paywall's document with the one given, as a new version (History in the dashboard shows it as `mcp: <note>` and can roll it back). Refused for a live paywall — copy it in the dashboard first. Needs an MCP key that can edit. Products, translations and other settings are kept.
- `search_docs`: Full-text search across the Fictura docs, grouped by page. Use this before answering any 'how do I…' question about the SDK, API, paywalls, entitlements, links or webhooks — the docs are the source of truth and are regenerated on every code change. Returns page paths; pass one to read_doc for the full text. No API key required.
- `search_error_events`: Single occurrences across issues, newest first, or counts with group_by. Use it to answer which release or route an error hits, whether a person hit it, or what failed in one trace. Open one with get_error_event.
- `search_error_issues`: Find an issue by text in its title or culprit, across every issue the app has. Use it when you know the error message, exception type or function. Same filters and rows as list_error_issues.
- `search_logs`: Application log lines from the backend SDK, newest first, or counts with group_by. Use it to see what happened around an error: pass trace_id for one request's lines, or q and level to search. Lines are kept 14 days, and the default range is the last 24 hours.
- `search_traces`: With no filters: every route and screen with its count, error rate, p50, p95 and slowest dependency. With any filter: matching spans from the backend and the app, or count, avg, p50, p95 and errors with group_by. Use it to find what is slow or failing, then open one with get_trace. Spans are kept 30 days.
- `set_uptime_monitor`: Set or replace the URL Fictura pings every minute (three failures in a row mark it down and alert). A new URL starts over as unknown. enabled false pauses it. Only works when the app allows MCP writes.
- `start_appsflyer_import`: Import everything AppsFlyer holds for this app: installs and the channel, campaign, adset and ad behind each one, in-app events and purchases, uninstalls, reinstalls, ad revenue and retargeting traffic. All twelve raw-data reports are walked; ones the AppsFlyer plan lacks are skipped, not failed. Runs in the background and keeps going after this call. mode 'auto' (default) only pulls the days since the last finished import when there is one, and walks the full history otherwise. 'full' re-walks everything. resume=true continues a failed or cancelled run from where it stopped. Safe to call while a run is going: it reports that run instead of starting another. Anything already imported is counted once. Check progress with get_appsflyer_import_status.
- `start_experiment`: Start a draft: from now on its arms are served to the users who pass its targeting. Refused when another test is running or paused on the same surface and placement. Only works when the app allows MCP writes.
- `start_fix_run`: Start a hosted fix run: Fictura's AI finds the root cause and, if allowed, opens a draft PR. It spends the app's own Anthropic money, capped per run and per day. Poll get_fix_run. Needs MCP writes and AI fixes on.
- `stop_experiment`: Stop a running or paused test for good without rolling anything out: everyone gets the live config again. It can't be restarted. Rolling out a winner is done by a person in the dashboard. Only works when the app allows MCP writes.
- `unpair_editor`: Stops this pairing. The editor shows that the agent left.
- `update_app_identity`: Saves what the app IS to Apple, Google and the web: the iOS bundle ID and Apple Team ID (which build the Universal Links file), the Android package and signing fingerprints (which build the App Links file), both store addresses and the website. Send only the fields you know. Every value is checked before saving, because a bad one makes links fail with no error anywhere. A value already saved is not overwritten unless replace_existing is true: changing a bundle ID on a live app breaks its links, so ask the person first. Needs read and edit access.
- `update_error_issue`: Resolve, ignore or reopen an issue, assign it, set its priority, or add a note. Only works when the app allows MCP writes (Issues settings → Let MCP keys change issues).
- `update_error_issues`: The same change on up to 100 issues: resolve, ignore or reopen them, assign them, set their priority, or add a note to each. Answers per issue, with counts. Only works when the app allows MCP writes (Issues settings → Let MCP keys change issues).
- `update_tracing_settings`: Set the share of traces the SDKs keep, and the hosts the app's SDK sends trace headers to (replacing the list). A field you leave out keeps its value. SDKs read it from their config within a minute. Only works when the app allows MCP writes.
- `validate_onboarding_doc`: Runs a document through the same parser, step-key check and renderer a save uses and reports what is wrong, if anything. Changes nothing.
- `validate_paywall_doc`: Runs a document through the same parser and renderer a save uses and reports what is wrong, if anything. Changes nothing.
