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.
# npm npm install @tars/sdk import { TarsReporter, TarsTransport }
from '@tars/sdk' // Wrap your existing transport const reporter = new TarsReporter()
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.
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.
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.
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.
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.
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.
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.
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.
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)
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()
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.
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.
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.
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.
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.
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.
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.
TypeScript/JavaScript ships first. A Python package follows with identical behaviour and the same privacy contract.
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.