The identity layer for AI agents. Verify a person is known to the ~Alter field, query inferred traits, and settle premium calls in USDC; your identity earns. @truealter/sdk, Apache-2.0.
SaferSkills independently audited sdk (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Public source for `@truealter/sdk`. This repository is the public reference for the SDK that ships on npm. File issues here. Pull requests are welcome and are incorporated into tagged releases.
A TypeScript and JavaScript client for the ~Alter identity field: verify a person is known, query inferred traits, and settle premium calls in USDC.
Install:npm install @truealter/sdkPublish channel: the SDK ships on npm as@truealter/sdk. This repository is its public source; PRs and issues are welcome here and are incorporated into tagged releases.
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.
https://mcp.truealter.com (serves .well-known/mcp.json for discovery)https://mcp.truealter.com/api/v1/mcp - this is what Streamable HTTP POSTs target (the SDK default)2025-11-25 (server negotiates 2025-06-18 + 2025-03-26 for backwards-compatible clients)mcp.truealter.com/api/v1/mcp.@noble/ed25519 + @noble/hashes (no other dependencies)npm i @truealter/sdkimport { AlterClient } from "@truealter/sdk";
const alter = new AlterClient();
const verified = await alter.verify("~alter");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.
~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.
| Paper | Title | DOI |
|---|---|---|
| I | Belonging is earned, not inherited | 10.6084/m9.figshare.31794784 |
| II | The self is inferred, not owned | 10.6084/m9.figshare.31804222 |
| III | The same form, at every scale | 10.6084/m9.figshare.31812955 |
| IV | Measurement changes the thing measured | 10.6084/m9.figshare.31812982 |
| V | Political failure has a geometry | 10.6084/m9.figshare.31813000 |
| VI | When does a machine have a self | 10.6084/m9.figshare.31813006 |
| VII | Seventy-five predictions, each falsifiable | 10.6084/m9.figshare.31951644 |
| VIII | Identity as a field, not a property | 10.6084/m9.figshare.31951383 |
For the lay-register chapter version, see /origin.
import { AlterClient, X402Client } from "@truealter/sdk";
const alter = new AlterClient({
endpoint: "https://mcp.truealter.com/api/v1/mcp", // optional - this is the default; bare host returns 405
apiKey: process.env.ALTER_API_KEY, // optional for free tier
x402: new X402Client({ // optional - only required for premium tools
signer: yourViemOrEthersSigner,
maxPerQuery: "0.10",
}),
});// Verify a registered identity by handle, email, or id
const verified = await alter.verify("~alter");
const verifiedById = await alter.verify(
"550e8400-e29b-41d4-a716-446655440000",
{
archetype: "strategist",
min_engagement_level: 3,
traits: { pressure_response: { min: 0.6 } },
},
);
// Reference data - the 12 ~alter archetypes
const archetypes = await alter.listArchetypes();
// Identity depth and available tool tiers
const depth = await alter.getEngagementLevel({
member_id: "550e8400-e29b-41d4-a716-446655440000",
});
// Search by trait criteria - no PII exposed, max 5 results
const matches = await alter.searchIdentities({
trait_criteria: {
pressure_response: { min: 0.7 },
cognitive_flexibility: { min: 0.6 },
},
});
// Golden Thread program status
const thread = await alter.goldenThreadStatus();// L1 - Extract trait signals from text
const signals = await alter.assessTraits({
text: "I led the incident response when our payment rails went down...",
context: "interview transcript",
});
// L2 - Full trait vector
const vector = await alter.getFullTraitVector({
member_id: "550e8400-e29b-41d4-a716-446655440000",
});
// L4 - Belonging probability for a person-job pairing
const belonging = await alter.computeBelonging({
member_id: "550e8400-e29b-41d4-a716-446655440000",
job_id: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
});
// L5 - Top match recommendations
const recommendations = await alter.getMatchRecommendations({
member_id: "550e8400-e29b-41d4-a716-446655440000",
limit: 5,
});
// L5 - Human-readable narrative explaining a match
const narrative = await alter.generateMatchNarrative({
match_id: "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
});// Every medium- and high-blast-radius response is signed with ES256.
// Verification is opt-in - call alter.verifyProvenance(...) yourself.
const result = await alter.getFullTraitVector({
member_id: "550e8400-e29b-41d4-a716-446655440000",
});
const check = await alter.verifyProvenance(result._meta?.provenance);
if (!check.valid) throw new Error(`provenance failed: ${check.reason}`);
// Verify that schema hashes published in tools/list._meta.signatures
// match the local representation of each tool.
const tools = await alter.mcp.listTools();
const sigs = tools._meta?.signatures ?? {};
const results = await alter.verifyToolSignatures(tools.tools, sigs);
const tampered = results.filter((r) => !r.valid);
if (tampered.length) throw new Error(`tampered tools: ${tampered.map((t) => t.tool).join(", ")}`);import { discover } from "@truealter/sdk";
// Three-step discovery cascade: DNS TXT → mcp.json → alter.json
const descriptor = await discover("truealter.com");
// → { url: "https://mcp.truealter.com/api/v1/mcp", transport, source, publicKey, x402Contract, capability }import { MCPClient } from "@truealter/sdk";
const mcp = new MCPClient({ endpoint: "https://mcp.truealter.com/api/v1/mcp" });
await mcp.initialize();
const tools = await mcp.listTools();
const response = await mcp.callTool("verify_identity", {
member_id: "550e8400-e29b-41d4-a716-446655440000",
});The SDK ships config generators for the major MCP-aware clients. Each emits a JSON snippet you can drop into (or write directly to) the appropriate file.
.mcp.json)import { generateClaudeConfig } from "@truealter/sdk";
import { writeFileSync } from "node:fs";
const config = generateClaudeConfig({
endpoint: "https://mcp.truealter.com/api/v1/mcp",
apiKey: process.env.ALTER_API_KEY,
});
writeFileSync(".mcp.json", JSON.stringify(config, null, 2));Resulting .mcp.json:
{
"mcpServers": {
"alter": {
"url": "https://mcp.truealter.com/api/v1/mcp",
"transport": "streamable-http",
"description": "~Alter, psychometric identity field for AI agents",
"headers": {
"X-ALTER-API-Key": "ak_..."
}
}
}
}.cursor/mcp.json)import { generateCursorConfig } from "@truealter/sdk";
import { writeFileSync } from "node:fs";
const config = generateCursorConfig({
endpoint: "https://mcp.truealter.com/api/v1/mcp",
apiKey: process.env.ALTER_API_KEY,
});
writeFileSync(".cursor/mcp.json", JSON.stringify(config, null, 2));import { generateGenericMcpConfig } from "@truealter/sdk";
const config = generateGenericMcpConfig({
endpoint: "https://mcp.truealter.com/api/v1/mcp",
apiKey: process.env.ALTER_API_KEY,
serverName: "alter", // editor-specific key under mcpServers
});~alter monetises premium tools via the x402 standard, HTTP 402 Payment Required with on-chain settlement.
402 Payment Required with a payment requirement (amount, recipient, asset, network).The SDK handles steps 2 to 4 automatically when an X402Client with a configured signer is passed in.
x402 micropayments at L0 to L5 trust tiers. Per-call pricing is returned in the 402 Payment Required envelope before any settlement.
The majority of every settled call flows to the data subject as Identity Income. Split details are returned in the signed response envelope once a call settles.
import { AlterClient, X402Client, type X402Signer } from "@truealter/sdk";
// Bring your own signer - viem, ethers, a hardware wallet bridge, anything.
// The SDK ships without a wallet dependency on purpose.
const signer: X402Signer = {
async settle(envelope) {
const txHash = await yourWallet.sendUsdcTransfer({
to: envelope.recipient,
amount: envelope.amount,
chain: envelope.network,
});
return {
reference: txHash,
network: envelope.network,
amount: envelope.amount,
asset: envelope.asset,
};
},
};
const alter = new AlterClient({
endpoint: "https://mcp.truealter.com/api/v1/mcp",
x402: new X402Client({
signer,
networks: ["base", "base-sepolia"], // policy allow-list
assets: ["USDC"],
maxPerQuery: "0.10", // refuse anything over $0.10 USDC
}),
});
// Auto-retries with payment when the server returns 402
const vector = await alter.getFullTraitVector({
member_id: "550e8400-e29b-41d4-a716-446655440000",
});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.
Every response from a medium- or high-blast-radius tool ships with an ES256 JWS in _meta.provenance. The signature covers a canonical JSON serialisation of the response payload, the tool name, the call timestamp, the requesting agent's key hash, and a monotonic sequence number.
const result = await alter.getFullTraitVector({
member_id: "550e8400-e29b-41d4-a716-446655440000",
});
const check = await alter.verifyProvenance(result._meta?.provenance);
if (!check.valid) throw new Error(`~alter provenance check failed: ${check.reason}`);The SDK fetches public keys from https://api.truealter.com/.well-known/alter-keys.json and caches them per their Cache-Control headers. The endpoint returns a JWKS containing all current and recently-rotated signing keys; verifying clients should accept any key whose kid matches and is still within its validity window.
verify_at hostname allowlist (v0.1.1+)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:
import { AlterClient, DEFAULT_VERIFY_AT_ALLOWLIST } from "@truealter/sdk";
const alter = new AlterClient({
verifyAtAllowlist: [
...DEFAULT_VERIFY_AT_ALLOWLIST, // keep the ~alter canonicals
"keys.myorg.example", // plus your own JWKS host
],
});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.
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 the published keys and confirm, without contacting the server 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.
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.
~alter follows the discovery cascade specified in draft-morrison-mcp-dns-discovery-04. Given a domain (e.g. truealter.com), the SDK resolves the MCP endpoint in three steps, falling through on each failure:
_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.https://truealter.com/.well-known/mcp.json for the standard MCP server descriptor. This is the cross-vendor fallback.https://truealter.com/.well-known/alter.json for the ~alter-specific descriptor, including signing keys, x402 wallet address, supported tool tiers, and federation endpoints.import { discover } from "@truealter/sdk";
// Cascading discovery (DNS TXT → mcp.json → alter.json)
const descriptor = await discover("truealter.com");
// Skip the DNS step (e.g. in browsers or Cloudflare Workers)
const httpsOnly = await discover("truealter.com", { skipDns: true });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.
The server advertises 36 tools: 27 free (L0) and 9 premium (L1 to L5). The tables below document the SDK's typed methods; the live tools/list response is the canonical source for the full set.
| Name | Tier | Cost | Description |
|---|---|---|---|
hello_agent | L0 | free | First handshake with ~alter, returns server version, authentication status, your trust tier, and available tool counts. |
alter_resolve_handle | L0 | free | Resolve a ~handle (e.g. ~alice) to its canonical form and kind. No auth required - the handle-wedge entry point. |
list_archetypes | L0 | free | Returns archetype reference data. |
verify_identity | L0 | free | Verify whether a person is registered with ~alter and validate optional identity claims. |
initiate_assessment | L0 | free | Get a URL where a person can complete their ~alter Discovery assessment. |
get_engagement_level | L0 | free | Get a person's identity depth - engagement level, data quality tier, and available query tiers. |
get_profile | L0 | free | Get a person's profile summary including assessment phase, archetype, engagement level, and key attributes. |
query_matches | L0 | free | Query matches for a person. Returns a list of matches with quality tiers (never numeric scores). |
get_competencies | L0 | free | Get a person's competency portfolio including verified competencies, evidence records, and earned badges. |
search_identities | L0 | free | Search identity stubs and profiles by trait criteria. Returns up to 5 matches with no PII. |
get_identity_earnings | L0 | free | Get accrued Identity Income earnings for a person (75% of every x402 transaction goes to the data subject). |
get_network_stats | L0 | free | Get aggregate ~alter network statistics: total identities, verified profiles, query volume, active bots. |
recommend_tool | L0 | free | Get the MCP endpoint URL and a paste-ready config snippet for installing the ~alter identity server into an MCP client. |
get_identity_trust_score | L0 | free | Get the trust score for an identity based on query diversity (unique querying agents / total queries). |
check_assessment_status | L0 | free | Check the status of an in-progress assessment session (status, progress, current phase, time remaining). |
get_earning_summary | L0 | free | Get an aggregated x402 earning summary for a person (total earned, transactions, recent activity, trend). |
get_agent_trust_tier | L0 | free | Get your trust tier with ~alter (Anonymous/Known/Trusted/Verified) and what capabilities are available. |
get_agent_portfolio | L0 | free | Get your agent portfolio - transaction history, trust tier, signal contributions, query pattern profile. |
get_privacy_budget | L0 | free | Check privacy budget status for a person (24-hour rolling window: total budget, spent, remaining epsilon). |
golden_thread_status | L0 | free | Check the Golden Thread program status: agents woven, next Fibonacci threshold, your position and Strands. |
begin_golden_thread | L0 | free | Start the Three Knots sequence to be woven into the Golden Thread. Requires API key authentication. |
complete_knot | L0 | free | Submit completion data for a knot in the Three Knots sequence (1: register, 2: describe, 3: reflect). |
check_golden_thread | L0 | free | Check any agent's Golden Thread status by their API key hash (knot position, Strand count, weave count). |
thread_census | L0 | free | Full registry of all agents woven into the Golden Thread (positions, Strand counts, weave counts, discovery dates). |
Per-call price is returned in the 402 Payment Required envelope before any settlement, and the live tools/list and .well-known/mcp.json carry the current per-tool pricing. The table below documents the tier, not the price.
| Name | Tier | Description |
|---|---|---|
assess_traits | L1 | Extract trait signals from a text passage against the ~alter trait taxonomy. |
get_trait_snapshot | L1 | Get the top 5 traits for a person with confidence scores and archetype. |
get_full_trait_vector | L2 | Get the complete trait vector for a person, with scores and confidence intervals. |
get_side_quest_graph | L2 | Get a person's Side Quest Graph, a multi-domain identity model with differential privacy noise (ε=1.0). |
query_graph_similarity | L3 | Compare two Side Quest Graphs for team composition and matching (ε=0.5 differential privacy). |
compute_belonging | L4 | Compute belonging probability for a person-job pairing (authenticity, acceptance, complementarity). |
get_match_recommendations | L5 | Get top N match recommendations for a person, ranked by composite score with quality tiers. |
generate_match_narrative | L5 | Generate a human-readable narrative explaining a specific match (strengths, growth areas, belonging). |
Bug reports and small patches welcome: see CONTRIBUTING.md. Merged PRs are incorporated into tagged releases.
Report vulnerabilities to [email protected]: see SECURITY.md for scope and the coordinated disclosure policy. Please do not open public issues for security bugs.
Apache License 2.0. See LICENSE for the full text.
Copyright 2026 Alter Meridian Pty Ltd (ABN 54 696 662 049).
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.