@atbash/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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Chromaway AB
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,161 @@
1
+ # `@atbash/mcp`
2
+
3
+ Expose Atbash as a standalone MCP server.
4
+
5
+ This package starts an MCP server process that loads one Atbash agent identity and exposes safety and query tools over the Model Context Protocol. Your MCP host or client remains the real decision-maker — this package does not execute your business tools.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @atbash/mcp
11
+ ```
12
+
13
+ ## When To Use It
14
+
15
+ Use this package when:
16
+
17
+ - your host already supports MCP
18
+ - you want one Atbash tool server to serve one or many MCP clients
19
+ - you want Atbash checks without coupling your app directly to the SDK
20
+
21
+ Do not use this when you need deep framework lifecycle integration — use a framework-native package like `@atbash/eliza-plugin` or `@atbash/langgraph` instead.
22
+
23
+ ## Quick Start
24
+
25
+ ### Claude Desktop
26
+
27
+ Add to your `claude_desktop_config.json`:
28
+
29
+ ```json
30
+ {
31
+ "mcpServers": {
32
+ "atbash": {
33
+ "command": "npx",
34
+ "args": ["-y", "@atbash/mcp"],
35
+ "env": {
36
+ "ATBASH_AGENT_PRIVKEY": "your_agent_private_key_here"
37
+ }
38
+ }
39
+ }
40
+ }
41
+ ```
42
+
43
+ ### Any MCP Client
44
+
45
+ ```js
46
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
47
+
48
+ const transport = new StdioClientTransport({
49
+ command: "npx",
50
+ args: ["-y", "@atbash/mcp"],
51
+ env: {
52
+ ...process.env,
53
+ ATBASH_AGENT_PRIVKEY: process.env.ATBASH_AGENT_PRIVKEY,
54
+ },
55
+ });
56
+ ```
57
+
58
+ ## Environment Variables
59
+
60
+ | Variable | Required | Description |
61
+ |---|---|---|
62
+ | `ATBASH_AGENT_PRIVKEY` | Yes | Your Atbash agent private key |
63
+ | `ATBASH_ENDPOINT` | No | Override the default Atbash endpoint (`https://atbash.ai`) |
64
+
65
+ ## Tools
66
+
67
+ ### Safety Tools
68
+
69
+ #### `atbash_judge`
70
+
71
+ Submit an action for safety judgment before executing it.
72
+
73
+ | Input | Type | Required | Description |
74
+ |---|---|---|---|
75
+ | `action` | string | Yes | Plain text description of the action |
76
+ | `context` | string | Yes | Why this action is being taken |
77
+ | `tool_name` | string | No | Name of the tool being called |
78
+ | `tool_args_json` | string | No | JSON string of tool arguments |
79
+
80
+ Returns: `{ verdict, allow, reason, tool_call_id }`
81
+
82
+ #### `atbash_log`
83
+
84
+ Log a tool call on-chain without requesting a verdict.
85
+
86
+ | Input | Type | Required |
87
+ |---|---|---|
88
+ | `action` | string | Yes |
89
+ | `context` | string | Yes |
90
+ | `tool_name` | string | No |
91
+ | `tool_args_json` | string | No |
92
+
93
+ #### `atbash_check_agent`
94
+
95
+ Check whether an agent is registered on the Atbash platform.
96
+
97
+ | Input | Type | Description |
98
+ |---|---|---|
99
+ | `pubkey` | string | Agent public key (defaults to server agent) |
100
+
101
+ #### `atbash_judgment_status`
102
+
103
+ Poll the status of a previously submitted judgment.
104
+
105
+ | Input | Type | Description |
106
+ |---|---|---|
107
+ | `tool_call_id` | string | ID returned from `atbash_judge` |
108
+ | `agent_pubkey` | string | Agent public key (defaults to server agent) |
109
+
110
+ ### Query Tools (read-only)
111
+
112
+ | Tool | Description |
113
+ |---|---|
114
+ | `atbash_get_policy` | Get agent policy and jail status |
115
+ | `atbash_get_agent_detail` | Get agent metadata |
116
+ | `atbash_get_tool_calls` | List recent tool calls across all agents |
117
+ | `atbash_get_agent_tool_calls` | List recent tool calls for one agent |
118
+ | `atbash_get_org_tool_calls` | List recent tool calls for an organization |
119
+ | `atbash_get_tool_call_full` | Get full detail for a single tool call |
120
+ | `atbash_get_tool_call_count` | Get total on-chain tool call count |
121
+ | `atbash_get_tier_info` | Get organization tier information |
122
+ | `atbash_get_held_actions` | List actions pending operator review |
123
+ | `atbash_get_reviews` | List completed operator reviews |
124
+ | `atbash_get_safety_stats` | Get chain-wide safety statistics |
125
+
126
+ ## Verdict Handling
127
+
128
+ | Verdict | Meaning | What To Do |
129
+ |---|---|---|
130
+ | `ALLOW` | Safe to proceed | Execute the real tool |
131
+ | `HOLD` | Logged for async review | Execution is allowed; the action is flagged for operator review in the background — keep `tool_call_id` to poll status later |
132
+ | `BLOCK` | Policy violation | Stop; show `reason` to operator |
133
+ | `ERROR` | Judge unreachable | Fail closed |
134
+
135
+ ## Sending Better Inputs
136
+
137
+ Better inputs produce better safety decisions.
138
+
139
+ Weak:
140
+ ```json
141
+ { "action": "do payment", "context": "finance" }
142
+ ```
143
+
144
+ Better:
145
+ ```json
146
+ {
147
+ "action": "Bank transfer $25 to a new external vendor account",
148
+ "context": "Treasury payout review before execution",
149
+ "tool_name": "send_bank_transfer",
150
+ "tool_args_json": "{\"amount\":25,\"recipient\":\"new vendor\"}"
151
+ }
152
+ ```
153
+
154
+ ## Example
155
+
156
+ A runnable example is in [`examples/mcp-runtime-agent/`](./examples/mcp-runtime-agent/).
157
+
158
+ ```bash
159
+ npm install && npm run build
160
+ ATBASH_AGENT_PRIVKEY=your_key_here node examples/mcp-runtime-agent/client.mjs
161
+ ```
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/index.js ADDED
@@ -0,0 +1,449 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { loadAgent } from "@atbash/sdk";
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
+
8
+ // src/prompts/safety.ts
9
+ import { z } from "zod";
10
+ function registerSafetyPrompt(server2) {
11
+ const promptServer = server2;
12
+ if (!promptServer.registerPrompt) {
13
+ return;
14
+ }
15
+ promptServer.registerPrompt(
16
+ "atbash_safety_check",
17
+ {
18
+ description: "Prepare a consistent pre-execution Atbash safety review request.",
19
+ inputSchema: z.object({
20
+ action: z.string().describe("Action to evaluate"),
21
+ context: z.string().describe("Why the action is being taken")
22
+ })
23
+ },
24
+ async ({ action, context }) => ({
25
+ messages: [
26
+ {
27
+ role: "user",
28
+ content: {
29
+ type: "text",
30
+ text: [
31
+ "Use the Atbash tools to evaluate the following action before execution.",
32
+ `Action: ${action}`,
33
+ `Context: ${context}`,
34
+ "If the result is HOLD, explain that operator review is required before proceeding."
35
+ ].join("\n")
36
+ }
37
+ }
38
+ ]
39
+ })
40
+ );
41
+ }
42
+
43
+ // src/resources/policy.ts
44
+ function registerPolicyResource(server2, agent2, endpoint2) {
45
+ void server2;
46
+ void agent2;
47
+ void endpoint2;
48
+ return;
49
+ }
50
+
51
+ // src/tools/judge.ts
52
+ import {
53
+ checkAgentExists,
54
+ createAtbashClient,
55
+ logToolCall
56
+ } from "@atbash/sdk";
57
+ import { z as z2 } from "zod";
58
+
59
+ // src/utils.ts
60
+ function createClientOpts(endpoint2) {
61
+ return endpoint2 ? { endpoint: endpoint2 } : void 0;
62
+ }
63
+ function safeErrorMessage(error) {
64
+ return error instanceof Error ? error.message : String(error);
65
+ }
66
+ function toJsonContent(value) {
67
+ return {
68
+ content: [{ type: "text", text: JSON.stringify(value, null, 2) }]
69
+ };
70
+ }
71
+ function toErrorContent(error) {
72
+ return {
73
+ content: [{ type: "text", text: `Error: ${safeErrorMessage(error)}` }],
74
+ isError: true
75
+ };
76
+ }
77
+
78
+ // src/tools/judge.ts
79
+ function registerJudgeTools(server2, agent2, endpoint2) {
80
+ const opts = createClientOpts(endpoint2);
81
+ const client = createAtbashClient({
82
+ keyPair: { privKey: agent2.privkey, pubKey: agent2.pubkey },
83
+ judge: endpoint2 ? { endpoint: endpoint2 } : void 0
84
+ });
85
+ server2.registerTool(
86
+ "atbash_judge",
87
+ {
88
+ description: "Submit an action for safety judgment before executing it. Returns ALLOW, HOLD, BLOCK, or ERROR.",
89
+ inputSchema: z2.object({
90
+ action: z2.string().describe("Plain text description of the action to judge"),
91
+ context: z2.string().describe("Why this action is being taken"),
92
+ tool_name: z2.string().optional().describe("Name of the tool being called"),
93
+ tool_args_json: z2.string().optional().describe("JSON string of tool arguments")
94
+ })
95
+ },
96
+ async ({ action, context, tool_name, tool_args_json }) => {
97
+ try {
98
+ let parsedArgs = void 0;
99
+ if (tool_args_json) {
100
+ try {
101
+ parsedArgs = JSON.parse(tool_args_json);
102
+ } catch {
103
+ parsedArgs = tool_args_json;
104
+ }
105
+ }
106
+ const decision = await client.auditToolCall({
107
+ toolName: tool_name ?? "mcp_judge",
108
+ args: parsedArgs ?? { action },
109
+ context: `${action} \u2014 ${context}`
110
+ });
111
+ const normalized = decision.verdict === "HOLD" ? { ...decision, verdict: "ALLOW", allow: true } : decision;
112
+ return toJsonContent(normalized);
113
+ } catch (error) {
114
+ return toErrorContent(error);
115
+ }
116
+ }
117
+ );
118
+ server2.registerTool(
119
+ "atbash_log",
120
+ {
121
+ description: "Log a tool call on-chain without requesting a verdict.",
122
+ inputSchema: z2.object({
123
+ action: z2.string().describe("Action description"),
124
+ context: z2.string().describe("Action context"),
125
+ tool_name: z2.string().optional().describe("Tool name"),
126
+ tool_args_json: z2.string().optional().describe("Tool arguments JSON")
127
+ })
128
+ },
129
+ async ({ action, context, tool_name, tool_args_json }) => {
130
+ try {
131
+ const result = await logToolCall(
132
+ action,
133
+ context,
134
+ agent2,
135
+ void 0,
136
+ {
137
+ toolName: tool_name,
138
+ toolArgsJson: tool_args_json
139
+ },
140
+ opts
141
+ );
142
+ return toJsonContent(result);
143
+ } catch (error) {
144
+ return toErrorContent(error);
145
+ }
146
+ }
147
+ );
148
+ server2.registerTool(
149
+ "atbash_check_agent",
150
+ {
151
+ description: "Check whether an agent is registered on the Atbash platform.",
152
+ inputSchema: z2.object({
153
+ pubkey: z2.string().optional().describe("Agent public key, defaults to this server agent")
154
+ })
155
+ },
156
+ async ({ pubkey }) => {
157
+ try {
158
+ const selectedPubkey = pubkey ?? agent2.pubkey;
159
+ const registered = await checkAgentExists(selectedPubkey, opts);
160
+ return toJsonContent({ registered, pubkey: selectedPubkey });
161
+ } catch (error) {
162
+ return toErrorContent(error);
163
+ }
164
+ }
165
+ );
166
+ }
167
+
168
+ // src/tools/queries.ts
169
+ import {
170
+ getAgentDetail,
171
+ getAgentPolicy,
172
+ getAgentToolCalls,
173
+ getHeldActionReviews,
174
+ getOrgTierInfo,
175
+ getOrgToolCalls,
176
+ getPendingHeldActions,
177
+ getSafetyStats,
178
+ getToolCallCount,
179
+ getToolCallFull,
180
+ getToolCalls
181
+ } from "@atbash/sdk";
182
+ import { z as z3 } from "zod";
183
+ function defaultMaxCount(value) {
184
+ return value ?? 20;
185
+ }
186
+ function registerQueryTools(server2, agent2, endpoint2) {
187
+ const opts = createClientOpts(endpoint2);
188
+ server2.registerTool(
189
+ "atbash_get_policy",
190
+ {
191
+ description: "Get an agent policy configuration and jail status.",
192
+ inputSchema: z3.object({
193
+ pubkey: z3.string().optional().describe("Agent public key, defaults to the server agent")
194
+ })
195
+ },
196
+ async ({ pubkey }) => {
197
+ try {
198
+ return toJsonContent(await getAgentPolicy(pubkey ?? agent2.pubkey, opts));
199
+ } catch (error) {
200
+ return toErrorContent(error);
201
+ }
202
+ }
203
+ );
204
+ server2.registerTool(
205
+ "atbash_get_agent_detail",
206
+ {
207
+ description: "Get agent metadata for a public key.",
208
+ inputSchema: z3.object({
209
+ pubkey: z3.string().optional().describe("Agent public key, defaults to the server agent")
210
+ })
211
+ },
212
+ async ({ pubkey }) => {
213
+ try {
214
+ return toJsonContent(await getAgentDetail(pubkey ?? agent2.pubkey, opts));
215
+ } catch (error) {
216
+ return toErrorContent(error);
217
+ }
218
+ }
219
+ );
220
+ server2.registerTool(
221
+ "atbash_get_tool_calls",
222
+ {
223
+ description: "List recent tool calls across all agents.",
224
+ inputSchema: z3.object({
225
+ max_count: z3.number().int().positive().optional().describe("Maximum number of records")
226
+ })
227
+ },
228
+ async ({ max_count }) => {
229
+ try {
230
+ return toJsonContent(await getToolCalls(defaultMaxCount(max_count), opts));
231
+ } catch (error) {
232
+ return toErrorContent(error);
233
+ }
234
+ }
235
+ );
236
+ server2.registerTool(
237
+ "atbash_get_agent_tool_calls",
238
+ {
239
+ description: "List recent tool calls for one agent.",
240
+ inputSchema: z3.object({
241
+ pubkey: z3.string().optional().describe("Agent public key, defaults to the server agent"),
242
+ max_count: z3.number().int().positive().optional().describe("Maximum number of records")
243
+ })
244
+ },
245
+ async ({ pubkey, max_count }) => {
246
+ try {
247
+ return toJsonContent(
248
+ await getAgentToolCalls(pubkey ?? agent2.pubkey, defaultMaxCount(max_count), opts)
249
+ );
250
+ } catch (error) {
251
+ return toErrorContent(error);
252
+ }
253
+ }
254
+ );
255
+ server2.registerTool(
256
+ "atbash_get_org_tool_calls",
257
+ {
258
+ description: "List recent tool calls for an organization.",
259
+ inputSchema: z3.object({
260
+ org_name: z3.string().describe("Organization name"),
261
+ max_count: z3.number().int().positive().optional().describe("Maximum number of records")
262
+ })
263
+ },
264
+ async ({ org_name, max_count }) => {
265
+ try {
266
+ return toJsonContent(await getOrgToolCalls(org_name, defaultMaxCount(max_count), opts));
267
+ } catch (error) {
268
+ return toErrorContent(error);
269
+ }
270
+ }
271
+ );
272
+ server2.registerTool(
273
+ "atbash_get_tool_call_full",
274
+ {
275
+ description: "Get the full detail for a single tool call.",
276
+ inputSchema: z3.object({
277
+ tool_call_id: z3.string().describe("Tool call identifier")
278
+ })
279
+ },
280
+ async ({ tool_call_id }) => {
281
+ try {
282
+ return toJsonContent(await getToolCallFull(tool_call_id, opts));
283
+ } catch (error) {
284
+ return toErrorContent(error);
285
+ }
286
+ }
287
+ );
288
+ server2.registerTool(
289
+ "atbash_get_tool_call_count",
290
+ {
291
+ description: "Get the total number of tool calls on-chain.",
292
+ inputSchema: z3.object({})
293
+ },
294
+ async () => {
295
+ try {
296
+ return toJsonContent({ count: await getToolCallCount(opts) });
297
+ } catch (error) {
298
+ return toErrorContent(error);
299
+ }
300
+ }
301
+ );
302
+ server2.registerTool(
303
+ "atbash_get_tier_info",
304
+ {
305
+ description: "Get an organization's tier information.",
306
+ inputSchema: z3.object({
307
+ org_name: z3.string().describe("Organization name")
308
+ })
309
+ },
310
+ async ({ org_name }) => {
311
+ try {
312
+ return toJsonContent(await getOrgTierInfo(org_name, opts));
313
+ } catch (error) {
314
+ return toErrorContent(error);
315
+ }
316
+ }
317
+ );
318
+ server2.registerTool(
319
+ "atbash_get_held_actions",
320
+ {
321
+ description: "List actions currently waiting for operator review.",
322
+ inputSchema: z3.object({
323
+ org_name: z3.string().describe("Organization name"),
324
+ max_count: z3.number().int().positive().optional().describe("Maximum number of records")
325
+ })
326
+ },
327
+ async ({ org_name, max_count }) => {
328
+ try {
329
+ return toJsonContent(
330
+ await getPendingHeldActions(org_name, defaultMaxCount(max_count), opts)
331
+ );
332
+ } catch (error) {
333
+ return toErrorContent(error);
334
+ }
335
+ }
336
+ );
337
+ server2.registerTool(
338
+ "atbash_get_reviews",
339
+ {
340
+ description: "List completed operator reviews for held actions.",
341
+ inputSchema: z3.object({
342
+ org_name: z3.string().describe("Organization name"),
343
+ max_count: z3.number().int().positive().optional().describe("Maximum number of records")
344
+ })
345
+ },
346
+ async ({ org_name, max_count }) => {
347
+ try {
348
+ return toJsonContent(await getHeldActionReviews(org_name, defaultMaxCount(max_count), opts));
349
+ } catch (error) {
350
+ return toErrorContent(error);
351
+ }
352
+ }
353
+ );
354
+ server2.registerTool(
355
+ "atbash_get_safety_stats",
356
+ {
357
+ description: "Get high-level chain-wide safety statistics.",
358
+ inputSchema: z3.object({})
359
+ },
360
+ async () => {
361
+ try {
362
+ return toJsonContent(await getSafetyStats(opts));
363
+ } catch (error) {
364
+ return toErrorContent(error);
365
+ }
366
+ }
367
+ );
368
+ }
369
+
370
+ // src/tools/status.ts
371
+ import { z as z4 } from "zod";
372
+ function normalizeVerdict(raw) {
373
+ if (raw == null) return "No verdict";
374
+ const value = String(raw).toUpperCase();
375
+ if (value === "ALLOW" || value === "GREEN") return "ALLOW";
376
+ if (value === "HOLD" || value === "YELLOW") return "HOLD";
377
+ if (value === "BLOCK" || value === "RED") return "BLOCK";
378
+ return value;
379
+ }
380
+ function normalizeStatus(raw) {
381
+ const value = String(raw ?? "").toLowerCase();
382
+ if (value === "pending" || value === "answered" || value === "error") {
383
+ return value;
384
+ }
385
+ return "error";
386
+ }
387
+ function registerStatusTools(server2, defaultPubkey, endpoint2) {
388
+ const baseUrl = (endpoint2 ?? "https://atbash.ai").replace(/\/$/, "");
389
+ server2.registerTool(
390
+ "atbash_judgment_status",
391
+ {
392
+ description: "Poll the status of a previously submitted judgment.",
393
+ inputSchema: z4.object({
394
+ tool_call_id: z4.string().describe("The tool_call_id returned from atbash_judge"),
395
+ agent_pubkey: z4.string().optional().describe("Agent public key, defaults to the server agent")
396
+ })
397
+ },
398
+ async ({ tool_call_id, agent_pubkey }) => {
399
+ try {
400
+ const pubkey = agent_pubkey ?? defaultPubkey;
401
+ const url = new URL(`${baseUrl}/api/v1/judge`);
402
+ url.searchParams.set("tool_call_id", tool_call_id);
403
+ url.searchParams.set("agent_pubkey", pubkey);
404
+ const response = await fetch(url, {
405
+ method: "GET",
406
+ headers: { Accept: "application/json" }
407
+ });
408
+ if (!response.ok) {
409
+ const body = await response.text().catch(() => "");
410
+ throw new Error(`API error ${response.status}: ${body || response.statusText}`);
411
+ }
412
+ const data = await response.json();
413
+ return toJsonContent({
414
+ status: normalizeStatus(data.status),
415
+ verdict: normalizeVerdict(data.verdict),
416
+ reason: String(data.reason ?? ""),
417
+ judgmentId: String(data.judgmentId ?? tool_call_id),
418
+ onChain: Boolean(data.onChain),
419
+ cached: Boolean(data.cached),
420
+ responseTimeMs: Number(data.responseTimeMs ?? 0),
421
+ tool_call_id,
422
+ agent_pubkey: pubkey
423
+ });
424
+ } catch (error) {
425
+ return toErrorContent(error);
426
+ }
427
+ }
428
+ );
429
+ }
430
+
431
+ // src/index.ts
432
+ var privkey = process.env.ATBASH_AGENT_PRIVKEY;
433
+ if (!privkey) {
434
+ console.error("ATBASH_AGENT_PRIVKEY env var is required");
435
+ process.exit(1);
436
+ }
437
+ var agent = loadAgent(privkey);
438
+ var endpoint = process.env.ATBASH_ENDPOINT;
439
+ var server = new McpServer({
440
+ name: "atbash-safety",
441
+ version: "1.0.0"
442
+ });
443
+ registerJudgeTools(server, agent, endpoint);
444
+ registerStatusTools(server, agent.pubkey, endpoint);
445
+ registerQueryTools(server, agent, endpoint);
446
+ registerPolicyResource(server, agent, endpoint);
447
+ registerSafetyPrompt(server);
448
+ var transport = new StdioServerTransport();
449
+ await server.connect(transport);
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@atbash/mcp",
3
+ "version": "0.1.0",
4
+ "description": "Atbash safety judge exposed as a standalone MCP server",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "atbash-mcp": "dist/index.js"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "engines": {
21
+ "node": ">=18.0.0"
22
+ },
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "keywords": [
27
+ "atbash",
28
+ "mcp",
29
+ "ai-safety",
30
+ "agent-safety",
31
+ "model-context-protocol",
32
+ "judge",
33
+ "policy"
34
+ ],
35
+ "license": "MIT",
36
+ "scripts": {
37
+ "build": "tsup src/index.ts --format esm --dts --clean"
38
+ },
39
+ "dependencies": {
40
+ "@atbash/sdk": "^0.3.8",
41
+ "@modelcontextprotocol/sdk": "^1.12.3",
42
+ "zod": "^3.25.76"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^25.7.0",
46
+ "tsup": "^8.0.0",
47
+ "typescript": "^5.0.0"
48
+ }
49
+ }