TrackVia MCP

Talk to TrackVia from any LLM.

A Model Context Protocol server that exposes your TrackVia account — apps, views, records, and files — plus a rich library of higher-level helpers for query, workflow, import, dedupe, aggregation, state machines, and lifecycle — for any MCP-aware assistant.

177 tools Streamable HTTP Bring-your-own token

What it does

Point an MCP-aware client at the server, pass through a TrackVia access token, and your model can work directly against your TrackVia apps.

Apps

List apps, look up by name, or fetch a single app by id.

Users

List account users, create one, bulk-invite many, or batch-resolve by email.

Views

List views, filter by name, page through records, run keyword search.

Records

Read, create (single or batch), update, or delete records — including bulk delete within a view.

Files

Download, upload, or delete files attached to record fields.

Inspect

Annotate a view, record, or whole account with field metadata; export an app's full schema.

Query

Filter, sort, select, and export records — evaluated inside the MCP server. Fan-out search across every view.

Workflows

Upsert by a unique field, or bulk-update / bulk-delete by filter (with preview, backup, and safety confirm).

Compose

Duplicate records, copy between views, and expand relationships inline.

Resolver

Turn human names (view, field, user) into the right ids.

Discovery

Locate fields across views and walk a relationship graph around any record.

Profile

Find and merge duplicates, and surface records missing required fields.

Ingest

Dry-run or execute CSV / JSON imports with casting and optional upsert.

Aggregation

Group-by, pivot, trend, and top-N — computed client-side over paginated records with bounded scans.

State machines

Status-field transitions with optimistic-concurrency checks, plus a bulk "advance workflow" variant.

Lifecycle

Soft-delete and restore patterns that flip an archive field instead of destroying data.

Server

Inventory every registered tool with version and status — useful for discovery from the model.

Install

The server speaks MCP over streamable HTTP at the /mcp endpoint. Every MCP request must carry a TrackVia access token (see Configure). Other MCP clients should work too, but Claude Code is the only one we currently document.

  1. Install the Claude Code CLI.
  2. Register the server with your TrackVia access token:
claude mcp add --transport http trackvia https://k8s-qa4.qa.xvia.com/mcp/mcp \
  --header "Authorization: Bearer YOUR_TRACKVIA_ACCESS_TOKEN"

