@igris-security/sdk 0.1.0 → 0.1.1
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/README.md +426 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/cybertron288/igris/main/apps/www/public/logo.svg" alt="Igris" width="60" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">@igris-security/sdk</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>TypeScript SDK for the Igris MCP Gateway</strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/@igris-security/sdk"><img src="https://img.shields.io/npm/v/@igris-security/sdk?color=teal&label=npm" alt="npm version" /></a>
|
|
13
|
+
<a href="https://github.com/cybertron288/igris/blob/main/packages/sdk/LICENSE"><img src="https://img.shields.io/npm/l/@igris-security/sdk?color=blue" alt="license" /></a>
|
|
14
|
+
<a href="https://docs.igris.dev"><img src="https://img.shields.io/badge/docs-igris.dev-teal" alt="docs" /></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
Govern every MCP tool call. Enforce policies, track users, audit everything.
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## What is Igris?
|
|
24
|
+
|
|
25
|
+
Igris is an **AI governance gateway** that sits between your AI agents and MCP servers. It enforces security policies, tracks who called what tool and when, detects anomalies, and gives you a complete audit trail.
|
|
26
|
+
|
|
27
|
+
The SDK connects your application to the Igris gateway with type-safe APIs.
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# bun
|
|
33
|
+
bun add @igris-security/sdk
|
|
34
|
+
|
|
35
|
+
# npm
|
|
36
|
+
npm install @igris-security/sdk
|
|
37
|
+
|
|
38
|
+
# pnpm
|
|
39
|
+
pnpm add @igris-security/sdk
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quick Start
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { Igris } from "@igris-security/sdk";
|
|
46
|
+
|
|
47
|
+
const igris = new Igris({
|
|
48
|
+
apiKey: "ig_your_api_key",
|
|
49
|
+
baseUrl: "https://your-igris-instance.com", // optional, defaults to gateway.igris.dev
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Get MCP config for your AI agent
|
|
53
|
+
const mcpConfig = igris.getMcpConfig("my-connection", {
|
|
54
|
+
user: "alice@company.com",
|
|
55
|
+
metadata: { role: "developer", team: "platform" },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
console.log(mcpConfig);
|
|
59
|
+
// {
|
|
60
|
+
// url: "https://your-igris-instance.com/v1/mcp/my-connection",
|
|
61
|
+
// headers: {
|
|
62
|
+
// Authorization: "Bearer ig_your_api_key",
|
|
63
|
+
// "X-Igris-Trace-Id": "ig_trace_a1b2c3d4e5f6g7h8",
|
|
64
|
+
// "X-Igris-User": "alice@company.com",
|
|
65
|
+
// "X-Igris-Metadata": '{"role":"developer","team":"platform"}'
|
|
66
|
+
// }
|
|
67
|
+
// }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Usage with MCP Clients
|
|
71
|
+
|
|
72
|
+
### Claude Desktop / Cursor / Windsurf
|
|
73
|
+
|
|
74
|
+
Use the SDK to generate the MCP config, then pass it to your MCP client:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { Igris } from "@igris-security/sdk";
|
|
78
|
+
|
|
79
|
+
const igris = new Igris({ apiKey: process.env.IGRIS_API_KEY! });
|
|
80
|
+
|
|
81
|
+
// Every tool call now flows through the Igris gateway
|
|
82
|
+
const config = igris.getMcpConfig("my-mcp-server", {
|
|
83
|
+
user: "developer@company.com",
|
|
84
|
+
traceId: "session-abc-123", // optional: correlate requests
|
|
85
|
+
metadata: { role: "admin" }, // optional: used for policy conditions
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Use config.url and config.headers with your MCP client
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Standalone Function
|
|
92
|
+
|
|
93
|
+
If you don't need the full client, use `buildMcpConfig` directly:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { buildMcpConfig } from "@igris-security/sdk";
|
|
97
|
+
|
|
98
|
+
const config = buildMcpConfig(
|
|
99
|
+
"ig_your_api_key",
|
|
100
|
+
"https://your-igris-instance.com",
|
|
101
|
+
"my-connection",
|
|
102
|
+
{ user: "alice@company.com" },
|
|
103
|
+
);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Resource APIs
|
|
107
|
+
|
|
108
|
+
The SDK provides typed access to the Igris management API for programmatic control.
|
|
109
|
+
|
|
110
|
+
### Connections (Virtual Keys)
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// List all connections
|
|
114
|
+
const { data: connections } = await igris.virtualKeys.list();
|
|
115
|
+
|
|
116
|
+
// Get a specific connection by slug
|
|
117
|
+
const connection = await igris.virtualKeys.get("my-connection");
|
|
118
|
+
console.log(connection.upstreamUrl); // "https://my-mcp-server.com"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Policies
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// List all policies
|
|
125
|
+
const { data: policies } = await igris.policies.list();
|
|
126
|
+
|
|
127
|
+
// List policies for a specific connection
|
|
128
|
+
const { data: filtered } = await igris.policies.list({
|
|
129
|
+
virtualKeySlug: "my-connection",
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Get a specific policy
|
|
133
|
+
const policy = await igris.policies.get("policy-uuid");
|
|
134
|
+
console.log(policy.rules);
|
|
135
|
+
// [
|
|
136
|
+
// { tool: "delete_*", action: "deny", conditions: { "metadata.role": "viewer" } },
|
|
137
|
+
// { tool: "*", action: "allow" }
|
|
138
|
+
// ]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Audit Events
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// List recent audit events
|
|
145
|
+
const { data: events } = await igris.auditEvents.list({ limit: 50 });
|
|
146
|
+
|
|
147
|
+
// Filter by user
|
|
148
|
+
const { data: userEvents } = await igris.auditEvents.list({
|
|
149
|
+
userId: "alice@company.com",
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Filter by trace ID (correlate a session)
|
|
153
|
+
const { data: traceEvents } = await igris.auditEvents.list({
|
|
154
|
+
traceId: "ig_trace_a1b2c3d4e5f6g7h8",
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Filter by connection
|
|
158
|
+
const { data: connectionEvents } = await igris.auditEvents.list({
|
|
159
|
+
virtualKey: "my-connection",
|
|
160
|
+
limit: 100,
|
|
161
|
+
offset: 0,
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Identity & Tracing
|
|
166
|
+
|
|
167
|
+
Igris tracks **who** made each tool call and lets you correlate requests across sessions.
|
|
168
|
+
|
|
169
|
+
### User Identity
|
|
170
|
+
|
|
171
|
+
Pass `user` to attach a user identity to every tool call flowing through the gateway:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
const config = igris.getMcpConfig("my-connection", {
|
|
175
|
+
user: "alice@company.com",
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
This shows up in the audit trail and can be used in policy conditions:
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{ "tool": "delete_*", "action": "deny", "conditions": { "metadata.role": "viewer" } }
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Trace IDs
|
|
186
|
+
|
|
187
|
+
Every request gets an auto-generated trace ID (`ig_trace_...`). You can also provide your own:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
const config = igris.getMcpConfig("my-connection", {
|
|
191
|
+
traceId: "my-custom-trace-id",
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Use trace IDs to correlate all tool calls within a single agent session.
|
|
196
|
+
|
|
197
|
+
### Metadata
|
|
198
|
+
|
|
199
|
+
Attach arbitrary key-value metadata for policy evaluation:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
const config = igris.getMcpConfig("my-connection", {
|
|
203
|
+
user: "alice@company.com",
|
|
204
|
+
metadata: {
|
|
205
|
+
role: "developer",
|
|
206
|
+
team: "platform",
|
|
207
|
+
environment: "production",
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Metadata is available in policy conditions via dot notation: `metadata.role`, `metadata.team`, etc.
|
|
213
|
+
|
|
214
|
+
## Headers Reference
|
|
215
|
+
|
|
216
|
+
| Header | Description | Auto-generated |
|
|
217
|
+
|--------|-------------|:--------------:|
|
|
218
|
+
| `Authorization` | `Bearer <apiKey>` | Yes |
|
|
219
|
+
| `X-Igris-Trace-Id` | Trace ID for request correlation | Yes (overridable) |
|
|
220
|
+
| `X-Igris-User` | User identity string | No |
|
|
221
|
+
| `X-Igris-Metadata` | JSON-encoded metadata object | No |
|
|
222
|
+
|
|
223
|
+
## API Reference
|
|
224
|
+
|
|
225
|
+
### `new Igris(config)`
|
|
226
|
+
|
|
227
|
+
| Parameter | Type | Required | Description |
|
|
228
|
+
|-----------|------|:--------:|-------------|
|
|
229
|
+
| `config.apiKey` | `string` | Yes | Your Igris API key (starts with `ig_`) |
|
|
230
|
+
| `config.baseUrl` | `string` | No | Gateway URL. Defaults to `https://gateway.igris.dev` |
|
|
231
|
+
|
|
232
|
+
### `igris.getMcpConfig(slug, options?)`
|
|
233
|
+
|
|
234
|
+
Returns `{ url: string, headers: Record<string, string> }` for wiring into an MCP client.
|
|
235
|
+
|
|
236
|
+
| Parameter | Type | Required | Description |
|
|
237
|
+
|-----------|------|:--------:|-------------|
|
|
238
|
+
| `slug` | `string` | Yes | Connection slug (virtual key) |
|
|
239
|
+
| `options.user` | `string` | No | User identity |
|
|
240
|
+
| `options.traceId` | `string` | No | Custom trace ID (auto-generated if omitted) |
|
|
241
|
+
| `options.metadata` | `Record<string, string \| number \| boolean>` | No | Key-value pairs for policy conditions |
|
|
242
|
+
|
|
243
|
+
### `igris.virtualKeys`
|
|
244
|
+
|
|
245
|
+
| Method | Returns | Description |
|
|
246
|
+
|--------|---------|-------------|
|
|
247
|
+
| `.list()` | `PaginatedResponse<VirtualKey>` | List all connections |
|
|
248
|
+
| `.get(slug)` | `VirtualKey` | Get connection by slug |
|
|
249
|
+
|
|
250
|
+
### `igris.policies`
|
|
251
|
+
|
|
252
|
+
| Method | Returns | Description |
|
|
253
|
+
|--------|---------|-------------|
|
|
254
|
+
| `.list(params?)` | `PaginatedResponse<Policy>` | List policies. Filter with `{ virtualKeySlug }` |
|
|
255
|
+
| `.get(id)` | `Policy` | Get policy by ID |
|
|
256
|
+
|
|
257
|
+
### `igris.auditEvents`
|
|
258
|
+
|
|
259
|
+
| Method | Returns | Description |
|
|
260
|
+
|--------|---------|-------------|
|
|
261
|
+
| `.list(params?)` | `PaginatedResponse<AuditEvent>` | List audit events. Filter with `{ userId, traceId, virtualKey, limit, offset }` |
|
|
262
|
+
|
|
263
|
+
## Types
|
|
264
|
+
|
|
265
|
+
All types are exported from the package:
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import type {
|
|
269
|
+
IgrisConfig,
|
|
270
|
+
McpConfig,
|
|
271
|
+
McpConfigOptions,
|
|
272
|
+
VirtualKey,
|
|
273
|
+
Policy,
|
|
274
|
+
PolicyRule,
|
|
275
|
+
AuditEvent,
|
|
276
|
+
PaginatedResponse,
|
|
277
|
+
} from "@igris-security/sdk";
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Full Example
|
|
281
|
+
|
|
282
|
+
A complete example: an AI agent simulator that makes governed MCP tool calls through the Igris gateway with role-based policy enforcement.
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import { Igris } from "@igris-security/sdk";
|
|
286
|
+
|
|
287
|
+
// ── Setup ────────────────────────────────────────────────────
|
|
288
|
+
const igris = new Igris({
|
|
289
|
+
apiKey: process.env.IGRIS_API_KEY!,
|
|
290
|
+
baseUrl: "http://localhost:3100",
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// ── Helper: Make a governed MCP tool call ────────────────────
|
|
294
|
+
async function callTool(
|
|
295
|
+
connectionSlug: string,
|
|
296
|
+
toolName: string,
|
|
297
|
+
args: Record<string, unknown>,
|
|
298
|
+
user: string,
|
|
299
|
+
metadata: Record<string, string> = {},
|
|
300
|
+
) {
|
|
301
|
+
// Get gateway config with user identity + metadata for policy evaluation
|
|
302
|
+
const mcp = igris.getMcpConfig(connectionSlug, { user, metadata });
|
|
303
|
+
|
|
304
|
+
// Make the JSON-RPC call through the gateway
|
|
305
|
+
const res = await fetch(mcp.url, {
|
|
306
|
+
method: "POST",
|
|
307
|
+
headers: mcp.headers,
|
|
308
|
+
body: JSON.stringify({
|
|
309
|
+
jsonrpc: "2.0",
|
|
310
|
+
method: "tools/call",
|
|
311
|
+
params: { name: toolName, arguments: args },
|
|
312
|
+
id: Date.now(),
|
|
313
|
+
}),
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
const json = (await res.json()) as any;
|
|
317
|
+
|
|
318
|
+
if (json.error) {
|
|
319
|
+
return { allowed: false, error: json.error.message };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const text = json.result?.content?.[0]?.text;
|
|
323
|
+
return { allowed: true, result: text ? JSON.parse(text) : json.result };
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// ── Scenario: Role-based access control ──────────────────────
|
|
327
|
+
//
|
|
328
|
+
// Policy on the gateway:
|
|
329
|
+
// { tool: "delete_*", action: "deny", conditions: { "metadata.role": "viewer" } }
|
|
330
|
+
// { tool: "*", action: "allow" }
|
|
331
|
+
|
|
332
|
+
const CONNECTION = "my-mcp-server";
|
|
333
|
+
|
|
334
|
+
console.log("=== Admin user (full access) ===\n");
|
|
335
|
+
|
|
336
|
+
const weather = await callTool(
|
|
337
|
+
CONNECTION,
|
|
338
|
+
"get_weather",
|
|
339
|
+
{ city: "San Francisco" },
|
|
340
|
+
"admin@company.com",
|
|
341
|
+
{ role: "admin" },
|
|
342
|
+
);
|
|
343
|
+
console.log(` get_weather: ${weather.allowed ? "ALLOWED" : "DENIED"}`);
|
|
344
|
+
|
|
345
|
+
const deleteResult = await callTool(
|
|
346
|
+
CONNECTION,
|
|
347
|
+
"delete_record",
|
|
348
|
+
{ id: "rec_123" },
|
|
349
|
+
"admin@company.com",
|
|
350
|
+
{ role: "admin" },
|
|
351
|
+
);
|
|
352
|
+
console.log(` delete_record: ${deleteResult.allowed ? "ALLOWED" : "DENIED"}`);
|
|
353
|
+
|
|
354
|
+
console.log("\n=== Viewer user (restricted) ===\n");
|
|
355
|
+
|
|
356
|
+
const viewerWeather = await callTool(
|
|
357
|
+
CONNECTION,
|
|
358
|
+
"get_weather",
|
|
359
|
+
{ city: "Tokyo" },
|
|
360
|
+
"viewer@company.com",
|
|
361
|
+
{ role: "viewer" },
|
|
362
|
+
);
|
|
363
|
+
console.log(` get_weather: ${viewerWeather.allowed ? "ALLOWED" : "DENIED"}`);
|
|
364
|
+
|
|
365
|
+
const viewerDelete = await callTool(
|
|
366
|
+
CONNECTION,
|
|
367
|
+
"delete_record",
|
|
368
|
+
{ id: "rec_456" },
|
|
369
|
+
"viewer@company.com",
|
|
370
|
+
{ role: "viewer" },
|
|
371
|
+
);
|
|
372
|
+
console.log(` delete_record: ${viewerDelete.allowed ? "DENIED" : "ALLOWED"}`);
|
|
373
|
+
// → DENIED by policy: delete_* blocked for viewers
|
|
374
|
+
|
|
375
|
+
// ── Query the audit trail ────────────────────────────────────
|
|
376
|
+
console.log("\n=== Audit Trail ===\n");
|
|
377
|
+
|
|
378
|
+
const { data: events } = await igris.auditEvents.list({ limit: 10 });
|
|
379
|
+
|
|
380
|
+
for (const event of events) {
|
|
381
|
+
console.log(
|
|
382
|
+
` [${event.policyAction?.toUpperCase().padEnd(5)}] ${event.toolName?.padEnd(20)} by ${event.userId ?? "unknown"}`,
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
// Output:
|
|
386
|
+
// [DENY ] delete_record by viewer@company.com
|
|
387
|
+
// [ALLOW] get_weather by viewer@company.com
|
|
388
|
+
// [ALLOW] delete_record by admin@company.com
|
|
389
|
+
// [ALLOW] get_weather by admin@company.com
|
|
390
|
+
|
|
391
|
+
// ── List connections & policies ──────────────────────────────
|
|
392
|
+
const { data: connections } = await igris.virtualKeys.list();
|
|
393
|
+
console.log(`\nConnections: ${connections.map((c) => c.slug).join(", ")}`);
|
|
394
|
+
|
|
395
|
+
const { data: policies } = await igris.policies.list({
|
|
396
|
+
virtualKeySlug: CONNECTION,
|
|
397
|
+
});
|
|
398
|
+
for (const policy of policies) {
|
|
399
|
+
console.log(`\nPolicy: ${policy.name}`);
|
|
400
|
+
for (const rule of policy.rules) {
|
|
401
|
+
console.log(` ${rule.tool} → ${rule.action}`);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Save as `demo.ts` and run:
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
IGRIS_API_KEY=ig_your_key bun demo.ts
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Requirements
|
|
413
|
+
|
|
414
|
+
- Node.js 18+ or Bun 1.0+
|
|
415
|
+
- An Igris API key ([get one from the dashboard](https://app.igris.dev/settings))
|
|
416
|
+
|
|
417
|
+
## Links
|
|
418
|
+
|
|
419
|
+
- [Documentation](https://docs.igris.dev)
|
|
420
|
+
- [Dashboard](https://app.igris.dev)
|
|
421
|
+
- [GitHub](https://github.com/cybertron288/igris)
|
|
422
|
+
- [npm](https://www.npmjs.com/package/@igris-security/sdk)
|
|
423
|
+
|
|
424
|
+
## License
|
|
425
|
+
|
|
426
|
+
MIT
|