harness.dataio.dev
MCP / REST Agent Test Harness · synthetic data & tool server for agent developers

What this is

A hosted test harness for exercising AI agents. It exposes the same set of capabilities over two faces from one shared registry, so they never drift:

MCP face

Model Context Protocol over Streamable HTTP. One tool per capability. Point an agent / AgentCore remote MCP server at it.

REST API

A standards-shaped REST API (GET resources, query filters, 201 on create) over the same data, with its own OpenAPI at /api/v1/openapi.json.

Domains covered

A capability is a single tool/operation (e.g. insurance_get_policy), exposed identically on MCP and REST. The four domains below (insurance, financial, healthcare, retail/CPG) are industry areas that group related capabilities.

Insurance

member · policy · claim · quote · coverage

Lookups, search, claims aggregation, and a file-claim write stub. VIN-bearing auto quotes.

Financial

account · transaction · balance · statement

Account/balance/statement lookups, transaction search, spending summary, transfer write stub. IBAN-bearing accounts.

Healthcare

patient · encounter · provider · appointment · prescription

Patient/provider/prescription lookups, encounter & appointment search/aggregation, schedule write stub. NPI-bearing providers.

Retail / CPG

product · customer · store · supplier · inventory · order

Product/customer/store/supplier/order lookups, order & inventory search, per-channel sales summary, place-order write stub. GTIN-bearing products.

~51 capabilities total across the four domains, plus a cross-domain session_reset. Each domain includes read tools and a non-persisting write stub.

Access & endpoints

SurfaceURL
MCP (Streamable HTTP)https://harness.dataio.dev/mcp
REST API (v1)https://harness.dataio.dev/api/v1 · idiomatic GET resources
REST API — interactive docshttps://harness.dataio.dev/api/v1/docs
REST API — OpenAPI 3.1https://harness.dataio.dev/api/v1/openapi.json
Health (health check)https://harness.dataio.dev/healthz

Auth posture: open no token required TLS at the edge

Tool names & entity ids

Tool names use underscores: insurance_get_policy, financial_get_account, healthcare_get_patient. Entities are addressed as {domain}/{type}/{ordinal} (slashes), e.g. insurance/policy/0, financial/account/0. Ordinals start at 0 and a handful always exist; use a search_* / list_* tool to discover valid ids.

Using the REST API (v1)

PatternExample
Collection (filters + pagination)GET /api/v1/financial/accounts?account_type=savings&limit=10
One record by id (ordinal)GET /api/v1/financial/accounts/0
Sub-resourceGET /api/v1/financial/accounts/0/balance
Create (POST → 201, not persisted)POST /api/v1/insurance/claims

Path ids are the bare ordinal (e.g. /0); a missing record returns 404. Pin data with ?seed= or the X-Seed header.

# Insurance — search policies, fetch one, then its coverages
curl -s 'https://harness.dataio.dev/api/v1/insurance/policies?limit=2&seed=demo-123'
curl -s 'https://harness.dataio.dev/api/v1/insurance/policies/0?seed=demo-123'
curl -s 'https://harness.dataio.dev/api/v1/insurance/policies/0/coverages?seed=demo-123'
# Financial — list accounts, fetch one, read its balance
curl -s 'https://harness.dataio.dev/api/v1/financial/accounts?account_type=savings&limit=2&seed=demo-123'
curl -s 'https://harness.dataio.dev/api/v1/financial/accounts/0?seed=demo-123'
curl -s 'https://harness.dataio.dev/api/v1/financial/accounts/0/balance?seed=demo-123'
# Healthcare — list providers, fetch a patient, schedule an appointment (201)
curl -s 'https://harness.dataio.dev/api/v1/healthcare/providers?limit=2&seed=demo-123'
curl -s 'https://harness.dataio.dev/api/v1/healthcare/patients/0?seed=demo-123'
curl -s -X POST https://harness.dataio.dev/api/v1/healthcare/appointments \
  -H 'Content-Type: application/json' \
  -d '{"patient_id":"healthcare/patient/0","provider_id":"healthcare/provider/0","requested_date":"2026-07-01"}'
