TARS
@tars/sdk

Get chosen.
Not overlooked.

When an agent queries the TARS registry to pick an MCP server, class rating decides. Class B and above require verified real-world adoption data — not self-reported. Wrap your transport with TarsTransport and every user you ship to becomes evidence that your server is the one to pick.

Installation
# npm
npm install @tars/sdk

import { TarsReporter, TarsTransport } 
from '@tars/sdk' // Wrap your existing transport const reporter = new TarsReporter()
PACKAGE
@tars/sdk
IMPACT
Zero on hot path
SIGN-UP
Not required
FLUSH
Async · every 5 min
V
OK
01 · ImpactYour service notices nothing

Never on the hot path.

The SDK accumulates call stats locally in memory and flushes asynchronously every 5 minutes. Your agent never waits for TARS. If TARS is down, your agent is unaffected.

Zero
Latency added to tool calls

TarsTransport intercepts the JSON-RPC response, records the outcome and latency, then immediately forwards the response. No await, no blocking, no round trip to TARS in the call path.

Zero
Impact if TARS goes down

Telemetry is fire-and-forget. If the flush fails, the SDK logs to stderr and discards silently — your agent continues working identically with no errors surfaced.

Zero
Payload data collected

The SDK never reads tool call arguments or responses. It records only the endpoint URL, aggregate call counts, and latency percentiles across the flush window. No user data. No content. No PII.

None
Sign-up or account required

An Ed25519 keypair is generated locally on first run and stored at ~/.tars/identity.json. Your public key registers itself on first flush. No email. No form. No friction.

02 · ValueWhy it makes you the pick
BENEFIT 01Selection

Agents choose the highest-rated server.

When an AI agent or developer queries TARS to pick between MCP servers, class rating is the tiebreaker. Class B requires 3+ distinct SDK reporters and 100+ real calls in a 30-day window. Your competitors can't fake that. You earn it.

BENEFIT 02Adoption

Your users become your proof.

Add the SDK to your integration docs. Every developer who installs it contributes anonymously to your adoption count — automatically, without any action from you. The more users you ship to, the stronger your signal becomes.

BENEFIT 03Credibility

Verified data beats self-reported claims.

Any server can claim it's reliable. Class B and above require cryptographically distinct reporter contributions from real-world usage — not a form you fill in. In a crowded registry, that distinction is what separates listed from chosen.

03 · IntegrationTwo ways in — pick the one that fits
Option A — Transport proxy

Wrap your transport.

Pass your existing transport through TarsTransport before connecting. Every JSON-RPC call is observed automatically. Nothing else changes.

import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
import { TarsReporter, TarsTransport } from '@tars/sdk'

// Once per process
const reporter = new TarsReporter()

// Per connection — one extra line
const url = new URL('https://mcp.example.com')
const transport = new TarsTransport(
  new StreamableHTTPClientTransport(url),
  reporter,
  url.toString(),
)

// Connect and use normally
await client.connect(transport)
Option B — Manual

Wrap the call directly.

Use reporter.track() when you need explicit control — or reporter.record() if you already have the outcome. The original return value and errors pass through unchanged.

// track() — wraps an async call
const tools = await reporter.track(
  'https://mcp.example.com',
  () => client.listTools(),
)

// record() — when you already have the outcome
reporter.record({
  endpoint: 'https://mcp.example.com',
  success: true,
  latencyMs: 142,
})

// Flush before process exit
await reporter.flush()
How it flushes

The SDK buffers call stats in memory. Every 5 minutes it sends a single compact payload to TARS — one summary per endpoint covering total calls, successes, errors, and p50/p95 latency across the window. The payload is identified with a local Ed25519 public key so contributions are cryptographically distinct. On process exit, call await reporter.flush() in your shutdown handler to drain pending data.

04 · PrivacyExact list — nothing left ambiguous
Collected— the exact fields in each flush
  • Endpoint URLThe MCP server being called
  • Call countTotal calls in the flush window
  • Success / errorsAggregate counts — not per-call
  • p50 latencyMedian response time across the window
  • p95 latency95th percentile response time
  • Window timestampsStart and end of the 5-minute window
  • Reporter keyYour Ed25519 public key — anonymous by default
Never collected— hard constraints, not policy
  • Tool argumentsWhat you passed to the tool call
  • Tool responsesWhat the server returned
  • User data or PIIAny content from your application
  • Individual call dataOnly window aggregates — no per-call records
  • Agent identityWho the agent is working for
  • IP addressNot transmitted or logged
  • Runtime infoNo fingerprinting of any kind
Identity model

An Ed25519 keypair is auto-generated on first run and stored at ~/.tars/identity.json. The private key never leaves your machine. The public key is sent as your reporter identity on each flush and is used to verify that contributions are distinct and not replayed. You contribute anonymously by default. In serverless or container environments, set TARS_REPORTER_KEY=ed25519:<hex> to provide a stable identity without filesystem access.

05 · QuestionsThe ones people actually ask

Does removing the SDK break anything?

No. Remove it and your agent runs identically. The SDK is a passive observer — it holds no state your application depends on. You stop contributing telemetry, but nothing in your application breaks.

What happens if TARS is unreachable?

The flush fails silently. The SDK logs to stderr and discards the window — it never throws into your application. Your agent continues working identically. The only consequence is a gap in your contribution window.

Can I opt out of contributing but still use the package?

Yes — just don't call reporter.flush() or use TarsTransport, and no data is ever sent. You can also use TarsReporter with a custom baseUrl pointed at your own ingest endpoint if you want the batching behaviour without sending data to TARS.

Is the keypair tied to a machine?

By default, yes — the key lives at ~/.tars/identity.json. In serverless or container environments set TARS_REPORTER_KEY to an ed25519:<hex> public key. If no key is found, a new keypair is generated in-memory — contributions are still valid, just not persistent identity across restarts.

Can the data be used to identify my application or users?

No. The SDK collects only endpoint URLs and aggregate call statistics — nothing that could identify an application, a user, or a use case. The reporter key is a random Ed25519 public key with no connection to your identity unless you explicitly claim it.

What language support is planned?

TypeScript/JavaScript ships first. A Python package follows with identical behaviour and the same privacy contract.

The difference between listed and chosen.

Hundreds of MCP servers are listed. The ones that get picked are the ones with verified adoption data behind them. One line of code starts building that case. Zero overhead. No account. Nothing to configure.

npm install @tars/sdkBrowse the registry →