@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 +161 -80
- package/dist/bin/alter-identity.js +532 -45
- package/dist/bin/mcp-bridge.js +56 -5
- package/dist/index.cjs +667 -60
- package/dist/index.d.cts +533 -144
- package/dist/index.d.ts +533 -144
- package/dist/index.js +645 -62
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @truealter/sdk
|
|
2
2
|
|
|
3
|
-
ALTER Identity SDK
|
|
3
|
+
ALTER Identity SDK - query the continuous identity field from any JavaScript/TypeScript environment.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@truealter/sdk)
|
|
6
6
|
[](./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`
|
|
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:** **
|
|
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 ~
|
|
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
|
|
34
|
-
per-invocation signing
|
|
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
|
|
38
|
-
carries the provenance envelope end-to-end. Bridge signing
|
|
39
|
-
|
|
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).
|
|
45
|
-
is
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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*
|
|
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
|
|
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
|
|
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
|
-
###
|
|
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("~
|
|
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
|
|
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
|
|
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 (L1
|
|
208
|
+
### Premium tier (L1-L5 - x402 payment required)
|
|
116
209
|
|
|
117
210
|
```ts
|
|
118
|
-
// L1
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
266
|
+
// Three-step discovery cascade: DNS TXT to mcp.json to alter.json
|
|
174
267
|
const descriptor = await discover("truealter.com");
|
|
175
|
-
//
|
|
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
|
|
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 ~
|
|
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
|
|
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 2
|
|
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 L0
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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**
|
|
369
|
-
2. **`.well-known/mcp.json`**
|
|
370
|
-
3. **`.well-known/alter.json`**
|
|
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
|
|
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
|
|
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
|
|
403
|
-
| `alter_resolve_handle` | L0 | free | Resolve a `~handle` (e.g. `~
|
|
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
|
|
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
|
|
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 (L1
|
|
508
|
+
### Premium tools (L1-L5 - x402 payment required)
|
|
428
509
|
|
|
429
510
|
| Name | Tier | Cost | Description |
|
|
430
511
|
|----------------------------|------|---------|---------------------------------------------------------------------------------------------------------------|
|
|
431
|
-
| `assess_traits` | L1 | $0.
|
|
432
|
-
| `get_trait_snapshot` | L1 | $0.
|
|
433
|
-
| `get_full_trait_vector` | L2 | $0.
|
|
434
|
-
| `get_side_quest_graph` | L2 | $0.
|
|
435
|
-
| `query_graph_similarity` | L3 | $0.
|
|
436
|
-
| `compute_belonging` | L4 | $0.
|
|
437
|
-
| `get_match_recommendations`| L5 | $
|
|
438
|
-
| `generate_match_narrative` | L5 | $
|
|
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
|
|