# Retail / CPG — list products, fetch one, place an order (201)
curl -s 'https://harness.dataio.dev/api/v1/retail/products?category=beverages&limit=2&seed=demo-123'
curl -s 'https://harness.dataio.dev/api/v1/retail/products/0?seed=demo-123'
curl -s -X POST https://harness.dataio.dev/api/v1/retail/orders \
  -H 'Content-Type: application/json' \
  -d '{"customer_id":"retail/customer/0","store_id":"retail/store/0","lines":[{"product_id":"retail/product/0","quantity":2}]}'

REST API resources

The full resource map (browse and try it at /api/v1/docs). {id} is the bare ordinal (e.g. 0); trailing comments list the available query filters.

# Insurance
GET  /api/v1/insurance/policies                  # member_id, status, limit, offset
GET  /api/v1/insurance/policies/{id}
GET  /api/v1/insurance/policies/{id}/coverages
GET  /api/v1/insurance/members/{id}
GET  /api/v1/insurance/claims                    # policy_id, status, filed_from, filed_to, limit, offset
GET  /api/v1/insurance/claims/{id}
GET  /api/v1/insurance/claims/summary            # member_id, policy_id
POST /api/v1/insurance/claims                    # file a claim (201, not persisted)
GET  /api/v1/insurance/quotes/{id}
GET  /api/v1/insurance/products/{id}
GET  /api/v1/insurance/documents/{id}
GET  /api/v1/insurance/assessors/{id}
GET  /api/v1/insurance/reserves/{id}
GET  /api/v1/insurance/claim-assessments/{id}
GET  /api/v1/insurance/claim-events/{id}
GET  /api/v1/insurance/decisions/{id}
# Financial
GET  /api/v1/financial/accounts                      # status, account_type, limit, offset
GET  /api/v1/financial/accounts/{id}
GET  /api/v1/financial/accounts/{id}/balance
GET  /api/v1/financial/accounts/{id}/statements
GET  /api/v1/financial/accounts/{id}/transactions  # type, category, posted_from, posted_to, limit, offset
GET  /api/v1/financial/accounts/{id}/spending-summary  # type
GET  /api/v1/financial/statements/{id}
GET  /api/v1/financial/transactions                  # account_id, type, category, posted_from, posted_to, limit, offset
POST /api/v1/financial/transfers                     # transfer funds (201, not persisted)
# Healthcare
GET  /api/v1/healthcare/providers                       # specialty, limit, offset
GET  /api/v1/healthcare/providers/{id}
GET  /api/v1/healthcare/patients/{id}
GET  /api/v1/healthcare/patients/{id}/prescriptions
GET  /api/v1/healthcare/prescriptions/{id}
GET  /api/v1/healthcare/encounters                      # patient_id, provider_id, type, date_from, date_to, limit, offset
GET  /api/v1/healthcare/appointments                    # patient_id, provider_id, status, date_from, date_to, limit, offset
GET  /api/v1/healthcare/appointments/summary            # patient_id, provider_id
POST /api/v1/healthcare/appointments                    # schedule (201, not persisted)
# Retail / CPG
GET  /api/v1/retail/products                         # category, brand, status, limit, offset
GET  /api/v1/retail/products/{id}
GET  /api/v1/retail/products/{id}/inventory        # stock across stores
GET  /api/v1/retail/customers                        # tier, status, limit, offset
GET  /api/v1/retail/customers/{id}
GET  /api/v1/retail/customers/{id}/orders          # status, placed_from, placed_to, limit, offset
GET  /api/v1/retail/stores                           # region, type, status, limit, offset
GET  /api/v1/retail/stores/{id}
GET  /api/v1/retail/stores/{id}/inventory
GET  /api/v1/retail/suppliers                        # status, limit, offset
GET  /api/v1/retail/suppliers/{id}
GET  /api/v1/retail/orders                           # customer_id, store_id, status, placed_from/to, limit, offset
GET  /api/v1/retail/orders/{id}
GET  /api/v1/retail/orders/{id}/lines
GET  /api/v1/retail/orders/summary                   # store_id, status (per-channel sales rollup)
GET  /api/v1/retail/inventory                        # product_id, store_id, limit, offset
POST /api/v1/retail/orders                           # place order (201, not persisted)

