multicorn-shield 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) 2026 Multicorn AI
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,453 @@
1
+ # Multicorn Shield
2
+
3
+ The permissions and control layer for AI agents. Open source.
4
+
5
+ [![CI](https://github.com/Multicorn-AI/multicorn-shield/actions/workflows/ci.yml/badge.svg)](https://github.com/Multicorn-AI/multicorn-shield/actions/workflows/ci.yml)
6
+ [![Coverage](https://img.shields.io/badge/coverage-85%25+-brightgreen.svg)](https://github.com/Multicorn-AI/multicorn-shield)
7
+ [![npm version](https://img.shields.io/npm/v/multicorn-shield.svg)](https://www.npmjs.com/package/multicorn-shield)
8
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
9
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/multicorn-shield)](https://bundlephobia.com/package/multicorn-shield)
10
+
11
+ ## Why?
12
+
13
+ AI agents are getting access to your email, calendar, bank accounts, and code repositories. Today, most agents operate with no permission boundaries: they can read, write, and spend with no oversight. Multicorn Shield gives developers a single SDK to enforce what agents can do, track what they did, and let users stay in control.
14
+
15
+ ## Quick Start
16
+
17
+ ### Option 1: Wrap your existing agents (no code changes)
18
+
19
+ Already using an MCP server with Claude Code, OpenClaw, or another agent? Add Shield as a proxy in front of it. No code changes required: the proxy intercepts every tool call, enforces permissions, and logs activity to your dashboard.
20
+
21
+ **Step 1: Install**
22
+
23
+ ```bash
24
+ npm install -g multicorn-shield
25
+ ```
26
+
27
+ **Step 2: Set up your API key**
28
+
29
+ ```bash
30
+ npx multicorn-proxy init
31
+ ```
32
+
33
+ **Step 3: Wrap your MCP server**
34
+
35
+ ```bash
36
+ npx multicorn-proxy --wrap <your-mcp-server>
37
+ ```
38
+
39
+ For example, to wrap the MCP filesystem server:
40
+
41
+ ```bash
42
+ npx multicorn-proxy --wrap npx @modelcontextprotocol/server-filesystem /tmp
43
+ ```
44
+
45
+ That's it. Every tool call now goes through Shield's permission layer, and activity appears in your [Multicorn dashboard](https://app.multicorn.ai) in real time.
46
+
47
+ See the [full MCP proxy guide](https://multicorn.ai/docs/mcp-proxy) for Claude Code, OpenClaw, and generic MCP client examples.
48
+
49
+ ### Option 2: Integrate the SDK
50
+
51
+ For full control over consent screens, spending limits, and action logging, use the SDK directly in your application code.
52
+
53
+ ```bash
54
+ npm install multicorn-shield
55
+ ```
56
+
57
+ ```typescript
58
+ import { MulticornShield } from "multicorn-shield";
59
+
60
+ const shield = new MulticornShield({ apiKey: "mcs_your_key_here" });
61
+
62
+ const decision = await shield.requestConsent({
63
+ agent: "OpenClaw",
64
+ scopes: ["read:gmail", "write:calendar"],
65
+ spendLimit: 200,
66
+ });
67
+
68
+ await shield.logAction({
69
+ agent: "OpenClaw",
70
+ service: "gmail",
71
+ action: "send_email",
72
+ status: "approved",
73
+ });
74
+ ```
75
+
76
+ That gives you a consent screen, scoped permissions, and an audit trail.
77
+
78
+ ## Built with Shield
79
+
80
+ Multicorn is developed using AI coding agents. Primarily Cursor for code generation and GitHub Actions as the deployment agent. Every one of those agents runs under Shield.
81
+
82
+ We're not just building a trust layer for AI agents. We're depending on it ourselves. If Shield fails to catch something in our own workflow, we feel it directly.
83
+
84
+ [Read how we use agents to build Multicorn →](https://multicorn.ai/blog/agents)
85
+
86
+ ## Features
87
+
88
+ ### Consent Screens
89
+
90
+ A drop-in web component (Shadow DOM, framework-agnostic) that lets users review and approve agent permissions before granting access.
91
+
92
+ ```typescript
93
+ const decision = await shield.requestConsent({
94
+ agent: "OpenClaw",
95
+ scopes: ["read:gmail", "write:calendar", "execute:payments"],
96
+ spendLimit: 500,
97
+ agentColor: "#8b5cf6",
98
+ });
99
+
100
+ // decision.grantedScopes - what the user actually approved
101
+ ```
102
+
103
+ ### Scopes
104
+
105
+ Type-safe permission scopes with built-in services (Gmail, Calendar, Slack, Drive, Payments, GitHub, Jira) and a registry for custom ones.
106
+
107
+ ```typescript
108
+ import { createScopeRegistry, parseScope } from "multicorn-shield";
109
+
110
+ const registry = createScopeRegistry();
111
+
112
+ registry.register({
113
+ name: "analytics",
114
+ description: "Internal analytics platform",
115
+ capabilities: ["read", "write"],
116
+ });
117
+
118
+ const scope = parseScope("read:analytics");
119
+ // { service: "analytics", permissionLevel: "read" }
120
+ ```
121
+
122
+ ### Action Logging
123
+
124
+ Structured audit trail of every action an agent takes. Supports immediate and batched delivery.
125
+
126
+ ```typescript
127
+ await shield.logAction({
128
+ agent: "OpenClaw",
129
+ service: "gmail",
130
+ action: "send_email",
131
+ status: "approved",
132
+ cost: 0.002,
133
+ metadata: { recipient: "user@example.com" },
134
+ });
135
+ ```
136
+
137
+ ### Spending Controls
138
+
139
+ Client-side enforcement of per-transaction, daily, and monthly spend limits. Currency-safe integer arithmetic (cents) prevents floating point issues.
140
+
141
+ ```typescript
142
+ const result = shield.checkSpending("OpenClaw", 849);
143
+
144
+ if (!result.allowed) {
145
+ // "Action blocked: $849.00 exceeds per-transaction limit of $200.00"
146
+ console.error(result.reason);
147
+ }
148
+ ```
149
+
150
+ ### MCP Integration
151
+
152
+ Middleware adapter for Model Context Protocol servers. Sits between the agent and MCP tools, enforcing permissions on every tool call.
153
+
154
+ ```typescript
155
+ import { createMcpAdapter, isBlockedResult } from "multicorn-shield";
156
+
157
+ const adapter = createMcpAdapter({
158
+ agentId: "inbox-assistant",
159
+ grantedScopes: [
160
+ { service: "gmail", permissionLevel: "execute" },
161
+ { service: "calendar", permissionLevel: "read" },
162
+ ],
163
+ logger,
164
+ });
165
+
166
+ const result = await adapter.intercept(
167
+ { toolName: "gmail_send_email", arguments: { to: "user@example.com" } },
168
+ (call) => mcpServer.callTool(call.toolName, call.arguments),
169
+ );
170
+
171
+ if (isBlockedResult(result)) {
172
+ console.error(result.reason);
173
+ }
174
+ ```
175
+
176
+ ## API Reference
177
+
178
+ Full API documentation is generated from source with TypeDoc:
179
+
180
+ ```bash
181
+ pnpm run docs
182
+ ```
183
+
184
+ This outputs to `docs/api/`. You can also browse the inline JSDoc on every public export. All interfaces, functions, and types are documented with examples.
185
+
186
+ ## Architecture
187
+
188
+ Multicorn Shield is the client-side SDK in the Multicorn ecosystem. It runs in the browser or Node.js and communicates with the Multicorn hosted API for persistence and policy enforcement.
189
+
190
+ ```
191
+ ┌─────────────────────────────────────────────────────┐
192
+ │ Your Application │
193
+ │ │
194
+ │ ┌──────────────────────────────────────────────┐ │
195
+ │ │ multicorn-shield (this SDK) │ │
196
+ │ │ │ │
197
+ │ │ ┌────────────┐ ┌──────────┐ ┌──────────┐ │ │
198
+ │ │ │ Consent │ │ Action │ │ Spending │ │ │
199
+ │ │ │ Screen │ │ Logger │ │ Checker │ │ │
200
+ │ │ └────────────┘ └────┬─────┘ └──────────┘ │ │
201
+ │ │ ┌────────────┐ │ │ │
202
+ │ │ │ MCP │ │ │ │
203
+ │ │ │ Adapter │ │ │ │
204
+ │ │ └────────────┘ │ │ │
205
+ │ └───────────────────────┼──────────────────────┘ │
206
+ │ │ HTTPS │
207
+ └──────────────────────────┼──────────────────────────┘
208
+
209
+
210
+ ┌────────────────────────┐
211
+ │ Multicorn Service API │
212
+ │ (hosted backend) │
213
+ └────────────┬───────────┘
214
+
215
+
216
+ ┌────────────────────────┐
217
+ │ Multicorn Dashboard │
218
+ │ (admin UI) │
219
+ └────────────────────────┘
220
+ ```
221
+
222
+ The SDK handles:
223
+
224
+ - **Consent**: renders a Shadow DOM web component for permission approval
225
+ - **Scope validation**: parses and validates `"permission:service"` scope strings locally
226
+ - **Action logging**: sends structured events to the hosted API over HTTPS
227
+ - **Spending checks**: client-side pre-validation (server is the source of truth)
228
+ - **MCP adapter**: middleware layer between AI agents and MCP tool servers
229
+
230
+ The hosted API handles persistence, policy enforcement, and the audit trail. The SDK never stores credentials locally. API keys are held in memory only.
231
+
232
+ ## Configuration
233
+
234
+ ### `MulticornShieldConfig`
235
+
236
+ | Option | Type | Default | Description |
237
+ | ----------- | ----------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------ |
238
+ | `apiKey` | `string` | - | **Required.** Your Multicorn API key. Must start with `mcs_` and be at least 16 characters. Stored in memory only. |
239
+ | `baseUrl` | `string` | `"https://api.multicorn.ai"` | Base URL for the Multicorn API. |
240
+ | `timeout` | `number` | `5000` | Request timeout in milliseconds. |
241
+ | `batchMode` | `BatchModeConfig` | - | Optional batch mode for action logging. When enabled, actions are queued and flushed periodically. |
242
+
243
+ ### `BatchModeConfig`
244
+
245
+ | Option | Type | Default | Description |
246
+ | ----------------- | --------- | ------- | ----------------------------------------- |
247
+ | `enabled` | `boolean` | - | Whether batch mode is active. |
248
+ | `maxSize` | `number` | `10` | Maximum actions to queue before flushing. |
249
+ | `flushIntervalMs` | `number` | `5000` | Maximum time (ms) between flushes. |
250
+
251
+ ### `ConsentOptions`
252
+
253
+ | Option | Type | Default | Description |
254
+ | ------------ | ---------- | ----------- | ------------------------------------------------------------------------------- |
255
+ | `agent` | `string` | - | **Required.** Name of the agent requesting access. Shown on the consent screen. |
256
+ | `scopes` | `string[]` | - | **Required.** Permission scopes to request. Format: `"permission:service"`. |
257
+ | `spendLimit` | `number` | `0` | Maximum spend per transaction in dollars. `0` disables spending controls. |
258
+ | `agentColor` | `string` | `"#8b5cf6"` | Hex colour for the agent icon on the consent screen. |
259
+
260
+ ### `McpAdapterConfig`
261
+
262
+ | Option | Type | Default | Description |
263
+ | ------------------------- | ------------------------------ | ------------------ | --------------------------------------------------------------------------- |
264
+ | `agentId` | `string` | - | **Required.** Agent identifier for audit logging. |
265
+ | `grantedScopes` | `Scope[]` | - | **Required.** Scopes granted via the consent screen. |
266
+ | `logger` | `ActionLogger` | - | Optional logger instance. When omitted, actions are checked but not logged. |
267
+ | `requiredPermissionLevel` | `PermissionLevel` | `"execute"` | Permission level required for MCP tool calls. |
268
+ | `extractService` | `(toolName: string) => string` | Split on first `_` | Custom function to derive the service name from a tool name. |
269
+ | `extractAction` | `(toolName: string) => string` | Split on first `_` | Custom function to derive the action type from a tool name. |
270
+
271
+ ## Framework Examples
272
+
273
+ > **Using MCP?** If your agent connects to tools via an MCP server, you may not need any of these. See [Option 1](#option-1-wrap-your-existing-agents-no-code-changes) to add Shield with zero code changes.
274
+
275
+ ### React
276
+
277
+ ```tsx
278
+ import { useEffect, useRef } from "react";
279
+ import { MulticornShield } from "multicorn-shield";
280
+
281
+ function AgentSetup() {
282
+ const shieldRef = useRef<MulticornShield | null>(null);
283
+
284
+ useEffect(() => {
285
+ shieldRef.current = new MulticornShield({ apiKey: "mcs_your_key_here" });
286
+ return () => shieldRef.current?.destroy();
287
+ }, []);
288
+
289
+ async function handleConnect() {
290
+ const decision = await shieldRef.current?.requestConsent({
291
+ agent: "OpenClaw",
292
+ scopes: ["read:gmail", "write:calendar"],
293
+ spendLimit: 200,
294
+ });
295
+ console.log("Granted:", decision?.grantedScopes);
296
+ }
297
+
298
+ return <button onClick={handleConnect}>Connect Agent</button>;
299
+ }
300
+ ```
301
+
302
+ ### Vue
303
+
304
+ ```vue
305
+ <script setup lang="ts">
306
+ import { ref, onMounted, onUnmounted } from "vue";
307
+ import { MulticornShield } from "multicorn-shield";
308
+
309
+ const shield = ref<MulticornShield | null>(null);
310
+
311
+ onMounted(() => {
312
+ shield.value = new MulticornShield({ apiKey: "mcs_your_key_here" });
313
+ });
314
+
315
+ onUnmounted(() => shield.value?.destroy());
316
+
317
+ async function handleConnect() {
318
+ const decision = await shield.value?.requestConsent({
319
+ agent: "OpenClaw",
320
+ scopes: ["read:gmail", "write:calendar"],
321
+ spendLimit: 200,
322
+ });
323
+ console.log("Granted:", decision?.grantedScopes);
324
+ }
325
+ </script>
326
+
327
+ <template>
328
+ <button @click="handleConnect">Connect Agent</button>
329
+ </template>
330
+ ```
331
+
332
+ ### Svelte
333
+
334
+ ```svelte
335
+ <script lang="ts">
336
+ import { onMount, onDestroy } from "svelte";
337
+ import { MulticornShield } from "multicorn-shield";
338
+
339
+ let shield: MulticornShield;
340
+
341
+ onMount(() => {
342
+ shield = new MulticornShield({ apiKey: "mcs_your_key_here" });
343
+ });
344
+
345
+ onDestroy(() => shield?.destroy());
346
+
347
+ async function handleConnect() {
348
+ const decision = await shield.requestConsent({
349
+ agent: "OpenClaw",
350
+ scopes: ["read:gmail", "write:calendar"],
351
+ spendLimit: 200,
352
+ });
353
+ console.log("Granted:", decision.grantedScopes);
354
+ }
355
+ </script>
356
+
357
+ <button on:click={handleConnect}>Connect Agent</button>
358
+ ```
359
+
360
+ ### Vanilla HTML
361
+
362
+ ```html
363
+ <button id="connect">Connect Agent</button>
364
+
365
+ <script type="module">
366
+ import { MulticornShield } from "multicorn-shield";
367
+
368
+ const shield = new MulticornShield({ apiKey: "mcs_your_key_here" });
369
+
370
+ document.getElementById("connect").addEventListener("click", async () => {
371
+ const decision = await shield.requestConsent({
372
+ agent: "OpenClaw",
373
+ scopes: ["read:gmail", "write:calendar"],
374
+ spendLimit: 200,
375
+ });
376
+ console.log("Granted:", decision.grantedScopes);
377
+ });
378
+ </script>
379
+ ```
380
+
381
+ ## Development
382
+
383
+ ### Prerequisites
384
+
385
+ - Node.js 20+
386
+ - pnpm 9+
387
+
388
+ ### Setup
389
+
390
+ ```bash
391
+ git clone https://github.com/Multicorn-AI/multicorn-shield.git
392
+ cd multicorn-shield
393
+ pnpm install
394
+ pnpm test
395
+ pnpm build
396
+ ```
397
+
398
+ ### Commands
399
+
400
+ | Command | Description |
401
+ | -------------------- | ------------------------------------------ |
402
+ | `pnpm build` | Build ESM and CJS bundles with tsup |
403
+ | `pnpm dev` | Build in watch mode |
404
+ | `pnpm lint` | Run ESLint and Prettier checks |
405
+ | `pnpm lint:fix` | Auto-fix lint and formatting issues |
406
+ | `pnpm test` | Run tests with Vitest |
407
+ | `pnpm test:watch` | Run tests in watch mode |
408
+ | `pnpm test:coverage` | Run tests with Istanbul coverage reporting |
409
+ | `pnpm typecheck` | Type-check without emitting |
410
+ | `pnpm docs` | Generate API docs with TypeDoc |
411
+
412
+ ## Project Structure
413
+
414
+ ```
415
+ multicorn-shield/
416
+ ├── src/
417
+ │ ├── index.ts # Package entry point (public API barrel)
418
+ │ ├── multicorn-shield.ts # Main SDK class that orchestrates all modules
419
+ │ ├── consent/ # Consent screen web component (Lit + Shadow DOM)
420
+ │ │ ├── multicorn-consent.ts # <multicorn-consent> custom element
421
+ │ │ ├── consent-events.ts # Custom event types and dispatchers
422
+ │ │ ├── consent-styles.ts # Scoped styles (no CSS leakage)
423
+ │ │ ├── focus-trap.ts # Keyboard focus management
424
+ │ │ └── scope-labels.ts # Human-readable scope display names
425
+ │ ├── scopes/ # Scope types, parsing, and validation
426
+ │ │ ├── scope-definitions.ts # Built-in service registry
427
+ │ │ ├── scope-parser.ts # "read:gmail" string parsing
428
+ │ │ └── scope-validator.ts # Permission access checks
429
+ │ ├── logger/ # Action logging client
430
+ │ │ └── action-logger.ts # HTTP client with batch mode and retry
431
+ │ ├── spending/ # Client-side spend enforcement
432
+ │ │ └── spending-checker.ts # Integer-cents arithmetic, limit checks
433
+ │ ├── mcp/ # MCP (Model Context Protocol) adapter
434
+ │ │ └── mcp-adapter.ts # Middleware for MCP tool call interception
435
+ │ └── types/ # Shared TypeScript types
436
+ │ └── index.ts # Interfaces, constants, type aliases
437
+ ├── docs/
438
+ │ └── adr/ # Architecture Decision Records
439
+ ├── examples/ # Runnable HTML examples
440
+ ├── dist/ # Built output (ESM + CJS + types)
441
+ ├── tsup.config.ts # Bundle configuration
442
+ ├── tsconfig.json # TypeScript strict mode configuration
443
+ ├── vitest.config.ts # Test runner configuration
444
+ └── eslint.config.ts # Linting rules
445
+ ```
446
+
447
+ ## Contributing
448
+
449
+ Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request.
450
+
451
+ ## License
452
+
453
+ [MIT](LICENSE) © Multicorn AI