TimeBack Analytics MCP Server

The MCP server for TimeBack Analytics. Exposes tools to query student learning data, analyze session patterns, and generate reports.

Version: 1.0.0

Connect to TimeBack Analytics MCP Server

Remote (HTTP)

Add the following to your ~/.cursor/mcp.json file:

{
  "mcpServers": {
    "timeback-analytics-mcp-server": {
      "type": "http",
      "url": "https://platform.timeback.com/mcps/analytics"
    }
  }
}

Remote (HTTP)

Add the following to your VS Code settings.json:

{
  "mcp.servers": {
    "timeback-analytics-mcp-server": {
      "type": "http",
      "url": "https://platform.timeback.com/mcps/analytics"
    }
  }
}

Remote (HTTP)

Run the following command:

claude mcp add --transport http timeback-analytics-mcp-server https://platform.timeback.com/mcps/analytics

In ChatGPT, go to Settings → Connectors and add the MCP server URL:

https://platform.timeback.com/mcps/analytics

Tools

The server exposes the following MCP tools:

Tool Description
timeback_get_help_topic Read this server's querying playbook, in short focused topics, and the three served skill documents. This is the how-to-use-me guide: progressive-disclosure workflow, hard limits, timeout tactics, anti-patterns, error recovery, data-model orientation, and worked SQL examples. Call with no argument to list playbook topics and documents; call with a topic name to read it. Documents: DICTIONARY.md (field meaning, genesis, numbered traps), ENABLEMENT.md (worked SQL and recipes), BRAINLIFT.md (business operating layer). Pass a document name for its section index; pass DOC#section for that heading subtree (example: DICTIONARY.md#known-traps); pass DOC#all for the whole file. Addresses are case-insensitive and the .md suffix is optional. TIMING: instant (static guidance; nothing is executed). TOPICS: - workflow: The three-step discovery flow, the estimate→restructure loop, cheap first steps (name→ID), and verifying empty results. - limits: Hard limits: 500-row cap, 110s timeout, single read-only SELECT, no schema prefixes, automatic org-scoping, pagination, CSV export for full dumps. - avoiding-timeouts: The rollup fast-path (student_daily_engagement), the two-step cohort pattern, aggregate-vs-per-event grain, and aggregating in SQL. - use-case-and-intent: Recording the use case and intent behind every query — on both the served and the unserved paths. - anti-patterns: Common anti-patterns that stall sessions or produce wrong numbers, and what to do instead. - raw-tables: Raw operational tables (public schema) for internal callers: addressing, discovery, caveats, and when to prefer the views. - error-recovery: Error messages you may hit and how to recover from each, including verifying zero-row results. - data-model: Orientation on the relations: the rollup, raw activity, integrity (aggregates, events, notifications, enforcement), placement, assessments, mastery, structure. - examples: Runnable SQL for the core patterns: reference lookups, the rollup, the cohort pattern, integrity, shown-versus-accrued warnings, placement, assessments, verification. - did-this-student-learn: How TimeBack measures whether a student learned, by default: the growth + integrity + waste rubric, each ingredient with its caveat, and where the full walk lives. New to this server? Read 'workflow' first, then 'avoiding-timeouts' and 'examples' before writing event-relation queries. An unknown topic name returns the topic index.
timeback_get_schema_overview Get the catalog of the TimeBack analytics database: every relation (view) with its description and bare column names. ALWAYS your first call. Call it ONCE per conversation and keep the result in context — do not re-fetch it. For internal callers (system administrators and internal clients) the catalog also lists the raw operational tables under the 'public.' prefix. Raw-table comment coverage is partial (check relation metadata for the table in hand) and there is no stability guarantee — prefer the documented views and reach for raw tables only to verify a view's number, to reach operational state the views omit, or to explore unpublished data (see the 'raw-tables' help topic). TIMING: 1-2 seconds. Returns: - Current database version (for SQL syntax compatibility) - organizationScope: unrestricted (boolean), visibleOrganizationCount, and platformOrganizationCount for this credential. When the two counts differ, a partialScopeWarning explains that an empty per-organization result may be a scope limit rather than absence, and that the remedy is a scope-grant request rather than an unserved-query filing about a data pipeline. - Every available relation with its description and the list of its column names (names only — no types or per-column documentation at this level) This is layer 1 of a progressive-disclosure flow. Use it to pick the 2-5 relations your question needs, then call timeback_get_relation_metadata for their full column detail before writing SQL. Do not write queries from this overview alone, and never guess column semantics. Flow: this tool → timeback_get_relation_metadata (chosen relations) → timeback_execute_query.
timeback_get_relation_metadata Get full column metadata for specific relations: name, type, and a rich description per column (semantics, null behavior, join keys, example values). Optionally includes sample rows. Layer 2 of the discovery flow. Call it for ONLY the relations your question needs (typically 2-5), after picking them from timeback_get_schema_overview. Required before writing SQL — column descriptions carry the join keys and value conventions the overview omits. TIMING: 1-3 seconds, plus ~1s per relation when sampleRows > 0. Parameters: - relations: view names without a schema prefix (e.g. ["students", "sessions"]). Internal callers may also request raw tables with the 'public.' prefix (e.g. ["public.one_roster_user"]). - sampleRows: 0-10 sample rows per relation (default 0). Use 3-5 when you are unsure about value formats; sampling is org-scoped and cheap. Relations that do not exist are reported in 'notFound' — check it before assuming a relation is available. For non-internal callers, 'public.'-prefixed names always land in 'notFound'.
timeback_estimate_query Estimate relative planner cost and plan shape for a query using EXPLAIN WITHOUT executing it. Verdicts bucket relative cost — they are not a wall-clock or 110s-budget guarantee. TIMING: 1-2 seconds (planner analysis only, no data scanned). Run this BEFORE timeback_execute_query whenever the query has multiple joins, a whole-table aggregation, or no date filter. Returns: - verdict: 'ok' (bounds plan shape and relative cost, not wall-clock — not a 110s-budget pass; an ok query can still time out), 'warning' (may be slow — consider narrowing), or 'likely_timeout' (restructure before executing; it will almost certainly hit the 110s timeout). On Redshift, those buckets use residual EXPLAIN cost after peeling each ~1e12 late-binding stamp, not Aurora's 5e6 / 50e6 - Estimated row count and query plan operations - Specific optimization suggestions (filters to add, joins to restructure) Workflow: estimate → if verdict is not 'ok', apply the suggestions (narrow the date range, pre-aggregate in a CTE) → re-estimate → execute. On a timeout, retry once unchanged first; only a second consecutive timeout is the signal to rewrite.
timeback_execute_query Execute a single SELECT query against the TimeBack analytics database. Layer 3 of the flow — call it after timeback_get_schema_overview and timeback_get_relation_metadata. Use the exact relation and column names they returned; never guess. TIMING: 2-10 seconds typical; complex queries 10-110 seconds. Make the database do the work: - SELECT syntax: CTEs, window functions, subqueries, aggregations (GROUP BY, percentile_cont(), ...) - Aggregate in SQL instead of pulling raw rows to post-process - Event relations (sessions, attempts, students_xp, sessions_waste, insight views) need BOTH a literal student_id IN (...) cohort list AND a date range — platform-wide aggregations over them time out. Fetch the cohort IDs with a cheap query first (students, student_schools). - Do not aggregate assessment_results until the traps ledger has been returned via timeback_get_help_topic, topic DICTIONARY.md#known-traps. Apply every lettered clause of trap 4 to the SELECT; trap 5 is not a substitute. Averaging across families is invalid. - When aggregating assessment_results, keep the SELECT within one assessment_type family only, with parent_id IS NULL, score_status = 'fully graded', score IS NOT NULL, and a single quoted equality assessment_type = '<family>' as trap 4c writes it (e.g. assessment_type = 'staar'). assessment_type IS NOT NULL and assessment_type IN (...) are not a family. A SELECT that aggregates assessment_results without that quoted equality is invalid and is refused. Limits: - Single SELECT/WITH statement only; the connection is read-only at the database level - Maximum 500 rows returned; 'hasMore: true' means the result was truncated. For the rest of a result, or a statement that exceeds 110s, use timeback_export_query instead of paging through OFFSET. - Maximum 110 seconds execution time (database-enforced) - Views need no schema prefix: "SELECT * FROM students", not "SELECT * FROM analytics.students" - Internal callers may reference raw operational tables with the 'public.' prefix (e.g. "public.one_roster_user"); other callers get a permission error (see the 'raw-tables' help topic) - Results are org-scoped automatically to your authorized organizations; raw tables are not org-scoped If hasMore is true, do not page with OFFSET for a full dump — submit the same SELECT to timeback_export_query (OAuth only) and poll timeback_get_export for a one-hour signed CSV URL. If the query times out, either narrow the date window or pre-aggregate in CTEs, or export it. The useCase and intent parameters are required and are recorded for every query: state the stakeholder's goal and this query's purpose honestly and specifically — they are how the platform learns which questions matter.
timeback_report_unserved_query Record a question that could NOT be answered because the analytics database lacks the data objects or shapes it needs — together with the full requirement set gathered from the stakeholder. Knowing that a question is not achievable is NOT enough. Before calling this tool, have a conversation with the stakeholder: ask questions until you hold a complete set of requirements (what they are trying to learn, which entities and granularity, time range, breakdowns and filters, expected output, what decision the answer feeds). Then record everything here. This record is treated like a feature request from a product manager — it is how the missing data gets built, so its completeness determines whether the work can happen without coming back to the stakeholder. After recording, tell the stakeholder their question is not supported yet and that support is in progress. TIMING: instant (log-only; nothing is executed). Returns { recorded: true } on success.
timeback_send_session_to_guardian Email a Vault session link to one of the session student's open guardians. Use this after discovering guardians from the student_guardians relation. The effect is irreversible: a successful call delivers mail and must not be replayed. Parameters: - sessionId (required): the session to share - guardianId (optional): which open guardian receives the link. Omit only when the student has exactly one open guardian; when several exist, the call is refused and the error lists every candidate so you can re-issue with guardianId. TIMING: 1-3 seconds (one org-scoped resolution query plus mail delivery). Returns a receipt with sessionId, sessionUrl, guardianId, guardianName, guardianEmail, and sentAt on success.
timeback_analyze_session_video Start an ad-hoc, free-form analysis of a StudyFilm session recording and get back a jobId to poll. The analysis runs inside the platform against the session recording; the raw video is never returned or exported — the output is the model's text analysis only. Access is bound to your organization: you can only analyze sessions in your org's grant. Because analyses of long windows take minutes (well past MCP client per-call timeouts), this tool does NOT return the result. It returns a jobId immediately; poll timeback_get_video_analysis for the outcome. TIMING: returns instantly; the analysis itself takes ~20s for a 2-minute window, up to several minutes for long windows. Parameters: - sessionId: a session slug or a full https://timeback.com/sessions/ URL - prompt: the free-form instruction for the analysis (1-8000 chars) - startSec / endSec (optional): analyze only this window; required for recordings over 1 hour (the analyzable cap)
timeback_get_video_analysis Retrieve the status or result of a session-video analysis started with timeback_analyze_session_video. Returns one of: pending/running (with the current processing stage — poll again), succeeded (the model's text analysis plus the model id), or failed (a typed code, message, and next-step guidance). Jobs are private to their creator. The raw video is never returned — text out only. TIMING: instant. Poll every 15-30s until the status is succeeded or failed.
timeback_export_query Start an asynchronous CSV export of a read-only SELECT/WITH statement and get back a jobId to poll. The rows never return in this tool body. Redshift UNLOAD writes one CSV to a private bucket under your organization scope. Poll timeback_get_export for a one-hour signed HTTPS GET URL. The object is deleted within one day. timeback_execute_query stays the interactive 500-row / 110s path. Ceilings: 1,000,000 rows (truncated: true means at least that many), 600s statement budget, URL lifetime 1 hour, object lifetime 1 day. Redshift UNLOAD only. A query that fails export validation is refused before a job is created. TIMING: returns instantly; the export itself takes seconds to minutes. Parameters match timeback_execute_query: query, useCase, intent.
timeback_get_export Retrieve the status or result of a CSV export started with timeback_export_query. Returns one of: pending/running (poll again), succeeded (downloadUrl, expiresAt, rowCount, columns, truncated), failed (code, message, guidance), or not_found. Jobs are private to their creator. The URL is minted on each successful poll and expires after 1 hour; truncated true means the result hit the 1,000,000-row cap (at least that many rows). The CSV object is gone within a day. TIMING: instant. Poll every 15-30s until the status is succeeded or failed.