@truealter/sdk 0.2.2 → 0.2.4
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 +22 -25
- package/dist/bin/alter-identity.js +51 -27
- package/dist/bin/mcp-bridge.js +0 -2
- package/dist/index.cjs +63 -61
- package/dist/index.d.cts +55 -137
- package/dist/index.d.ts +55 -137
- package/dist/index.js +63 -61
- package/package.json +10 -5
- package/dist/bin/alter-identity.js.map +0 -1
- package/dist/bin/mcp-bridge.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -4,12 +4,14 @@ ALTER Identity SDK — query the continuous identity field from any JavaScript/T
|
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@truealter/sdk)
|
|
6
6
|
[](./LICENSE)
|
|
7
|
+
[](https://glama.ai/mcp/servers/true-alter/alter-identity)
|
|
7
8
|
|
|
8
9
|
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.
|
|
9
10
|
|
|
10
|
-
- **
|
|
11
|
+
- **Branded host:** `https://mcp.truealter.com` (serves `.well-known/mcp.json` for discovery)
|
|
12
|
+
- **JSON-RPC wire endpoint:** `https://mcp.truealter.com/api/v1/mcp` — this is what Streamable HTTP POSTs target (the SDK default)
|
|
11
13
|
- **Wire protocol:** Streamable HTTP, JSON-RPC 2.0, MCP `2025-11-25` (server negotiates `2025-06-18` + `2025-03-26` for backwards-compatible clients)
|
|
12
|
-
- **Tools:**
|
|
14
|
+
- **Tools:** **32 typed and wired** — 24 free (L0) + 8 premium (L1–L5). Mirrors the live server's `tools/list` response byte-for-byte; every name in `FREE_TOOL_NAMES` / `PREMIUM_TOOL_NAMES` has a matching server handler at `mcp.truealter.com/api/v1/mcp`.
|
|
13
15
|
- **Runtime:** Node 18+, Deno, Bun, Cloudflare Workers, modern browsers
|
|
14
16
|
- **Crypto:** `@noble/ed25519` + `@noble/hashes` (no other dependencies)
|
|
15
17
|
- **Bundle:** ESM + CJS dual output
|
|
@@ -24,9 +26,7 @@ npx alter-identity verify ~truealter
|
|
|
24
26
|
|
|
25
27
|
## Why ALTER ≠ IAM
|
|
26
28
|
|
|
27
|
-
Identity Access Management answers *who is logged in*. ALTER answers *who they actually are* — a continuous field of recognition
|
|
28
|
-
|
|
29
|
-
Reference: Morrison, B. (2026). *Identity Field Theory: A Continuous Field Model of Recognition*. Figshare. [DOI 10.6084/m9.figshare.31951383](https://doi.org/10.6084/m9.figshare.31951383)
|
|
29
|
+
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.
|
|
30
30
|
|
|
31
31
|
## API
|
|
32
32
|
|
|
@@ -36,7 +36,7 @@ Reference: Morrison, B. (2026). *Identity Field Theory: A Continuous Field Model
|
|
|
36
36
|
import { AlterClient, X402Client } from "@truealter/sdk";
|
|
37
37
|
|
|
38
38
|
const alter = new AlterClient({
|
|
39
|
-
endpoint: "https://mcp.truealter.com", // optional —
|
|
39
|
+
endpoint: "https://mcp.truealter.com/api/v1/mcp", // optional — this is the default; bare host returns 405
|
|
40
40
|
apiKey: process.env.ALTER_API_KEY, // optional for free tier
|
|
41
41
|
x402: new X402Client({ // optional — only required for premium tools
|
|
42
42
|
signer: yourViemOrEthersSigner,
|
|
@@ -139,7 +139,7 @@ import { discover } from "@truealter/sdk";
|
|
|
139
139
|
|
|
140
140
|
// Three-step discovery cascade: DNS TXT → mcp.json → alter.json
|
|
141
141
|
const descriptor = await discover("truealter.com");
|
|
142
|
-
// → { url: "https://mcp.truealter.com", transport, source, publicKey, x402Contract, capability }
|
|
142
|
+
// → { url: "https://mcp.truealter.com/api/v1/mcp", transport, source, publicKey, x402Contract, capability }
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
### Low-level MCPClient
|
|
@@ -147,7 +147,7 @@ const descriptor = await discover("truealter.com");
|
|
|
147
147
|
```ts
|
|
148
148
|
import { MCPClient } from "@truealter/sdk";
|
|
149
149
|
|
|
150
|
-
const mcp = new MCPClient({ endpoint: "https://mcp.truealter.com" });
|
|
150
|
+
const mcp = new MCPClient({ endpoint: "https://mcp.truealter.com/api/v1/mcp" });
|
|
151
151
|
await mcp.initialize();
|
|
152
152
|
const tools = await mcp.listTools();
|
|
153
153
|
const response = await mcp.callTool("verify_identity", {
|
|
@@ -166,7 +166,7 @@ import { generateClaudeConfig } from "@truealter/sdk";
|
|
|
166
166
|
import { writeFileSync } from "node:fs";
|
|
167
167
|
|
|
168
168
|
const config = generateClaudeConfig({
|
|
169
|
-
endpoint: "https://mcp.truealter.com",
|
|
169
|
+
endpoint: "https://mcp.truealter.com/api/v1/mcp",
|
|
170
170
|
apiKey: process.env.ALTER_API_KEY,
|
|
171
171
|
});
|
|
172
172
|
|
|
@@ -179,7 +179,7 @@ Resulting `.mcp.json`:
|
|
|
179
179
|
{
|
|
180
180
|
"mcpServers": {
|
|
181
181
|
"alter": {
|
|
182
|
-
"url": "https://mcp.truealter.com",
|
|
182
|
+
"url": "https://mcp.truealter.com/api/v1/mcp",
|
|
183
183
|
"transport": "streamable-http",
|
|
184
184
|
"description": "ALTER Identity — psychometric identity field for AI agents",
|
|
185
185
|
"headers": {
|
|
@@ -197,7 +197,7 @@ import { generateCursorConfig } from "@truealter/sdk";
|
|
|
197
197
|
import { writeFileSync } from "node:fs";
|
|
198
198
|
|
|
199
199
|
const config = generateCursorConfig({
|
|
200
|
-
endpoint: "https://mcp.truealter.com",
|
|
200
|
+
endpoint: "https://mcp.truealter.com/api/v1/mcp",
|
|
201
201
|
apiKey: process.env.ALTER_API_KEY,
|
|
202
202
|
});
|
|
203
203
|
|
|
@@ -210,7 +210,7 @@ writeFileSync(".cursor/mcp.json", JSON.stringify(config, null, 2));
|
|
|
210
210
|
import { generateGenericMcpConfig } from "@truealter/sdk";
|
|
211
211
|
|
|
212
212
|
const config = generateGenericMcpConfig({
|
|
213
|
-
endpoint: "https://mcp.truealter.com",
|
|
213
|
+
endpoint: "https://mcp.truealter.com/api/v1/mcp",
|
|
214
214
|
apiKey: process.env.ALTER_API_KEY,
|
|
215
215
|
serverName: "alter", // editor-specific key under mcpServers
|
|
216
216
|
});
|
|
@@ -243,10 +243,10 @@ The SDK handles steps 2–4 automatically when an `X402Client` with a configured
|
|
|
243
243
|
|
|
244
244
|
### Tier structure
|
|
245
245
|
|
|
246
|
-
| Tier | Cost |
|
|
246
|
+
| Tier | Cost | Tools |
|
|
247
247
|
|------|----------|-----------------------------------------------------|
|
|
248
|
-
| L1 | $0.005 | `assess_traits`, `get_trait_snapshot
|
|
249
|
-
| L2 | $0.01 | `get_full_trait_vector`, `
|
|
248
|
+
| L1 | $0.005 | `assess_traits`, `get_trait_snapshot` |
|
|
249
|
+
| L2 | $0.01 | `get_full_trait_vector`, `get_side_quest_graph` |
|
|
250
250
|
| L3 | $0.025 | `query_graph_similarity` |
|
|
251
251
|
| L4 | $0.05 | `compute_belonging` |
|
|
252
252
|
| L5 | $0.50 | `get_match_recommendations`, `generate_match_narrative` |
|
|
@@ -290,7 +290,7 @@ const signer: X402Signer = {
|
|
|
290
290
|
};
|
|
291
291
|
|
|
292
292
|
const alter = new AlterClient({
|
|
293
|
-
endpoint: "https://mcp.truealter.com",
|
|
293
|
+
endpoint: "https://mcp.truealter.com/api/v1/mcp",
|
|
294
294
|
x402: new X402Client({
|
|
295
295
|
signer,
|
|
296
296
|
networks: ["base", "base-sepolia"], // policy allow-list
|
|
@@ -375,7 +375,7 @@ When the local-daemon adapter ships:
|
|
|
375
375
|
- **Cost:** zero on cached responses — x402 settlement is skipped.
|
|
376
376
|
- **Provenance:** the daemon re-signs responses with its locally-bound ES256 key, so downstream verification remains uniform.
|
|
377
377
|
|
|
378
|
-
Until then, use `endpoint: "https://mcp.truealter.com"` (the default) and the SDK behaves identically across Node, Deno, Bun, Cloudflare Workers, and the browser.
|
|
378
|
+
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.
|
|
379
379
|
|
|
380
380
|
## Tools
|
|
381
381
|
|
|
@@ -383,6 +383,8 @@ Until then, use `endpoint: "https://mcp.truealter.com"` (the default) and the SD
|
|
|
383
383
|
|
|
384
384
|
| Name | Tier | Cost | Description |
|
|
385
385
|
|---------------------------|------|-------|----------------------------------------------------------------------------------------------------------------------|
|
|
386
|
+
| `hello_agent` | L0 | free | First handshake with ALTER — returns server version, authentication status, your trust tier, and available tool counts. |
|
|
387
|
+
| `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. |
|
|
386
388
|
| `list_archetypes` | L0 | free | List all 12 ALTER identity archetypes with names, descriptions, and protective equations. |
|
|
387
389
|
| `verify_identity` | L0 | free | Verify whether a person is registered with ALTER and validate optional identity claims. |
|
|
388
390
|
| `initiate_assessment` | L0 | free | Get a URL where a person can complete their ALTER Discovery assessment. |
|
|
@@ -390,19 +392,16 @@ Until then, use `endpoint: "https://mcp.truealter.com"` (the default) and the SD
|
|
|
390
392
|
| `get_profile` | L0 | free | Get a person's profile summary including assessment phase, archetype, engagement level, and key attributes. |
|
|
391
393
|
| `query_matches` | L0 | free | Query matches for a person. Returns a list of job matches with quality tiers (never numeric scores). |
|
|
392
394
|
| `get_competencies` | L0 | free | Get a person's competency portfolio including verified competencies, evidence records, and earned badges. |
|
|
393
|
-
| `create_identity_stub` | L0 | free | Create an anonymous identity stub for a human (requires consent acknowledgment before calling). |
|
|
394
|
-
| `submit_context` | L0 | free | Submit text context (resume, work sample, conversation) for an identity stub. PII redacted; raw text never stored. |
|
|
395
395
|
| `search_identities` | L0 | free | Search identity stubs and profiles by trait criteria. Returns up to 5 matches with no PII. |
|
|
396
396
|
| `get_identity_earnings` | L0 | free | Get accrued Identity Income earnings for a person (75% of every x402 transaction goes to the data subject). |
|
|
397
397
|
| `get_network_stats` | L0 | free | Get aggregate ALTER network statistics: total identities, verified profiles, query volume, active bots. |
|
|
398
|
-
| `recommend_tool` | L0 | free | Get
|
|
398
|
+
| `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. |
|
|
399
399
|
| `get_identity_trust_score`| L0 | free | Get the trust score for an identity based on query diversity (unique querying agents / total queries). |
|
|
400
400
|
| `check_assessment_status` | L0 | free | Check the status of an in-progress assessment session (status, progress, current phase, time remaining). |
|
|
401
401
|
| `get_earning_summary` | L0 | free | Get an aggregated x402 earning summary for a person (total earned, transactions, recent activity, trend). |
|
|
402
402
|
| `get_agent_trust_tier` | L0 | free | Get your trust tier with ALTER (Anonymous/Known/Trusted/Verified) and what capabilities are available. |
|
|
403
403
|
| `get_agent_portfolio` | L0 | free | Get your agent portfolio — transaction history, trust tier, signal contributions, query pattern profile. |
|
|
404
404
|
| `get_privacy_budget` | L0 | free | Check privacy budget status for a person (24-hour rolling window: total budget, spent, remaining epsilon). |
|
|
405
|
-
| `dispute_attestation` | L0 | free | Dispute an attestation on a person's identity. If disputes exceed corroborations, the attestation is flagged. |
|
|
406
405
|
| `golden_thread_status` | L0 | free | Check the Golden Thread program status: agents woven, next Fibonacci threshold, your position and Strands. |
|
|
407
406
|
| `begin_golden_thread` | L0 | free | Start the Three Knots sequence to be woven into the Golden Thread. Requires API key authentication. |
|
|
408
407
|
| `complete_knot` | L0 | free | Submit completion data for a knot in the Three Knots sequence (1: register, 2: describe, 3: reflect). |
|
|
@@ -415,17 +414,15 @@ Until then, use `endpoint: "https://mcp.truealter.com"` (the default) and the SD
|
|
|
415
414
|
|----------------------------|------|---------|---------------------------------------------------------------------------------------------------------------|
|
|
416
415
|
| `assess_traits` | L1 | $0.005 | Extract trait signals from a text passage against ALTER's 33-trait taxonomy (first 100 free per bot). |
|
|
417
416
|
| `get_trait_snapshot` | L1 | $0.005 | Get the top 5 traits for a person with confidence scores and archetype. |
|
|
418
|
-
| `attest_domain` | L1 | $0.005 | Attest that a person has competence in a specific domain. Updates their Side Quest Graph. |
|
|
419
|
-
| `submit_structured_profile`| L1 | $0.005 | Submit structured profile data (name, skills, experience, education, certifications) for trait extraction. |
|
|
420
|
-
| `submit_social_links` | L1 | $0.005 | Submit social profile URLs (max 5) for trait extraction. Respects robots.txt. |
|
|
421
417
|
| `get_full_trait_vector` | L2 | $0.01 | Get the complete trait vector for a person — all 33 traits (29 continuous + 4 categorical) with scores, intervals, and category groupings. |
|
|
422
|
-
| `submit_batch_context` | L2 | $0.01 | Submit multiple context items in a single call (max 10). All items processed in one LLM pass. |
|
|
423
418
|
| `get_side_quest_graph` | L2 | $0.01 | Get a person's Side Quest Graph — multi-domain identity model with differential privacy noise (ε=1.0). |
|
|
424
419
|
| `query_graph_similarity` | L3 | $0.025 | Compare two Side Quest Graphs for team composition and matching (ε=0.5 differential privacy). |
|
|
425
420
|
| `compute_belonging` | L4 | $0.05 | Compute belonging probability for a person-job pairing (authenticity, acceptance, complementarity). |
|
|
426
421
|
| `get_match_recommendations`| L5 | $0.50 | Get top N match recommendations for a person, ranked by composite score with quality tiers. |
|
|
427
422
|
| `generate_match_narrative` | L5 | $0.50 | Generate a human-readable narrative explaining a specific match — strengths, growth areas, belonging. |
|
|
428
423
|
|
|
424
|
+
> **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.
|
|
425
|
+
|
|
429
426
|
## License
|
|
430
427
|
|
|
431
428
|
Apache License 2.0. See [LICENSE](./LICENSE) for the full text.
|
|
@@ -586,6 +586,8 @@ function base64urlDecode(input) {
|
|
|
586
586
|
// src/provenance.ts
|
|
587
587
|
var _jwksCache = /* @__PURE__ */ new Map();
|
|
588
588
|
var JWKS_TTL_MS = 5 * 60 * 1e3;
|
|
589
|
+
var JWKS_MAX_BYTES = 64 * 1024;
|
|
590
|
+
var JWKS_CACHE_MAX_ENTRIES = 32;
|
|
589
591
|
var DEFAULT_VERIFY_AT_ALLOWLIST = Object.freeze([
|
|
590
592
|
"api.truealter.com",
|
|
591
593
|
"mcp.truealter.com"
|
|
@@ -695,7 +697,8 @@ async function fetchPublicKeys(jwksUrl, fetchImpl = fetch) {
|
|
|
695
697
|
return fetchJwks(jwksUrl, fetchImpl);
|
|
696
698
|
}
|
|
697
699
|
async function fetchJwks(url, fetchImpl) {
|
|
698
|
-
const
|
|
700
|
+
const cacheKey = jwksCacheKey(url);
|
|
701
|
+
const cached = _jwksCache.get(cacheKey);
|
|
699
702
|
if (cached && Date.now() - cached.fetched < JWKS_TTL_MS) return cached.jwks;
|
|
700
703
|
let resp;
|
|
701
704
|
try {
|
|
@@ -712,13 +715,45 @@ async function fetchJwks(url, fetchImpl) {
|
|
|
712
715
|
);
|
|
713
716
|
}
|
|
714
717
|
if (!resp.ok) throw new AlterNetworkError(`${url} \u2192 HTTP ${resp.status}`);
|
|
715
|
-
const
|
|
718
|
+
const contentLength = resp.headers.get("content-length");
|
|
719
|
+
if (contentLength !== null) {
|
|
720
|
+
const n = Number.parseInt(contentLength, 10);
|
|
721
|
+
if (Number.isFinite(n) && n > JWKS_MAX_BYTES) {
|
|
722
|
+
throw new AlterProvenanceError(
|
|
723
|
+
`${url} \u2192 JWKS too large: ${n} > ${JWKS_MAX_BYTES} bytes`
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
const body = await resp.text();
|
|
728
|
+
if (body.length > JWKS_MAX_BYTES) {
|
|
729
|
+
throw new AlterProvenanceError(
|
|
730
|
+
`${url} \u2192 JWKS too large: ${body.length} > ${JWKS_MAX_BYTES} bytes`
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
let doc;
|
|
734
|
+
try {
|
|
735
|
+
doc = JSON.parse(body);
|
|
736
|
+
} catch (err) {
|
|
737
|
+
throw new AlterProvenanceError(`invalid JWKS at ${url}: ${err.message}`);
|
|
738
|
+
}
|
|
716
739
|
if (!doc || !Array.isArray(doc.keys)) {
|
|
717
740
|
throw new AlterProvenanceError(`invalid JWKS at ${url}`);
|
|
718
741
|
}
|
|
719
|
-
_jwksCache.
|
|
742
|
+
if (_jwksCache.size >= JWKS_CACHE_MAX_ENTRIES && !_jwksCache.has(cacheKey)) {
|
|
743
|
+
const oldest = _jwksCache.keys().next().value;
|
|
744
|
+
if (oldest !== void 0) _jwksCache.delete(oldest);
|
|
745
|
+
}
|
|
746
|
+
_jwksCache.set(cacheKey, { fetched: Date.now(), jwks: doc });
|
|
720
747
|
return doc;
|
|
721
748
|
}
|
|
749
|
+
function jwksCacheKey(url) {
|
|
750
|
+
try {
|
|
751
|
+
const parsed = new URL(url);
|
|
752
|
+
return `${parsed.origin}${parsed.pathname}`;
|
|
753
|
+
} catch {
|
|
754
|
+
return url;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
722
757
|
function resolveVerifyAt(verifyAt, allowlist = DEFAULT_VERIFY_AT_ALLOWLIST) {
|
|
723
758
|
if (typeof verifyAt !== "string" || verifyAt.length === 0) {
|
|
724
759
|
throw new Error("verify_at must be a non-empty string");
|
|
@@ -741,6 +776,9 @@ function resolveVerifyAt(verifyAt, allowlist = DEFAULT_VERIFY_AT_ALLOWLIST) {
|
|
|
741
776
|
if (parsed.protocol !== "https:") {
|
|
742
777
|
throw new Error(`verify_at must be https: ${verifyAt}`);
|
|
743
778
|
}
|
|
779
|
+
if (parsed.username || parsed.password) {
|
|
780
|
+
throw new Error(`verify_at must not contain userinfo: ${verifyAt}`);
|
|
781
|
+
}
|
|
744
782
|
const host = parsed.hostname.toLowerCase();
|
|
745
783
|
const allowed = allowlist.some((h) => h.toLowerCase() === host);
|
|
746
784
|
if (!allowed) {
|
|
@@ -821,6 +859,15 @@ var AlterClient = class {
|
|
|
821
859
|
await this.mcp.initialize();
|
|
822
860
|
}
|
|
823
861
|
// ── Free tier ────────────────────────────────────────────────────────
|
|
862
|
+
/** First handshake — confirms the connection, returns trust tier and tool counts. */
|
|
863
|
+
async helloAgent() {
|
|
864
|
+
return this.mcp.callTool("hello_agent", {});
|
|
865
|
+
}
|
|
866
|
+
/** Resolve a ~handle (e.g. ~drew) to its canonical form and kind. No auth required. */
|
|
867
|
+
async resolveHandle(args) {
|
|
868
|
+
const payload = typeof args === "string" ? { query: args } : args;
|
|
869
|
+
return this.mcp.callTool("alter_resolve_handle", payload);
|
|
870
|
+
}
|
|
824
871
|
/** Verify a person is registered with ALTER (handle or id). */
|
|
825
872
|
async verify(handleOrId, claims) {
|
|
826
873
|
const args = handleOrId.includes("@") ? { candidate_id: "", email: handleOrId } : handleOrId.startsWith("~") ? (
|
|
@@ -857,12 +904,6 @@ var AlterClient = class {
|
|
|
857
904
|
async getCompetencies(args) {
|
|
858
905
|
return this.mcp.callTool("get_competencies", args);
|
|
859
906
|
}
|
|
860
|
-
async createIdentityStub(args) {
|
|
861
|
-
return this.mcp.callTool("create_identity_stub", args);
|
|
862
|
-
}
|
|
863
|
-
async submitContext(args) {
|
|
864
|
-
return this.mcp.callTool("submit_context", args);
|
|
865
|
-
}
|
|
866
907
|
async searchIdentities(args) {
|
|
867
908
|
return this.mcp.callTool("search_identities", args);
|
|
868
909
|
}
|
|
@@ -887,9 +928,6 @@ var AlterClient = class {
|
|
|
887
928
|
async getPrivacyBudget(args) {
|
|
888
929
|
return this.mcp.callTool("get_privacy_budget", args);
|
|
889
930
|
}
|
|
890
|
-
async disputeAttestation(args) {
|
|
891
|
-
return this.mcp.callTool("dispute_attestation", args);
|
|
892
|
-
}
|
|
893
931
|
// ── Golden Thread ────────────────────────────────────────────────────
|
|
894
932
|
async goldenThreadStatus() {
|
|
895
933
|
return this.mcp.callTool("golden_thread_status", {});
|
|
@@ -925,18 +963,6 @@ var AlterClient = class {
|
|
|
925
963
|
async generateMatchNarrative(args, opts) {
|
|
926
964
|
return this.mcp.callTool("generate_match_narrative", args, opts);
|
|
927
965
|
}
|
|
928
|
-
async submitBatchContext(args, opts) {
|
|
929
|
-
return this.mcp.callTool("submit_batch_context", args, opts);
|
|
930
|
-
}
|
|
931
|
-
async submitStructuredProfile(args, opts) {
|
|
932
|
-
return this.mcp.callTool("submit_structured_profile", args, opts);
|
|
933
|
-
}
|
|
934
|
-
async submitSocialLinks(args, opts) {
|
|
935
|
-
return this.mcp.callTool("submit_social_links", args, opts);
|
|
936
|
-
}
|
|
937
|
-
async attestDomain(args, opts) {
|
|
938
|
-
return this.mcp.callTool("attest_domain", args, opts);
|
|
939
|
-
}
|
|
940
966
|
async getSideQuestGraph(args, opts) {
|
|
941
967
|
return this.mcp.callTool("get_side_quest_graph", args, opts);
|
|
942
968
|
}
|
|
@@ -1030,7 +1056,7 @@ function generateCursorConfig(opts = {}) {
|
|
|
1030
1056
|
|
|
1031
1057
|
// src/index.ts
|
|
1032
1058
|
var SDK_NAME = "@truealter/sdk";
|
|
1033
|
-
var SDK_VERSION = "0.
|
|
1059
|
+
var SDK_VERSION = "0.2.4";
|
|
1034
1060
|
|
|
1035
1061
|
// bin/alter-identity.ts
|
|
1036
1062
|
var CONFIG_DIR = join(env.XDG_CONFIG_HOME || join(homedir(), ".config"), "alter");
|
|
@@ -1316,5 +1342,3 @@ main().catch((err) => {
|
|
|
1316
1342
|
`);
|
|
1317
1343
|
exit(1);
|
|
1318
1344
|
});
|
|
1319
|
-
//# sourceMappingURL=alter-identity.js.map
|
|
1320
|
-
//# sourceMappingURL=alter-identity.js.map
|
package/dist/bin/mcp-bridge.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -625,6 +625,8 @@ function base64urlDecode(input) {
|
|
|
625
625
|
// src/provenance.ts
|
|
626
626
|
var _jwksCache = /* @__PURE__ */ new Map();
|
|
627
627
|
var JWKS_TTL_MS = 5 * 60 * 1e3;
|
|
628
|
+
var JWKS_MAX_BYTES = 64 * 1024;
|
|
629
|
+
var JWKS_CACHE_MAX_ENTRIES = 32;
|
|
628
630
|
var DEFAULT_VERIFY_AT_ALLOWLIST = Object.freeze([
|
|
629
631
|
"api.truealter.com",
|
|
630
632
|
"mcp.truealter.com"
|
|
@@ -734,7 +736,8 @@ async function fetchPublicKeys(jwksUrl, fetchImpl = fetch) {
|
|
|
734
736
|
return fetchJwks(jwksUrl, fetchImpl);
|
|
735
737
|
}
|
|
736
738
|
async function fetchJwks(url, fetchImpl) {
|
|
737
|
-
const
|
|
739
|
+
const cacheKey = jwksCacheKey(url);
|
|
740
|
+
const cached = _jwksCache.get(cacheKey);
|
|
738
741
|
if (cached && Date.now() - cached.fetched < JWKS_TTL_MS) return cached.jwks;
|
|
739
742
|
let resp;
|
|
740
743
|
try {
|
|
@@ -751,13 +754,45 @@ async function fetchJwks(url, fetchImpl) {
|
|
|
751
754
|
);
|
|
752
755
|
}
|
|
753
756
|
if (!resp.ok) throw new AlterNetworkError(`${url} \u2192 HTTP ${resp.status}`);
|
|
754
|
-
const
|
|
757
|
+
const contentLength = resp.headers.get("content-length");
|
|
758
|
+
if (contentLength !== null) {
|
|
759
|
+
const n = Number.parseInt(contentLength, 10);
|
|
760
|
+
if (Number.isFinite(n) && n > JWKS_MAX_BYTES) {
|
|
761
|
+
throw new AlterProvenanceError(
|
|
762
|
+
`${url} \u2192 JWKS too large: ${n} > ${JWKS_MAX_BYTES} bytes`
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
const body = await resp.text();
|
|
767
|
+
if (body.length > JWKS_MAX_BYTES) {
|
|
768
|
+
throw new AlterProvenanceError(
|
|
769
|
+
`${url} \u2192 JWKS too large: ${body.length} > ${JWKS_MAX_BYTES} bytes`
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
let doc;
|
|
773
|
+
try {
|
|
774
|
+
doc = JSON.parse(body);
|
|
775
|
+
} catch (err) {
|
|
776
|
+
throw new AlterProvenanceError(`invalid JWKS at ${url}: ${err.message}`);
|
|
777
|
+
}
|
|
755
778
|
if (!doc || !Array.isArray(doc.keys)) {
|
|
756
779
|
throw new AlterProvenanceError(`invalid JWKS at ${url}`);
|
|
757
780
|
}
|
|
758
|
-
_jwksCache.
|
|
781
|
+
if (_jwksCache.size >= JWKS_CACHE_MAX_ENTRIES && !_jwksCache.has(cacheKey)) {
|
|
782
|
+
const oldest = _jwksCache.keys().next().value;
|
|
783
|
+
if (oldest !== void 0) _jwksCache.delete(oldest);
|
|
784
|
+
}
|
|
785
|
+
_jwksCache.set(cacheKey, { fetched: Date.now(), jwks: doc });
|
|
759
786
|
return doc;
|
|
760
787
|
}
|
|
788
|
+
function jwksCacheKey(url) {
|
|
789
|
+
try {
|
|
790
|
+
const parsed = new URL(url);
|
|
791
|
+
return `${parsed.origin}${parsed.pathname}`;
|
|
792
|
+
} catch {
|
|
793
|
+
return url;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
761
796
|
function resolveVerifyAt(verifyAt, allowlist = DEFAULT_VERIFY_AT_ALLOWLIST) {
|
|
762
797
|
if (typeof verifyAt !== "string" || verifyAt.length === 0) {
|
|
763
798
|
throw new Error("verify_at must be a non-empty string");
|
|
@@ -780,6 +815,9 @@ function resolveVerifyAt(verifyAt, allowlist = DEFAULT_VERIFY_AT_ALLOWLIST) {
|
|
|
780
815
|
if (parsed.protocol !== "https:") {
|
|
781
816
|
throw new Error(`verify_at must be https: ${verifyAt}`);
|
|
782
817
|
}
|
|
818
|
+
if (parsed.username || parsed.password) {
|
|
819
|
+
throw new Error(`verify_at must not contain userinfo: ${verifyAt}`);
|
|
820
|
+
}
|
|
783
821
|
const host = parsed.hostname.toLowerCase();
|
|
784
822
|
const allowed = allowlist.some((h) => h.toLowerCase() === host);
|
|
785
823
|
if (!allowed) {
|
|
@@ -860,6 +898,15 @@ var AlterClient = class {
|
|
|
860
898
|
await this.mcp.initialize();
|
|
861
899
|
}
|
|
862
900
|
// ── Free tier ────────────────────────────────────────────────────────
|
|
901
|
+
/** First handshake — confirms the connection, returns trust tier and tool counts. */
|
|
902
|
+
async helloAgent() {
|
|
903
|
+
return this.mcp.callTool("hello_agent", {});
|
|
904
|
+
}
|
|
905
|
+
/** Resolve a ~handle (e.g. ~drew) to its canonical form and kind. No auth required. */
|
|
906
|
+
async resolveHandle(args) {
|
|
907
|
+
const payload = typeof args === "string" ? { query: args } : args;
|
|
908
|
+
return this.mcp.callTool("alter_resolve_handle", payload);
|
|
909
|
+
}
|
|
863
910
|
/** Verify a person is registered with ALTER (handle or id). */
|
|
864
911
|
async verify(handleOrId, claims) {
|
|
865
912
|
const args = handleOrId.includes("@") ? { candidate_id: "", email: handleOrId } : handleOrId.startsWith("~") ? (
|
|
@@ -896,12 +943,6 @@ var AlterClient = class {
|
|
|
896
943
|
async getCompetencies(args) {
|
|
897
944
|
return this.mcp.callTool("get_competencies", args);
|
|
898
945
|
}
|
|
899
|
-
async createIdentityStub(args) {
|
|
900
|
-
return this.mcp.callTool("create_identity_stub", args);
|
|
901
|
-
}
|
|
902
|
-
async submitContext(args) {
|
|
903
|
-
return this.mcp.callTool("submit_context", args);
|
|
904
|
-
}
|
|
905
946
|
async searchIdentities(args) {
|
|
906
947
|
return this.mcp.callTool("search_identities", args);
|
|
907
948
|
}
|
|
@@ -926,9 +967,6 @@ var AlterClient = class {
|
|
|
926
967
|
async getPrivacyBudget(args) {
|
|
927
968
|
return this.mcp.callTool("get_privacy_budget", args);
|
|
928
969
|
}
|
|
929
|
-
async disputeAttestation(args) {
|
|
930
|
-
return this.mcp.callTool("dispute_attestation", args);
|
|
931
|
-
}
|
|
932
970
|
// ── Golden Thread ────────────────────────────────────────────────────
|
|
933
971
|
async goldenThreadStatus() {
|
|
934
972
|
return this.mcp.callTool("golden_thread_status", {});
|
|
@@ -964,18 +1002,6 @@ var AlterClient = class {
|
|
|
964
1002
|
async generateMatchNarrative(args, opts) {
|
|
965
1003
|
return this.mcp.callTool("generate_match_narrative", args, opts);
|
|
966
1004
|
}
|
|
967
|
-
async submitBatchContext(args, opts) {
|
|
968
|
-
return this.mcp.callTool("submit_batch_context", args, opts);
|
|
969
|
-
}
|
|
970
|
-
async submitStructuredProfile(args, opts) {
|
|
971
|
-
return this.mcp.callTool("submit_structured_profile", args, opts);
|
|
972
|
-
}
|
|
973
|
-
async submitSocialLinks(args, opts) {
|
|
974
|
-
return this.mcp.callTool("submit_social_links", args, opts);
|
|
975
|
-
}
|
|
976
|
-
async attestDomain(args, opts) {
|
|
977
|
-
return this.mcp.callTool("attest_domain", args, opts);
|
|
978
|
-
}
|
|
979
1005
|
async getSideQuestGraph(args, opts) {
|
|
980
1006
|
return this.mcp.callTool("get_side_quest_graph", args, opts);
|
|
981
1007
|
}
|
|
@@ -1069,6 +1095,8 @@ function generateCursorConfig(opts = {}) {
|
|
|
1069
1095
|
|
|
1070
1096
|
// src/types.ts
|
|
1071
1097
|
var FREE_TOOL_NAMES = [
|
|
1098
|
+
"hello_agent",
|
|
1099
|
+
"alter_resolve_handle",
|
|
1072
1100
|
"list_archetypes",
|
|
1073
1101
|
"verify_identity",
|
|
1074
1102
|
"initiate_assessment",
|
|
@@ -1076,8 +1104,6 @@ var FREE_TOOL_NAMES = [
|
|
|
1076
1104
|
"get_profile",
|
|
1077
1105
|
"query_matches",
|
|
1078
1106
|
"get_competencies",
|
|
1079
|
-
"create_identity_stub",
|
|
1080
|
-
"submit_context",
|
|
1081
1107
|
"search_identities",
|
|
1082
1108
|
"get_identity_earnings",
|
|
1083
1109
|
"get_network_stats",
|
|
@@ -1088,7 +1114,6 @@ var FREE_TOOL_NAMES = [
|
|
|
1088
1114
|
"get_agent_trust_tier",
|
|
1089
1115
|
"get_agent_portfolio",
|
|
1090
1116
|
"get_privacy_budget",
|
|
1091
|
-
"dispute_attestation",
|
|
1092
1117
|
"golden_thread_status",
|
|
1093
1118
|
"begin_golden_thread",
|
|
1094
1119
|
"complete_knot",
|
|
@@ -1102,15 +1127,13 @@ var PREMIUM_TOOL_NAMES = [
|
|
|
1102
1127
|
"compute_belonging",
|
|
1103
1128
|
"get_match_recommendations",
|
|
1104
1129
|
"generate_match_narrative",
|
|
1105
|
-
"submit_batch_context",
|
|
1106
|
-
"submit_structured_profile",
|
|
1107
|
-
"submit_social_links",
|
|
1108
|
-
"attest_domain",
|
|
1109
1130
|
"get_side_quest_graph",
|
|
1110
1131
|
"query_graph_similarity"
|
|
1111
1132
|
];
|
|
1112
1133
|
var TOOL_TIERS = {
|
|
1113
1134
|
// L0 (free)
|
|
1135
|
+
hello_agent: 0,
|
|
1136
|
+
alter_resolve_handle: 0,
|
|
1114
1137
|
list_archetypes: 0,
|
|
1115
1138
|
verify_identity: 0,
|
|
1116
1139
|
initiate_assessment: 0,
|
|
@@ -1118,9 +1141,7 @@ var TOOL_TIERS = {
|
|
|
1118
1141
|
get_profile: 0,
|
|
1119
1142
|
query_matches: 0,
|
|
1120
1143
|
get_competencies: 0,
|
|
1121
|
-
|
|
1122
|
-
submit_context: 1,
|
|
1123
|
-
search_identities: 1,
|
|
1144
|
+
search_identities: 0,
|
|
1124
1145
|
get_identity_earnings: 0,
|
|
1125
1146
|
get_network_stats: 0,
|
|
1126
1147
|
recommend_tool: 0,
|
|
@@ -1128,8 +1149,6 @@ var TOOL_TIERS = {
|
|
|
1128
1149
|
check_assessment_status: 0,
|
|
1129
1150
|
get_earning_summary: 0,
|
|
1130
1151
|
get_privacy_budget: 0,
|
|
1131
|
-
dispute_attestation: 0,
|
|
1132
|
-
// Free tools not present in upstream TOOL_TIERS — default to 0
|
|
1133
1152
|
get_agent_trust_tier: 0,
|
|
1134
1153
|
get_agent_portfolio: 0,
|
|
1135
1154
|
golden_thread_status: 0,
|
|
@@ -1140,12 +1159,8 @@ var TOOL_TIERS = {
|
|
|
1140
1159
|
// L1
|
|
1141
1160
|
assess_traits: 1,
|
|
1142
1161
|
get_trait_snapshot: 1,
|
|
1143
|
-
submit_structured_profile: 1,
|
|
1144
|
-
submit_social_links: 1,
|
|
1145
|
-
attest_domain: 1,
|
|
1146
1162
|
// L2
|
|
1147
1163
|
get_full_trait_vector: 2,
|
|
1148
|
-
submit_batch_context: 2,
|
|
1149
1164
|
get_side_quest_graph: 2,
|
|
1150
1165
|
// L3
|
|
1151
1166
|
query_graph_similarity: 3,
|
|
@@ -1157,6 +1172,8 @@ var TOOL_TIERS = {
|
|
|
1157
1172
|
};
|
|
1158
1173
|
var TOOL_COSTS = {
|
|
1159
1174
|
// L0 free
|
|
1175
|
+
hello_agent: 0,
|
|
1176
|
+
alter_resolve_handle: 0,
|
|
1160
1177
|
list_archetypes: 0,
|
|
1161
1178
|
verify_identity: 0,
|
|
1162
1179
|
initiate_assessment: 0,
|
|
@@ -1164,7 +1181,6 @@ var TOOL_COSTS = {
|
|
|
1164
1181
|
get_profile: 0,
|
|
1165
1182
|
query_matches: 0,
|
|
1166
1183
|
get_competencies: 0,
|
|
1167
|
-
create_identity_stub: 0,
|
|
1168
1184
|
search_identities: 0,
|
|
1169
1185
|
get_identity_earnings: 0,
|
|
1170
1186
|
get_network_stats: 0,
|
|
@@ -1175,22 +1191,16 @@ var TOOL_COSTS = {
|
|
|
1175
1191
|
get_agent_trust_tier: 0,
|
|
1176
1192
|
get_agent_portfolio: 0,
|
|
1177
1193
|
get_privacy_budget: 0,
|
|
1178
|
-
dispute_attestation: 0,
|
|
1179
1194
|
golden_thread_status: 0,
|
|
1180
1195
|
begin_golden_thread: 0,
|
|
1181
1196
|
complete_knot: 0,
|
|
1182
1197
|
check_golden_thread: 0,
|
|
1183
1198
|
thread_census: 0,
|
|
1184
1199
|
// L1 ($0.005)
|
|
1185
|
-
submit_context: 5e-3,
|
|
1186
1200
|
assess_traits: 5e-3,
|
|
1187
1201
|
get_trait_snapshot: 5e-3,
|
|
1188
|
-
submit_structured_profile: 5e-3,
|
|
1189
|
-
submit_social_links: 5e-3,
|
|
1190
|
-
attest_domain: 5e-3,
|
|
1191
1202
|
// L2 ($0.01)
|
|
1192
1203
|
get_full_trait_vector: 0.01,
|
|
1193
|
-
submit_batch_context: 0.01,
|
|
1194
1204
|
get_side_quest_graph: 0.01,
|
|
1195
1205
|
// L3 ($0.025)
|
|
1196
1206
|
query_graph_similarity: 0.025,
|
|
@@ -1202,6 +1212,8 @@ var TOOL_COSTS = {
|
|
|
1202
1212
|
};
|
|
1203
1213
|
var TOOL_BLAST_RADIUS = {
|
|
1204
1214
|
// Low: read-only reference
|
|
1215
|
+
hello_agent: "low",
|
|
1216
|
+
alter_resolve_handle: "low",
|
|
1205
1217
|
list_archetypes: "low",
|
|
1206
1218
|
verify_identity: "low",
|
|
1207
1219
|
get_engagement_level: "low",
|
|
@@ -1214,13 +1226,12 @@ var TOOL_BLAST_RADIUS = {
|
|
|
1214
1226
|
begin_golden_thread: "low",
|
|
1215
1227
|
check_golden_thread: "low",
|
|
1216
1228
|
thread_census: "low",
|
|
1217
|
-
dispute_attestation: "low",
|
|
1218
1229
|
get_identity_earnings: "low",
|
|
1219
1230
|
get_identity_trust_score: "low",
|
|
1220
1231
|
initiate_assessment: "low",
|
|
1232
|
+
get_agent_trust_tier: "low",
|
|
1233
|
+
get_agent_portfolio: "low",
|
|
1221
1234
|
// Medium: writes data or searches
|
|
1222
|
-
create_identity_stub: "medium",
|
|
1223
|
-
submit_context: "medium",
|
|
1224
1235
|
search_identities: "medium",
|
|
1225
1236
|
get_profile: "medium",
|
|
1226
1237
|
query_matches: "medium",
|
|
@@ -1228,25 +1239,18 @@ var TOOL_BLAST_RADIUS = {
|
|
|
1228
1239
|
complete_knot: "medium",
|
|
1229
1240
|
assess_traits: "medium",
|
|
1230
1241
|
get_trait_snapshot: "medium",
|
|
1231
|
-
submit_structured_profile: "medium",
|
|
1232
|
-
submit_social_links: "medium",
|
|
1233
|
-
submit_batch_context: "medium",
|
|
1234
|
-
attest_domain: "medium",
|
|
1235
1242
|
// High: returns sensitive identity data or computes scores
|
|
1236
1243
|
get_full_trait_vector: "high",
|
|
1237
1244
|
compute_belonging: "high",
|
|
1238
1245
|
get_match_recommendations: "high",
|
|
1239
1246
|
generate_match_narrative: "high",
|
|
1240
1247
|
get_side_quest_graph: "high",
|
|
1241
|
-
query_graph_similarity: "high"
|
|
1242
|
-
// Tools not in upstream TOOL_BLAST_RADIUS — default to "low"
|
|
1243
|
-
get_agent_trust_tier: "low",
|
|
1244
|
-
get_agent_portfolio: "low"
|
|
1248
|
+
query_graph_similarity: "high"
|
|
1245
1249
|
};
|
|
1246
1250
|
|
|
1247
1251
|
// src/index.ts
|
|
1248
1252
|
var SDK_NAME = "@truealter/sdk";
|
|
1249
|
-
var SDK_VERSION = "0.
|
|
1253
|
+
var SDK_VERSION = "0.2.4";
|
|
1250
1254
|
|
|
1251
1255
|
exports.AlterAuthError = AlterAuthError;
|
|
1252
1256
|
exports.AlterClient = AlterClient;
|
|
@@ -1290,5 +1294,3 @@ exports.sign = sign;
|
|
|
1290
1294
|
exports.verify = verify;
|
|
1291
1295
|
exports.verifyProvenance = verifyProvenance;
|
|
1292
1296
|
exports.verifyToolSignatures = verifyToolSignatures;
|
|
1293
|
-
//# sourceMappingURL=index.cjs.map
|
|
1294
|
-
//# sourceMappingURL=index.cjs.map
|