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 (25s on the API-key POST /mcp endpoint), 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, enforcement), placement, assessments, mastery, structure. - examples: Runnable SQL for the core patterns: reference lookups, the rollup, the cohort pattern, integrity, 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' (a high plan-cost bucket, not a wall-clock prediction: the query may still run quickly, so run it once on a shorter date window before restructuring). 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); 25 seconds for the whole request on the API-key POST /mcp endpoint - 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 this server declined, and why — after classifying it per BRAINLIFT.md#answer-scope. gapKind values: - no_data — the analytics database lacks the data objects or shapes the question needs. - no_definition — the data exists but the business meaning is not defined on this wire. - not_answerable_from_analytics — the question belongs to another system or to human judgment. Omit gapKind to record unclassified. Do not send unclassified as a gapKind value. For no_data and no_definition, have a conversation with the stakeholder before calling: ask until you hold a complete requirement set (what they are trying to learn, entities and granularity, time range, breakdowns and filters, expected output, what decision the answer feeds). That record is treated like a feature request — completeness determines whether the work can happen without going back. For not_answerable_from_analytics, record where the question routes instead. No feature-request conversation. After recording, tell the stakeholder what analytics can support, what it cannot conclude, and (for no_data / no_definition) that support is in progress when applicable. 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/
|
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. |
