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 +21 -0
- package/README.md +453 -0
- package/dist/index.cjs +2507 -0
- package/dist/index.d.cts +2182 -0
- package/dist/index.d.ts +2182 -0
- package/dist/index.js +2477 -0
- package/dist/multicorn-proxy.js +1153 -0
- package/dist/openclaw-hook/HOOK.md +75 -0
- package/dist/openclaw-hook/handler.js +447 -0
- package/dist/openclaw-plugin/index.js +692 -0
- package/dist/openclaw-plugin/openclaw.plugin.json +51 -0
- package/package.json +122 -0
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
|
+
[](https://github.com/Multicorn-AI/multicorn-shield/actions/workflows/ci.yml)
|
|
6
|
+
[](https://github.com/Multicorn-AI/multicorn-shield)
|
|
7
|
+
[](https://www.npmjs.com/package/multicorn-shield)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](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
|