@vorim/mcp-server 1.1.6 → 1.1.8

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 (2) hide show
  1. package/build/index.js +60 -18
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -35,19 +35,32 @@ import { z } from "zod";
35
35
  // kills exactly one installation.
36
36
  const API_KEY = process.env.VORIM_API_KEY || "";
37
37
  const BASE_URL = (process.env.VORIM_BASE_URL || "https://api.vorim.ai").replace(/\/$/, "");
38
+ // The 7 canonical permission scopes (must match the API's VALID_SCOPES).
39
+ const SCOPE_ENUM = z.enum([
40
+ "agent:read", "agent:write", "agent:execute", "agent:transact",
41
+ "agent:communicate", "agent:delegate", "agent:elevate",
42
+ ]);
38
43
  if (!API_KEY) {
39
44
  console.error("Error: VORIM_API_KEY environment variable is required");
40
45
  process.exit(1);
41
46
  }
42
47
  // ─── HTTP Client ──────────────────────────────────────────────────────────
43
- // Read the package version once so the User-Agent string and the MCP
44
- // server's advertised version stay in sync with package.json. The
45
- // hardcoded fallback is the last-known version — operators see a
46
- // loud-fail if it ever drifts in CI because `npm test` re-reads
47
- // package.json and compares.
48
+ // Read the package version once so the User-Agent string and the
49
+ // MCP server's advertised version stay in sync with package.json.
50
+ //
51
+ // Caveats:
52
+ // 1. Bundlers (esbuild / webpack) that inline the source can break
53
+ // the readFileSync path because import.meta.url no longer points
54
+ // at the npm install layout. The fallback constant below is the
55
+ // last-known version and MUST be bumped in lockstep with
56
+ // package.json — there is NO CI assertion enforcing this today.
57
+ // 2. If readFileSync succeeds but JSON.parse fails (corrupt file),
58
+ // we log a warning so operators see the silent drift rather
59
+ // than discovering it via a User-Agent grep weeks later.
48
60
  import { readFileSync } from "node:fs";
49
61
  import { fileURLToPath } from "node:url";
50
62
  import { dirname, join } from "node:path";
