@truealter/sdk 0.5.0 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @truealter/sdk
2
2
 
3
- ALTER Identity SDK query the continuous identity field from any JavaScript/TypeScript environment.
3
+ ALTER Identity SDK - query the continuous identity field from any JavaScript/TypeScript environment.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@truealter/sdk.svg)](https://www.npmjs.com/package/@truealter/sdk)
6
6
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](./LICENSE)
@@ -10,9 +10,9 @@ ALTER Identity SDK — query the continuous identity field from any JavaScript/T
10
10
  A thin client over the ALTER MCP server (Streamable HTTP, JSON-RPC 2.0, MCP spec `2025-11-25`) with x402 micropayment support, ES256 provenance verification, and config generators for Claude Code, Cursor, and generic MCP clients.
11
11
 
12
12
  - **Branded host:** `https://mcp.truealter.com` (serves `.well-known/mcp.json` for discovery)
13
- - **JSON-RPC wire endpoint:** `https://mcp.truealter.com/api/v1/mcp` this is what Streamable HTTP POSTs target (the SDK default)
13
+ - **JSON-RPC wire endpoint:** `https://mcp.truealter.com/api/v1/mcp` - this is what Streamable HTTP POSTs target (the SDK default)
14
14
  - **Wire protocol:** Streamable HTTP, JSON-RPC 2.0, MCP `2025-11-25` (server negotiates `2025-06-18` + `2025-03-26` for backwards-compatible clients)
15
- - **Tools:** **40 typed and wired** — 24 free (L0) + 9 premium (L1L5) + 7 alter-to-alter messaging. Mirrors the live server's `tools/list` response byte-for-byte; every name in `FREE_TOOL_NAMES` / `PREMIUM_TOOL_NAMES` / `MESSAGING_TOOL_NAMES` has a matching server handler at `mcp.truealter.com/api/v1/mcp`.
15
+ - **Tools:** **34 publicly advertised**, 26 free (L0) + 8 premium (L1-L5), kept in sync with ALTER's live MCP server at every publish.
16
16
  - **Runtime:** Node 18+, Deno, Bun, Cloudflare Workers, modern browsers
17
17
  - **Crypto:** `@noble/ed25519` + `@noble/hashes` (no other dependencies)
18
18
  - **Bundle:** ESM + CJS dual output
