Privacy & Data Handling
This document describes what data flows through the SMI Aware MCP server, what is deliberately never stored or logged, and the server's telemetry posture. It reflects the current implementation — every claim below is grounded in the code paths cited alongside it.
What data flows through the server
- SMI Aware credential (PAT). The server authenticates to the SMI Aware
Public API using a Personal Access Token supplied by the caller as the MCP
connection's handshake
Authorization: Bearerheader. The credential is held only in memory for the session's lifetime, is never persisted to disk, and is never logged (README.md— Authentication (README.md#authentication)). It flows through theCredentialProviderabstraction (src/auth/), which treats the credential as opaque and re-acquires it per request attempt. Two forms exist today — a PAT read from the connection header, and, when the server's own OAuth flow is enabled, a PAT unsealed from the issued access token (src/auth/issuedTokenCredentialProvider.ts; see "No credential store" below). Neither reachessrc/api/orsrc/tools/as anything but an opaque credential, so no caller assumes a particular token shape. A connection that presents no PAT is accepted anonymously with a reduced, onboarding-only tool set; no credential is stored for it. - Tool call arguments. Requests to
smi_*tools (deep report / export data, subject enrichment fields, search queries) pass through the server to the SMI Aware Public API to fulfil the call. The server itself does not persist this data — it is not written to a database or file by this codebase. - Non-PII identity fields. When the HTTP transport verifies a
connection's PAT (
GET /user), it retains onlyuserId,accountId, androleIdon the in-memory session record — neveremailor name fields from that response (README — Token verification on connect (README.md#token-verification-on-connect)).
What is NOT stored or logged
- No PII in logs.
src/config/logger.tswrites one JSON line per event tostderronly (neverstdout, which is reserved for the JSON-RPC channel). Everyfieldsobject passed to a log call is run throughsrc/observability/redactPii.tsfirst: any key matching a denylist (name,dob,birth,address,email,phone,url,alias,subject,finding,summary,gap,args,arguments,body,payload,token,authorization,secret,password,apikey,api_key,ssn,credential— case-insensitive substring match, at any depth) has its value replaced with"[REDACTED]". A narrow allowlist of exact technical keys (toolName,hostname,traceId,durationMs,requestCount,statusCode,errorId,transport,level,message,time) is exempted so operational fields survive redaction. An ESLint rule (no-restricted-syntaxineslint.config.js) additionally flags denylisted keys written directly in a log call at review time, as a static backstop on top of the runtime redaction. - No credential logging. The PAT itself is never included in a log
line —
defineTool()(src/tools/defineTool.ts) logs only the tool name and outcome (tool invoked: <name>), never arguments or results. - No credential store, including under OAuth. When the server acts as
its own OAuth authorization server (
OAUTH_ENABLED=true, see the "OAuth authorization server" section ofREADME.md), it still keeps no database of user credentials. The PAT is encrypted into the issued access token itself with AES-256-GCM (src/auth/sealing.ts), so recovering it on a later request is a decrypt rather than a lookup, and there is no table of customer API keys to breach. The only server-side state the flow keeps is a set of spent authorization-code identifiers, used to enforce single use; those are opaque ids, never credentials, and they expire with the codes they refer to. - No raw upstream error bodies.
src/tools/smi/errorGuidance.tsmaps SMI Aware API failures to actionable Markdown without echoing the upstreammessagetext for field-validation errors, and never echoes response bodies for 5xx / invalid-response failures — only an opaqueerrorIdplus{ status, kind, code }are logged server-side for those. This is asserted, not just intended:test/tools/smi/upstreamErrorLeakage.test.tsdrives real tools against an upstream that returns a subject name, an email address, and the session token inside its error body, and fails if any of them reaches the caller's error text or any log line — on both the 422 field-validation path and the 5xx error-reference path. - No job-completion PII. The job-completion push
(
src/notifications/notifyJobCompletion.ts,jobCompletionPayloadSchema) carries only{ jobId, status, kind? }—statusis one ofreleased/failed,kindisdeep_report/export. No subject data, name, or account identifier rides along; a client that wants details calls a read tool separately. - Non-PII user routing key. The identity-based connection registry
(
src/notifications/) routes notifications by auserKeythat is an HMAC-SHA256 of the session's handshake token (or verifieduserId), keyed by the operator-suppliedUSER_IDENTITY_SALT(src/notifications/userIdentity.ts,userKeyForOpaqueToken/userKeyForVerifiedUserId) — never the raw PAT or user id itself. This holds for both the in-memory registry (default) and the Redis Pub/Sub-backed registry used whenREDIS_URLis set. - No persistent store. This server has no database. Session state (bound token, identity, live SSE connection) lives in memory for the process lifetime.
Telemetry posture
- Telemetry is optional and off by default. The server has an
OpenTelemetry integration (
src/telemetry/) gated byOTEL_ENABLED(defaultfalse). When disabled, every instrumentation call site short-circuits to a true no-op — no spans, no metrics, and no outbound telemetry of any kind. There is no third-party vendor SDK, no auto-instrumentation, and no console exporter baked in. - When enabled, signals go only where the operator points them. The
bootstrap (
src/telemetry/bootstrap.ts) uses OTLP-over-HTTP exporters aimed at an operator-configured collector endpoint — nothing is sent to Anthropic, SMI Aware, or any hosted telemetry vendor by this codebase. - No PII or payloads in telemetry, structurally. Every emitted
attribute passes through closed builders (
src/telemetry/attributes.ts) instead of a free-form object, so a raw request argument or response body cannot become a span or metric attribute. The complete emitted set is: amcp.tool.invokespan plusmcp.tool.invocationscounter carrying only the tool name and outcome, and asmi.api.request.durationhistogram carrying method, outcome, status, and a PII-freehttp.routewhere ids are templated to:id(never the raw path or query string). - Logs remain local operational output. Structured logs write to
stderronly (neverstdout, reserved for the JSON-RPC channel), for the operator running the server. Operators who forwardstderrto their own logging infrastructure inherit the redaction guarantees above but are responsible for their own retention policy. - Trace context (
traceId,transport,toolName—src/observability/requestContext.ts) exists to correlate log lines for a single request; it carries no PII and no request payload.
Data retention
- The server retains nothing after the session ends. There is no database and no file store. Session state — the bound credential, the non-PII identity fields, and any live SSE connection — lives in process memory and is gone when the session closes or the process restarts.
- Credentials are not retained at all. A PAT supplied on the connection header exists only for that session. Under the server's own OAuth flow the PAT is sealed inside the issued access token rather than stored, so it is retained by the client holding the token, not by this server. The only server-side state the OAuth flow keeps is a set of spent authorization-code identifiers, which expire with the codes they refer to.
- Tool call arguments and results are not retained. They pass through to the SMI Aware Public API to fulfil the call and are not written anywhere by this codebase.
- Operational logs are
stderroutput belonging to whoever runs the server. They carry no PII (see above), and their retention is set by the operator's own logging infrastructure, not by this server.
Sharing with third parties
- No data is sold, rented, or shared for advertising. This server has no such integrations.
- The only upstream this server calls is the SMI Aware Public API, to fulfil the caller's own requests. It is a pass-through for those calls, not a second data store.
- No analytics or telemetry vendor is embedded. Telemetry is off by default; when an operator enables it, signals go only to the collector endpoint that operator configures. Nothing is sent to Anthropic, to SMI Aware, or to any hosted telemetry vendor by this codebase.
Scope and limits of this policy
- This document describes the server's own handling. Calls made on the caller's behalf still reach the SMI Aware Public API, which has its own data-handling practices under SMI Aware's terms — this server is a pass-through for those calls, not a second data store.
- "Non-PII" claims above describe what the server code does; they are not
a guarantee about data an operator chooses to log, forward, or persist
outside this codebase (e.g. redirecting
stderrinto a system that itself retains PII-adjacent fields likeerrorIdcorrelation records).
Contact
Privacy and data-handling questions about this connector go to a monitored SMI Aware address:
- Email: support@smiaware.com
- Postal address: 700 River Avenue, Pittsburgh, PA 15212