agent-authority 0.1.0

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.
Files changed (85) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/LICENSE +21 -0
  3. package/QUICKSTART.md +91 -0
  4. package/README.md +553 -0
  5. package/dist/a2a.d.ts +73 -0
  6. package/dist/a2a.d.ts.map +1 -0
  7. package/dist/a2a.js +117 -0
  8. package/dist/a2a.js.map +1 -0
  9. package/dist/audit.d.ts +12 -0
  10. package/dist/audit.d.ts.map +1 -0
  11. package/dist/audit.js +52 -0
  12. package/dist/audit.js.map +1 -0
  13. package/dist/behalf.d.ts +173 -0
  14. package/dist/behalf.d.ts.map +1 -0
  15. package/dist/behalf.js +475 -0
  16. package/dist/behalf.js.map +1 -0
  17. package/dist/capability.d.ts +56 -0
  18. package/dist/capability.d.ts.map +1 -0
  19. package/dist/capability.js +176 -0
  20. package/dist/capability.js.map +1 -0
  21. package/dist/cli.d.ts +3 -0
  22. package/dist/cli.d.ts.map +1 -0
  23. package/dist/cli.js +273 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/control-plane.d.ts +57 -0
  26. package/dist/control-plane.d.ts.map +1 -0
  27. package/dist/control-plane.js +332 -0
  28. package/dist/control-plane.js.map +1 -0
  29. package/dist/crypto.d.ts +68 -0
  30. package/dist/crypto.d.ts.map +1 -0
  31. package/dist/crypto.js +105 -0
  32. package/dist/crypto.js.map +1 -0
  33. package/dist/errors.d.ts +25 -0
  34. package/dist/errors.d.ts.map +1 -0
  35. package/dist/errors.js +40 -0
  36. package/dist/errors.js.map +1 -0
  37. package/dist/index.d.ts +35 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +34 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/lint.d.ts +17 -0
  42. package/dist/lint.d.ts.map +1 -0
  43. package/dist/lint.js +75 -0
  44. package/dist/lint.js.map +1 -0
  45. package/dist/mandate.d.ts +99 -0
  46. package/dist/mandate.d.ts.map +1 -0
  47. package/dist/mandate.js +141 -0
  48. package/dist/mandate.js.map +1 -0
  49. package/dist/mcp-server.d.ts +26 -0
  50. package/dist/mcp-server.d.ts.map +1 -0
  51. package/dist/mcp-server.js +111 -0
  52. package/dist/mcp-server.js.map +1 -0
  53. package/dist/mcp.d.ts +63 -0
  54. package/dist/mcp.d.ts.map +1 -0
  55. package/dist/mcp.js +123 -0
  56. package/dist/mcp.js.map +1 -0
  57. package/dist/persist.d.ts +51 -0
  58. package/dist/persist.d.ts.map +1 -0
  59. package/dist/persist.js +150 -0
  60. package/dist/persist.js.map +1 -0
  61. package/dist/quickstart.d.ts +63 -0
  62. package/dist/quickstart.d.ts.map +1 -0
  63. package/dist/quickstart.js +171 -0
  64. package/dist/quickstart.js.map +1 -0
  65. package/dist/remote.d.ts +93 -0
  66. package/dist/remote.d.ts.map +1 -0
  67. package/dist/remote.js +120 -0
  68. package/dist/remote.js.map +1 -0
  69. package/dist/seal.d.ts +12 -0
  70. package/dist/seal.d.ts.map +1 -0
  71. package/dist/seal.js +96 -0
  72. package/dist/seal.js.map +1 -0
  73. package/dist/store.d.ts +119 -0
  74. package/dist/store.d.ts.map +1 -0
  75. package/dist/store.js +139 -0
  76. package/dist/store.js.map +1 -0
  77. package/dist/types.d.ts +173 -0
  78. package/dist/types.d.ts.map +1 -0
  79. package/dist/types.js +17 -0
  80. package/dist/types.js.map +1 -0
  81. package/llms.txt +106 -0
  82. package/package.json +107 -0
  83. package/schemas/capability.schema.json +14 -0
  84. package/schemas/mandate.schema.json +68 -0
  85. package/vectors/mandate-vector.json +63 -0
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Behalf — the reference implementation of agent authority.
3
+ *
4
+ * Five verbs, one primitive (the Mandate):
5
+ *
6
+ * import { Behalf } from "agent-authority";
7
+ *
8
+ * const mandate = await Behalf.grant({ // 1. GRANT
9
+ * principal: user.id,
10
+ * agent: "research-agent",
11
+ * can: ["read:calendar", "spend:usd<=50"],
12
+ * expiresIn: "1h",
13
+ * });
14
+ *
15
+ * await mandate.authorize("spend:usd=20"); // 2. AUTHORIZE
16
+ * const child = mandate.attenuate({ can: ["read:calendar"], expiresIn: "10m" }); // 3. DELEGATE
17
+ * await Behalf.revoke(mandate.id); // 4. REVOKE
18
+ * const trail = await Behalf.audit(mandate.id); // 5. AUDIT
19
+ */
20
+ export { Behalf, createBehalf, BehalfDelegationError, type BehalfConfig, } from "./behalf.js";
21
+ export { Mandate } from "./mandate.js";
22
+ export { newKeyPair, exportPublicKey, importPublicKey, exportPrivateKey, importPrivateKey, type KeyPair, } from "./crypto.js";
23
+ export { parse as parseCapability, permits, isNarrowing, type Capability, } from "./capability.js";
24
+ export { MemoryRevocationStore, MemoryAuditStore, MemoryRateStore, TokenBucketRateStore, MemoryConsentStore, MemoryPolicyStore, CachingRevocationStore, type RevocationStore, type AuditStore, type RateStore, type ConsentStore, type PolicyStore, type CacheOptions, } from "./store.js";
25
+ export { FileRevocationStore, FileAuditStore, FileConsentStore, FilePolicyStore, FileRateStore, } from "./persist.js";
26
+ export { createControlPlane, type ControlPlane, type ControlPlaneOptions, type ConsentRecord, } from "./control-plane.js";
27
+ export { HttpRevocationStore, HttpAuditStore, HttpRateStore, ControlPlaneClient, controlPlaneConsent, type RemoteOptions, type ConsentProviderOptions, type ConsentRequest, } from "./remote.js";
28
+ export { newSealKeyPair, seal, unseal, type SealKeyPair } from "./seal.js";
29
+ export { verify as verifyAuditLog } from "./audit.js";
30
+ export { lint, isClean, type LintFinding, type LintLevel } from "./lint.js";
31
+ export { generateQuickstart, findSurface, listSurfaces, DEFAULT_SURFACES, type Surface, type QuickstartOptions, type Quickstart, } from "./quickstart.js";
32
+ export { present, behalfFetch, authorizeIncoming, guard, MANDATE_HEADER, type PresentOptions, type GuardOptions, type GuardedRequest, } from "./a2a.js";
33
+ export { BehalfError, AuthorizationError, WideningError, IntegrityError, CapabilityParseError, } from "./errors.js";
34
+ export type { Caveat, Block, Proof, MandateToken, GrantOptions, AttenuateOptions, AuditEntry, AuditIntegrity, } from "./types.js";
35
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EACL,MAAM,EACN,YAAY,EACZ,qBAAqB,EACrB,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EACL,UAAU,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,KAAK,OAAO,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,IAAI,eAAe,EACxB,OAAO,EACP,WAAW,EACX,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,KAAK,OAAO,EACZ,KAAK,iBAAiB,EACtB,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,OAAO,EACP,WAAW,EACX,iBAAiB,EACjB,KAAK,EACL,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,MAAM,EACN,KAAK,EACL,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Behalf — the reference implementation of agent authority.
3
+ *
4
+ * Five verbs, one primitive (the Mandate):
5
+ *
6
+ * import { Behalf } from "agent-authority";
7
+ *
8
+ * const mandate = await Behalf.grant({ // 1. GRANT
9
+ * principal: user.id,
10
+ * agent: "research-agent",
11
+ * can: ["read:calendar", "spend:usd<=50"],
12
+ * expiresIn: "1h",
13
+ * });
14
+ *
15
+ * await mandate.authorize("spend:usd=20"); // 2. AUTHORIZE
16
+ * const child = mandate.attenuate({ can: ["read:calendar"], expiresIn: "10m" }); // 3. DELEGATE
17
+ * await Behalf.revoke(mandate.id); // 4. REVOKE
18
+ * const trail = await Behalf.audit(mandate.id); // 5. AUDIT
19
+ */
20
+ export { Behalf, createBehalf, BehalfDelegationError, } from "./behalf.js";
21
+ export { Mandate } from "./mandate.js";
22
+ export { newKeyPair, exportPublicKey, importPublicKey, exportPrivateKey, importPrivateKey, } from "./crypto.js";
23
+ export { parse as parseCapability, permits, isNarrowing, } from "./capability.js";
24
+ export { MemoryRevocationStore, MemoryAuditStore, MemoryRateStore, TokenBucketRateStore, MemoryConsentStore, MemoryPolicyStore, CachingRevocationStore, } from "./store.js";
25
+ export { FileRevocationStore, FileAuditStore, FileConsentStore, FilePolicyStore, FileRateStore, } from "./persist.js";
26
+ export { createControlPlane, } from "./control-plane.js";
27
+ export { HttpRevocationStore, HttpAuditStore, HttpRateStore, ControlPlaneClient, controlPlaneConsent, } from "./remote.js";
28
+ export { newSealKeyPair, seal, unseal } from "./seal.js";
29
+ export { verify as verifyAuditLog } from "./audit.js";
30
+ export { lint, isClean } from "./lint.js";
31
+ export { generateQuickstart, findSurface, listSurfaces, DEFAULT_SURFACES, } from "./quickstart.js";
32
+ export { present, behalfFetch, authorizeIncoming, guard, MANDATE_HEADER, } from "./a2a.js";
33
+ export { BehalfError, AuthorizationError, WideningError, IntegrityError, CapabilityParseError, } from "./errors.js";
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EACL,MAAM,EACN,YAAY,EACZ,qBAAqB,GAEtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EACL,UAAU,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,gBAAgB,GAEjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,IAAI,eAAe,EACxB,OAAO,EACP,WAAW,GAEZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,GAOvB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,GAInB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GAIpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAoB,MAAM,WAAW,CAAC;AAC3E,OAAO,EAAE,MAAM,IAAI,cAAc,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAoC,MAAM,WAAW,CAAC;AAC5E,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,gBAAgB,GAIjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,OAAO,EACP,WAAW,EACX,iBAAiB,EACjB,KAAK,EACL,cAAc,GAIf,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,oBAAoB,GACrB,MAAM,aAAa,CAAC"}
package/dist/lint.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Capability linting. The grammar permits broad or unbounded scopes (`*`, an
3
+ * unconstrained `spend:`, ...); the spec says these are "discouraged; lint
4
+ * warns". This surfaces them so humans and agents write tight scopes by default.
5
+ */
6
+ export type LintLevel = "error" | "warn" | "info";
7
+ export interface LintFinding {
8
+ capability: string;
9
+ level: LintLevel;
10
+ rule: string;
11
+ message: string;
12
+ }
13
+ /** Lint a set of capability strings; returns findings ordered by input. */
14
+ export declare function lint(capabilities: string[]): LintFinding[];
15
+ /** True if linting found nothing at `warn` or `error` level. */
16
+ export declare function isClean(capabilities: string[]): boolean;
17
+ //# sourceMappingURL=lint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAOD,2EAA2E;AAC3E,wBAAgB,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAoE1D;AAED,gEAAgE;AAChE,wBAAgB,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAEvD"}
package/dist/lint.js ADDED
@@ -0,0 +1,75 @@
1
+ import { parse } from "./capability.js";
2
+ import { CapabilityParseError } from "./errors.js";
3
+ /** Verbs that move a quantity and should carry an amount limit. */
4
+ const QUANTITATIVE_VERBS = new Set(["spend", "pay", "transfer", "charge", "withdraw", "refund"]);
5
+ /** Verbs that fan out and should usually carry a rate limit. */
6
+ const RATE_VERBS = new Set(["send", "email", "sms", "notify", "post", "publish", "call"]);
7
+ /** Lint a set of capability strings; returns findings ordered by input. */
8
+ export function lint(capabilities) {
9
+ const findings = [];
10
+ const seen = new Set();
11
+ for (const raw of capabilities) {
12
+ if (seen.has(raw)) {
13
+ findings.push({
14
+ capability: raw,
15
+ level: "warn",
16
+ rule: "duplicate",
17
+ message: "duplicate capability; remove the repeat",
18
+ });
19
+ continue;
20
+ }
21
+ seen.add(raw);
22
+ let cap;
23
+ try {
24
+ cap = parse(raw);
25
+ }
26
+ catch (e) {
27
+ findings.push({
28
+ capability: raw,
29
+ level: "error",
30
+ rule: "unparseable",
31
+ message: e instanceof CapabilityParseError ? e.message : String(e),
32
+ });
33
+ continue;
34
+ }
35
+ if (cap.wildcard) {
36
+ findings.push({
37
+ capability: raw,
38
+ level: "warn",
39
+ rule: "wildcard",
40
+ message: "`*` grants unlimited authority; grant specific capabilities instead",
41
+ });
42
+ continue;
43
+ }
44
+ if (cap.verb === "*" || cap.resource === "*") {
45
+ findings.push({
46
+ capability: raw,
47
+ level: "warn",
48
+ rule: "wildcard-part",
49
+ message: "a `*` verb or resource is overly broad; name it explicitly",
50
+ });
51
+ }
52
+ if (QUANTITATIVE_VERBS.has(cap.verb) && !cap.amount) {
53
+ findings.push({
54
+ capability: raw,
55
+ level: "warn",
56
+ rule: "unbounded-amount",
57
+ message: `"${cap.verb}" has no limit; add a cap like "${cap.verb}:${cap.resource}<=50"`,
58
+ });
59
+ }
60
+ if (RATE_VERBS.has(cap.verb) && !cap.rate) {
61
+ findings.push({
62
+ capability: raw,
63
+ level: "info",
64
+ rule: "no-rate-limit",
65
+ message: `"${cap.verb}" has no rate limit; consider "${raw} rate<=10/h"`,
66
+ });
67
+ }
68
+ }
69
+ return findings;
70
+ }
71
+ /** True if linting found nothing at `warn` or `error` level. */
72
+ export function isClean(capabilities) {
73
+ return !lint(capabilities).some((f) => f.level !== "info");
74
+ }
75
+ //# sourceMappingURL=lint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,99 @@
1
+ import type { AttenuateOptions, AuditEntry, MandateToken, Proof } from "./types.js";
2
+ import { type KeyPair } from "./crypto.js";
3
+ import type { KeyObject } from "node:crypto";
4
+ /**
5
+ * The engine that actually verifies and enforces — implemented by {@link Behalf}.
6
+ * Kept as an interface here to avoid a circular import with the Mandate wrapper.
7
+ */
8
+ export interface Engine {
9
+ authorizeAsHolder(token: MandateToken, action: string, delegationKey: KeyObject | undefined): Promise<void>;
10
+ attenuate(token: MandateToken, delegationKey: KeyObject | undefined, opts: AttenuateOptions): Mandate;
11
+ provePossession(token: MandateToken, delegationKey: KeyObject, action: string, nonce?: string, agentKeys?: KeyObject[]): Proof;
12
+ revoke(id: string): Promise<void>;
13
+ audit(id: string): Promise<AuditEntry[]>;
14
+ }
15
+ /**
16
+ * A handle to a capability token. Construction is internal — obtain one via
17
+ * `Behalf.grant(...)`, `mandate.attenuate(...)`, or `Behalf.import(token)`.
18
+ *
19
+ * A mandate obtained from `grant`/`attenuate` also carries an in-memory
20
+ * `delegationKey` (the Ed25519 private key that authorizes the next block), so
21
+ * it can be further attenuated. A mandate restored via `import` has only the
22
+ * public token: it can be verified, authorized, and audited, but not delegated.
23
+ */
24
+ export declare class Mandate {
25
+ /** The serializable wire token. */
26
+ readonly token: MandateToken;
27
+ private readonly engine;
28
+ /** Private key for the next attenuation block; undefined if imported. */
29
+ private readonly delegationKey?;
30
+ constructor(
31
+ /** The serializable wire token. */
32
+ token: MandateToken, engine: Engine,
33
+ /** Private key for the next attenuation block; undefined if imported. */
34
+ delegationKey?: KeyObject | undefined);
35
+ /** Every caveat across every block, in chain order. */
36
+ private get caveats();
37
+ /** This mandate's own id (the deepest id in the chain). */
38
+ get id(): string;
39
+ /** Full chain of ids, root → this mandate. Revoking any kills this one. */
40
+ get chain(): string[];
41
+ /** The principal that authorized the root grant, if present. */
42
+ get principal(): string | undefined;
43
+ /** The agent this mandate is currently bound to (latest binding wins). */
44
+ get agent(): string | undefined;
45
+ /** Effective expiry (earliest expires caveat). */
46
+ get expiresAt(): number | undefined;
47
+ /** True if this mandate carries the secret needed to delegate further. */
48
+ get canDelegate(): boolean;
49
+ /**
50
+ * Prove authority for a concrete action. Resolves if permitted; throws
51
+ * {@link AuthorizationError} otherwise. Always writes an audit record.
52
+ *
53
+ * Requires this mandate to hold its delegation key (i.e. it came from
54
+ * `grant`/`attenuate`, not `import`): authorization includes a proof of
55
+ * possession of the chain's terminal key, which closes truncation and makes a
56
+ * serialized token unusable as a bare bearer credential. To authorize a
57
+ * mandate you received from elsewhere, the holder must present a proof — see
58
+ * `agent-authority/a2a`, or use `engine.inspect()` for an advisory (no-possession)
59
+ * check.
60
+ */
61
+ authorize(action: string): Promise<void>;
62
+ /** Hand a narrowed mandate to a sub-agent. Can only shrink scope. */
63
+ attenuate(opts: AttenuateOptions): Mandate;
64
+ /**
65
+ * Mint a fresh proof of possession for performing `action`, to present this
66
+ * mandate across a trust boundary (e.g. an A2A call). Bound to the action and
67
+ * the exact chain. Requires the delegation key, so only the legitimate holder
68
+ * can produce it.
69
+ */
70
+ prove(action: string, opts?: {
71
+ nonce?: string;
72
+ agentKeys?: KeyPair[];
73
+ }): Proof;
74
+ /** Revoke this mandate and its entire downstream chain. */
75
+ revoke(): Promise<void>;
76
+ /** This mandate's hash-chained audit trail. */
77
+ audit(): Promise<AuditEntry[]>;
78
+ /** Compact, transmittable string form (base64url JSON of the public token). */
79
+ serialize(): string;
80
+ /**
81
+ * Transferable holder credential: the token PLUS its delegation key, so the
82
+ * recipient can authorize, prove, and attenuate after `engine.import(...)`.
83
+ * This is how a delegated mandate is handed to a sub-agent in another process.
84
+ *
85
+ * TREAT AS A SECRET: anyone holding this string can exercise the mandate's
86
+ * full authority until expiry/revocation. Deliver only over a secure channel.
87
+ * Use `serialize()` for the public, presentation-only form.
88
+ */
89
+ serializeWithKey(): string;
90
+ /**
91
+ * Holder credential, encrypted to a recipient's X25519 sealing key — so the
92
+ * credential is unreadable in transit/at rest to anyone but the intended
93
+ * agent. Open it with `engine.importSealed(sealed, recipientKeyPair)`. This is
94
+ * `serializeWithKey()` wrapped in `seal()`; use it when the delivery channel
95
+ * isn't fully trusted. (Defense-in-depth on top of `bindAgent`.)
96
+ */
97
+ sealForRecipient(recipientPublicKey: string): string;
98
+ }
99
+ //# sourceMappingURL=mandate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mandate.d.ts","sourceRoot":"","sources":["../src/mandate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAU,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC5F,OAAO,EAAoB,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,iBAAiB,CACf,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,SAAS,GAAG,SAAS,GACnC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,SAAS,CAAC,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,GAAG,SAAS,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC;IACtG,eAAe,CACb,KAAK,EAAE,YAAY,EACnB,aAAa,EAAE,SAAS,EACxB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,SAAS,EAAE,GACtB,KAAK,CAAC;IACT,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;CAC1C;AAED;;;;;;;;GAQG;AACH,qBAAa,OAAO;IAEhB,mCAAmC;IACnC,QAAQ,CAAC,KAAK,EAAE,YAAY;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,yEAAyE;IACzE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;;IAJ/B,mCAAmC;IAC1B,KAAK,EAAE,YAAY,EACX,MAAM,EAAE,MAAM;IAC/B,yEAAyE;IACxD,aAAa,CAAC,EAAE,SAAS,YAAA;IAG5C,uDAAuD;IACvD,OAAO,KAAK,OAAO,GAElB;IAED,2DAA2D;IAC3D,IAAI,EAAE,IAAI,MAAM,CAGf;IAED,2EAA2E;IAC3E,IAAI,KAAK,IAAI,MAAM,EAAE,CAIpB;IAED,gEAAgE;IAChE,IAAI,SAAS,IAAI,MAAM,GAAG,SAAS,CAGlC;IAED,0EAA0E;IAC1E,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAI9B;IAED,kDAAkD;IAClD,IAAI,SAAS,IAAI,MAAM,GAAG,SAAS,CAMlC;IAED,0EAA0E;IAC1E,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,qEAAqE;IACrE,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO;IAI1C;;;;;OAKG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAA;KAAO,GAAG,KAAK;IAQlF,2DAA2D;IAC3D,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvB,+CAA+C;IAC/C,KAAK,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;IAI9B,+EAA+E;IAC/E,SAAS,IAAI,MAAM;IAInB;;;;;;;;OAQG;IACH,gBAAgB,IAAI,MAAM;IAQ1B;;;;;;OAMG;IACH,gBAAgB,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM;CAGrD"}
@@ -0,0 +1,141 @@
1
+ import { exportPrivateKey } from "./crypto.js";
2
+ import { seal } from "./seal.js";
3
+ /**
4
+ * A handle to a capability token. Construction is internal — obtain one via
5
+ * `Behalf.grant(...)`, `mandate.attenuate(...)`, or `Behalf.import(token)`.
6
+ *
7
+ * A mandate obtained from `grant`/`attenuate` also carries an in-memory
8
+ * `delegationKey` (the Ed25519 private key that authorizes the next block), so
9
+ * it can be further attenuated. A mandate restored via `import` has only the
10
+ * public token: it can be verified, authorized, and audited, but not delegated.
11
+ */
12
+ export class Mandate {
13
+ token;
14
+ engine;
15
+ delegationKey;
16
+ constructor(
17
+ /** The serializable wire token. */
18
+ token, engine,
19
+ /** Private key for the next attenuation block; undefined if imported. */
20
+ delegationKey) {
21
+ this.token = token;
22
+ this.engine = engine;
23
+ this.delegationKey = delegationKey;
24
+ }
25
+ /** Every caveat across every block, in chain order. */
26
+ get caveats() {
27
+ return this.token.blocks.flatMap((b) => b.caveats);
28
+ }
29
+ /** This mandate's own id (the deepest id in the chain). */
30
+ get id() {
31
+ const ids = this.chain;
32
+ return ids[ids.length - 1];
33
+ }
34
+ /** Full chain of ids, root → this mandate. Revoking any kills this one. */
35
+ get chain() {
36
+ const ids = [this.token.id];
37
+ for (const c of this.caveats)
38
+ if (c.t === "id")
39
+ ids.push(c.id);
40
+ return ids;
41
+ }
42
+ /** The principal that authorized the root grant, if present. */
43
+ get principal() {
44
+ for (const c of this.caveats)
45
+ if (c.t === "principal")
46
+ return c.principal;
47
+ return undefined;
48
+ }
49
+ /** The agent this mandate is currently bound to (latest binding wins). */
50
+ get agent() {
51
+ let agent;
52
+ for (const c of this.caveats)
53
+ if (c.t === "agent")
54
+ agent = c.agent;
55
+ return agent;
56
+ }
57
+ /** Effective expiry (earliest expires caveat). */
58
+ get expiresAt() {
59
+ let earliest;
60
+ for (const c of this.caveats) {
61
+ if (c.t === "expires")
62
+ earliest = earliest === undefined ? c.at : Math.min(earliest, c.at);
63
+ }
64
+ return earliest;
65
+ }
66
+ /** True if this mandate carries the secret needed to delegate further. */
67
+ get canDelegate() {
68
+ return this.delegationKey !== undefined;
69
+ }
70
+ /**
71
+ * Prove authority for a concrete action. Resolves if permitted; throws
72
+ * {@link AuthorizationError} otherwise. Always writes an audit record.
73
+ *
74
+ * Requires this mandate to hold its delegation key (i.e. it came from
75
+ * `grant`/`attenuate`, not `import`): authorization includes a proof of
76
+ * possession of the chain's terminal key, which closes truncation and makes a
77
+ * serialized token unusable as a bare bearer credential. To authorize a
78
+ * mandate you received from elsewhere, the holder must present a proof — see
79
+ * `agent-authority/a2a`, or use `engine.inspect()` for an advisory (no-possession)
80
+ * check.
81
+ */
82
+ authorize(action) {
83
+ return this.engine.authorizeAsHolder(this.token, action, this.delegationKey);
84
+ }
85
+ /** Hand a narrowed mandate to a sub-agent. Can only shrink scope. */
86
+ attenuate(opts) {
87
+ return this.engine.attenuate(this.token, this.delegationKey, opts);
88
+ }
89
+ /**
90
+ * Mint a fresh proof of possession for performing `action`, to present this
91
+ * mandate across a trust boundary (e.g. an A2A call). Bound to the action and
92
+ * the exact chain. Requires the delegation key, so only the legitimate holder
93
+ * can produce it.
94
+ */
95
+ prove(action, opts = {}) {
96
+ if (!this.delegationKey) {
97
+ throw new Error("cannot prove possession: this mandate was imported without its key");
98
+ }
99
+ const agentKeys = opts.agentKeys?.map((k) => k.privateKey);
100
+ return this.engine.provePossession(this.token, this.delegationKey, action, opts.nonce, agentKeys);
101
+ }
102
+ /** Revoke this mandate and its entire downstream chain. */
103
+ revoke() {
104
+ return this.engine.revoke(this.id);
105
+ }
106
+ /** This mandate's hash-chained audit trail. */
107
+ audit() {
108
+ return this.engine.audit(this.id);
109
+ }
110
+ /** Compact, transmittable string form (base64url JSON of the public token). */
111
+ serialize() {
112
+ return Buffer.from(JSON.stringify(this.token), "utf8").toString("base64url");
113
+ }
114
+ /**
115
+ * Transferable holder credential: the token PLUS its delegation key, so the
116
+ * recipient can authorize, prove, and attenuate after `engine.import(...)`.
117
+ * This is how a delegated mandate is handed to a sub-agent in another process.
118
+ *
119
+ * TREAT AS A SECRET: anyone holding this string can exercise the mandate's
120
+ * full authority until expiry/revocation. Deliver only over a secure channel.
121
+ * Use `serialize()` for the public, presentation-only form.
122
+ */
123
+ serializeWithKey() {
124
+ if (!this.delegationKey) {
125
+ throw new Error("cannot export with key: this mandate was imported without its key");
126
+ }
127
+ const payload = { token: this.token, key: exportPrivateKey(this.delegationKey) };
128
+ return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
129
+ }
130
+ /**
131
+ * Holder credential, encrypted to a recipient's X25519 sealing key — so the
132
+ * credential is unreadable in transit/at rest to anyone but the intended
133
+ * agent. Open it with `engine.importSealed(sealed, recipientKeyPair)`. This is
134
+ * `serializeWithKey()` wrapped in `seal()`; use it when the delivery channel
135
+ * isn't fully trusted. (Defense-in-depth on top of `bindAgent`.)
136
+ */
137
+ sealForRecipient(recipientPublicKey) {
138
+ return seal(this.serializeWithKey(), recipientPublicKey);
139
+ }
140
+ }
141
+ //# sourceMappingURL=mandate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mandate.js","sourceRoot":"","sources":["../src/mandate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAgB,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAyBjC;;;;;;;;GAQG;AACH,MAAM,OAAO,OAAO;IAGP;IACQ;IAEA;IALnB;IACE,mCAAmC;IAC1B,KAAmB,EACX,MAAc;IAC/B,yEAAyE;IACxD,aAAyB;QAHjC,UAAK,GAAL,KAAK,CAAc;QACX,WAAM,GAAN,MAAM,CAAQ;QAEd,kBAAa,GAAb,aAAa,CAAY;IACzC,CAAC;IAEJ,uDAAuD;IACvD,IAAY,OAAO;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IAED,2DAA2D;IAC3D,IAAI,EAAE;QACJ,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,2EAA2E;IAC3E,IAAI,KAAK;QACP,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;gBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/D,OAAO,GAAG,CAAC;IACb,CAAC;IAED,gEAAgE;IAChE,IAAI,SAAS;QACX,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW;gBAAE,OAAO,CAAC,CAAC,SAAS,CAAC;QAC1E,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,0EAA0E;IAC1E,IAAI,KAAK;QACP,IAAI,KAAyB,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO;gBAAE,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;QACnE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,kDAAkD;IAClD,IAAI,SAAS;QACX,IAAI,QAA4B,CAAC;QACjC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS;gBAAE,QAAQ,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7F,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,0EAA0E;IAC1E,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,aAAa,KAAK,SAAS,CAAC;IAC1C,CAAC;IAED;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,MAAc;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IAC/E,CAAC;IAED,qEAAqE;IACrE,SAAS,CAAC,IAAsB;QAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IACrE,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAc,EAAE,OAAkD,EAAE;QACxE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;QACxF,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACpG,CAAC;IAED,2DAA2D;IAC3D,MAAM;QACJ,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,+CAA+C;IAC/C,KAAK;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,+EAA+E;IAC/E,SAAS;QACP,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC/E,CAAC;IAED;;;;;;;;OAQG;IACH,gBAAgB;QACd,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QACjF,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC5E,CAAC;IAED;;;;;;OAMG;IACH,gBAAgB,CAAC,kBAA0B;QACzC,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,kBAAkB,CAAC,CAAC;IAC3D,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ import { Behalf } from "./behalf.js";
3
+ interface JsonRpcRequest {
4
+ jsonrpc: "2.0";
5
+ id?: string | number | null;
6
+ method: string;
7
+ params?: Record<string, unknown>;
8
+ }
9
+ interface JsonRpcResponse {
10
+ jsonrpc: "2.0";
11
+ id: string | number | null;
12
+ result?: unknown;
13
+ error?: {
14
+ code: number;
15
+ message: string;
16
+ };
17
+ }
18
+ export interface McpServer {
19
+ /** Handle one JSON-RPC request; returns a response, or null for notifications. */
20
+ dispatch(req: JsonRpcRequest): Promise<JsonRpcResponse | null>;
21
+ /** Wire the server to stdin/stdout and run until the stream closes. */
22
+ start(): void;
23
+ }
24
+ export declare function createMcpServer(engine?: Behalf): McpServer;
25
+ export {};
26
+ //# sourceMappingURL=mcp-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAarC,UAAU,cAAc;IACtB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED,MAAM,WAAW,SAAS;IACxB,kFAAkF;IAClF,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAC/D,uEAAuE;IACvE,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,eAAe,CAAC,MAAM,GAAE,MAAuB,GAAG,SAAS,CAiF1E"}
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env node
2
+ import { createInterface } from "node:readline";
3
+ import { fileURLToPath } from "node:url";
4
+ import { realpathSync } from "node:fs";
5
+ import { Behalf } from "./behalf.js";
6
+ import { behalfMcpTools } from "./mcp.js";
7
+ /**
8
+ * A minimal, dependency-free MCP server over stdio (newline-delimited JSON-RPC
9
+ * 2.0). It exposes the Behalf discovery tools — `request_mandate`,
10
+ * `present_mandate`, `check_authority` — so any MCP client (Claude Desktop,
11
+ * Cursor, ...) can obtain and use authority natively. Staying SDK-free keeps the
12
+ * "thin, near-zero-deps" principle: the wire protocol is small enough to own.
13
+ */
14
+ const PROTOCOL_VERSION = "2024-11-05";
15
+ export function createMcpServer(engine = Behalf.default) {
16
+ const tools = behalfMcpTools(engine);
17
+ const byName = new Map(tools.map((t) => [t.name, t]));
18
+ async function dispatch(req) {
19
+ const id = req.id ?? null;
20
+ const ok = (result) => ({ jsonrpc: "2.0", id, result });
21
+ const err = (code, message) => ({
22
+ jsonrpc: "2.0",
23
+ id,
24
+ error: { code, message },
25
+ });
26
+ switch (req.method) {
27
+ case "initialize":
28
+ return ok({
29
+ protocolVersion: PROTOCOL_VERSION,
30
+ capabilities: { tools: {} },
31
+ serverInfo: { name: "agent-authority", version: "0.1.0" },
32
+ });
33
+ case "notifications/initialized":
34
+ case "initialized":
35
+ return null; // notification, no reply
36
+ case "ping":
37
+ return ok({});
38
+ case "tools/list":
39
+ return ok({
40
+ tools: tools.map((t) => ({
41
+ name: t.name,
42
+ description: t.description,
43
+ inputSchema: t.inputSchema,
44
+ })),
45
+ });
46
+ case "tools/call": {
47
+ const name = req.params?.name;
48
+ const args = req.params?.arguments ?? {};
49
+ const tool = byName.get(name);
50
+ if (!tool)
51
+ return err(-32602, `unknown tool "${name}"`);
52
+ try {
53
+ const result = await tool.handler(args);
54
+ return ok({
55
+ content: [{ type: "text", text: JSON.stringify(result) }],
56
+ isError: false,
57
+ });
58
+ }
59
+ catch (e) {
60
+ return ok({
61
+ content: [{ type: "text", text: e.message }],
62
+ isError: true,
63
+ });
64
+ }
65
+ }
66
+ default:
67
+ // Ignore other notifications; error on unknown requests.
68
+ if (req.id === undefined)
69
+ return null;
70
+ return err(-32601, `method not found: ${req.method}`);
71
+ }
72
+ }
73
+ function start() {
74
+ const rl = createInterface({ input: process.stdin });
75
+ rl.on("line", (line) => {
76
+ const trimmed = line.trim();
77
+ if (!trimmed)
78
+ return;
79
+ let req;
80
+ try {
81
+ req = JSON.parse(trimmed);
82
+ }
83
+ catch {
84
+ return; // ignore malformed input
85
+ }
86
+ dispatch(req).then((res) => {
87
+ if (res)
88
+ process.stdout.write(JSON.stringify(res) + "\n");
89
+ });
90
+ });
91
+ }
92
+ return { dispatch, start };
93
+ }
94
+ // Allow `node dist/mcp-server.js` (and the `agent-authority-mcp` bin) to run the server,
95
+ // while never auto-starting when imported (e.g. by tests). Compares real paths
96
+ // so an npm bin symlink still resolves to this module.
97
+ function runningAsMain() {
98
+ const entry = process.argv[1];
99
+ if (!entry)
100
+ return false;
101
+ try {
102
+ return realpathSync(entry) === realpathSync(fileURLToPath(import.meta.url));
103
+ }
104
+ catch {
105
+ return false;
106
+ }
107
+ }
108
+ if (runningAsMain()) {
109
+ createMcpServer().start();
110
+ }
111
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}