63
+ const MCP_VERSION_FALLBACK = "1.1.8";
51
64
  function readMcpVersion() {
52
65
  try {
53
66
  const here = dirname(fileURLToPath(import.meta.url));
@@ -55,9 +68,16 @@ function readMcpVersion() {
55
68
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
56
69
  if (typeof pkg.version === "string")
57
70
  return pkg.version;
71
+ // eslint-disable-next-line no-console
72
+ console.warn(`[vorim-mcp-server] package.json missing version field — using fallback ${MCP_VERSION_FALLBACK}`);
73
+ }
74
+ catch (err) {
75
+ // eslint-disable-next-line no-console
76
+ console.warn(`[vorim-mcp-server] could not read package.json (${err.message ?? err}) — ` +
77
+ `using fallback ${MCP_VERSION_FALLBACK}. If this is a bundled build, bump ` +
78
+ `MCP_VERSION_FALLBACK in lockstep with the published package.`);
58
79
  }
59
- catch { /* fall through */ }
60
- return "1.1.6"; // hardcoded fallback; bump alongside package.json
80
+ return MCP_VERSION_FALLBACK;
61
81
  }
62
82
  const MCP_VERSION = readMcpVersion();
63
83
  /**
@@ -117,6 +137,24 @@ async function vorimRequest(method, path, body) {
117
137
  async function vorimGet(path) {
118
138
  return vorimRequest("GET", path);
119
139
  }
140
+ // List endpoints return { data, meta } and vorimRequest unwraps to data,
141
+ // dropping pagination meta. For list tools, fetch the full envelope so the
142
+ // caller can paginate (page/total/total_pages).
143
+ async function vorimGetEnvelope(path) {
144
+ const response = await fetch(`${BASE_URL}/v1${path}`, {
145
+ headers: {
146
+ "Authorization": `Bearer ${API_KEY}`,
147
+ "User-Agent": `vorim-mcp-server/${MCP_VERSION}`,
148
+ },
149
+ });
150
+ if (!response.ok) {
151
+ const j = await response.json().catch(() => ({}));
152
+ const err = j.error;
153
+ throw new Error(err?.message || `HTTP ${response.status}`);
154
+ }
155
+ const json = await response.json();
156
+ return { data: json.data, meta: json.meta };
157
+ }
120
158
  async function vorimPost(path, body) {
121
159
  return vorimRequest("POST", path, body);
122
160
  }
@@ -193,17 +231,19 @@ server.registerTool("vorim_list_agents", {
193
231
  if (status)
194
232
  params.set("status", status);
195
233
  const qs = params.toString();
196
- const result = await vorimGet(`/agents${qs ? "?" + qs : ""}`);
197
- return text(result);
234
+ const { data, meta } = await vorimGetEnvelope(`/agents${qs ? "?" + qs : ""}`);
235
+ return text({ agents: data, meta });
198
236
  });
199
237
  server.registerTool("vorim_update_agent", {
200
- description: "Update an agent's metadata (name, description, status, capabilities).",
238
+ description: "Update an agent's metadata (name, description, status).",
201
239
  inputSchema: {
202
240
  agent_id: z.string().describe("The agent identifier"),
203
241
  name: z.string().optional().describe("New name"),
204
242
  description: z.string().optional().describe("New description"),
205
- status: z.string().optional().describe("New status: active, suspended"),
206
- capabilities: z.array(z.string()).optional().describe("New capabilities list"),
243
+ status: z.enum(["pending", "active", "suspended", "revoked", "expired"]).optional()
244
+ .describe("New status"),
245
+ // capabilities are set at registration only; the update API does not
246
+ // change them, so the field is intentionally omitted.
207
247
  },
208
248
  }, async ({ agent_id, ...updates }) => {
209
249
  const body = Object.fromEntries(Object.entries(updates).filter(([, v]) => v !== undefined));
@@ -225,7 +265,7 @@ server.registerTool("vorim_check_permission", {
225
265
  description: "Check if an agent has a specific permission scope. Returns allowed (boolean), reason if denied, and remaining quota. Sub-5ms via Redis cache.",
226
266
  inputSchema: {
227
267
  agent_id: z.string().describe("The agent identifier"),
228
- scope: z.string().describe("Permission scope to check (e.g. agent:read, agent:execute)"),
268
+ scope: SCOPE_ENUM.describe("Permission scope to check"),
229
269
  },
230
270
  annotations: { readOnlyHint: true },
231
271
  }, async ({ agent_id, scope }) => {
@@ -236,7 +276,7 @@ server.registerTool("vorim_grant_permission", {
236
276
  description: "Grant a permission scope to an agent. Optionally set expiry and rate limits.",
237
277
  inputSchema: {
238
278
  agent_id: z.string().describe("The agent identifier"),
239
- scope: z.string().describe("Permission scope to grant"),
279
+ scope: SCOPE_ENUM.describe("Permission scope to grant"),
240
280
  valid_until: z.string().optional().describe("Expiry timestamp (ISO 8601)"),
241
281
  rate_limit_max: z.number().optional().describe("Maximum uses per window"),
242
282
  rate_limit_window: z.string().optional().describe("Rate limit window: 1m, 1h, or 1d"),
@@ -265,7 +305,7 @@ server.registerTool("vorim_revoke_permission", {
265
305
  description: "Revoke a specific permission scope from an agent.",
266
306
  inputSchema: {
267
307
  agent_id: z.string().describe("The agent identifier"),
268
- scope: z.string().describe("Permission scope to revoke"),
308
+ scope: SCOPE_ENUM.describe("Permission scope to revoke"),
269
309
  },
270
310
  annotations: { destructiveHint: true, idempotentHint: true, readOnlyHint: false },
271
311
  }, async ({ agent_id, scope }) => {
@@ -277,11 +317,13 @@ server.registerTool("vorim_emit_event", {
277
317
  description: "Log an audit event for an agent action. Every agent action should be logged for compliance and traceability. NOTE: events emitted via the MCP server are sent unsigned because the MCP server does not hold the agent's private key. For tamper-evident audit trails sign client-side via @vorim/sdk before emit.",
278
318
  inputSchema: {
279
319
  agent_id: z.string().describe("The agent that performed the action"),
280
- event_type: z.string().describe("Event category: tool_call, api_request, message_sent, permission_change, status_change"),
320
+ event_type: z.enum(["tool_call", "api_request", "message_sent", "permission_change", "status_change", "key_rotation", "login", "export"])
321
+ .describe("Event category"),
281
322
  action: z.string().describe("What the agent did (e.g. 'search_documents', 'send_email')"),
282
- result: z.string().describe("Outcome: success, denied, or error"),
323
+ result: z.enum(["success", "denied", "error"]).describe("Outcome"),
283
324
  resource: z.string().optional().describe("Target resource identifier"),
284
- permission: z.string().optional().describe("Permission scope used"),
325
+ permission: z.enum(["agent:read", "agent:write", "agent:execute", "agent:transact", "agent:communicate", "agent:delegate", "agent:elevate"])
326
+ .optional().describe("Permission scope used"),
285
327
  latency_ms: z.number().optional().describe("Execution time in milliseconds"),
286
328
  error_code: z.string().optional().describe("Error code if result is 'error'"),
287
329
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vorim/mcp-server",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "mcpName": "io.github.Kzino/vorim-mcp-server",
5
5
  "description": "MCP server for Vorim AI — AI agent identity, permissions, and audit trails",
6
6
  "type": "module",