MCP tools by domain

The MCP face (and the OpenAPI tool-mirror gateways ingest) expose these tools — the REST API above serves the same data as resource paths. Each domain also has a <domain>_list_capabilities tool that returns this list, with descriptions and scopes, at runtime.

Insurance

Get: insurance_get_member, insurance_get_policy, insurance_get_product, insurance_get_quote, insurance_get_reserve, insurance_get_assessor, insurance_get_document, insurance_get_claim, insurance_get_claim_assessment, insurance_get_claim_event, insurance_get_decision

List / search: insurance_list_coverages, insurance_search_policies, insurance_search_claims, insurance_list_capabilities

Aggregate: insurance_claims_summary

Write (stub): insurance_file_claim

Financial

Get: financial_get_account, financial_get_balance, financial_get_statement

List / search: financial_list_accounts, financial_list_statements, financial_search_transactions, financial_list_capabilities

Aggregate: financial_spending_summary

Write (stub): financial_transfer_funds

Healthcare

Get: healthcare_get_patient, healthcare_get_provider, healthcare_get_prescription

List / search: healthcare_list_providers, healthcare_list_patient_prescriptions, healthcare_search_appointments, healthcare_search_encounters, healthcare_list_capabilities

Aggregate: healthcare_appointments_summary

Write (stub): healthcare_schedule_appointment

Retail / CPG

Get: retail_get_product, retail_get_customer, retail_get_store, retail_get_supplier, retail_get_order

List / search: retail_list_products, retail_list_customers, retail_list_stores, retail_list_suppliers, retail_list_order_lines, retail_search_orders, retail_list_inventory, retail_list_capabilities

Aggregate: retail_sales_summary

Write (stub): retail_place_order

Plus a cross-domain session_reset.

Seeding & reproducibility

All data is a pure function of an opaque seed string — the same seed always yields the same universe, regardless of call order. This is what makes test runs reproducible. There is no database; nothing is stored.

WhereHow to set the seed
Any client / agent — per call"seed": "my-seed" in the tool arguments / JSON body (works everywhere, incl. clients that can't set headers and through gateways)
REST — sessionX-Seed: my-seed request header (header-capable clients / curl)
MCP — connectionX-Seed: my-seed header on the connection (header-capable clients only)
If omitteda seed is auto-generated and echoed back (X-Seed response header + seed in the body) so you can replay it

The seed argument is the universal way to pin a run: an agent simply passes seed in each tool call, so it works in every client (including ones whose UI can't set custom headers). The X-Seed header is a set-and-forget alternative for header-capable clients and curl.

# Pin a seed so results are identical every time (header or ?seed=):
curl -s https://harness.dataio.dev/api/v1/insurance/policies/0 -H 'X-Seed: demo-123'
curl -s 'https://harness.dataio.dev/api/v1/insurance/policies/0?seed=demo-123'

Reset / reseed

For most uses, just pin the seed per call (the ?seed= query param or the X-Seed header on the REST API) — that fixes the data deterministically with no session state. MCP clients that hold a session can also call the cross-domain session_reset tool, which installs a new seed (or auto-generates one) and clears any session overlay; it does not persist server-side in v1.

# Same seed -> identical universe every time:
curl -s 'https://harness.dataio.dev/api/v1/financial/accounts?seed=demo-123'

# Omit the seed and one is auto-generated and echoed in the X-Seed header:
curl -si 'https://harness.dataio.dev/api/v1/financial/accounts' | grep -i x-seed

Writes are not persisted

The write tools (insurance_file_claim, financial_transfer_funds, healthcare_schedule_appointment) validate input and return a realistic, seed-derived success response marked _mock: "not_persisted" — but they do not store anything. "Write then read it back" is intentionally inconsistent in this version.