@agentvalet/register 0.4.11 → 0.4.12
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/dist/index.js +22 -28
- package/dist/mcp-server-R3LG4PNM.js +46 -0
- package/package.json +10 -10
- package/dist/mcp-server-SBGWYBP7.js +0 -139
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
+
import { createRequire } from "module";
|
|
4
5
|
import { Command as Command5 } from "commander";
|
|
5
6
|
import chalk12 from "chalk";
|
|
6
7
|
|
|
@@ -192,9 +193,23 @@ async function saveOutput(opts) {
|
|
|
192
193
|
|
|
193
194
|
// src/commands/refresh.ts
|
|
194
195
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync3, mkdirSync, statSync } from "fs";
|
|
195
|
-
import { createSign, createPrivateKey } from "crypto";
|
|
196
196
|
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
197
197
|
|
|
198
|
+
// src/lib/jwt.ts
|
|
199
|
+
import { createSign, createPrivateKey } from "crypto";
|
|
200
|
+
function signJwt(agentId, ownerId, privateKeyPem) {
|
|
201
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
202
|
+
const b64 = (s) => Buffer.from(s).toString("base64url");
|
|
203
|
+
const header = b64(JSON.stringify({ alg: "RS256", typ: "JWT" }));
|
|
204
|
+
const payload = b64(
|
|
205
|
+
JSON.stringify({ agent_id: agentId, owner_id: ownerId, iat: now, exp: now + 300 })
|
|
206
|
+
);
|
|
207
|
+
const signingInput = `${header}.${payload}`;
|
|
208
|
+
const sign = createSign("RSA-SHA256");
|
|
209
|
+
sign.update(signingInput);
|
|
210
|
+
return `${signingInput}.${sign.sign(createPrivateKey(privateKeyPem), "base64url")}`;
|
|
211
|
+
}
|
|
212
|
+
|
|
198
213
|
// src/lib/skill-writer.ts
|
|
199
214
|
import { existsSync, writeFileSync } from "fs";
|
|
200
215
|
import { execSync } from "child_process";
|
|
@@ -500,19 +515,6 @@ var CLAUDE_START = "<!-- agentvalet:start -->";
|
|
|
500
515
|
var CLAUDE_END = "<!-- agentvalet:end -->";
|
|
501
516
|
var HOOK_COMMAND = "npx @agentvalet/register refresh --if-stale --quiet 2>/dev/null || true";
|
|
502
517
|
var HOOK_MARKER = "agentvalet/register refresh";
|
|
503
|
-
function base64url(input) {
|
|
504
|
-
return Buffer.from(input).toString("base64url");
|
|
505
|
-
}
|
|
506
|
-
function signJwt(agentId, ownerId, privateKeyPem) {
|
|
507
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
508
|
-
const header = base64url(JSON.stringify({ alg: "RS256", typ: "JWT" }));
|
|
509
|
-
const payload = base64url(JSON.stringify({ agent_id: agentId, owner_id: ownerId, iat: now, exp: now + 300 }));
|
|
510
|
-
const signingInput = `${header}.${payload}`;
|
|
511
|
-
const sign = createSign("RSA-SHA256");
|
|
512
|
-
sign.update(signingInput);
|
|
513
|
-
const signature = sign.sign(createPrivateKey(privateKeyPem), "base64url");
|
|
514
|
-
return `${signingInput}.${signature}`;
|
|
515
|
-
}
|
|
516
518
|
function writePermissionsFromEvent(agentId, ownerId, platforms, outputPath = "./.claude/agentvalet-permissions.md") {
|
|
517
519
|
const content = generatePermissionsFile(agentId, ownerId, platforms);
|
|
518
520
|
const resolvedPath = resolve3(outputPath);
|
|
@@ -1529,20 +1531,9 @@ import chalk11 from "chalk";
|
|
|
1529
1531
|
import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync3, rmSync } from "fs";
|
|
1530
1532
|
import { resolve as resolve4, join as join3 } from "path";
|
|
1531
1533
|
import { homedir as homedir2 } from "os";
|
|
1532
|
-
import { createSign as createSign2, createPrivateKey as createPrivateKey2 } from "crypto";
|
|
1533
1534
|
var CLAUDE_START2 = "<!-- agentvalet:start -->";
|
|
1534
1535
|
var CLAUDE_END2 = "<!-- agentvalet:end -->";
|
|
1535
1536
|
var HOOK_MARKER2 = "agentvalet/register refresh";
|
|
1536
|
-
function signJwt2(agentId, ownerId, privateKeyPem) {
|
|
1537
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
1538
|
-
const b64 = (s) => Buffer.from(s).toString("base64url");
|
|
1539
|
-
const header = b64(JSON.stringify({ alg: "RS256", typ: "JWT" }));
|
|
1540
|
-
const payload = b64(JSON.stringify({ agent_id: agentId, owner_id: ownerId, iat: now, exp: now + 300 }));
|
|
1541
|
-
const signingInput = `${header}.${payload}`;
|
|
1542
|
-
const sign = createSign2("RSA-SHA256");
|
|
1543
|
-
sign.update(signingInput);
|
|
1544
|
-
return `${signingInput}.${sign.sign(createPrivateKey2(privateKeyPem), "base64url")}`;
|
|
1545
|
-
}
|
|
1546
1537
|
function stripClaudeMd() {
|
|
1547
1538
|
const path7 = resolve4("CLAUDE.md");
|
|
1548
1539
|
if (!existsSync7(path7)) return;
|
|
@@ -1718,7 +1709,7 @@ function uninstallCommand() {
|
|
|
1718
1709
|
}
|
|
1719
1710
|
console.log(chalk11.dim(`
|
|
1720
1711
|
Submitting revocation request for ${creds.agentId}...`));
|
|
1721
|
-
const jwt =
|
|
1712
|
+
const jwt = signJwt(creds.agentId, creds.ownerId, privateKeyPem);
|
|
1722
1713
|
let revocationToken;
|
|
1723
1714
|
try {
|
|
1724
1715
|
const res = await fetch(`${creds.apiUrl}/v1/revoke-request`, {
|
|
@@ -1765,11 +1756,13 @@ function uninstallCommand() {
|
|
|
1765
1756
|
}
|
|
1766
1757
|
|
|
1767
1758
|
// src/index.ts
|
|
1759
|
+
var require2 = createRequire(import.meta.url);
|
|
1760
|
+
var { version } = require2("../package.json");
|
|
1768
1761
|
function collectScope(value, previous) {
|
|
1769
1762
|
return [...previous, value];
|
|
1770
1763
|
}
|
|
1771
1764
|
var program = new Command5();
|
|
1772
|
-
program.name("agentvalet-register").description("Self-register an AI agent with AgentValet").version(
|
|
1765
|
+
program.name("agentvalet-register").description("Self-register an AI agent with AgentValet").version(version).option("--owner <uuid>", "Owner ID (or set AGENTVALET_OWNER env var)").option("--name <name>", "Agent name").option("--description <desc>", "Agent description").option("--scope <platform:scope>", "Requested scope, repeatable", collectScope, []).option("--api-url <url>", "AgentValet API base URL", "https://api.agentvalet.ai").option("--output <path>", "Path to write .env file", "./.env.agentvalet").option("--key-path <path>", "Path to write private key", "./agentvalet.key").option("--json", "Machine-readable JSON output").option("--no-wait", "Register only, do not wait for approval").option("--timeout <seconds>", "Approval wait timeout in seconds", "300").action(async (opts) => {
|
|
1773
1766
|
const isJson = !!opts.json;
|
|
1774
1767
|
let ownerId = opts.owner ?? process.env.AGENTVALET_OWNER ?? "";
|
|
1775
1768
|
let agentName = opts.name ?? "";
|
|
@@ -1940,7 +1933,8 @@ program.command("refresh").description("Refresh approved permissions and update
|
|
|
1940
1933
|
}
|
|
1941
1934
|
});
|
|
1942
1935
|
program.command("mcp-server").description("Start the AgentValet MCP server (stdio transport)").action(async () => {
|
|
1943
|
-
await import("./mcp-server-
|
|
1936
|
+
const { mcpServerCommand } = await import("./mcp-server-R3LG4PNM.js");
|
|
1937
|
+
await mcpServerCommand();
|
|
1944
1938
|
});
|
|
1945
1939
|
program.addCommand(listCommand());
|
|
1946
1940
|
program.addCommand(revokeCommand());
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/commands/mcp-server.ts
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import { createRequire } from "module";
|
|
4
|
+
function resolveMcpServerBin() {
|
|
5
|
+
try {
|
|
6
|
+
const require2 = createRequire(import.meta.url);
|
|
7
|
+
return require2.resolve("@agentvalet/mcp-server/dist/index.js");
|
|
8
|
+
} catch {
|
|
9
|
+
try {
|
|
10
|
+
const require2 = createRequire(import.meta.url);
|
|
11
|
+
const pkgRoot = require2.resolve("@agentvalet/mcp-server/package.json");
|
|
12
|
+
return pkgRoot.replace("package.json", "dist/index.js");
|
|
13
|
+
} catch {
|
|
14
|
+
throw new Error(
|
|
15
|
+
"@agentvalet/mcp-server is not installed. Run: npx @agentvalet/register"
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function mcpServerCommand() {
|
|
21
|
+
let binPath;
|
|
22
|
+
try {
|
|
23
|
+
binPath = resolveMcpServerBin();
|
|
24
|
+
} catch (err) {
|
|
25
|
+
process.stderr.write(
|
|
26
|
+
`[agentvalet] ${err instanceof Error ? err.message : String(err)}
|
|
27
|
+
`
|
|
28
|
+
);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const child = spawn(process.execPath, [binPath], {
|
|
32
|
+
stdio: "inherit",
|
|
33
|
+
env: process.env
|
|
34
|
+
});
|
|
35
|
+
child.on("error", (err) => {
|
|
36
|
+
process.stderr.write(`[agentvalet] Failed to start MCP server: ${err.message}
|
|
37
|
+
`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
});
|
|
40
|
+
child.on("exit", (code) => {
|
|
41
|
+
process.exit(code ?? 0);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
mcpServerCommand
|
|
46
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentvalet/register",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.12",
|
|
4
4
|
"description": "Self-register AI agents with AgentValet",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,14 +10,8 @@
|
|
|
10
10
|
"dist",
|
|
11
11
|
"README.md"
|
|
12
12
|
],
|
|
13
|
-
"scripts": {
|
|
14
|
-
"build": "tsup src/index.ts --format esm --dts --clean --shims",
|
|
15
|
-
"dev": "tsx src/index.ts",
|
|
16
|
-
"test": "vitest run",
|
|
17
|
-
"typecheck": "tsc --noEmit",
|
|
18
|
-
"prepublishOnly": "pnpm build"
|
|
19
|
-
},
|
|
20
13
|
"dependencies": {
|
|
14
|
+
"@agentvalet/mcp-server": "*",
|
|
21
15
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
22
16
|
"@octokit/auth-oauth-device": "^7.0.0",
|
|
23
17
|
"chalk": "^5.3.0",
|
|
@@ -54,5 +48,11 @@
|
|
|
54
48
|
"valet",
|
|
55
49
|
"agentvalet"
|
|
56
50
|
],
|
|
57
|
-
"license": "MIT"
|
|
58
|
-
|
|
51
|
+
"license": "MIT",
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsup src/index.ts --format esm --dts --clean --shims",
|
|
54
|
+
"dev": "tsx src/index.ts",
|
|
55
|
+
"test": "vitest run",
|
|
56
|
+
"typecheck": "tsc --noEmit"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
// src/commands/mcp-server.ts
|
|
2
|
-
import { readFileSync } from "fs";
|
|
3
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
-
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
-
import { SignJWT, importPKCS8 } from "jose";
|
|
7
|
-
if (!process.env.AGENT_PRIVATE_KEY && process.env.AGENT_PRIVATE_KEY_PATH) {
|
|
8
|
-
try {
|
|
9
|
-
process.env.AGENT_PRIVATE_KEY = readFileSync(process.env.AGENT_PRIVATE_KEY_PATH, "utf-8").trim();
|
|
10
|
-
} catch (err) {
|
|
11
|
-
process.stderr.write(`[agentvalet] Cannot read AGENT_PRIVATE_KEY_PATH: ${err instanceof Error ? err.message : err}
|
|
12
|
-
`);
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
var REQUIRED = ["AGENT_PRIVATE_KEY", "AGENT_ID", "OWNER_ID", "PROXY_URL"];
|
|
17
|
-
for (const key of REQUIRED) {
|
|
18
|
-
if (!process.env[key]) {
|
|
19
|
-
process.stderr.write(`[agentvalet] Missing env var: ${key}
|
|
20
|
-
`);
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
var AGENT_PRIVATE_KEY_RAW = process.env.AGENT_PRIVATE_KEY;
|
|
25
|
-
var AGENT_ID = process.env.AGENT_ID;
|
|
26
|
-
var OWNER_ID = process.env.OWNER_ID;
|
|
27
|
-
var PROXY_URL = process.env.PROXY_URL.replace(/\/$/, "");
|
|
28
|
-
var _privateKey = null;
|
|
29
|
-
var _keyError = null;
|
|
30
|
-
async function getPrivateKey() {
|
|
31
|
-
if (_keyError) throw new Error(_keyError);
|
|
32
|
-
if (_privateKey) return _privateKey;
|
|
33
|
-
if (AGENT_PRIVATE_KEY_RAW === "PENDING_FIRST_CALL") return null;
|
|
34
|
-
const raw = AGENT_PRIVATE_KEY_RAW.trim();
|
|
35
|
-
const pem = raw.startsWith("-----") ? raw.replace(/\\n/g, "\n") : `-----BEGIN PRIVATE KEY-----
|
|
36
|
-
${raw}
|
|
37
|
-
-----END PRIVATE KEY-----`;
|
|
38
|
-
try {
|
|
39
|
-
_privateKey = await importPKCS8(pem, "RS256");
|
|
40
|
-
return _privateKey;
|
|
41
|
-
} catch (err) {
|
|
42
|
-
_keyError = `Invalid private key: ${err instanceof Error ? err.message : err}`;
|
|
43
|
-
throw new Error(_keyError);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
async function signJWT() {
|
|
47
|
-
const key = await getPrivateKey();
|
|
48
|
-
if (!key) throw new Error("Private key not loaded");
|
|
49
|
-
return new SignJWT({ agent_id: AGENT_ID, owner_id: OWNER_ID }).setProtectedHeader({ alg: "RS256" }).setIssuedAt().setExpirationTime("60s").sign(key);
|
|
50
|
-
}
|
|
51
|
-
function fetchWithTimeout(url, init, ms = 15e3) {
|
|
52
|
-
const ac = new AbortController();
|
|
53
|
-
const t = setTimeout(() => ac.abort(), ms);
|
|
54
|
-
return fetch(url, { ...init, signal: ac.signal }).finally(() => clearTimeout(t));
|
|
55
|
-
}
|
|
56
|
-
async function bearerFetch(url, init) {
|
|
57
|
-
const token = await signJWT();
|
|
58
|
-
return fetchWithTimeout(url, {
|
|
59
|
-
...init,
|
|
60
|
-
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", ...init.headers }
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
function errResult(msg) {
|
|
64
|
-
return { content: [{ type: "text", text: msg }], isError: true };
|
|
65
|
-
}
|
|
66
|
-
var ALLOWED_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
67
|
-
var server = new Server(
|
|
68
|
-
{ name: "agentvalet", version: "1.0.0" },
|
|
69
|
-
{ capabilities: { tools: {} } }
|
|
70
|
-
);
|
|
71
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
72
|
-
tools: [
|
|
73
|
-
{
|
|
74
|
-
name: "list_platforms",
|
|
75
|
-
description: "List the platforms and permission scopes this agent has access to.",
|
|
76
|
-
inputSchema: { type: "object", properties: {} }
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
name: "use_platform",
|
|
80
|
-
description: "Call an external platform API through the AgentValet proxy.",
|
|
81
|
-
inputSchema: {
|
|
82
|
-
type: "object",
|
|
83
|
-
properties: {
|
|
84
|
-
platform: { type: "string", description: "Platform ID (e.g. slack, github)" },
|
|
85
|
-
endpoint: { type: "string", description: "API path on the target platform" },
|
|
86
|
-
method: { type: "string", enum: ["GET", "POST", "PUT", "PATCH", "DELETE"] },
|
|
87
|
-
scope: { type: "string", description: "Permission scope required" },
|
|
88
|
-
data: { type: "object", description: "Optional request body" }
|
|
89
|
-
},
|
|
90
|
-
required: ["platform", "endpoint", "method", "scope"]
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
]
|
|
94
|
-
}));
|
|
95
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
96
|
-
const { name, arguments: args } = request.params;
|
|
97
|
-
if (name === "list_platforms") {
|
|
98
|
-
if (AGENT_PRIVATE_KEY_RAW === "PENDING_FIRST_CALL") {
|
|
99
|
-
return errResult("Agent not yet activated \u2014 owner confirmation pending. Retry in 60 seconds.");
|
|
100
|
-
}
|
|
101
|
-
try {
|
|
102
|
-
const res = await bearerFetch(`${PROXY_URL}/v1/agent/permissions`, { method: "GET", headers: {} });
|
|
103
|
-
const body = await res.text();
|
|
104
|
-
if (!res.ok) return errResult(`Proxy error ${res.status}: ${body}`);
|
|
105
|
-
return { content: [{ type: "text", text: body }] };
|
|
106
|
-
} catch (e) {
|
|
107
|
-
return errResult(`Error: ${e instanceof Error ? e.message : e}`);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (name === "use_platform") {
|
|
111
|
-
if (AGENT_PRIVATE_KEY_RAW === "PENDING_FIRST_CALL") {
|
|
112
|
-
return errResult("Agent not yet activated \u2014 owner confirmation pending. Retry in 60 seconds.");
|
|
113
|
-
}
|
|
114
|
-
if (!args || typeof args.platform !== "string" || typeof args.endpoint !== "string" || typeof args.method !== "string" || typeof args.scope !== "string") {
|
|
115
|
-
return errResult("Missing required args: platform, endpoint, method, scope");
|
|
116
|
-
}
|
|
117
|
-
if (!ALLOWED_METHODS.includes(args.method)) return errResult(`Invalid method: ${args.method}`);
|
|
118
|
-
try {
|
|
119
|
-
const res = await bearerFetch(`${PROXY_URL}/v1/actions`, {
|
|
120
|
-
method: "POST",
|
|
121
|
-
body: JSON.stringify({
|
|
122
|
-
platform: args.platform,
|
|
123
|
-
endpoint: args.endpoint,
|
|
124
|
-
method: args.method,
|
|
125
|
-
scope: args.scope,
|
|
126
|
-
...args.data !== void 0 && { data: args.data }
|
|
127
|
-
})
|
|
128
|
-
});
|
|
129
|
-
const body = await res.text();
|
|
130
|
-
if (!res.ok) return errResult(`Proxy error ${res.status}: ${body}`);
|
|
131
|
-
return { content: [{ type: "text", text: body }] };
|
|
132
|
-
} catch (e) {
|
|
133
|
-
return errResult(`Error: ${e instanceof Error ? e.message : e}`);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return errResult(`Unknown tool: ${name}`);
|
|
137
|
-
});
|
|
138
|
-
var transport = new StdioServerTransport();
|
|
139
|
-
await server.connect(transport);
|