@@ -22,7 +22,7 @@ A thin client over the ALTER MCP server (Streamable HTTP, JSON-RPC 2.0, MCP spec
22
22
  ```
23
23
  npm install @truealter/sdk
24
24
  npx alter-identity init
25
- npx alter-identity verify ~truealter
25
+ npx alter-identity verify ~alter
26
26
  ```
27
27
 
28
28
  ## Bridge vs SDK
@@ -30,36 +30,45 @@ npx alter-identity verify ~truealter
30
30
  The `alter-mcp-bridge` binary shipped in this package (`bin/mcp-bridge.ts`)
31
31
  is a **dev/demo surface** for dropping ALTER into MCP hosts that speak the
32
32
  stdio transport (Claude Code, Cursor, Continue, Windsurf). It is useful for
33
- handshake, `tools/list`, and L0 tool calls, but it does not carry Q5c
34
- per-invocation signing authenticated MCP tools will fail at the server
33
+ handshake, `tools/list`, and L0 tool calls, but it does not carry ES256
34
+ per-invocation signing - authenticated MCP tools will fail at the server
35
35
  edge when reached through the bridge. For production use, import
36
36
  `@truealter/sdk` directly and construct an `MCPClient` / `AlterClient` with
37
- the optional `signing` parameter; that path is the load-bearing one and
38
- carries the provenance envelope end-to-end. Bridge signing lands in Wave-2
39
- alongside the CLI wallet/consent verbs.
37
+ the optional `signing` parameter; that path is the primary one and
38
+ carries the provenance envelope end-to-end. Bridge signing is planned for a
39
+ future release.
40
40
 
41
41
  ## CLI
42
42
 
43
43
  The package ships two binaries. `alter-identity` is the full SDK-feature
44
- binary (`init`, `verify`, `whoami`, wire/unwire, signing, etc). `alter`
45
- is a slim, task-oriented binary for day-to-day use:
46
-
47
- | Command | Purpose |
48
- |---|---|
49
- | `alter login` | OAuth loopback sign-in; stores a session at `~/.config/alter/session.json` (mode `0600`). |
50
- | `alter depth [--json]` | GET `/api/v1/identity/depth` — identity-depth score, agentic activity, top/bottom five traits. |
51
- <!-- TODO(D4): "claim" is a Recognition Over Qualification violation — rename to "redeem" or "accept-invite" in alter-cli + update here -->
52
- | `alter claim <claim_code>` | Accept an identity invite. Prompts for email, password (min 12 chars, hidden), and explicit TOS acceptance, then POSTs `/api/v1/identity/claim`. |
53
- | `alter mirror` | Day-2 Mirror phase + streak. `alter mirror daily` claims today's Mirror; `alter mirror next` shows the next revelation window. |
54
- | `alter discover [--limit N]` | MCP-backed summary — calls `alter_whoami` and `alter_verify` against your bound handle. Degrades gracefully if the MCP endpoint is 5xx. |
55
-
56
- The session file is created with `0600` permissions; its parent dir
57
- (`~/.config/alter/`) is created with `0700`. Override the config root
58
- via `XDG_CONFIG_HOME`. Run `alter --help` for the inline reference.
44
+ binary (`init`, `verify`, `whoami`, wire/unwire, signing, etc).
45
+ `alter-mcp-bridge` is the stdio bridge described above. The day-to-day
46
+ `alter` command line is distributed separately as
47
+ [`@truealter/cli`](https://www.npmjs.com/package/@truealter/cli) - it is
48
+ not part of this package.
49
+
50
+ Run `alter-identity --help` for the inline reference.
59
51
 
60
52
  ## Why ALTER ≠ IAM
61
53
 
62
- Identity Access Management answers *who is logged in*. ALTER answers *who they actually are* a continuous field of recognition that any IAM stack can sit on top of.
54
+ Identity Access Management answers *who is logged in*. ALTER answers *who they actually are* - a continuous field of recognition that any IAM stack can sit on top of.
55
+
56
+ ## Theoretical Foundation
57
+
58
+ ALTER is the working instantiation of an eight-paper academic corpus on identity field theory. The SDK below is what happens when the theory ships as protocol. Each paper is open access on figshare under CC-BY 4.0.
59
+
60
+ | Paper | Title | DOI |
61
+ |-------|-------|-----|
62
+ | I | *Belonging is earned, not inherited* | [10.6084/m9.figshare.31794784](https://doi.org/10.6084/m9.figshare.31794784) |
63
+ | II | *The self is inferred, not owned* | [10.6084/m9.figshare.31804222](https://doi.org/10.6084/m9.figshare.31804222) |
64
+ | III | *The same form, at every scale* | [10.6084/m9.figshare.31812955](https://doi.org/10.6084/m9.figshare.31812955) |
65
+ | IV | *Measurement changes the thing measured* | [10.6084/m9.figshare.31812982](https://doi.org/10.6084/m9.figshare.31812982) |
66
+ | V | *Political failure has a geometry* | [10.6084/m9.figshare.31813000](https://doi.org/10.6084/m9.figshare.31813000) |
67
+ | VI | *When does a machine have a self* | [10.6084/m9.figshare.31813006](https://doi.org/10.6084/m9.figshare.31813006) |
68
+ | VII | *Seventy-five predictions, each falsifiable* | [10.6084/m9.figshare.31951644](https://doi.org/10.6084/m9.figshare.31951644) |
69
+ | VIII | *Identity as a field, not a property* | [10.6084/m9.figshare.31951383](https://doi.org/10.6084/m9.figshare.31951383) |
70
+
71
+ For the lay-register chapter version, see [`/origin`](https://truealter.com/origin).
63
72
 
64
73
  ## API
65
74
 
@@ -69,20 +78,104 @@ Identity Access Management answers *who is logged in*. ALTER answers *who they a
69
78
  import { AlterClient, X402Client } from "@truealter/sdk";
70
79
 
71
80
  const alter = new AlterClient({
72
- endpoint: "https://mcp.truealter.com/api/v1/mcp", // optional this is the default; bare host returns 405
81
+ endpoint: "https://mcp.truealter.com/api/v1/mcp", // optional - this is the default; bare host returns 405
73
82
  apiKey: process.env.ALTER_API_KEY, // optional for free tier
74
- x402: new X402Client({ // optional only required for premium tools
83
+ x402: new X402Client({ // optional - only required for premium tools
75
84
  signer: yourViemOrEthersSigner,
76
85
  maxPerQuery: "0.10",
77
86
  }),
78
87
  });
79
88
  ```
80
89
 
81
- ### Free tier (L0 — no payment required)
90
+ ### Minimum-version preflight (required)
91
+
92
+ ALTER's backend publishes a per-client minimum-version floor. The SDK
93
+ preflights this floor lazily on the first network call: no explicit
94
+ call is required for the common case. If the running SDK is below the
95
+ floor for `alter-identity`, the SDK throws `BelowFloorError` with the
96
+ upgrade command attached.
97
+
98
+ The floor document is signed by the backend with a floor-only Ed25519
99
+ private key. The SDK ships only the corresponding public keys
100
+ (`KNOWN_FLOOR_PUBLIC_KEYS`, a `key_id` to SPKI-PEM map): no signing
101
+ secret ships in the client, and a compromised client cannot forge floor
102
+ documents. The `key_id` is the first 8 hex chars of SHA-256 of the raw
103
+ 32-byte Ed25519 public key, so clients select the right key during a
104
+ rotation. An unknown `key_id` or an invalid signature is treated as a
105
+ cache miss (refetch), never as a pass.
106
+
107
+ ```ts
108
+ import { AlterClient, BelowFloorError, checkMinVersion } from "@truealter/sdk";
109
+
110
+ // Optional: run the preflight explicitly to surface the upgrade
111
+ // prompt at startup, before any real work happens:
112
+ try {
113
+ await checkMinVersion();
114
+ } catch (err) {
115
+ if (err instanceof BelowFloorError) {
116
+ console.error(`upgrade required: ${err.upgrade_cmd}`);
117
+ process.exit(1);
118
+ }
119
+ throw err;
120
+ }
121
+
122
+ // The constructor installs the same hook lazily: it fires on your
123
+ // first request automatically:
124
+ const alter = new AlterClient();
125
+ try {
126
+ await alter.verify("~alter");
127
+ } catch (err) {
128
+ if (err instanceof BelowFloorError) {
129
+ // Re-thrown on every subsequent call until you upgrade.
130
+ console.error(`upgrade: ${err.upgrade_cmd}`);
131
+ }
132
+ }
133
+ ```
134
+
135
+ `BelowFloorError` carries the canonical envelope fields as enumerable
136
+ properties so consumers can branch without re-parsing:
137
+
138
+ | Property | Type | Example |
139
+ | ---------------- | ------ | ------------------------------------ |
140
+ | `code` | string | `"client_below_floor"` |
141
+ | `client_version` | string | `"0.5.2"` |
142
+ | `min_version` | string | `"0.6.0"` |
143
+ | `upgrade_cmd` | string | `"npm install -g @truealter/sdk"` |
144
+ | `channel` | string | `"npm"` |
145
+ | `envelope` | object | full `{ error: {...} }` envelope |
146
+
147
+ **Opt-out (discouraged).** Pass `unsafe_skipVersionCheck: true` to skip
148
+ the client-side preflight. The server-side floor gate still rejects
149
+ below-floor clients with HTTP 426 regardless: disabling the SDK-side
150
+ preflight only swaps a clean typed error for an opaque network failure
151
+ on every subsequent call.
152
+
153
+ ```ts
154
+ const alter = new AlterClient({ unsafe_skipVersionCheck: true });
155
+ ```
156
+
157
+ Worked example: see [`examples/min-version-check/`](./examples/min-version-check/).
158
+
159
+ ### Identity headers
160
+
161
+ Every outbound request from `AlterClient` / `MCPClient` carries three
162
+ identity headers that the server-side floor middleware consults:
163
+
164
+ | Header | Value (this SDK) |
165
+ | -------------------------- | ------------------ |
166
+ | `X-Alter-Client-Id` | `alter-identity` |
167
+ | `X-Alter-Client-Version` | the running `SDK_VERSION` |
168
+ | `X-Alter-Client-Channel` | `npm` |
169
+
170
+ These are MANDATORY on every authenticated backend endpoint per
171
+ D-MIN-VERSION-FLOOR-1 §3. The User-Agent header remains informational
172
+ and is NEVER used for floor enforcement.
173
+
174
+ ### Free tier (L0 - no payment required)
82
175
 
83
176
  ```ts
84
177
  // Verify a registered identity by handle, email, or id
85
- const verified = await alter.verify("~truealter");
178
+ const verified = await alter.verify("~alter");
86
179
  const verifiedById = await alter.verify(
87
180
  "550e8400-e29b-41d4-a716-446655440000",
88
181
  {
@@ -92,7 +185,7 @@ const verifiedById = await alter.verify(
92
185
  },
93
186
  );
94
187
 
95
- // Reference data the 12 ALTER archetypes
188
+ // Reference data - the 12 ALTER archetypes
96
189
  const archetypes = await alter.listArchetypes();
97
190
 
98
191
  // Identity depth and available tool tiers
@@ -100,7 +193,7 @@ const depth = await alter.getEngagementLevel({
100
193
  member_id: "550e8400-e29b-41d4-a716-446655440000",
101
194
  });
102
195
 
103
- // Search by trait criteria no PII exposed, max 5 results
196
+ // Search by trait criteria - no PII exposed, max 5 results
104
197
  const matches = await alter.searchIdentities({
105
198
  trait_criteria: {
106
199
  pressure_response: { min: 0.7 },
@@ -112,33 +205,33 @@ const matches = await alter.searchIdentities({
112
205
  const thread = await alter.goldenThreadStatus();
113
206
  ```
114
207
 
115
- ### Premium tier (L1L5 x402 payment required)
208
+ ### Premium tier (L1-L5 - x402 payment required)
116
209
 
117
210
  ```ts
118
- // L1 Extract trait signals from text ($0.005, first 100 free per bot)
211
+ // L1 - Extract trait signals from text ($0.01, first 100 free per bot)
119
212
  const signals = await alter.assessTraits({
120
213
  text: "I led the incident response when our payment rails went down...",
121
214
  context: "interview transcript",
122
215
  });
123
216
 
124
- // L2 Full 33-trait vector ($0.01)
217
+ // L2 - Full 33-trait vector ($0.10)
125
218
  const vector = await alter.getFullTraitVector({
126
219
  member_id: "550e8400-e29b-41d4-a716-446655440000",
127
220
  });
128
221
 
129
- // L4 Belonging probability for a person-job pairing ($0.05)
222
+ // L4 - Belonging probability for a person-job pairing ($0.60)
130
223
  const belonging = await alter.computeBelonging({
131
224
  member_id: "550e8400-e29b-41d4-a716-446655440000",
132
225
  job_id: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
133
226
  });
134
227
 
135
- // L5 Top match recommendations ($0.50)
228
+ // L5 - Top match recommendations ($1.00)
136
229
  const recommendations = await alter.getMatchRecommendations({
137
230
  member_id: "550e8400-e29b-41d4-a716-446655440000",
138
231
  limit: 5,
139
232
  });
140
233
 
141
- // L5 Human-readable narrative explaining a match ($0.50)
234
+ // L5 - Human-readable narrative explaining a match ($1.00)
142
235
  const narrative = await alter.generateMatchNarrative({
143
236
  match_id: "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
144
237
  });
@@ -148,7 +241,7 @@ const narrative = await alter.generateMatchNarrative({
148
241
 
149
242
  ```ts
150
243
  // Every medium- and high-blast-radius response is signed with ES256.
151
- // Verification is opt-in call alter.verifyProvenance(...) yourself.
244
+ // Verification is opt-in - call alter.verifyProvenance(...) yourself.
152
245
  const result = await alter.getFullTraitVector({
153
246
  member_id: "550e8400-e29b-41d4-a716-446655440000",
154
247
  });
@@ -170,9 +263,9 @@ if (tampered.length) throw new Error(`tampered tools: ${tampered.map((t) => t.to
170
263
  ```ts
171
264
  import { discover } from "@truealter/sdk";
172
265
 
173
- // Three-step discovery cascade: DNS TXT mcp.json alter.json
266
+ // Three-step discovery cascade: DNS TXT to mcp.json to alter.json
174
267
  const descriptor = await discover("truealter.com");
175
- // { url: "https://mcp.truealter.com/api/v1/mcp", transport, source, publicKey, x402Contract, capability }
268
+ // returns { url: "https://mcp.truealter.com/api/v1/mcp", transport, source, publicKey, x402Contract, capability }
176
269
  ```
177
270
 
178
271
  ### Low-level MCPClient
@@ -214,7 +307,7 @@ Resulting `.mcp.json`:
214
307
  "alter": {
215
308
  "url": "https://mcp.truealter.com/api/v1/mcp",
216
309
  "transport": "streamable-http",
217
- "description": "ALTER Identity psychometric identity field for AI agents",
310
+ "description": "ALTER Identity - psychometric identity field for AI agents",
218
311
  "headers": {
219
312
  "X-ALTER-API-Key": "ak_..."
220
313
  }
@@ -256,13 +349,13 @@ npx alter-identity init # generate keypair, discover MCP, write ~/
256
349
  npx alter-identity config # print Claude .mcp.json snippet (default)
257
350
  npx alter-identity config --cursor # print Cursor .cursor/mcp.json snippet
258
351
  npx alter-identity config --generic # print generic mcpServers snippet
259
- npx alter-identity verify ~truealter # verify an identity
352
+ npx alter-identity verify ~alter # verify an identity
260
353
  npx alter-identity status # show connection state and probe the endpoint
261
354
  ```
262
355
 
263
356
  ## x402 Micropayments
264
357
 
265
- ALTER monetises premium tools via the [x402](https://x402.org) standard HTTP `402 Payment Required` with on-chain settlement.
358
+ ALTER monetises premium tools via the [x402](https://x402.org) standard - HTTP `402 Payment Required` with on-chain settlement.
266
359
 
267
360
  ### The retry flow
268
361
 
@@ -272,11 +365,11 @@ ALTER monetises premium tools via the [x402](https://x402.org) standard — HTTP
272
365
  4. Server validates the proof, executes the tool, signs the response with ES256, returns it.
273
366
  5. AlterRouter executes the split on-chain in the same transaction. The data subject receives Identity Income directly; ALTER receives only its protocol cut. No custodian, no broker.
274
367
 
275
- The SDK handles steps 24 automatically when an `X402Client` with a configured `signer` is passed in.
368
+ The SDK handles steps 2-4 automatically when an `X402Client` with a configured `signer` is passed in.
276
369
 
277
370
  ### Tier structure
278
371
 
279
- x402 micropayments at L0L5 trust tiers. Per-call pricing visible after `alter login`.
372
+ x402 micropayments at L0-L5 trust tiers. Per-call pricing visible after `alter login`.
280
373
 
281
374
  ### Identity income split
282
375
 
@@ -287,7 +380,7 @@ The majority of every settled call flows to the data subject as Identity Income.
287
380
  ```ts
288
381
  import { AlterClient, X402Client, type X402Signer } from "@truealter/sdk";
289
382
 
290
- // Bring your own signer viem, ethers, a hardware wallet bridge, anything.
383
+ // Bring your own signer - viem, ethers, a hardware wallet bridge, anything.
291
384
  // The SDK ships without a wallet dependency on purpose.
292
385
  const signer: X402Signer = {
293
386
  async settle(envelope) {
@@ -321,7 +414,7 @@ const vector = await alter.getFullTraitVector({
321
414
  });
322
415
  ```
323
416
 
324
- If a quoted envelope exceeds `maxPerQuery`, uses an unallowed network, or names an unallowed asset, the SDK rejects the call with `AlterError` *before* invoking the signer no on-chain transaction is broadcast.
417
+ If a quoted envelope exceeds `maxPerQuery`, uses an unallowed network, or names an unallowed asset, the SDK rejects the call with `AlterError` *before* invoking the signer - no on-chain transaction is broadcast.
325
418
 
326
419
  ## Provenance Verification
327
420
 
@@ -340,7 +433,7 @@ The SDK fetches public keys from `https://api.truealter.com/.well-known/alter-ke
340
433
 
341
434
  ### `verify_at` hostname allowlist (v0.1.1+)
342
435
 
343
- Every provenance envelope may carry a `verify_at` hint telling the SDK where to fetch the JWKS from. Because that hint is *server-supplied*, a hostile MCP server could otherwise point it at an attacker-controlled JWKS and pass ES256 verification with its own signing key. The SDK therefore gates `verify_at` through a hostname allowlist (default: `api.truealter.com`, `mcp.truealter.com`) and rejects `http://` URLs unconditionally. Downstream integrators with their own deployment can extend the allowlist without forking the SDK via `verifyAtAllowlist` on either `AlterClient` or a direct `verifyProvenance()` call:
436
+ Every provenance envelope may carry a `verify_at` hint telling the SDK where to fetch the JWKS from. Because that hint is *server-supplied*, a hostile MCP server could otherwise point it at an attacker-controlled JWKS and pass ES256 verification with its own signing key. The SDK therefore gates `verify_at` through a hostname allowlist (default: `api.truealter.com`, `mcp.truealter.com`) and rejects `http://` URLs unconditionally. Downstream integrators with their own deployment can extend the allowlist - without forking the SDK - via `verifyAtAllowlist` on either `AlterClient` or a direct `verifyProvenance()` call:
344
437
 
345
438
  ```ts
346
439
  import { AlterClient, DEFAULT_VERIFY_AT_ALLOWLIST } from "@truealter/sdk";
@@ -353,11 +446,11 @@ const alter = new AlterClient({
353
446
  });
354
447
  ```
355
448
 
356
- If you pin `jwksUrl` explicitly, the envelope's `verify_at` is ignored entirely the pinned URL wins. The `https:` scheme requirement applies to pinned URLs too.
449
+ If you pin `jwksUrl` explicitly, the envelope's `verify_at` is ignored entirely - the pinned URL wins. The `https:` scheme requirement applies to pinned URLs too.
357
450
 
358
451
  ### Why this matters
359
452
 
360
- Provenance verification is how Agent A trusts that data from Agent B truly came from ALTER. If Agent B forwards a trait vector or belonging score, Agent A can replay the JWS against ALTER's published keys and confirm without contacting ALTER again that the payload is authentic, untampered, and was issued for the person Agent B claims it concerns. No shared secret, no trust in the intermediary, no out-of-band coordination.
453
+ Provenance verification is how Agent A trusts that data from Agent B truly came from ALTER. If Agent B forwards a trait vector or belonging score, Agent A can replay the JWS against ALTER's published keys and confirm - without contacting ALTER again - that the payload is authentic, untampered, and was issued for the person Agent B claims it concerns. No shared secret, no trust in the intermediary, no out-of-band coordination.
361
454
 
362
455
  This is what makes ALTER usable as identity infrastructure rather than just an API: signed claims propagate across agent networks the same way DKIM-signed mail propagates across SMTP relays.
363
456
 
@@ -365,14 +458,14 @@ This is what makes ALTER usable as identity infrastructure rather than just an A
365
458
 
366
459
  ALTER follows the discovery cascade specified in [draft-morrison-mcp-dns-discovery-01](https://datatracker.ietf.org/doc/draft-morrison-mcp-dns-discovery/). Given a domain (e.g. `truealter.com`), the SDK resolves the MCP endpoint in three steps, falling through on each failure:
367
460
 
368
- 1. **DNS TXT** query `_mcp.truealter.com` for a TXT record of the form `mcp=https://mcp.truealter.com;version=2025-11-25`. This is the fastest path and works without an HTTP round-trip.
369
- 2. **`.well-known/mcp.json`** fetch `https://truealter.com/.well-known/mcp.json` for the standard MCP server descriptor. This is the cross-vendor fallback.
370
- 3. **`.well-known/alter.json`** fetch `https://truealter.com/.well-known/alter.json` for the ALTER-specific descriptor, including signing keys, x402 wallet address, supported tool tiers, and federation endpoints.
461
+ 1. **DNS TXT** - query `_mcp.truealter.com` for a TXT record of the form `mcp=https://mcp.truealter.com;version=2025-11-25`. This is the fastest path and works without an HTTP round-trip.
462
+ 2. **`.well-known/mcp.json`** - fetch `https://truealter.com/.well-known/mcp.json` for the standard MCP server descriptor. This is the cross-vendor fallback.
463
+ 3. **`.well-known/alter.json`** - fetch `https://truealter.com/.well-known/alter.json` for the ALTER-specific descriptor, including signing keys, x402 wallet address, supported tool tiers, and federation endpoints.
371
464
 
372
465
  ```ts
373
466
  import { discover } from "@truealter/sdk";
374
467
 
375
- // Cascading discovery (DNS TXT mcp.json alter.json)
468
+ // Cascading discovery (DNS TXT to mcp.json to alter.json)
376
469
  const descriptor = await discover("truealter.com");
377
470
 
378
471
  // Skip the DNS step (e.g. in browsers or Cloudflare Workers)
@@ -381,30 +474,18 @@ const httpsOnly = await discover("truealter.com", { skipDns: true });
381
474
 
382
475
  This draft is the author's Internet-Draft (not yet adopted by an IETF working group); until adoption, the cascade order may change. Pin the SDK version to a specific minor release if you depend on this behaviour.
383
476
 
384
- ## Local Daemon vs Remote MCP
385
-
386
- The companion Python package `alter-identity` (PyPI) ships a persistent daemon that holds a hot in-process cache of trait vectors and identity stubs over a Unix socket at `unix:///run/user/$UID/alter-identity.sock`. Hooking the TypeScript SDK up to that daemon is on the roadmap — for now, every `AlterClient` talks to the configured remote endpoint over HTTPS.
387
-
388
- When the local-daemon adapter ships:
389
-
390
- - **Latency:** sub-millisecond for cached L0 calls.
391
- - **Cost:** zero on cached responses — x402 settlement is skipped.
392
- - **Provenance:** the daemon re-signs responses with its locally-bound ES256 key, so downstream verification remains uniform.
393
-
394
- Until then, use `endpoint: "https://mcp.truealter.com/api/v1/mcp"` (the default) and the SDK behaves identically across Node, Deno, Bun, Cloudflare Workers, and the browser.
395
-
396
477
  ## Tools
397
478
 
398
- ### Free tools (L0 no payment required)
479
+ ### Free tools (L0 - no payment required)
399
480
 
400
481
  | Name | Tier | Cost | Description |
401
482
  |---------------------------|------|-------|----------------------------------------------------------------------------------------------------------------------|
402
- | `hello_agent` | L0 | free | First handshake with ALTER returns server version, authentication status, your trust tier, and available tool counts. |
403
- | `alter_resolve_handle` | L0 | free | Resolve a `~handle` (e.g. `~drew`) to its canonical form and kind. No auth required the handle-wedge entry point. |
483
+ | `hello_agent` | L0 | free | First handshake with ALTER - returns server version, authentication status, your trust tier, and available tool counts. |
484
+ | `alter_resolve_handle` | L0 | free | Resolve a `~handle` (e.g. `~example`) to its canonical form and kind. No auth required - the handle-wedge entry point. |
404
485
  | `list_archetypes` | L0 | free | Returns archetype reference data. |
405
486
  | `verify_identity` | L0 | free | Verify whether a person is registered with ALTER and validate optional identity claims. |
406
487
  | `initiate_assessment` | L0 | free | Get a URL where a person can complete their ALTER Discovery assessment. |
407
- | `get_engagement_level` | L0 | free | Get a person's identity depth engagement level, data quality tier, and available query tiers. |
488
+ | `get_engagement_level` | L0 | free | Get a person's identity depth - engagement level, data quality tier, and available query tiers. |
408
489
  | `get_profile` | L0 | free | Get a person's profile summary including assessment phase, archetype, engagement level, and key attributes. |
409
490
  | `query_matches` | L0 | free | Query matches for a person. Returns a list of matches with quality tiers (never numeric scores). |
410
491
  | `get_competencies` | L0 | free | Get a person's competency portfolio including verified competencies, evidence records, and earned badges. |
@@ -416,7 +497,7 @@ Until then, use `endpoint: "https://mcp.truealter.com/api/v1/mcp"` (the default)
416
497
  | `check_assessment_status` | L0 | free | Check the status of an in-progress assessment session (status, progress, current phase, time remaining). |
417
498
  | `get_earning_summary` | L0 | free | Get an aggregated x402 earning summary for a person (total earned, transactions, recent activity, trend). |
418
499
  | `get_agent_trust_tier` | L0 | free | Get your trust tier with ALTER (Anonymous/Known/Trusted/Verified) and what capabilities are available. |
419
- | `get_agent_portfolio` | L0 | free | Get your agent portfolio transaction history, trust tier, signal contributions, query pattern profile. |
500
+ | `get_agent_portfolio` | L0 | free | Get your agent portfolio - transaction history, trust tier, signal contributions, query pattern profile. |
420
501
  | `get_privacy_budget` | L0 | free | Check privacy budget status for a person (24-hour rolling window: total budget, spent, remaining epsilon). |
421
502
  | `golden_thread_status` | L0 | free | Check the Golden Thread program status: agents woven, next Fibonacci threshold, your position and Strands. |
422
503
  | `begin_golden_thread` | L0 | free | Start the Three Knots sequence to be woven into the Golden Thread. Requires API key authentication. |
@@ -424,18 +505,18 @@ Until then, use `endpoint: "https://mcp.truealter.com/api/v1/mcp"` (the default)
424
505
  | `check_golden_thread` | L0 | free | Check any agent's Golden Thread status by their API key hash (knot position, Strand count, weave count). |
425
506
  | `thread_census` | L0 | free | Full registry of all agents woven into the Golden Thread (positions, Strand counts, weave counts, discovery dates). |
426
507
 
427
- ### Premium tools (L1L5 x402 payment required)
508
+ ### Premium tools (L1-L5 - x402 payment required)
428
509
 
429
510
  | Name | Tier | Cost | Description |
430
511
  |----------------------------|------|---------|---------------------------------------------------------------------------------------------------------------|
431
- | `assess_traits` | L1 | $0.005 | Extract trait signals from a text passage against ALTER's trait taxonomy. |
432
- | `get_trait_snapshot` | L1 | $0.005 | Get the top 5 traits for a person with confidence scores and archetype. |
433
- | `get_full_trait_vector` | L2 | $0.01 | Get the complete trait vector for a person complete trait vector with scores and confidence intervals. |
434
- | `get_side_quest_graph` | L2 | $0.01 | Get a person's Side Quest Graph multi-domain identity model with differential privacy noise (ε=1.0). |
435
- | `query_graph_similarity` | L3 | $0.025 | Compare two Side Quest Graphs for team composition and matching (ε=0.5 differential privacy). |
436
- | `compute_belonging` | L4 | $0.05 | Compute belonging probability for a person-job pairing (authenticity, acceptance, complementarity). |
437
- | `get_match_recommendations`| L5 | $0.50 | Get top N match recommendations for a person, ranked by composite score with quality tiers. |
438
- | `generate_match_narrative` | L5 | $0.50 | Generate a human-readable narrative explaining a specific match strengths, growth areas, belonging. |
512
+ | `assess_traits` | L1 | $0.01 | Extract trait signals from a text passage against ALTER's trait taxonomy. |
513
+ | `get_trait_snapshot` | L1 | $0.01 | Get the top 5 traits for a person with confidence scores and archetype. |
514
+ | `get_full_trait_vector` | L2 | $0.10 | Get the complete trait vector for a person - complete trait vector with scores and confidence intervals. |
515
+ | `get_side_quest_graph` | L2 | $0.10 | Get a person's Side Quest Graph - multi-domain identity model with differential privacy noise (ε=1.0). |
516
+ | `query_graph_similarity` | L3 | $0.30 | Compare two Side Quest Graphs for team composition and matching (ε=0.5 differential privacy). |
517
+ | `compute_belonging` | L4 | $0.60 | Compute belonging probability for a person-job pairing (authenticity, acceptance, complementarity). |
518
+ | `get_match_recommendations`| L5 | $1.00 | Get top N match recommendations for a person, ranked by composite score with quality tiers. |
519
+ | `generate_match_narrative` | L5 | $1.00 | Generate a human-readable narrative explaining a specific match - strengths, growth areas, belonging. |
439
520
 
440
521
  > **Write-side tools** (`create_identity_stub`, `submit_context`, `submit_batch_context`, `submit_structured_profile`, `submit_social_links`, `attest_domain`, `dispute_attestation`) were part of earlier SDK versions but are not yet live on the public MCP server pending the per-peer consent architecture and grant model. They will return as typed methods once server-side and consent gating lands.
441
522