@veridocs/mcp 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.
- package/dist/index.mjs +170 -0
- package/package.json +31 -0
- package/src/index.ts +210 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
#!/usr/bin/env node
|
|
3
|
+
|
|
4
|
+
// src/index.ts
|
|
5
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
6
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import {
|
|
8
|
+
CallToolRequestSchema,
|
|
9
|
+
ListToolsRequestSchema
|
|
10
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
11
|
+
var API_KEY = process.env.VERIDOCS_API_KEY ?? "";
|
|
12
|
+
var BASE_URL = (process.env.VERIDOCS_API_URL ?? "https://veridocs.dev").replace(/\/$/, "");
|
|
13
|
+
if (!API_KEY) {
|
|
14
|
+
process.stderr.write("[veridocs-mcp] VERIDOCS_API_KEY is not set. Get a key at veridocs.dev\n");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
async function vd(method, path, body) {
|
|
18
|
+
const res = await fetch(`${BASE_URL}${path}`, {
|
|
19
|
+
method,
|
|
20
|
+
headers: {
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
"x-api-key": API_KEY
|
|
23
|
+
},
|
|
24
|
+
body: body ? JSON.stringify(body) : void 0
|
|
25
|
+
});
|
|
26
|
+
const text = await res.text();
|
|
27
|
+
let json;
|
|
28
|
+
try {
|
|
29
|
+
json = JSON.parse(text);
|
|
30
|
+
} catch {
|
|
31
|
+
throw new Error(`VeriDOCS API returned non-JSON (${res.status}): ${text.slice(0, 200)}`);
|
|
32
|
+
}
|
|
33
|
+
if (!res.ok) {
|
|
34
|
+
const err = json;
|
|
35
|
+
throw new Error(`VeriDOCS API error ${res.status}: ${err.error ?? err.message ?? text.slice(0, 200)}`);
|
|
36
|
+
}
|
|
37
|
+
return json;
|
|
38
|
+
}
|
|
39
|
+
var tools = [
|
|
40
|
+
{
|
|
41
|
+
name: "vd_evaluate",
|
|
42
|
+
description: "Submit an AI agent action proposal to VeriDOCS for governance evaluation. Returns a cryptographically-signed receipt with a verdict of EXECUTE, BLOCK, REVIEW, or SHADOW. Use this before any consequential agent action (sending emails, modifying data, making payments, etc.).",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: "object",
|
|
45
|
+
required: ["action_type", "agent_id"],
|
|
46
|
+
properties: {
|
|
47
|
+
action_type: {
|
|
48
|
+
type: "string",
|
|
49
|
+
description: "Semantic name for the action (e.g. 'send_email', 'delete_record', 'make_payment')"
|
|
50
|
+
},
|
|
51
|
+
agent_id: {
|
|
52
|
+
type: "string",
|
|
53
|
+
description: "Identifier for the AI agent making the proposal"
|
|
54
|
+
},
|
|
55
|
+
parameters: {
|
|
56
|
+
type: "object",
|
|
57
|
+
description: "Action-specific parameters as a JSON object"
|
|
58
|
+
},
|
|
59
|
+
idempotency_key: {
|
|
60
|
+
type: "string",
|
|
61
|
+
description: "Optional unique key \u2014 same key returns the cached receipt"
|
|
62
|
+
},
|
|
63
|
+
guardian_timeout_policy: {
|
|
64
|
+
type: "string",
|
|
65
|
+
enum: ["fail_closed", "fail_open"],
|
|
66
|
+
description: "What to do if the Guardian times out. Default: fail_closed (block the action)"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "vd_get_receipt",
|
|
73
|
+
description: "Retrieve a VeriDOCS audit receipt by its UUID. Returns the full receipt including verdict, signature, and policy pack hash.",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
type: "object",
|
|
76
|
+
required: ["receipt_id"],
|
|
77
|
+
properties: {
|
|
78
|
+
receipt_id: { type: "string", description: "UUID of the receipt to retrieve" }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "vd_verify_receipt",
|
|
84
|
+
description: "Cryptographically verify a VeriDOCS receipt. Checks the Ed25519 signature and confirms the signing key is ACTIVE. Returns valid: true/false with a reason.",
|
|
85
|
+
inputSchema: {
|
|
86
|
+
type: "object",
|
|
87
|
+
required: ["receipt_id"],
|
|
88
|
+
properties: {
|
|
89
|
+
receipt_id: { type: "string", description: "UUID of the receipt to verify" }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "vd_list_receipts",
|
|
95
|
+
description: "List recent VeriDOCS audit receipts for the authenticated tenant. Supports filtering by agent and verdict.",
|
|
96
|
+
inputSchema: {
|
|
97
|
+
type: "object",
|
|
98
|
+
properties: {
|
|
99
|
+
limit: { type: "number", description: "Number of receipts to return (max 100, default 20)" },
|
|
100
|
+
offset: { type: "number", description: "Pagination offset (default 0)" },
|
|
101
|
+
agent_id: { type: "string", description: "Filter by agent ID" },
|
|
102
|
+
verdict: { type: "string", enum: ["EXECUTE", "BLOCK", "REVIEW", "SHADOW"], description: "Filter by verdict" }
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "vd_usage",
|
|
108
|
+
description: "Get current VeriDOCS quota usage \u2014 receipts used, receipts remaining, credit balance, billing cycle dates, and plan tier.",
|
|
109
|
+
inputSchema: { type: "object", properties: {} }
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: "vd_list_policy_packs",
|
|
113
|
+
description: "List all governance policy packs for the authenticated tenant, including which one is currently active.",
|
|
114
|
+
inputSchema: { type: "object", properties: {} }
|
|
115
|
+
}
|
|
116
|
+
];
|
|
117
|
+
var server = new Server(
|
|
118
|
+
{ name: "veridocs", version: "0.1.0" },
|
|
119
|
+
{ capabilities: { tools: {} } }
|
|
120
|
+
);
|
|
121
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
|
|
122
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
123
|
+
const { name, arguments: args = {} } = req.params;
|
|
124
|
+
try {
|
|
125
|
+
switch (name) {
|
|
126
|
+
case "vd_evaluate": {
|
|
127
|
+
const result = await vd("POST", "/v1/evaluate", {
|
|
128
|
+
action_type: args.action_type,
|
|
129
|
+
agent_id: args.agent_id,
|
|
130
|
+
parameters: args.parameters ?? {},
|
|
131
|
+
idempotency_key: args.idempotency_key,
|
|
132
|
+
guardian_timeout_policy: args.guardian_timeout_policy ?? "fail_closed"
|
|
133
|
+
});
|
|
134
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
135
|
+
}
|
|
136
|
+
case "vd_get_receipt": {
|
|
137
|
+
const result = await vd("GET", `/v1/receipts/${args.receipt_id}`);
|
|
138
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
139
|
+
}
|
|
140
|
+
case "vd_verify_receipt": {
|
|
141
|
+
const result = await vd("GET", `/v1/receipts/${args.receipt_id}/verify`);
|
|
142
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
143
|
+
}
|
|
144
|
+
case "vd_list_receipts": {
|
|
145
|
+
const params = new URLSearchParams();
|
|
146
|
+
if (args.limit) params.set("limit", String(args.limit));
|
|
147
|
+
if (args.offset) params.set("offset", String(args.offset));
|
|
148
|
+
if (args.agent_id) params.set("agent_id", String(args.agent_id));
|
|
149
|
+
if (args.verdict) params.set("verdict", String(args.verdict));
|
|
150
|
+
const result = await vd("GET", `/v1/receipts?${params}`);
|
|
151
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
152
|
+
}
|
|
153
|
+
case "vd_usage": {
|
|
154
|
+
const result = await vd("GET", "/v1/usage");
|
|
155
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
156
|
+
}
|
|
157
|
+
case "vd_list_policy_packs": {
|
|
158
|
+
const result = await vd("GET", "/v1/policy-packs");
|
|
159
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
160
|
+
}
|
|
161
|
+
default:
|
|
162
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
163
|
+
}
|
|
164
|
+
} catch (err) {
|
|
165
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
166
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
var transport = new StdioServerTransport();
|
|
170
|
+
await server.connect(transport);
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@veridocs/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "VeriDOCS MCP server — drop cryptographic AI governance into Claude Desktop, Cursor, Cline, or any MCP-aware host.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.mts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"veridocs-mcp": "./dist/index.mjs"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.mts",
|
|
14
|
+
"import": "./dist/index.mjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": ["dist", "src"],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"tsup": "^8.0.0",
|
|
26
|
+
"typescript": "^5.0.0"
|
|
27
|
+
},
|
|
28
|
+
"engines": { "node": ">=18" },
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"keywords": ["veridocs", "mcp", "model-context-protocol", "ai-governance", "audit", "receipts", "claude", "cursor"]
|
|
31
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* VeriDOCS MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Drop AI governance into any MCP-aware host (Claude Desktop, Cursor, Cline, etc.)
|
|
6
|
+
* with a single config entry.
|
|
7
|
+
*
|
|
8
|
+
* Quick start — Claude Desktop (~/.claude/claude_desktop_config.json):
|
|
9
|
+
* {
|
|
10
|
+
* "mcpServers": {
|
|
11
|
+
* "veridocs": {
|
|
12
|
+
* "command": "npx",
|
|
13
|
+
* "args": ["-y", "@veridocs/mcp"],
|
|
14
|
+
* "env": {
|
|
15
|
+
* "VERIDOCS_API_KEY": "vdk_...",
|
|
16
|
+
* "VERIDOCS_API_URL": "https://veridocs.dev"
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* Environment variables:
|
|
23
|
+
* VERIDOCS_API_KEY — required; your vdk_... key (get one at veridocs.dev)
|
|
24
|
+
* VERIDOCS_API_URL — optional; defaults to https://veridocs.dev
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
28
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
29
|
+
import {
|
|
30
|
+
CallToolRequestSchema,
|
|
31
|
+
ListToolsRequestSchema,
|
|
32
|
+
type Tool,
|
|
33
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
34
|
+
|
|
35
|
+
const API_KEY = process.env.VERIDOCS_API_KEY ?? "";
|
|
36
|
+
const BASE_URL = (process.env.VERIDOCS_API_URL ?? "https://veridocs.dev").replace(/\/$/, "");
|
|
37
|
+
|
|
38
|
+
if (!API_KEY) {
|
|
39
|
+
process.stderr.write("[veridocs-mcp] VERIDOCS_API_KEY is not set. Get a key at veridocs.dev\n");
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function vd<T = unknown>(
|
|
44
|
+
method: "GET" | "POST",
|
|
45
|
+
path: string,
|
|
46
|
+
body?: unknown,
|
|
47
|
+
): Promise<T> {
|
|
48
|
+
const res = await fetch(`${BASE_URL}${path}`, {
|
|
49
|
+
method,
|
|
50
|
+
headers: {
|
|
51
|
+
"Content-Type": "application/json",
|
|
52
|
+
"x-api-key": API_KEY,
|
|
53
|
+
},
|
|
54
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
55
|
+
});
|
|
56
|
+
const text = await res.text();
|
|
57
|
+
let json: T;
|
|
58
|
+
try { json = JSON.parse(text) as T; }
|
|
59
|
+
catch { throw new Error(`VeriDOCS API returned non-JSON (${res.status}): ${text.slice(0, 200)}`); }
|
|
60
|
+
if (!res.ok) {
|
|
61
|
+
const err = json as Record<string, string>;
|
|
62
|
+
throw new Error(`VeriDOCS API error ${res.status}: ${err.error ?? err.message ?? text.slice(0, 200)}`);
|
|
63
|
+
}
|
|
64
|
+
return json;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const tools: Tool[] = [
|
|
68
|
+
{
|
|
69
|
+
name: "vd_evaluate",
|
|
70
|
+
description:
|
|
71
|
+
"Submit an AI agent action proposal to VeriDOCS for governance evaluation. " +
|
|
72
|
+
"Returns a cryptographically-signed receipt with a verdict of EXECUTE, BLOCK, REVIEW, or SHADOW. " +
|
|
73
|
+
"Use this before any consequential agent action (sending emails, modifying data, making payments, etc.).",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
type: "object",
|
|
76
|
+
required: ["action_type", "agent_id"],
|
|
77
|
+
properties: {
|
|
78
|
+
action_type: {
|
|
79
|
+
type: "string",
|
|
80
|
+
description: "Semantic name for the action (e.g. 'send_email', 'delete_record', 'make_payment')",
|
|
81
|
+
},
|
|
82
|
+
agent_id: {
|
|
83
|
+
type: "string",
|
|
84
|
+
description: "Identifier for the AI agent making the proposal",
|
|
85
|
+
},
|
|
86
|
+
parameters: {
|
|
87
|
+
type: "object",
|
|
88
|
+
description: "Action-specific parameters as a JSON object",
|
|
89
|
+
},
|
|
90
|
+
idempotency_key: {
|
|
91
|
+
type: "string",
|
|
92
|
+
description: "Optional unique key — same key returns the cached receipt",
|
|
93
|
+
},
|
|
94
|
+
guardian_timeout_policy: {
|
|
95
|
+
type: "string",
|
|
96
|
+
enum: ["fail_closed", "fail_open"],
|
|
97
|
+
description: "What to do if the Guardian times out. Default: fail_closed (block the action)",
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "vd_get_receipt",
|
|
104
|
+
description: "Retrieve a VeriDOCS audit receipt by its UUID. Returns the full receipt including verdict, signature, and policy pack hash.",
|
|
105
|
+
inputSchema: {
|
|
106
|
+
type: "object",
|
|
107
|
+
required: ["receipt_id"],
|
|
108
|
+
properties: {
|
|
109
|
+
receipt_id: { type: "string", description: "UUID of the receipt to retrieve" },
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "vd_verify_receipt",
|
|
115
|
+
description:
|
|
116
|
+
"Cryptographically verify a VeriDOCS receipt. Checks the Ed25519 signature and confirms " +
|
|
117
|
+
"the signing key is ACTIVE. Returns valid: true/false with a reason.",
|
|
118
|
+
inputSchema: {
|
|
119
|
+
type: "object",
|
|
120
|
+
required: ["receipt_id"],
|
|
121
|
+
properties: {
|
|
122
|
+
receipt_id: { type: "string", description: "UUID of the receipt to verify" },
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
name: "vd_list_receipts",
|
|
128
|
+
description: "List recent VeriDOCS audit receipts for the authenticated tenant. Supports filtering by agent and verdict.",
|
|
129
|
+
inputSchema: {
|
|
130
|
+
type: "object",
|
|
131
|
+
properties: {
|
|
132
|
+
limit: { type: "number", description: "Number of receipts to return (max 100, default 20)" },
|
|
133
|
+
offset: { type: "number", description: "Pagination offset (default 0)" },
|
|
134
|
+
agent_id: { type: "string", description: "Filter by agent ID" },
|
|
135
|
+
verdict: { type: "string", enum: ["EXECUTE", "BLOCK", "REVIEW", "SHADOW"], description: "Filter by verdict" },
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
name: "vd_usage",
|
|
141
|
+
description:
|
|
142
|
+
"Get current VeriDOCS quota usage — receipts used, receipts remaining, credit balance, " +
|
|
143
|
+
"billing cycle dates, and plan tier.",
|
|
144
|
+
inputSchema: { type: "object", properties: {} },
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "vd_list_policy_packs",
|
|
148
|
+
description: "List all governance policy packs for the authenticated tenant, including which one is currently active.",
|
|
149
|
+
inputSchema: { type: "object", properties: {} },
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const server = new Server(
|
|
154
|
+
{ name: "veridocs", version: "0.1.0" },
|
|
155
|
+
{ capabilities: { tools: {} } },
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
|
|
159
|
+
|
|
160
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
161
|
+
const { name, arguments: args = {} } = req.params;
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
switch (name) {
|
|
165
|
+
case "vd_evaluate": {
|
|
166
|
+
const result = await vd("POST", "/v1/evaluate", {
|
|
167
|
+
action_type: args.action_type,
|
|
168
|
+
agent_id: args.agent_id,
|
|
169
|
+
parameters: args.parameters ?? {},
|
|
170
|
+
idempotency_key: args.idempotency_key,
|
|
171
|
+
guardian_timeout_policy: args.guardian_timeout_policy ?? "fail_closed",
|
|
172
|
+
});
|
|
173
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
174
|
+
}
|
|
175
|
+
case "vd_get_receipt": {
|
|
176
|
+
const result = await vd("GET", `/v1/receipts/${args.receipt_id}`);
|
|
177
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
178
|
+
}
|
|
179
|
+
case "vd_verify_receipt": {
|
|
180
|
+
const result = await vd("GET", `/v1/receipts/${args.receipt_id}/verify`);
|
|
181
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
182
|
+
}
|
|
183
|
+
case "vd_list_receipts": {
|
|
184
|
+
const params = new URLSearchParams();
|
|
185
|
+
if (args.limit) params.set("limit", String(args.limit));
|
|
186
|
+
if (args.offset) params.set("offset", String(args.offset));
|
|
187
|
+
if (args.agent_id) params.set("agent_id", String(args.agent_id));
|
|
188
|
+
if (args.verdict) params.set("verdict", String(args.verdict));
|
|
189
|
+
const result = await vd("GET", `/v1/receipts?${params}`);
|
|
190
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
191
|
+
}
|
|
192
|
+
case "vd_usage": {
|
|
193
|
+
const result = await vd("GET", "/v1/usage");
|
|
194
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
195
|
+
}
|
|
196
|
+
case "vd_list_policy_packs": {
|
|
197
|
+
const result = await vd("GET", "/v1/policy-packs");
|
|
198
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
199
|
+
}
|
|
200
|
+
default:
|
|
201
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
202
|
+
}
|
|
203
|
+
} catch (err: unknown) {
|
|
204
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
205
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const transport = new StdioServerTransport();
|
|
210
|
+
await server.connect(transport);
|