Optional: pin a specific TrackVia host (defaults to the server's configured host) and/or target a sandbox account inside that account:

claude mcp add --transport http trackvia https://k8s-qa4.qa.xvia.com/mcp/mcp \
  --header "Authorization: Bearer YOUR_TRACKVIA_ACCESS_TOKEN" \
  --header "X-TrackVia-Host: qa1.qa.xvia.com" \
  --header "X-TrackVia-Account-Id: 12345"

Verify with claude mcp list — TrackVia should appear as connected.

Configure

Headers your MCP client passes through on every request. The client sets them for you once you paste the values in at install time.

Header Required Purpose
Authorization Yes TrackVia OAuth access token, as Bearer <token>.
X-TrackVia-Host Optional Override the upstream TrackVia host this request targets — e.g. qa1.qa.xvia.com. Falls back to the default host https://go.trackvia.com. Must match the hardcoded allowlist: *.trackvia.com, *.xvia.com, or localhost.
X-TrackVia-Account-Id Optional Target a sandbox account id inside the account implied by the access token. Must be a positive integer. Omit to use the access token's default account.

Tools reference

Every tool the server registers at startup.

Group Tool Description
BootstrapwhoAmIReturns the session's cached AccountContext: {userId, email, defaultAccountId, accounts: [...]}.
serverCapabilitiesReturns `{name, version, tools: [{name, since, status, replacedBy?}]}` — the authoritative list of what this server exposes and how stable each tool is.
AppsgetAppsReturns every app visible to the caller.
getAppByNameReturns apps whose name matches the given value.
getAppFetches a single app's definition (name, description, status, sandbox flags).
createAppCreates a new app in the account.
updateAppUpdates an app by merging the caller's partial `updates` into the current App body.
deleteAppPermanently deletes an app and its tables, views, and records.
duplicateAppCreates a new app from an existing app used as a template.
TablesgetTableFetches a table's metadata, including its field definitions.
listTablesLists every table in the given app.
createTableCreates a new table in the app.
updateTableUpdates a table by merging the caller's partial `updates` into the current Table body.
deleteTablePermanently deletes a table, its fields, and its records.
FieldsaddFieldAppends a field to a table.
updateFieldLocates a field by id or name and merges `updates` into it (shallow merge).
removeFieldRemoves a field from a table.
reorderFieldsReorders the table's `fields` array to match the given name sequence.
Calculated / triggered fieldsaddCalculatedFieldAdds a calculated field to a table via read-modify-write on the Table object (there's no fields sub-resource).
addTriggeredFieldAdds a triggered field.
formulaReferenceReturns the canonical TrackVia formula grammar + every supported function, grouped by category (Logic, Text, Math, Aggregate, Child aggregate, Date/time, Geospatial, Triggered-only).
ViewsgetViewsWalks every app + every table in the account and returns view summaries.
getViewByNameWalks every view in the account and returns the ones with an exact-matching name.
getViewRecordsReturns records from a view with offset pagination.
findViewRecordsRuns a keyword search against a view's records.
createViewCreates a new view on the table.
updateViewApplies a partial update to a view (rename, edit filters, replace column projection).
deleteViewPermanently deletes a view.
getViewLayoutReturns the /extra payload: column widths, pinned fields, grouping, and other layout metadata.
updateViewLayoutReplaces the view's layout metadata (columns, pinning, grouping).
RecordsgetRecordReturns a single record from a view via the platform's RecordController.
addRecordCreates a record in a view. `recordData` is a flat map of fieldName → value.
addRecordsCreates multiple records in a view in one request.
updateRecordUpdates a single record. `recordData` is a flat map of fieldName → value.
deleteRecordDeletes a single record.
deleteAllRecordsInViewDeletes every record accessible through the view.
getRecordHistoryReads the record change history via RecordHistoryController.
FilesgetRecordFileDownloads a file (or image) from a record field.
uploadRecordFileUploads (or replaces) a file in a record field.
deleteRecordFileRemoves the file stored in a record field.
FormsgetFormFetches a single form's definition.
listFormsLists every form defined on the given table.
createFormCreates a new form on the table.
updateFormApplies a partial update to a form (rename, edit layout, replace projection).
deleteFormPermanently deletes a form.
UsersgetUsersReturns the TrackVia account users (paginated).
addUserCreates a new account user.
getUserFetches a single user by ID.
updateUserApplies a field-level update to a user.
deactivateUserSets the user's status field to "Inactive".
reactivateUserRestores the user's status field to "Active".
deleteUserPermanently deletes a user record.
bulkInviteUsersRuns `addUser` over an array of user payloads with bounded concurrency.
findUsersByEmailPages the account user list once, then builds a lookup map.
User groupslistUserGroupsLists user groups on the account.
getUserGroupFetches a single user group, including its member list.
searchUserGroupsKeyword-search user groups by name.
createUserGroupCreates a new user group.
updateUserGroupApplies a partial update to a user group.
deleteUserGroupPermanently deletes a user group.
RolesgetRoleFetches a single role by ID, including its full `roleRules`, `resources`, `forms`, and `views` tree.
listRolesLists every role defined on the given app.
createRoleCreates a new role in the account. `name` and `appId` are required; `roleRules` / `resources` / `forms` / `views` describe the permission tree.
updateRolePUT on `/roles/{roleId}`.
deleteRolePermanently deletes a role.
assignUsersToRolePUT on `/roles/{roleId}/users`.
listRolePermissionsReturns the users currently assigned to the role — the read-only signal for per-role membership auditing.
AuditlistAuditEventsLists audit events for the chosen resource type.
getAuditEventReturns a single audit event from a `listAuditEvents` page.
DashboardsgetDashboardFetches a single dashboard by ID.
listDashboardsLists dashboards in the account.
createDashboardCreates a new dashboard in the account.
updateDashboardReplaces a dashboard's metadata and elements.
deleteDashboardPermanently deletes a dashboard.
FilterslistFiltersLists every named filter defined on the given table.
getFilterFetches a single filter by ID.
createFilterCreates a named filter on the table.
updateFilterApplies a full-replacement update to a filter.
deleteFilterPermanently deletes a filter.
RelationshipscreateRelationshipCreates a relationship between two tables and verifies it actually persisted on BOTH sides.
updateRelationshipRenames a relationship.
deleteRelationshipRemoves a relationship between two tables.
FlowslistFlowsLists every flow attached to the given app.
getFlowFetches a single flow's full definition (trigger, steps, config).
createFlowCreates a new flow on the app.
updateFlowApplies a partial update to a flow (rename, edit steps, toggle enabled).
deleteFlowPermanently deletes a flow.
Notification ruleslistNotificationRulesLists every notification rule attached to the given view.
getNotificationRuleFetches a single notification rule by ID.
createNotificationRuleAttaches a new notification rule to the view.
updateNotificationRuleApplies a partial update to a notification rule.
deleteNotificationRulePermanently deletes a notification rule.
InspectdescribeViewReturns the field metadata (structure) for a view plus the total record count.
describeRecordReturns the record plus, for every field, its type, required flag, writability, and (for relationship fields) the linked id.
describeAccountFetches every app, every view, and (by default) a handful of sample field names per view in a single response.
exportAppSchemaThe canonical 'load the entire schema' call.
QueryqueryRecordsPaginates a view's records, then applies filter / sort / select in the MCP server.
exportViewPaginates a view fully (up to the limit) and returns the records as json / ndjson / csv text.
searchAllViewsRuns `/find?q=<keyword>` in parallel across every view (optionally scoped to an app) and returns the top matches per view.
WorkflowsupsertRecordLooks up a record by uniqueField=uniqueValue.
bulkUpdateRecordsQueries the view, evaluates the filter client-side, then PUTs the recordData to each matching record (bounded concurrency, default 4).
bulkDeleteRecordsQueries the view, evaluates the filter client-side, then DELETEs each matching record.
previewBulkUpdateTakes the same {viewId, filter, recordData} as `bulkUpdateRecords` but performs no writes.
backupThenBulkUpdateStep 1: paginate matching records and return them as an NDJSON resource (the backup).
ComposeduplicateRecordFetches a record, strips system fields + id + caller-specified excludes, then creates a new record in the same view with the surviving field values plus any `overrides`.
copyRecordsBetweenViewsFetches records from sourceViewId (optionally filtered), remaps field names via fieldMapping, applies overrides, and batch-creates in targetViewId.
expandRecordFetches a record, then for each field in `relationshipMap` follows the 'fieldName(id)' relationship reference and embeds the linked record under a `${fieldName}__expanded` key.
DiscoverywhichViewHasFieldScans every view's structure (optionally scoped to an app) and returns the views whose field list contains a matching field.
buildRecordGraphUnifies `expandRecord`-style parent traversal with `listChildRecords`-style reverse lookup.
ProfilefindDuplicatesPaginates the view, groups records by the value of `field` (or a composite key from `fields[]`), and returns only the groups with count ≥ `minCount`.
mergeDuplicatesPicks a primary record (per `keep` strategy), fills in gaps from the others per `onConflict`, updates the primary, then deletes the rest.
findMissingRequiredReads the view's structure, identifies fields marked `required: true`, then scans records and returns those with any such field null/empty.
IngestimportRecordsFromCsvParses `csv` (or accepts a pre-parsed `records` array), optionally remaps column names via `fieldMapping`, casts values against the view's structure, then either batch-creates or upserts on `uniqueField`.
previewImportSame parse + cast + lint pipeline as `importRecordsFromCsv` but without writing.
AggregationgroupByPaginates the view (up to 10k records), optionally applies a filter, groups by `field`, then computes `aggregate` (count/sum/avg/min/max) over `valueField`.
pivotRecordsMirrors TrackVia's Pivot View.
trendRecordsGroups records into day/week/month/quarter/year buckets based on `dateField`, applies the aggregate, and returns `[{bucket, value}]` sorted ascending.
topNRuns `groupBy` then slices the first N entries of the sorted result.
State machinestransitionRecordFetches the record, verifies `statusField === fromStatus`, then writes `statusField = toStatus` (plus optional timestamp/note).
advanceWorkflowQueries for records where `statusField === fromStatus`, then runs `transitionRecord` semantics on each with bounded concurrency.
LifecyclesoftDeleteWrites `archiveField = archiveValue` via updateRecord.
restoreSoftDeletedInverse of `softDelete`.
ResolverresolveViewReturns `{viewId, viewName, appName, isDefault}` for the matching view, or `{match: null, candidates: [...]}` when the name is ambiguous.
resolveFieldReturns a single field's metadata from a view — type, required, unique, canCreate, canUpdate, and choices (if applicable).
resolveUserScans the account-users list and returns the first match.
ScaffoldingscaffoldTableCreates a table with its fields in a
scaffoldAppCreates an app, scaffolds each requested table (with fields inline), and by default creates at least one dashboard so the app has a landing surface from day one.
cloneAppStructure**KNOWN BROKEN — platform bug, do not use.** The platform's app-create-from-template path (`AppService.populateTemplateApp`) hard-codes the 'Inventory Tracking' template and ignores both the supplied `templateId` query parameter and any body overrides — so this tool produces an Inventory Tracking app no matter which `sourceAppId` or `name` you pass.
inviteUserWithRolesCreates an account user.
createRoleWithAccessCreates a role and optionally pre-assigns users to it in one call.
createUserGroupWithMembersCreates a user group.
Cross-resource conveniencegrantRoleAccessToViewGETs the role, splices a `{id, type:'resultProjection', actions[]}` entry into `resources.views[]` (replacing any prior entry for that viewId), then PUTs the role back.
grantRoleAccessToFormGETs the role, splices a `{id, type:'form', actions[]}` entry into `resources.forms[]`, then PUTs the role back.
revokeRoleAccessRemoves the matching grant from the role's `resources.{views|forms|tables}` list.
listRoleAccessGETs the role and returns `{tables, views, forms}` lists with `{id, name?, permission}` entries — the high-level shape collapses the platform's `resources.*[]` action arrays back to `'read' | 'edit' | 'admin'` (or `'unknown'` when the action set is non-standard).
whoCanAccessViewWalks every role in the app and returns `{roleId, roleName, permission}` for each role with a grant on the given viewId.
duplicateViewGETs the source view, strips `id` and timestamps, applies `overrides`, then POSTs as a new view on the same table.
duplicateFormGETs the source form, strips `id` and timestamps, applies `overrides`, then POSTs as a new form on the same table.
findViewsUsingFieldLists views on the table and returns those whose projection includes the given fieldMetaId.
findFormsUsingFieldFans out per-form GETs and returns the forms whose `elements[]` tree contains a Field referencing the given fieldMetaId.
Form-authoring helpersaddFormShowHideRuleGETs the form, appends a rule entry to the form's top-level `rules[]` array, then PUTs the full form body back (Spring `@Valid` requires the complete FormRequest shape).
setFormFieldDefaultGETs the form, locates the matching field element, sets its `defaultValue` setting, then PUTs the full form body.
togglePublicWebformGETs the form, toggles the top-level `isPublic` boolean, then PUTs the full body back.
assignParentViewToRelationshipGETs the form, locates the relationship-typed field element, sets its `preferredParentView` to the supplied viewId, then PUTs the full body back.
bulkSetFieldRequiredOnFormGETs the form, walks the elements tree, sets `required` on every matching field element, then PUTs the full body back.
addChildRecordSectionGETs the form, appends a child-view section element to the form's root container (or to top-level `elements` if no root container exists), then PUTs the full body back.
View-authoring helperscreatePivotViewCreates a `pivotView` on the same table as `baseView`.
createLanesViewCreates a `laneView` (kanban board) on the same table as `baseView`.
createCalendarViewCreates a `schedulerView` configured for month-grid calendar rendering.
createTimelineViewCreates a `schedulerView` configured for horizontal Gantt-style timeline rendering, with rows grouped by a relationship field's parent records.
createMapViewCreates a `mapView` on the same table as `baseView`. `locationField` is the pin coordinate; `colorField` (optional) colors each pin; `defaultZoom` (optional) sets the initial zoom.
createLineChartViewCreates a `chartView` of type `LineChart`.
createComboChartViewCreates a `chartView` of type `ComboChart` (mixed bar and line series).
createPieChartViewCreates a `chartView` of type `PieChart`.
createBarChartViewCreates a `chartView` of type `BarChart` (horizontal bars).
createAreaChartViewCreates a `chartView` of type `AreaChart`.
createSteppedAreaChartViewCreates a `chartView` of type `SteppedAreaChart` (staircase-style filled area, always stacked).
createColumnChartViewCreates a `chartView` of type `ColumnChart` (vertical bars).
createScatterChartViewCreates a `chartView` of type `ScatterChart`.
createParetoChartViewCreates a `chartView` of type `ParetoChart` (descending bars with a cumulative frequency line).
createBubbleChartViewCreates a `chartView` with `chartAttributes.type = 'BubbleChart'`.
createGanttChartViewCreates a `chartView` with `chartAttributes.type = 'Timeline'` (the Google Charts class name for Gantt-style bar charts).
createAggregateViewCreates a `gridView` with grouped rows and aggregated value columns — the platform's summary-grid variant.
addConditionalFormatRuleGETs the view's layout `/extra` blob (`{viewExtra: <jsonString>}`), parses it, splices a new rule of shape `{fieldId, operator, value, color, scope}` into the array under `extraKey`, then PUTs the JSON-stringified result back.
Schema helpersfindFieldImpactReturns the union of `findViewsUsingField` + `findFormsUsingField` PLUS a heuristic scan of flows and notification rules.
createDependentDropdownsAdds two `dropDown` fields to the table (parent first, then child) and stamps the parent->child mapping onto the child field under `dependencyMapping` (override via `dependencyMappingKey`).
createManyToManyCreates a junction table and two MANY_TO_ONE relationships (junction -> tableA, junction -> tableB).
renameFieldSafelyComputes `findFieldImpact` first.
Automation helperssetupNotificationRuleEnd-to-end notification authoring: resolves viewId → location, maps `triggerFields` (field names) to fieldMetaIds via the view's projection, then POSTs a strict-shape NotificationRuleRequest to `/notificationRules`.
publishDashboardToRoleComposes three platform primitives: GETs the dashboard, walks `elements[]` for embedded view IDs (view / viewShortCut / search / searchBarcode), grants the role read access on each via the role-permission GET-modify-PUT cycle, and optionally writes `homepageDashboardId` on the role payload.
listAccountAutomationsWalks every app in the account and aggregates flow + notification-rule summaries.
exportAccountSchemaSnapshotAccount-wide schema dump extending `exportAppSchema` with admin/automation surfaces.
createFlowFromTemplateStamps a name + `variables[]` scaffold and POSTs it to `/accounts/{a}/apps/{p}/flows`.
createDuplicatePreviewPaginates the view, groups records by the named `fields` composite key, and returns every group with count ≥ `minCount`.
Record / user lifecycle helperssummarizeRecordChangesReads the table's record history (the same endpoint getRecordHistory wraps), filters to the requested record + time range, and collapses each event into a flat list of `{fieldName, fromValue, toValue, modifiedAt, modifiedBy}` rows.
restoreRecordsLeavingViewFinds records that recently fell out of a view (typically because a filter field was edited), and optionally reverts them.
offboardUserMulti-step user lifecycle workflow: (1) deactivate the user (PUT status=Inactive); (2) when `reassignTo` + `userOwnedRecords` are provided, replace the user reference on each listed (viewId, fieldName) pair; (3) when `transferGroups:true` and `reassignTo` is set, move the user out of every group containing them and add `reassignTo` in their place; (4) when `removeFromRoles:true`, list every role this user belongs to and surface them as `pendingRoleRemovals` for the caller to finalize via assignUsersToRole.

FAQ

Where do I get a TrackVia access token?

From your TrackVia account — exchange your API user credentials for a short-lived OAuth access token through TrackVia's OAuth flow. Refer to the TrackVia API docs for the exact steps; this server does not issue tokens.

Are my credentials stored anywhere?

No. Access tokens are extracted from request headers, used for the outbound TrackVia call, and discarded. The logger redacts credential fields rather than writing them.

When should I set X-TrackVia-Host?

Only when you need to point this request at a non-default TrackVia environment — e.g. qa1.qa.xvia.com while developing against QA. The host must match the hardcoded allowlist: *.trackvia.com, *.xvia.com, or localhost. Omit the header to use the server's default host.

When should I set X-TrackVia-Account-Id?

Only when you want to target a sandbox account inside the account your access token belongs to. Pass the sandbox's numeric account id; omit the header to use the access token's default account.

Usage examples

Once connected, ask your model in plain language. The server composes small tools into real workflows, so most of these are one sentence.

Getting oriented

I'm new to this account. Give me a one-shot orientation — apps, views, and a few sample fields per view — so I know what I'm working with.
Tell me which tools this server exposes, when each was introduced, and whether any are marked experimental or deprecated.

Finding things across the account

Search every view in the "Operations" app for the word "urgent" and show me the top hits per view.
Which views anywhere in the account have a field called "Priority"?

Reading a single record

Pull record 7421 from the "Orders" view with every field annotated — type, required, writable, and linked ids.
Upsert this lead into the "Leads" view, keying on Email — update if it exists, otherwise create.

Bulk changes with a safety net

Preview what would happen if I set Status="Archived" on every record in "Old Tickets" last updated before 2025-01-01. Don't write anything yet.
Back up every matching record first, then archive every "Inactive" contact in the "Contacts" view.

Imports

Here's a CSV of new leads. Dry-run the import first, using Email as the unique key, and tell me which rows would create vs. update vs. fail validation.
The dry run looks clean. Now actually run the import and upsert on Email.

Data quality

Find duplicate contacts in the "Contacts" view grouped by email, case-insensitive, with at least 2 matches per cluster.
Take this cluster of duplicate contacts, merge them into one — keep the oldest record and fill any empty fields from the others.
In the "Projects" view, show me every record that's missing any required field, annotated with which fields are missing.

Exploring relationships

Build a 3-deep graph around record 7421 in "Orders" — every parent, every child, every link.
Pull record 7421 from "Orders" and expand its Customer and Owner relationship fields inline.

Query & export

Export every "Active" deal as CSV with just Name, Amount, Stage, and CloseDate.
Page through the "Tickets" view filtered to Status="Open", sorted by Priority desc — return up to 5000 records.

Schema

Export the full schema of the "Operations" app so I can see every view, every field, every choice, and every relationship target in one JSON blob.
Describe the "Contacts" view — show me every field's type, requiredness, writability, and choices.

Aggregation & reporting

In "Orders", group by Status and show me the count and the sum of Amount per group.
Build a pivot of "Deals" with Stage across the rows and Region across the columns, averaging Amount.
Show me a month-by-month trend of new records created in "Leads" this year — bucket by CreatedAt.
Who are the top 10 customers by total order amount in "Orders"?

State machines & approvals

Move record 4412 from Status "Submitted" to "Approved" — only if it's still "Submitted" right now — and stamp ApprovedAt with the current timestamp.
For every "Expense Report" still sitting in "Pending Manager" assigned to user 88, advance Status to "Pending Finance".

Soft delete & lifecycle

Archive record 8890 in "Contacts" by setting Archived=true and ArchivedAt=now. Don't actually delete.
Restore record 8890 in "Contacts": Archived=false, clear ArchivedAt.

User administration

Invite these 20 users — pasted below as CSV — and tell me which rows failed and why. confirm: true.
Look up these emails in the account and return the user ids, plus any that didn't match.