@vorim/mcp-server 1.0.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.
- package/build/index.d.ts +2 -0
- package/build/index.js +251 -0
- package/package.json +39 -0
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// Vorim AI — MCP Server
|
|
4
|
+
// Exposes Vorim agent identity, permissions, audit, and trust operations
|
|
5
|
+
// as MCP tools for Claude, Cursor, VS Code, and any MCP-compatible client.
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// VORIM_API_KEY=agid_sk_live_... vorim-mcp-server
|
|
9
|
+
//
|
|
10
|
+
// Or configure in Claude Desktop:
|
|
11
|
+
// {
|
|
12
|
+
// "mcpServers": {
|
|
13
|
+
// "vorim": {
|
|
14
|
+
// "command": "npx",
|
|
15
|
+
// "args": ["@vorim/mcp-server"],
|
|
16
|
+
// "env": { "VORIM_API_KEY": "agid_sk_live_..." }
|
|
17
|
+
// }
|
|
18
|
+
// }
|
|
19
|
+
// }
|
|
20
|
+
// ============================================================================
|
|
21
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
22
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
23
|
+
import { z } from "zod";
|
|
24
|
+
const API_KEY = process.env.VORIM_API_KEY || "";
|
|
25
|
+
const BASE_URL = (process.env.VORIM_BASE_URL || "https://api.vorim.ai").replace(/\/$/, "");
|
|
26
|
+
if (!API_KEY) {
|
|
27
|
+
console.error("Error: VORIM_API_KEY environment variable is required");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
// ─── HTTP Client ──────────────────────────────────────────────────────────
|
|
31
|
+
async function vorimRequest(method, path, body) {
|
|
32
|
+
const response = await fetch(`${BASE_URL}/v1${path}`, {
|
|
33
|
+
method,
|
|
34
|
+
headers: {
|
|
35
|
+
"Authorization": `Bearer ${API_KEY}`,
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
"User-Agent": "vorim-mcp-server/1.0.0",
|
|
38
|
+
},
|
|
39
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
40
|
+
});
|
|
41
|
+
const json = await response.json();
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const err = json.error;
|
|
44
|
+
throw new Error(err?.message || `HTTP ${response.status}`);
|
|
45
|
+
}
|
|
46
|
+
return json.data;
|
|
47
|
+
}
|
|
48
|
+
async function vorimGet(path) {
|
|
49
|
+
return vorimRequest("GET", path);
|
|
50
|
+
}
|
|
51
|
+
async function vorimPost(path, body) {
|
|
52
|
+
return vorimRequest("POST", path, body);
|
|
53
|
+
}
|
|
54
|
+
async function vorimPatch(path, body) {
|
|
55
|
+
return vorimRequest("PATCH", path, body);
|
|
56
|
+
}
|
|
57
|
+
async function vorimDelete(path) {
|
|
58
|
+
return vorimRequest("DELETE", path);
|
|
59
|
+
}
|
|
60
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
61
|
+
function text(data) {
|
|
62
|
+
return { content: [{ type: "text", text: typeof data === "string" ? data : JSON.stringify(data, null, 2) }] };
|
|
63
|
+
}
|
|
64
|
+
// ─── MCP Server ───────────────────────────────────────────────────────────
|
|
65
|
+
const server = new McpServer({
|
|
66
|
+
name: "vorim",
|
|
67
|
+
version: "1.0.0",
|
|
68
|
+
});
|
|
69
|
+
// ─── Health ───────────────────────────────────────────────────────────────
|
|
70
|
+
server.registerTool("vorim_ping", {
|
|
71
|
+
description: "Check Vorim AI API health and connectivity. Returns status, version, and service health.",
|
|
72
|
+
inputSchema: {},
|
|
73
|
+
}, async () => {
|
|
74
|
+
const response = await fetch(`${BASE_URL}/health`, {
|
|
75
|
+
headers: { "User-Agent": "vorim-mcp-server/1.0.0" },
|
|
76
|
+
});
|
|
77
|
+
const data = await response.json();
|
|
78
|
+
return text(data);
|
|
79
|
+
});
|
|
80
|
+
// ─── Agent Identity ───────────────────────────────────────────────────────
|
|
81
|
+
server.registerTool("vorim_register_agent", {
|
|
82
|
+
description: "Register a new AI agent with Vorim. Returns the agent identity (Ed25519 keypair, agent_id, trust score). The private key is shown once — store it securely.",
|
|
83
|
+
inputSchema: {
|
|
84
|
+
name: z.string().describe("Human-readable agent name"),
|
|
85
|
+
description: z.string().optional().describe("Purpose or function of the agent"),
|
|
86
|
+
capabilities: z.array(z.string()).describe("List of agent capabilities (e.g. ['search', 'write', 'calculate'])"),
|
|
87
|
+
scopes: z.array(z.string()).describe("Permission scopes to grant (e.g. ['agent:read', 'agent:execute']). Available: agent:read, agent:write, agent:execute, agent:transact, agent:communicate, agent:delegate, agent:elevate"),
|
|
88
|
+
},
|
|
89
|
+
}, async ({ name, description, capabilities, scopes }) => {
|
|
90
|
+
const result = await vorimPost("/agents", { name, description, capabilities, scopes });
|
|
91
|
+
return text(result);
|
|
92
|
+
});
|
|
93
|
+
server.registerTool("vorim_get_agent", {
|
|
94
|
+
description: "Get details of a specific agent by agent_id. Returns name, status, trust score, capabilities, permissions, and metadata.",
|
|
95
|
+
inputSchema: {
|
|
96
|
+
agent_id: z.string().describe("The agent identifier (e.g. agid_acme_a1b2c3d4)"),
|
|
97
|
+
},
|
|
98
|
+
}, async ({ agent_id }) => {
|
|
99
|
+
const result = await vorimGet(`/agents/${agent_id}`);
|
|
100
|
+
return text(result);
|
|
101
|
+
});
|
|
102
|
+
server.registerTool("vorim_list_agents", {
|
|
103
|
+
description: "List all agents in the organisation. Supports pagination and filtering by status.",
|
|
104
|
+
inputSchema: {
|
|
105
|
+
page: z.number().optional().describe("Page number (default 1)"),
|
|
106
|
+
per_page: z.number().optional().describe("Items per page (default 20)"),
|
|
107
|
+
status: z.string().optional().describe("Filter by status: active, suspended, revoked"),
|
|
108
|
+
},
|
|
109
|
+
}, async ({ page, per_page, status }) => {
|
|
110
|
+
const params = new URLSearchParams();
|
|
111
|
+
if (page)
|
|
112
|
+
params.set("page", String(page));
|
|
113
|
+
if (per_page)
|
|
114
|
+
params.set("per_page", String(per_page));
|
|
115
|
+
if (status)
|
|
116
|
+
params.set("status", status);
|
|
117
|
+
const qs = params.toString();
|
|
118
|
+
const result = await vorimGet(`/agents${qs ? "?" + qs : ""}`);
|
|
119
|
+
return text(result);
|
|
120
|
+
});
|
|
121
|
+
server.registerTool("vorim_update_agent", {
|
|
122
|
+
description: "Update an agent's metadata (name, description, status, capabilities).",
|
|
123
|
+
inputSchema: {
|
|
124
|
+
agent_id: z.string().describe("The agent identifier"),
|
|
125
|
+
name: z.string().optional().describe("New name"),
|
|
126
|
+
description: z.string().optional().describe("New description"),
|
|
127
|
+
status: z.string().optional().describe("New status: active, suspended"),
|
|
128
|
+
capabilities: z.array(z.string()).optional().describe("New capabilities list"),
|
|
129
|
+
},
|
|
130
|
+
}, async ({ agent_id, ...updates }) => {
|
|
131
|
+
const body = Object.fromEntries(Object.entries(updates).filter(([, v]) => v !== undefined));
|
|
132
|
+
const result = await vorimPatch(`/agents/${agent_id}`, body);
|
|
133
|
+
return text(result);
|
|
134
|
+
});
|
|
135
|
+
server.registerTool("vorim_revoke_agent", {
|
|
136
|
+
description: "Permanently revoke an agent. This cannot be undone. The agent's identity will be deactivated and its trust score set to 0.",
|
|
137
|
+
inputSchema: {
|
|
138
|
+
agent_id: z.string().describe("The agent identifier to revoke"),
|
|
139
|
+
},
|
|
140
|
+
}, async ({ agent_id }) => {
|
|
141
|
+
const result = await vorimDelete(`/agents/${agent_id}`);
|
|
142
|
+
return text(result);
|
|
143
|
+
});
|
|
144
|
+
// ─── Permissions ──────────────────────────────────────────────────────────
|
|
145
|
+
server.registerTool("vorim_check_permission", {
|
|
146
|
+
description: "Check if an agent has a specific permission scope. Returns allowed (boolean), reason if denied, and remaining quota. Sub-5ms via Redis cache.",
|
|
147
|
+
inputSchema: {
|
|
148
|
+
agent_id: z.string().describe("The agent identifier"),
|
|
149
|
+
scope: z.string().describe("Permission scope to check (e.g. agent:read, agent:execute)"),
|
|
150
|
+
},
|
|
151
|
+
}, async ({ agent_id, scope }) => {
|
|
152
|
+
const result = await vorimPost(`/agents/${agent_id}/permissions/verify`, { scope });
|
|
153
|
+
return text(result);
|
|
154
|
+
});
|
|
155
|
+
server.registerTool("vorim_grant_permission", {
|
|
156
|
+
description: "Grant a permission scope to an agent. Optionally set expiry and rate limits.",
|
|
157
|
+
inputSchema: {
|
|
158
|
+
agent_id: z.string().describe("The agent identifier"),
|
|
159
|
+
scope: z.string().describe("Permission scope to grant"),
|
|
160
|
+
valid_until: z.string().optional().describe("Expiry timestamp (ISO 8601)"),
|
|
161
|
+
rate_limit_max: z.number().optional().describe("Maximum uses per window"),
|
|
162
|
+
rate_limit_window: z.string().optional().describe("Rate limit window: 1m, 1h, or 1d"),
|
|
163
|
+
},
|
|
164
|
+
}, async ({ agent_id, scope, valid_until, rate_limit_max, rate_limit_window }) => {
|
|
165
|
+
const body = { scope };
|
|
166
|
+
if (valid_until)
|
|
167
|
+
body.valid_until = valid_until;
|
|
168
|
+
if (rate_limit_max && rate_limit_window) {
|
|
169
|
+
body.rate_limit = { max: rate_limit_max, window: rate_limit_window };
|
|
170
|
+
}
|
|
171
|
+
const result = await vorimPost(`/agents/${agent_id}/permissions`, body);
|
|
172
|
+
return text(result);
|
|
173
|
+
});
|
|
174
|
+
server.registerTool("vorim_list_permissions", {
|
|
175
|
+
description: "List all active permissions for an agent.",
|
|
176
|
+
inputSchema: {
|
|
177
|
+
agent_id: z.string().describe("The agent identifier"),
|
|
178
|
+
},
|
|
179
|
+
}, async ({ agent_id }) => {
|
|
180
|
+
const result = await vorimGet(`/agents/${agent_id}/permissions`);
|
|
181
|
+
return text(result);
|
|
182
|
+
});
|
|
183
|
+
server.registerTool("vorim_revoke_permission", {
|
|
184
|
+
description: "Revoke a specific permission scope from an agent.",
|
|
185
|
+
inputSchema: {
|
|
186
|
+
agent_id: z.string().describe("The agent identifier"),
|
|
187
|
+
scope: z.string().describe("Permission scope to revoke"),
|
|
188
|
+
},
|
|
189
|
+
}, async ({ agent_id, scope }) => {
|
|
190
|
+
const result = await vorimDelete(`/agents/${agent_id}/permissions/${scope}`);
|
|
191
|
+
return text(result);
|
|
192
|
+
});
|
|
193
|
+
// ─── Audit ────────────────────────────────────────────────────────────────
|
|
194
|
+
server.registerTool("vorim_emit_event", {
|
|
195
|
+
description: "Log an audit event for an agent action. Every agent action should be logged for compliance and traceability.",
|
|
196
|
+
inputSchema: {
|
|
197
|
+
agent_id: z.string().describe("The agent that performed the action"),
|
|
198
|
+
event_type: z.string().describe("Event category: tool_call, api_request, message_sent, permission_change, status_change"),
|
|
199
|
+
action: z.string().describe("What the agent did (e.g. 'search_documents', 'send_email')"),
|
|
200
|
+
result: z.string().describe("Outcome: success, denied, or error"),
|
|
201
|
+
resource: z.string().optional().describe("Target resource identifier"),
|
|
202
|
+
permission: z.string().optional().describe("Permission scope used"),
|
|
203
|
+
latency_ms: z.number().optional().describe("Execution time in milliseconds"),
|
|
204
|
+
error_code: z.string().optional().describe("Error code if result is 'error'"),
|
|
205
|
+
},
|
|
206
|
+
}, async ({ agent_id, event_type, action, result, resource, permission, latency_ms, error_code }) => {
|
|
207
|
+
const event = { agent_id, event_type, action, result };
|
|
208
|
+
if (resource)
|
|
209
|
+
event.resource = resource;
|
|
210
|
+
if (permission)
|
|
211
|
+
event.permission = permission;
|
|
212
|
+
if (latency_ms)
|
|
213
|
+
event.latency_ms = latency_ms;
|
|
214
|
+
if (error_code)
|
|
215
|
+
event.error_code = error_code;
|
|
216
|
+
const data = await vorimPost("/audit/events", { events: [event] });
|
|
217
|
+
return text(data);
|
|
218
|
+
});
|
|
219
|
+
server.registerTool("vorim_export_audit", {
|
|
220
|
+
description: "Export a signed audit bundle for a date range. Returns events with a SHA-256 manifest for tamper-proof verification.",
|
|
221
|
+
inputSchema: {
|
|
222
|
+
from: z.string().describe("Start date (ISO 8601)"),
|
|
223
|
+
to: z.string().describe("End date (ISO 8601)"),
|
|
224
|
+
},
|
|
225
|
+
}, async ({ from, to }) => {
|
|
226
|
+
const result = await vorimPost("/audit/export", { from, to });
|
|
227
|
+
return text(result);
|
|
228
|
+
});
|
|
229
|
+
// ─── Trust ────────────────────────────────────────────────────────────────
|
|
230
|
+
server.registerTool("vorim_verify_trust", {
|
|
231
|
+
description: "Verify an agent's identity and trust score. Public endpoint — no authentication required. Returns trust score (0-100), status, active scopes, and key fingerprint.",
|
|
232
|
+
inputSchema: {
|
|
233
|
+
agent_id: z.string().describe("The agent identifier to verify"),
|
|
234
|
+
},
|
|
235
|
+
}, async ({ agent_id }) => {
|
|
236
|
+
const response = await fetch(`${BASE_URL}/v1/trust/verify/${agent_id}`, {
|
|
237
|
+
headers: { "User-Agent": "vorim-mcp-server/1.0.0" },
|
|
238
|
+
});
|
|
239
|
+
const json = await response.json();
|
|
240
|
+
return text(json.data || json);
|
|
241
|
+
});
|
|
242
|
+
// ─── Start ────────────────────────────────────────────────────────────────
|
|
243
|
+
async function main() {
|
|
244
|
+
const transport = new StdioServerTransport();
|
|
245
|
+
await server.connect(transport);
|
|
246
|
+
console.error("Vorim MCP Server running — connected via stdio");
|
|
247
|
+
}
|
|
248
|
+
main().catch((err) => {
|
|
249
|
+
console.error("Fatal:", err);
|
|
250
|
+
process.exit(1);
|
|
251
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vorim/mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for Vorim AI — AI agent identity, permissions, and audit trails",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"vorim-mcp-server": "./build/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc && chmod 755 build/index.js",
|
|
11
|
+
"dev": "tsx src/index.ts"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"build"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [
|
|
17
|
+
"mcp",
|
|
18
|
+
"model-context-protocol",
|
|
19
|
+
"vorim",
|
|
20
|
+
"ai-agent",
|
|
21
|
+
"identity",
|
|
22
|
+
"permissions",
|
|
23
|
+
"audit"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/Kzino/vorim-protocol"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
32
|
+
"zod": "^3.25.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.0.0",
|
|
36
|
+
"tsx": "^4.0.0",
|
|
37
|
+
"typescript": "^5.4.0"
|
|
38
|
+
}
|
|
39
|
+
}
|