sovr-mcp-server 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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +341 -0
  3. package/dist/api/client.d.ts +59 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/client.js +162 -0
  6. package/dist/api/client.js.map +1 -0
  7. package/dist/auth/apiKey.d.ts +53 -0
  8. package/dist/auth/apiKey.d.ts.map +1 -0
  9. package/dist/auth/apiKey.js +146 -0
  10. package/dist/auth/apiKey.js.map +1 -0
  11. package/dist/cli.d.ts +10 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +59 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/crypto/ed25519.d.ts +46 -0
  16. package/dist/crypto/ed25519.d.ts.map +1 -0
  17. package/dist/crypto/ed25519.js +144 -0
  18. package/dist/crypto/ed25519.js.map +1 -0
  19. package/dist/index.d.ts +13 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +335 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/local/client.d.ts +74 -0
  24. package/dist/local/client.d.ts.map +1 -0
  25. package/dist/local/client.js +118 -0
  26. package/dist/local/client.js.map +1 -0
  27. package/dist/local/store.d.ts +127 -0
  28. package/dist/local/store.d.ts.map +1 -0
  29. package/dist/local/store.js +384 -0
  30. package/dist/local/store.js.map +1 -0
  31. package/dist/tools/auditQuery.d.ts +101 -0
  32. package/dist/tools/auditQuery.d.ts.map +1 -0
  33. package/dist/tools/auditQuery.js +136 -0
  34. package/dist/tools/auditQuery.js.map +1 -0
  35. package/dist/tools/gateCheck.d.ts +61 -0
  36. package/dist/tools/gateCheck.d.ts.map +1 -0
  37. package/dist/tools/gateCheck.js +96 -0
  38. package/dist/tools/gateCheck.js.map +1 -0
  39. package/dist/tools/grantPermit.d.ts +45 -0
  40. package/dist/tools/grantPermit.d.ts.map +1 -0
  41. package/dist/tools/grantPermit.js +121 -0
  42. package/dist/tools/grantPermit.js.map +1 -0
  43. package/dist/tools/index.d.ts +163 -0
  44. package/dist/tools/index.d.ts.map +1 -0
  45. package/dist/tools/index.js +31 -0
  46. package/dist/tools/index.js.map +1 -0
  47. package/dist/tools/killSwitch.d.ts +52 -0
  48. package/dist/tools/killSwitch.d.ts.map +1 -0
  49. package/dist/tools/killSwitch.js +85 -0
  50. package/dist/tools/killSwitch.js.map +1 -0
  51. package/dist/tools/policyList.d.ts +68 -0
  52. package/dist/tools/policyList.d.ts.map +1 -0
  53. package/dist/tools/policyList.js +96 -0
  54. package/dist/tools/policyList.js.map +1 -0
  55. package/dist/tools/requestApproval.d.ts +56 -0
  56. package/dist/tools/requestApproval.d.ts.map +1 -0
  57. package/dist/tools/requestApproval.js +97 -0
  58. package/dist/tools/requestApproval.js.map +1 -0
  59. package/dist/tools/submitReceipt.d.ts +145 -0
  60. package/dist/tools/submitReceipt.d.ts.map +1 -0
  61. package/dist/tools/submitReceipt.js +162 -0
  62. package/dist/tools/submitReceipt.js.map +1 -0
  63. package/dist/tools/systemStatus.d.ts +32 -0
  64. package/dist/tools/systemStatus.d.ts.map +1 -0
  65. package/dist/tools/systemStatus.js +67 -0
  66. package/dist/tools/systemStatus.js.map +1 -0
  67. package/dist/types/index.d.ts +146 -0
  68. package/dist/types/index.d.ts.map +1 -0
  69. package/dist/types/index.js +33 -0
  70. package/dist/types/index.js.map +1 -0
  71. package/package.json +71 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SOVR
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,341 @@
1
+ # SOVR MCP Server
2
+
3
+ > **SOVR MCP Server turns any AI agent into a governed executor: no irreversible action without a verifiable permit, audit trail, and evidence bundle.**
4
+
5
+ ## Overview
6
+
7
+ SOVR MCP Server is a [Model Context Protocol](https://modelcontextprotocol.io/) server that provides a **Responsibility Layer** for AI agents. It intercepts irreversible operations and ensures:
8
+
9
+ - **Gate Check**: Every action is evaluated against policies before execution
10
+ - **Approval Workflow**: High-risk operations require human approval
11
+ - **Verifiable Permits**: Signed, time-limited execution credentials
12
+ - **Audit Trail**: Immutable evidence chain for compliance
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ # Via npx (recommended)
18
+ npx sovr-mcp-server
19
+
20
+ # Or install globally
21
+ npm install -g sovr-mcp-server
22
+ sovr-mcp-server
23
+ ```
24
+
25
+ ## Configuration
26
+
27
+ Set the following environment variables:
28
+
29
+ ```bash
30
+ # Required (unless using local mode)
31
+ export SOVR_API_KEY="sovr_sk_your_tenant_id_your_key"
32
+
33
+ # Optional
34
+ export SOVR_API_URL="https://api.sovr.inc" # Default API endpoint
35
+ export SOVR_SIGNING_KEY="your_ed25519_private_key_hex" # For production
36
+ export SOVR_LOCAL_MODE="true" # Enable local mode (no API required)
37
+ ```
38
+
39
+ ### Local Development Mode
40
+
41
+ For testing without a remote API, enable local mode:
42
+
43
+ ```json
44
+ {
45
+ "mcpServers": {
46
+ "sovr": {
47
+ "command": "npx",
48
+ "args": ["sovr-mcp-server"],
49
+ "env": {
50
+ "SOVR_LOCAL_MODE": "true"
51
+ }
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ Local mode provides:
58
+ - In-memory policy engine with default rules
59
+ - Full gate_check, approval, permit, and receipt workflow
60
+ - Additional tools: `kill_switch`, `audit_query`, `policy_list`
61
+
62
+ ## Claude Desktop Integration
63
+
64
+ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "sovr": {
70
+ "command": "npx",
71
+ "args": ["sovr-mcp-server"],
72
+ "env": {
73
+ "SOVR_API_KEY": "sovr_sk_your_tenant_id_your_key"
74
+ }
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ ## Available Tools
81
+
82
+ ### `gate_check`
83
+
84
+ Evaluate if an irreversible action should be allowed.
85
+
86
+ **Input:**
87
+ ```json
88
+ {
89
+ "action": "delete_database",
90
+ "resource": "production/users",
91
+ "context": { "reason": "cleanup" }
92
+ }
93
+ ```
94
+
95
+ **Output:**
96
+ ```json
97
+ {
98
+ "decision_id": "dec_abc123",
99
+ "allowed": true,
100
+ "requires_approval": false,
101
+ "reason": "Action matches allowed policy",
102
+ "risk_score": 45,
103
+ "value_score": 80,
104
+ "policy_version": "v1.2.0"
105
+ }
106
+ ```
107
+
108
+ ### `request_approval`
109
+
110
+ Request human approval for high-risk operations.
111
+
112
+ **Input:**
113
+ ```json
114
+ {
115
+ "decision_id": "dec_abc123",
116
+ "justification": "Need to delete test data before production release",
117
+ "urgency": "high"
118
+ }
119
+ ```
120
+
121
+ **Output:**
122
+ ```json
123
+ {
124
+ "approval_id": "apr_xyz789",
125
+ "status": "pending",
126
+ "approval_url": "https://sovr.inc/approve/apr_xyz789",
127
+ "estimated_wait_seconds": 300,
128
+ "expires_at": 1706745600
129
+ }
130
+ ```
131
+
132
+ ### `grant_permit`
133
+
134
+ Issue a cryptographically signed execution permit.
135
+
136
+ **Input:**
137
+ ```json
138
+ {
139
+ "decision_id": "dec_abc123",
140
+ "ttl_seconds": 300
141
+ }
142
+ ```
143
+
144
+ **Output:**
145
+ ```json
146
+ {
147
+ "permit_id": "permit_def456",
148
+ "jti": "unique_token_id",
149
+ "decision_id": "dec_abc123",
150
+ "expires_at": 1706745900,
151
+ "signature": "ed25519_signature_hex",
152
+ "public_key": "ed25519_public_key_hex"
153
+ }
154
+ ```
155
+
156
+ ### `submit_receipt`
157
+
158
+ Record execution evidence to complete the audit trail.
159
+
160
+ ### `system_status`
161
+
162
+ Check system health and kill switch state.
163
+
164
+ **Output:**
165
+ ```json
166
+ {
167
+ "healthy": true,
168
+ "kill_switch_active": false,
169
+ "api_version": "v1.0.0",
170
+ "policy_version": "v1.2.0"
171
+ }
172
+ ```
173
+
174
+ ### Local Mode Tools
175
+
176
+ #### `kill_switch`
177
+
178
+ Emergency stop mechanism (local mode only).
179
+
180
+ **Input:**
181
+ ```json
182
+ {
183
+ "action": "activate",
184
+ "reason": "Security incident detected",
185
+ "confirmation": "CONFIRM_KILL_SWITCH"
186
+ }
187
+ ```
188
+
189
+ #### `audit_query`
190
+
191
+ Query the audit trail (local mode only).
192
+
193
+ **Input:**
194
+ ```json
195
+ {
196
+ "decision_id": "dec_abc123",
197
+ "limit": 20
198
+ }
199
+ ```
200
+
201
+ #### `policy_list`
202
+
203
+ View policy configurations (local mode only).
204
+
205
+ **Input:**
206
+ ```json
207
+ {
208
+ "active_only": true,
209
+ "include_rules": true
210
+ }
211
+ ```
212
+
213
+ **Input:**
214
+ ```json
215
+ {
216
+ "decision_id": "dec_abc123",
217
+ "permit_id": "permit_def456",
218
+ "external_ref": "job_12345",
219
+ "status": "success",
220
+ "started_at": 1706745600,
221
+ "finished_at": 1706745650,
222
+ "output_hash": "sha512_hash_of_output",
223
+ "artifact_refs": ["s3://bucket/logs/job_12345.log"],
224
+ "idempotency_key": "unique_receipt_key"
225
+ }
226
+ ```
227
+
228
+ **Output:**
229
+ ```json
230
+ {
231
+ "receipt_id": "rcpt_ghi789",
232
+ "trust_hash": "sha512_trust_chain_hash",
233
+ "evidence_hash": "sha512_evidence_hash",
234
+ "chain_position": 42,
235
+ "recorded_at": 1706745660
236
+ }
237
+ ```
238
+
239
+ ## Execution Flow
240
+
241
+ ```
242
+ ┌─────────────────────────────────────────────────────────────────┐
243
+ │ AI Agent │
244
+ │ │
245
+ │ 1. "I want to delete the production database" │
246
+ │ │ │
247
+ │ ▼ │
248
+ │ ┌─────────────────────────────────────────────────────────────┐│
249
+ │ │ gate_check ││
250
+ │ │ action: "delete_database" ││
251
+ │ │ resource: "production/users" ││
252
+ │ └─────────────────────────────────────────────────────────────┘│
253
+ │ │ │
254
+ │ ▼ │
255
+ │ ┌─────────────────────────────────────────────────────────────┐│
256
+ │ │ Decision: requires_approval ││
257
+ │ └─────────────────────────────────────────────────────────────┘│
258
+ │ │ │
259
+ │ ▼ │
260
+ │ ┌─────────────────────────────────────────────────────────────┐│
261
+ │ │ request_approval ││
262
+ │ │ justification: "Cleanup before release" ││
263
+ │ └─────────────────────────────────────────────────────────────┘│
264
+ │ │ │
265
+ │ ▼ │
266
+ │ ┌─────────────────────────────────────────────────────────────┐│
267
+ │ │ Human approves via URL ││
268
+ │ └─────────────────────────────────────────────────────────────┘│
269
+ │ │ │
270
+ │ ▼ │
271
+ │ ┌─────────────────────────────────────────────────────────────┐│
272
+ │ │ grant_permit ││
273
+ │ │ → Signed permit (Ed25519, TTL: 5min) ││
274
+ │ └─────────────────────────────────────────────────────────────┘│
275
+ │ │ │
276
+ │ ▼ │
277
+ │ ┌─────────────────────────────────────────────────────────────┐│
278
+ │ │ Execute Action ││
279
+ │ │ (Agent performs the actual deletion) ││
280
+ │ └─────────────────────────────────────────────────────────────┘│
281
+ │ │ │
282
+ │ ▼ │
283
+ │ ┌─────────────────────────────────────────────────────────────┐│
284
+ │ │ submit_receipt ││
285
+ │ │ → Evidence recorded to audit chain ││
286
+ │ └─────────────────────────────────────────────────────────────┘│
287
+ │ │
288
+ └─────────────────────────────────────────────────────────────────┘
289
+ ```
290
+
291
+ ## API Key Scopes
292
+
293
+ | Scope | Description | Default |
294
+ |-------|-------------|---------|
295
+ | `gate:check` | Call gate_check | ✅ |
296
+ | `receipt:submit` | Submit execution receipts | ✅ |
297
+ | `permit:grant` | Grant execution permits | Admin only |
298
+ | `approval:request` | Request human approval | Admin only |
299
+ | `audit:read` | Read audit logs | Admin only |
300
+ | `status:read` | Read system status | Admin only |
301
+
302
+ ## Security
303
+
304
+ - **Ed25519 Signatures**: Permits are cryptographically signed
305
+ - **Time-Limited Permits**: Default 5 minutes, configurable 60-900 seconds
306
+ - **Audit Trail**: All operations are logged with trace IDs
307
+ - **Rate Limiting**: Per-key rate limits enforced
308
+
309
+ ## Pricing
310
+
311
+ | Metric | Description |
312
+ |--------|-------------|
313
+ | `irreversible.allowed` | Primary billing metric |
314
+ | `trust_bundle.exported` | Trust evidence packages |
315
+ | `approval.requested` | Human approval workflows |
316
+
317
+ ## Development
318
+
319
+ ```bash
320
+ # Install dependencies
321
+ pnpm install
322
+
323
+ # Run tests
324
+ pnpm test
325
+
326
+ # Build
327
+ pnpm build
328
+
329
+ # Run locally
330
+ SOVR_API_KEY=sovr_sk_test_key pnpm dev
331
+ ```
332
+
333
+ ## License
334
+
335
+ MIT
336
+
337
+ ## Links
338
+
339
+ - [SOVR Website](https://sovr.inc)
340
+ - [Documentation](https://docs.sovr.inc)
341
+ - [MCP Protocol](https://modelcontextprotocol.io/)
@@ -0,0 +1,59 @@
1
+ /**
2
+ * SOVR API Client
3
+ *
4
+ * Communicates with the SOVR backend (https://api.sovr.inc)
5
+ * All MCP tools delegate to this client for actual operations.
6
+ */
7
+ import type { GateCheckInput, GateCheckResult, RequestApprovalInput, ApprovalResult, SubmitReceiptInput, ReceiptResult, SystemStatus, ApiKey } from '../types/index.js';
8
+ export interface SovrClientConfig {
9
+ baseUrl: string;
10
+ apiKey: string;
11
+ timeout?: number;
12
+ }
13
+ export declare class SovrApiClient {
14
+ private baseUrl;
15
+ private apiKey;
16
+ private timeout;
17
+ constructor(config: SovrClientConfig);
18
+ /**
19
+ * Gate Check - Evaluate if an action should be allowed
20
+ */
21
+ gateCheck(input: GateCheckInput): Promise<GateCheckResult>;
22
+ /**
23
+ * Request Approval - Initiate human approval workflow
24
+ */
25
+ requestApproval(input: RequestApprovalInput): Promise<ApprovalResult>;
26
+ /**
27
+ * Get Approval Status
28
+ */
29
+ getApprovalStatus(approvalId: string): Promise<ApprovalResult>;
30
+ /**
31
+ * Submit Receipt - Record execution evidence
32
+ */
33
+ submitReceipt(input: SubmitReceiptInput): Promise<ReceiptResult>;
34
+ /**
35
+ * Get System Status
36
+ */
37
+ getSystemStatus(): Promise<SystemStatus>;
38
+ /**
39
+ * Validate API Key and get key info
40
+ */
41
+ validateApiKey(): Promise<ApiKey>;
42
+ /**
43
+ * Get Decision Details
44
+ */
45
+ getDecision(decisionId: string): Promise<GateCheckResult & {
46
+ approval?: ApprovalResult;
47
+ permit_granted?: boolean;
48
+ }>;
49
+ private request;
50
+ }
51
+ export declare class SovrApiError extends Error {
52
+ status: number;
53
+ code: string;
54
+ details?: Record<string, unknown> | undefined;
55
+ constructor(status: number, code: string, message: string, details?: Record<string, unknown> | undefined);
56
+ }
57
+ export declare function createClient(config: SovrClientConfig): SovrApiClient;
58
+ export declare function getClient(): SovrApiClient;
59
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,MAAM,EAEP,MAAM,mBAAmB,CAAC;AAM3B,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,gBAAgB;IAepC;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAOhE;;OAEG;IACG,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,cAAc,CAAC;IAO3E;;OAEG;IACG,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAMpE;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;IAOtE;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC;IAM9C;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAMvC;;OAEG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG;QAC/D,QAAQ,CAAC,EAAE,cAAc,CAAC;QAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;YAUY,OAAO;CAwDtB;AAMD,qBAAa,YAAa,SAAQ,KAAK;IAE5B,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,MAAM;IAEZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAHjC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAK3C;AAgBD,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,CAGpE;AAED,wBAAgB,SAAS,IAAI,aAAa,CAKzC"}
@@ -0,0 +1,162 @@
1
+ /**
2
+ * SOVR API Client
3
+ *
4
+ * Communicates with the SOVR backend (https://api.sovr.inc)
5
+ * All MCP tools delegate to this client for actual operations.
6
+ */
7
+ const DEFAULT_TIMEOUT = 30000; // 30 seconds
8
+ const MAX_RETRIES = 3;
9
+ const RETRY_DELAY = 1000; // 1 second
10
+ export class SovrApiClient {
11
+ baseUrl;
12
+ apiKey;
13
+ timeout;
14
+ constructor(config) {
15
+ // Support env var override for API URL
16
+ this.baseUrl = (config.baseUrl || process.env.SOVR_API_URL || 'https://api.sovr.inc').replace(/\/$/, '');
17
+ this.apiKey = config.apiKey;
18
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
19
+ // Log connection info (without exposing full API key)
20
+ const keyPreview = this.apiKey.slice(0, 15) + '...';
21
+ console.error(`[SOVR API] Connecting to ${this.baseUrl} with key ${keyPreview}`);
22
+ }
23
+ // ==========================================================================
24
+ // Core API Methods
25
+ // ==========================================================================
26
+ /**
27
+ * Gate Check - Evaluate if an action should be allowed
28
+ */
29
+ async gateCheck(input) {
30
+ return this.request('/api/mcp/gate-check', {
31
+ method: 'POST',
32
+ body: input,
33
+ });
34
+ }
35
+ /**
36
+ * Request Approval - Initiate human approval workflow
37
+ */
38
+ async requestApproval(input) {
39
+ return this.request('/api/mcp/request-approval', {
40
+ method: 'POST',
41
+ body: input,
42
+ });
43
+ }
44
+ /**
45
+ * Get Approval Status
46
+ */
47
+ async getApprovalStatus(approvalId) {
48
+ return this.request(`/api/mcp/approval/${approvalId}`, {
49
+ method: 'GET',
50
+ });
51
+ }
52
+ /**
53
+ * Submit Receipt - Record execution evidence
54
+ */
55
+ async submitReceipt(input) {
56
+ return this.request('/api/mcp/submit-receipt', {
57
+ method: 'POST',
58
+ body: input,
59
+ });
60
+ }
61
+ /**
62
+ * Get System Status
63
+ */
64
+ async getSystemStatus() {
65
+ return this.request('/api/mcp/status', {
66
+ method: 'GET',
67
+ });
68
+ }
69
+ /**
70
+ * Validate API Key and get key info
71
+ */
72
+ async validateApiKey() {
73
+ return this.request('/api/mcp/validate-key', {
74
+ method: 'GET',
75
+ });
76
+ }
77
+ /**
78
+ * Get Decision Details
79
+ */
80
+ async getDecision(decisionId) {
81
+ return this.request(`/api/mcp/decision/${decisionId}`, {
82
+ method: 'GET',
83
+ });
84
+ }
85
+ // ==========================================================================
86
+ // Internal Request Handler
87
+ // ==========================================================================
88
+ async request(path, options) {
89
+ const url = `${this.baseUrl}${path}`;
90
+ let lastError = null;
91
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
92
+ try {
93
+ const controller = new AbortController();
94
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
95
+ const response = await fetch(url, {
96
+ method: options.method,
97
+ headers: {
98
+ 'Content-Type': 'application/json',
99
+ 'Authorization': `Bearer ${this.apiKey}`,
100
+ 'X-SOVR-Client': 'sovr-mcp-server/0.1.0',
101
+ },
102
+ body: options.body ? JSON.stringify(options.body) : undefined,
103
+ signal: controller.signal,
104
+ });
105
+ clearTimeout(timeoutId);
106
+ if (!response.ok) {
107
+ const errorBody = await response.json().catch(() => ({}));
108
+ throw new SovrApiError(response.status, String(errorBody.code || 'API_ERROR'), String(errorBody.message || `HTTP ${response.status}`), errorBody.details);
109
+ }
110
+ return await response.json();
111
+ }
112
+ catch (error) {
113
+ lastError = error instanceof Error ? error : new Error(String(error));
114
+ // Don't retry on client errors (4xx)
115
+ if (error instanceof SovrApiError && error.status >= 400 && error.status < 500) {
116
+ throw error;
117
+ }
118
+ // Wait before retry (exponential backoff)
119
+ if (attempt < MAX_RETRIES - 1) {
120
+ await sleep(RETRY_DELAY * Math.pow(2, attempt));
121
+ }
122
+ }
123
+ }
124
+ throw lastError || new Error('Request failed after retries');
125
+ }
126
+ }
127
+ // ==========================================================================
128
+ // Error Class
129
+ // ==========================================================================
130
+ export class SovrApiError extends Error {
131
+ status;
132
+ code;
133
+ details;
134
+ constructor(status, code, message, details) {
135
+ super(message);
136
+ this.status = status;
137
+ this.code = code;
138
+ this.details = details;
139
+ this.name = 'SovrApiError';
140
+ }
141
+ }
142
+ // ==========================================================================
143
+ // Utilities
144
+ // ==========================================================================
145
+ function sleep(ms) {
146
+ return new Promise(resolve => setTimeout(resolve, ms));
147
+ }
148
+ // ==========================================================================
149
+ // Factory
150
+ // ==========================================================================
151
+ let clientInstance = null;
152
+ export function createClient(config) {
153
+ clientInstance = new SovrApiClient(config);
154
+ return clientInstance;
155
+ }
156
+ export function getClient() {
157
+ if (!clientInstance) {
158
+ throw new Error('SOVR API client not initialized. Call createClient() first.');
159
+ }
160
+ return clientInstance;
161
+ }
162
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,aAAa;AAC5C,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,WAAW;AAQrC,MAAM,OAAO,aAAa;IAChB,OAAO,CAAS;IAChB,MAAM,CAAS;IACf,OAAO,CAAS;IAExB,YAAY,MAAwB;QAClC,uCAAuC;QACvC,IAAI,CAAC,OAAO,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,sBAAsB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzG,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,eAAe,CAAC;QAEjD,sDAAsD;QACtD,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,4BAA4B,IAAI,CAAC,OAAO,aAAa,UAAU,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,6EAA6E;IAC7E,mBAAmB;IACnB,6EAA6E;IAE7E;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,KAAqB;QACnC,OAAO,IAAI,CAAC,OAAO,CAAkB,qBAAqB,EAAE;YAC1D,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,KAA2B;QAC/C,OAAO,IAAI,CAAC,OAAO,CAAiB,2BAA2B,EAAE;YAC/D,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB,CAAC,UAAkB;QACxC,OAAO,IAAI,CAAC,OAAO,CAAiB,qBAAqB,UAAU,EAAE,EAAE;YACrE,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,KAAyB;QAC3C,OAAO,IAAI,CAAC,OAAO,CAAgB,yBAAyB,EAAE;YAC5D,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe;QACnB,OAAO,IAAI,CAAC,OAAO,CAAe,iBAAiB,EAAE;YACnD,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc;QAClB,OAAO,IAAI,CAAC,OAAO,CAAS,uBAAuB,EAAE;YACnD,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,UAAkB;QAIlC,OAAO,IAAI,CAAC,OAAO,CAAC,qBAAqB,UAAU,EAAE,EAAE;YACrD,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;IACL,CAAC;IAED,6EAA6E;IAC7E,2BAA2B;IAC3B,6EAA6E;IAErE,KAAK,CAAC,OAAO,CACnB,IAAY,EACZ,OAGC;QAED,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QACrC,IAAI,SAAS,GAAiB,IAAI,CAAC;QAEnC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;YACvD,IAAI,CAAC;gBACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;gBACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBAErE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;oBAChC,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,eAAe,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;wBACxC,eAAe,EAAE,uBAAuB;qBACzC;oBACD,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;oBAC7D,MAAM,EAAE,UAAU,CAAC,MAAM;iBAC1B,CAAC,CAAC;gBAEH,YAAY,CAAC,SAAS,CAAC,CAAC;gBAExB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;oBACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAA4B,CAAC;oBACrF,MAAM,IAAI,YAAY,CACpB,QAAQ,CAAC,MAAM,EACf,MAAM,CAAC,SAAS,CAAC,IAAI,IAAI,WAAW,CAAC,EACrC,MAAM,CAAC,SAAS,CAAC,OAAO,IAAI,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC,EACtD,SAAS,CAAC,OAA8C,CACzD,CAAC;gBACJ,CAAC;gBAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAO,CAAC;YACpC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBAEtE,qCAAqC;gBACrC,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;oBAC/E,MAAM,KAAK,CAAC;gBACd,CAAC;gBAED,0CAA0C;gBAC1C,IAAI,OAAO,GAAG,WAAW,GAAG,CAAC,EAAE,CAAC;oBAC9B,MAAM,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC/D,CAAC;CACF;AAED,6EAA6E;AAC7E,cAAc;AACd,6EAA6E;AAE7E,MAAM,OAAO,YAAa,SAAQ,KAAK;IAE5B;IACA;IAEA;IAJT,YACS,MAAc,EACd,IAAY,EACnB,OAAe,EACR,OAAiC;QAExC,KAAK,CAAC,OAAO,CAAC,CAAC;QALR,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAQ;QAEZ,YAAO,GAAP,OAAO,CAA0B;QAGxC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,6EAA6E;AAC7E,YAAY;AACZ,6EAA6E;AAE7E,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,6EAA6E;AAC7E,UAAU;AACV,6EAA6E;AAE7E,IAAI,cAAc,GAAyB,IAAI,CAAC;AAEhD,MAAM,UAAU,YAAY,CAAC,MAAwB;IACnD,cAAc,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * API Key Authentication Module
3
+ *
4
+ * Validates API keys and enforces scopes/rate limits.
5
+ * All key usage is automatically audited.
6
+ */
7
+ import type { Scope, AuditEvent } from '../types/index.js';
8
+ /**
9
+ * API Key format: sovr_sk_<tenant_id>_<random>
10
+ * Example: sovr_sk_tenant123_abc123xyz789
11
+ */
12
+ export declare function parseApiKey(key: string): {
13
+ tenantId: string;
14
+ keyId: string;
15
+ } | null;
16
+ /**
17
+ * Generate a new API key
18
+ */
19
+ export declare function generateApiKey(tenantId: string): string;
20
+ export declare const DEFAULT_SCOPES: Scope[];
21
+ export declare const ADMIN_SCOPES: Scope[];
22
+ export declare function hasRequiredScopes(keyScopes: Scope[], toolName: string): boolean;
23
+ export declare function getMissingScopes(keyScopes: Scope[], toolName: string): Scope[];
24
+ export declare function checkRateLimit(keyId: string, limit: number): {
25
+ allowed: boolean;
26
+ remaining: number;
27
+ resetAt: number;
28
+ };
29
+ export declare function logAuditEvent(event: Omit<AuditEvent, 'event_id' | 'timestamp'>): AuditEvent;
30
+ export declare function getRecentAuditEvents(limit?: number): AuditEvent[];
31
+ export interface AuthContext {
32
+ keyId: string;
33
+ tenantId: string;
34
+ scopes: Scope[];
35
+ rateLimit: number;
36
+ traceId: string;
37
+ }
38
+ /**
39
+ * Validate API key and return auth context
40
+ * In production, this would call the SOVR API to validate
41
+ */
42
+ export declare function validateApiKey(apiKey: string): Promise<AuthContext | null>;
43
+ /**
44
+ * Authenticate and authorize a tool call
45
+ */
46
+ export declare function authenticateToolCall(apiKey: string, toolName: string): Promise<{
47
+ success: true;
48
+ context: AuthContext;
49
+ } | {
50
+ success: false;
51
+ error: string;
52
+ }>;
53
+ //# sourceMappingURL=apiKey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiKey.d.ts","sourceRoot":"","sources":["../../src/auth/apiKey.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAU,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAMnE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAOnF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGvD;AAMD,eAAO,MAAM,cAAc,EAAE,KAAK,EAAqC,CAAC;AACxE,eAAO,MAAM,YAAY,EAAE,KAAK,EAAsG,CAAC;AAevI,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI/E;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,KAAK,EAAE,CAI9E;AAcD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAiBrH;AASD,wBAAgB,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,WAAW,CAAC,GAAG,UAAU,CAkB3F;AAED,wBAAgB,oBAAoB,CAAC,KAAK,GAAE,MAAY,GAAG,UAAU,EAAE,CAEtE;AAMD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAahF;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA6BtF"}