@agentwares/agentguard 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/README.md +188 -0
- package/dist/cli.js +4179 -0
- package/dist/cli.js.map +1 -0
- package/dist/fixtures/crm-server.js +1216 -0
- package/dist/fixtures/crm-server.js.map +1 -0
- package/dist/fixtures/demo-agent.js +120 -0
- package/dist/fixtures/demo-agent.js.map +1 -0
- package/dist/index.d.ts +488 -0
- package/dist/index.js +4595 -0
- package/dist/index.js.map +1 -0
- package/llms.txt +11 -0
- package/package.json +70 -0
- package/server.json +38 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { RequestId, Tool, ListResourcesResult, ListResourceTemplatesResult, ReadResourceResult, ListPromptsResult, GetPromptResult, CompleteRequest, CompleteResult, LoggingLevel, ServerRequest, ServerNotification, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import { AgentScope, Classification, Guard, GuardResult, GuardEvent, ApprovalRecord, Policy, Upstream, Finding } from '@agentwares/agentguard-core';
|
|
5
|
+
import { LoadedPolicy, FileKillSwitch, FileAuditSink, FileApprovalStore } from '@agentwares/agentguard-core/node';
|
|
6
|
+
import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
7
|
+
import { ToolDef } from '@agentwares/mcp-kit';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Upstream side of the proxy: one MCP client per upstream (stdio or Streamable HTTP), the merged
|
|
11
|
+
* tool table, resource/prompt routing, notification fan-out to downstream sessions, and
|
|
12
|
+
* `callTool` through the policy engine.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
interface ExposedTool {
|
|
16
|
+
/** the name the agent sees */
|
|
17
|
+
name: string;
|
|
18
|
+
upstream: string;
|
|
19
|
+
/** the name the upstream knows */
|
|
20
|
+
original: string;
|
|
21
|
+
tool: Tool;
|
|
22
|
+
classification: Classification;
|
|
23
|
+
}
|
|
24
|
+
interface DownstreamSession {
|
|
25
|
+
id: string;
|
|
26
|
+
server: McpServer;
|
|
27
|
+
lastActive: number;
|
|
28
|
+
/** upstream name → downstream request ids currently waiting on it (newest last) */
|
|
29
|
+
inflight: Map<string, RequestId[]>;
|
|
30
|
+
}
|
|
31
|
+
interface UpstreamStatus {
|
|
32
|
+
name: string;
|
|
33
|
+
connected: boolean;
|
|
34
|
+
tools: number;
|
|
35
|
+
transport: "stdio" | "http";
|
|
36
|
+
error?: string;
|
|
37
|
+
}
|
|
38
|
+
interface RuntimeOptions {
|
|
39
|
+
loaded: LoadedPolicy;
|
|
40
|
+
guard: Guard;
|
|
41
|
+
/** fixed agent scope for stdio (`--agent`) */
|
|
42
|
+
agent?: AgentScope | null;
|
|
43
|
+
/** run id when neither `X-Run-Id` nor `_meta.runId` is present */
|
|
44
|
+
defaultRunId: string;
|
|
45
|
+
log?: (line: string) => void;
|
|
46
|
+
/** connect timeout per upstream (ms) */
|
|
47
|
+
connectTimeoutMs?: number;
|
|
48
|
+
/** in-process upstreams for tests: name → already-connected client */
|
|
49
|
+
clients?: Record<string, Client>;
|
|
50
|
+
}
|
|
51
|
+
interface CallContext {
|
|
52
|
+
runId: string;
|
|
53
|
+
agent?: AgentScope | null;
|
|
54
|
+
sessionId?: string;
|
|
55
|
+
onprogress?: (progress: {
|
|
56
|
+
progress: number;
|
|
57
|
+
total?: number;
|
|
58
|
+
message?: string;
|
|
59
|
+
}) => void;
|
|
60
|
+
/** downstream session + request id, so upstream notifications can be related to this call */
|
|
61
|
+
session?: DownstreamSession;
|
|
62
|
+
requestId?: RequestId;
|
|
63
|
+
}
|
|
64
|
+
declare class ProxyRuntime {
|
|
65
|
+
readonly loaded: LoadedPolicy;
|
|
66
|
+
readonly guard: Guard;
|
|
67
|
+
readonly agent: AgentScope | null | undefined;
|
|
68
|
+
readonly defaultRunId: string;
|
|
69
|
+
readonly sessions: Set<DownstreamSession>;
|
|
70
|
+
private readonly connections;
|
|
71
|
+
private exposed;
|
|
72
|
+
private readonly resourceOwner;
|
|
73
|
+
private readonly templateOwner;
|
|
74
|
+
private readonly promptOwner;
|
|
75
|
+
private readonly log;
|
|
76
|
+
private readonly connectTimeoutMs;
|
|
77
|
+
private readonly testClients;
|
|
78
|
+
/** stop relaying upstream stderr once we are tearing down — shutdown noise is not the user's problem */
|
|
79
|
+
private closing;
|
|
80
|
+
constructor(opts: RuntimeOptions);
|
|
81
|
+
get policy(): {
|
|
82
|
+
version: 1;
|
|
83
|
+
mode: "dry-run" | "enforce";
|
|
84
|
+
upstreams: {
|
|
85
|
+
name: string;
|
|
86
|
+
headers: Record<string, string>;
|
|
87
|
+
args: string[];
|
|
88
|
+
env: Record<string, string>;
|
|
89
|
+
prefix: string | boolean;
|
|
90
|
+
timeout_ms: number;
|
|
91
|
+
url?: string | undefined;
|
|
92
|
+
auth?: string | undefined;
|
|
93
|
+
command?: string | undefined;
|
|
94
|
+
cwd?: string | undefined;
|
|
95
|
+
}[];
|
|
96
|
+
classify: {
|
|
97
|
+
read: string[];
|
|
98
|
+
write: string[];
|
|
99
|
+
spend: string[];
|
|
100
|
+
unknown: "read" | "write" | "block";
|
|
101
|
+
};
|
|
102
|
+
deny: string[];
|
|
103
|
+
caps: {
|
|
104
|
+
per_run: {
|
|
105
|
+
[x: string]: number;
|
|
106
|
+
tool_calls?: number | undefined;
|
|
107
|
+
writes?: number | undefined;
|
|
108
|
+
deletes?: number | undefined;
|
|
109
|
+
emails?: number | undefined;
|
|
110
|
+
spend_usd?: number | undefined;
|
|
111
|
+
};
|
|
112
|
+
per_day: {
|
|
113
|
+
[x: string]: number;
|
|
114
|
+
tool_calls?: number | undefined;
|
|
115
|
+
writes?: number | undefined;
|
|
116
|
+
deletes?: number | undefined;
|
|
117
|
+
emails?: number | undefined;
|
|
118
|
+
spend_usd?: number | undefined;
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
counters: Record<string, string[]>;
|
|
122
|
+
loop: {
|
|
123
|
+
window: number;
|
|
124
|
+
max_repeats: number;
|
|
125
|
+
max_cycle_len: number;
|
|
126
|
+
ignore_args: string[];
|
|
127
|
+
max_read_repeats: number;
|
|
128
|
+
};
|
|
129
|
+
dry_run: {
|
|
130
|
+
tools: string[];
|
|
131
|
+
synthesize: boolean;
|
|
132
|
+
};
|
|
133
|
+
approval: {
|
|
134
|
+
tools: string[];
|
|
135
|
+
wait_s: number;
|
|
136
|
+
ttl_s: number;
|
|
137
|
+
notify: {
|
|
138
|
+
slack?: string | undefined;
|
|
139
|
+
webhook?: string | undefined;
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
kill: {
|
|
143
|
+
file: string;
|
|
144
|
+
env: string;
|
|
145
|
+
};
|
|
146
|
+
spend: {
|
|
147
|
+
tools: Record<string, {
|
|
148
|
+
divisor: number;
|
|
149
|
+
amount_arg?: string | undefined;
|
|
150
|
+
currency_arg?: string | undefined;
|
|
151
|
+
fixed_usd?: number | undefined;
|
|
152
|
+
}>;
|
|
153
|
+
result_fields: string[];
|
|
154
|
+
models: Record<string, {
|
|
155
|
+
input_per_mtok: number;
|
|
156
|
+
output_per_mtok: number;
|
|
157
|
+
cached_input_per_mtok?: number | undefined;
|
|
158
|
+
}>;
|
|
159
|
+
default_usd: number;
|
|
160
|
+
};
|
|
161
|
+
agents: {
|
|
162
|
+
name: string;
|
|
163
|
+
allow: string[];
|
|
164
|
+
deny: string[];
|
|
165
|
+
key_hash?: string | undefined;
|
|
166
|
+
caps?: {
|
|
167
|
+
per_run: {
|
|
168
|
+
[x: string]: number;
|
|
169
|
+
tool_calls?: number | undefined;
|
|
170
|
+
writes?: number | undefined;
|
|
171
|
+
deletes?: number | undefined;
|
|
172
|
+
emails?: number | undefined;
|
|
173
|
+
spend_usd?: number | undefined;
|
|
174
|
+
};
|
|
175
|
+
per_day: {
|
|
176
|
+
[x: string]: number;
|
|
177
|
+
tool_calls?: number | undefined;
|
|
178
|
+
writes?: number | undefined;
|
|
179
|
+
deletes?: number | undefined;
|
|
180
|
+
emails?: number | undefined;
|
|
181
|
+
spend_usd?: number | undefined;
|
|
182
|
+
};
|
|
183
|
+
} | undefined;
|
|
184
|
+
mode?: "dry-run" | "enforce" | undefined;
|
|
185
|
+
upstreams?: string[] | undefined;
|
|
186
|
+
}[];
|
|
187
|
+
audit: {
|
|
188
|
+
path: string;
|
|
189
|
+
redact: boolean;
|
|
190
|
+
include_results: boolean;
|
|
191
|
+
max_chars: number;
|
|
192
|
+
};
|
|
193
|
+
alerts: {
|
|
194
|
+
on: ("KILLED" | "APPROVAL_REQUIRED" | "LOOP_DETECTED" | "CAP_EXCEEDED" | "TOOL_DENIED")[];
|
|
195
|
+
slack?: string | undefined;
|
|
196
|
+
webhook?: string | undefined;
|
|
197
|
+
};
|
|
198
|
+
state: {
|
|
199
|
+
dir: string;
|
|
200
|
+
};
|
|
201
|
+
allow?: string[] | undefined;
|
|
202
|
+
};
|
|
203
|
+
start(): Promise<void>;
|
|
204
|
+
private connect;
|
|
205
|
+
private wire;
|
|
206
|
+
private pickSession;
|
|
207
|
+
private broadcast;
|
|
208
|
+
private refreshTools;
|
|
209
|
+
private rebuildExposed;
|
|
210
|
+
listTools(agent?: AgentScope | null): ExposedTool[];
|
|
211
|
+
findTool(name: string): ExposedTool | undefined;
|
|
212
|
+
upstreamStatus(): UpstreamStatus[];
|
|
213
|
+
attach(session: DownstreamSession): void;
|
|
214
|
+
detach(session: DownstreamSession): void;
|
|
215
|
+
/** Run a tool call through the policy engine and, if allowed, the upstream. */
|
|
216
|
+
callTool(name: string, args: unknown, ctx: CallContext): Promise<{
|
|
217
|
+
result: GuardResult;
|
|
218
|
+
tool?: ExposedTool;
|
|
219
|
+
}>;
|
|
220
|
+
private connectedWith;
|
|
221
|
+
listResources(): Promise<ListResourcesResult>;
|
|
222
|
+
listResourceTemplates(): Promise<ListResourceTemplatesResult>;
|
|
223
|
+
private ownerForUri;
|
|
224
|
+
readResource(uri: string): Promise<ReadResourceResult>;
|
|
225
|
+
subscribe(uri: string, on: boolean): Promise<void>;
|
|
226
|
+
listPrompts(): Promise<ListPromptsResult>;
|
|
227
|
+
getPrompt(name: string, args: Record<string, string> | undefined): Promise<GetPromptResult>;
|
|
228
|
+
complete(params: CompleteRequest["params"]): Promise<CompleteResult>;
|
|
229
|
+
setLevel(level: LoggingLevel): Promise<void>;
|
|
230
|
+
close(): Promise<void>;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Downstream side of the proxy: the MCP server an agent connects to. One instance per session
|
|
235
|
+
* (stdio: one; Streamable HTTP: one per `Mcp-Session-Id`). Every request is served from the
|
|
236
|
+
* runtime; tool calls go through the policy engine.
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
type Extra = RequestHandlerExtra<ServerRequest, ServerNotification>;
|
|
240
|
+
interface DownstreamOptions {
|
|
241
|
+
/** run id for calls that carry neither `X-Run-Id` nor `_meta.runId` (default: runtime.defaultRunId) */
|
|
242
|
+
defaultRunId?: string;
|
|
243
|
+
}
|
|
244
|
+
declare function runIdFor(extra: Extra, meta: Record<string, unknown> | undefined, fallback: string): string;
|
|
245
|
+
/** Shape the engine's verdict into what the MCP client receives. */
|
|
246
|
+
declare function toCallToolResult(result: GuardResult, tool: ExposedTool | undefined): CallToolResult;
|
|
247
|
+
/** Build the per-session MCP server. */
|
|
248
|
+
declare function createDownstreamServer(runtime: ProxyRuntime, opts?: DownstreamOptions): McpServer;
|
|
249
|
+
|
|
250
|
+
interface HttpProxyOptions {
|
|
251
|
+
runtime: ProxyRuntime;
|
|
252
|
+
port?: number;
|
|
253
|
+
host?: string;
|
|
254
|
+
path?: string;
|
|
255
|
+
token?: string;
|
|
256
|
+
/** write `<stateDir>/http.json` for the CLI (default true) */
|
|
257
|
+
registerFile?: boolean;
|
|
258
|
+
}
|
|
259
|
+
interface HttpProxy {
|
|
260
|
+
url: string;
|
|
261
|
+
port: number;
|
|
262
|
+
token: string;
|
|
263
|
+
close(): Promise<void>;
|
|
264
|
+
}
|
|
265
|
+
interface HttpRegistration {
|
|
266
|
+
url: string;
|
|
267
|
+
baseUrl: string;
|
|
268
|
+
token: string;
|
|
269
|
+
pid: number;
|
|
270
|
+
startedAt: string;
|
|
271
|
+
}
|
|
272
|
+
declare function registrationPath(stateDir: string): string;
|
|
273
|
+
declare function startHttpProxy(opts: HttpProxyOptions): Promise<HttpProxy>;
|
|
274
|
+
|
|
275
|
+
/** Tiny argv parser: `--flag value`, `--flag=value`, `--bool`, `--no-bool`, repeated flags → arrays. */
|
|
276
|
+
interface ParsedArgs {
|
|
277
|
+
command: string | undefined;
|
|
278
|
+
positionals: string[];
|
|
279
|
+
flags: Record<string, string | boolean | string[]>;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
interface Io {
|
|
283
|
+
out: (line: string) => void;
|
|
284
|
+
err: (line: string) => void;
|
|
285
|
+
cwd: string;
|
|
286
|
+
env: NodeJS.ProcessEnv;
|
|
287
|
+
/** false when stdout is a pipe — an MCP client spawned us and wants a server, not the help text */
|
|
288
|
+
tty?: boolean;
|
|
289
|
+
}
|
|
290
|
+
declare function loadPolicyFor(args: ParsedArgs, io: Io, opts?: {
|
|
291
|
+
allowMissingEnv?: boolean;
|
|
292
|
+
}): LoadedPolicy;
|
|
293
|
+
interface FileGuard {
|
|
294
|
+
guard: Guard;
|
|
295
|
+
kill: FileKillSwitch;
|
|
296
|
+
audit: FileAuditSink;
|
|
297
|
+
approvals: FileApprovalStore;
|
|
298
|
+
loaded: LoadedPolicy;
|
|
299
|
+
}
|
|
300
|
+
/** A guard wired to the state dir, audit file, KILL file and approvals of a loaded policy. */
|
|
301
|
+
declare function createFileGuard(loaded: LoadedPolicy, opts?: {
|
|
302
|
+
onEvent?: (e: GuardEvent) => void | Promise<void>;
|
|
303
|
+
approvalUrl?: (r: ApprovalRecord) => string | undefined;
|
|
304
|
+
log?: (line: string) => void;
|
|
305
|
+
alerts?: boolean;
|
|
306
|
+
env?: NodeJS.ProcessEnv;
|
|
307
|
+
}): FileGuard;
|
|
308
|
+
/** A running HTTP proxy for this policy, if one registered itself. */
|
|
309
|
+
declare function readRegistration(loaded: LoadedPolicy): HttpRegistration | undefined;
|
|
310
|
+
|
|
311
|
+
interface AlerterOptions {
|
|
312
|
+
policy: Policy;
|
|
313
|
+
approvalUrl?: (record: ApprovalRecord) => string | undefined;
|
|
314
|
+
log?: (line: string) => void;
|
|
315
|
+
fetch?: typeof fetch;
|
|
316
|
+
}
|
|
317
|
+
declare function approvalSlackMessage(event: GuardEvent, url: string | undefined): {
|
|
318
|
+
text: string;
|
|
319
|
+
blocks: unknown[];
|
|
320
|
+
};
|
|
321
|
+
declare function haltSlackMessage(event: GuardEvent): {
|
|
322
|
+
text: string;
|
|
323
|
+
blocks: unknown[];
|
|
324
|
+
};
|
|
325
|
+
/** Returns a `Guard.onEvent` handler. Never throws; failures are logged. */
|
|
326
|
+
declare function createAlerter(opts: AlerterOptions): (event: GuardEvent) => Promise<void>;
|
|
327
|
+
|
|
328
|
+
type ClientKind = "claude-code-project" | "claude-code-user" | "claude-desktop" | "cursor-project" | "cursor-user" | "vscode" | "windsurf" | "generic";
|
|
329
|
+
interface ClientConfigFile {
|
|
330
|
+
kind: ClientKind;
|
|
331
|
+
label: string;
|
|
332
|
+
path: string;
|
|
333
|
+
/** `mcpServers` (most clients) or `servers` (VS Code) */
|
|
334
|
+
serversKey: "mcpServers" | "servers";
|
|
335
|
+
}
|
|
336
|
+
interface ServerEntry {
|
|
337
|
+
type?: string;
|
|
338
|
+
command?: string;
|
|
339
|
+
args?: string[];
|
|
340
|
+
env?: Record<string, string>;
|
|
341
|
+
cwd?: string;
|
|
342
|
+
url?: string;
|
|
343
|
+
headers?: Record<string, string>;
|
|
344
|
+
[k: string]: unknown;
|
|
345
|
+
}
|
|
346
|
+
declare function candidateConfigs(cwd?: string, home?: string, env?: NodeJS.ProcessEnv): ClientConfigFile[];
|
|
347
|
+
/** Configs that exist on disk, project-level first. */
|
|
348
|
+
declare function detectClientConfigs(cwd?: string, home?: string, env?: NodeJS.ProcessEnv): ClientConfigFile[];
|
|
349
|
+
declare function readServers(file: ClientConfigFile): Record<string, ServerEntry>;
|
|
350
|
+
/** Client servers → policy upstreams. Names are sanitized; secrets stay where they were (in the config). */
|
|
351
|
+
declare function serversToUpstreams(servers: Record<string, ServerEntry>): {
|
|
352
|
+
upstreams: Upstream[];
|
|
353
|
+
skipped: {
|
|
354
|
+
name: string;
|
|
355
|
+
reason: string;
|
|
356
|
+
}[];
|
|
357
|
+
};
|
|
358
|
+
/** The entry that replaces every server: one proxy, all upstreams behind it. */
|
|
359
|
+
declare function proxyEntry(file: ClientConfigFile, policyPath: string, opts?: {
|
|
360
|
+
agent?: string;
|
|
361
|
+
}): ServerEntry;
|
|
362
|
+
/** Back up the file (once) and replace its servers with the single proxy entry. */
|
|
363
|
+
declare function rewriteClientConfig(file: ClientConfigFile, policyPath: string, opts?: {
|
|
364
|
+
agent?: string;
|
|
365
|
+
}): {
|
|
366
|
+
backup: string;
|
|
367
|
+
replaced: string[];
|
|
368
|
+
};
|
|
369
|
+
/** `agentguard init --undo`: restore the backup. */
|
|
370
|
+
declare function restoreClientConfig(file: ClientConfigFile): boolean;
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* `agentguard tools` — connect to every upstream and print the tools the agent will see,
|
|
374
|
+
* with their class and why. Also the probe `init` uses to seed the policy.
|
|
375
|
+
*/
|
|
376
|
+
|
|
377
|
+
interface ProbedTool {
|
|
378
|
+
upstream: string;
|
|
379
|
+
name: string;
|
|
380
|
+
tool: Tool;
|
|
381
|
+
classification: Classification;
|
|
382
|
+
}
|
|
383
|
+
interface ProbeResult {
|
|
384
|
+
tools: ProbedTool[];
|
|
385
|
+
upstreams: {
|
|
386
|
+
name: string;
|
|
387
|
+
connected: boolean;
|
|
388
|
+
tools: number;
|
|
389
|
+
error?: string;
|
|
390
|
+
}[];
|
|
391
|
+
}
|
|
392
|
+
/** Connect to the upstreams (with a policy for classification), list tools, disconnect. */
|
|
393
|
+
declare function probeUpstreams(upstreams: Upstream[], opts?: {
|
|
394
|
+
policy?: Policy;
|
|
395
|
+
timeoutMs?: number;
|
|
396
|
+
log?: (l: string) => void;
|
|
397
|
+
env?: NodeJS.ProcessEnv;
|
|
398
|
+
}): Promise<ProbeResult>;
|
|
399
|
+
|
|
400
|
+
interface StarterPolicyOptions {
|
|
401
|
+
upstreams: Upstream[];
|
|
402
|
+
tools?: ProbedTool[];
|
|
403
|
+
mode?: "dry-run" | "enforce";
|
|
404
|
+
generatedAt?: Date;
|
|
405
|
+
probeErrors?: string[];
|
|
406
|
+
}
|
|
407
|
+
/** The commented starter policy — the file people read, so every knob explains itself. */
|
|
408
|
+
declare function renderStarterPolicy(opts: StarterPolicyOptions): string;
|
|
409
|
+
|
|
410
|
+
declare const DEFAULT_PERMISSION_PATHS: string[];
|
|
411
|
+
interface PermissionDiffResult {
|
|
412
|
+
base: string;
|
|
413
|
+
head: string;
|
|
414
|
+
files: string[];
|
|
415
|
+
findings: Finding[];
|
|
416
|
+
markdown: string;
|
|
417
|
+
}
|
|
418
|
+
declare function runPermissionDiff(cwd: string, opts: {
|
|
419
|
+
base?: string;
|
|
420
|
+
head?: string;
|
|
421
|
+
paths?: string[];
|
|
422
|
+
title?: string;
|
|
423
|
+
}): PermissionDiffResult;
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Fake CRM MCP server used by the tests, the demo agent and the README walkthrough. In-memory
|
|
427
|
+
* contacts; every mutation is recorded so tests can assert what really happened upstream.
|
|
428
|
+
*
|
|
429
|
+
* node dist/fixtures/crm-server.js # stdio
|
|
430
|
+
* node dist/fixtures/crm-server.js --http # Streamable HTTP on 127.0.0.1:<port> (prints the URL)
|
|
431
|
+
*/
|
|
432
|
+
|
|
433
|
+
interface Contact {
|
|
434
|
+
id: string;
|
|
435
|
+
name: string;
|
|
436
|
+
email: string;
|
|
437
|
+
updated_at: string;
|
|
438
|
+
}
|
|
439
|
+
interface CrmState {
|
|
440
|
+
contacts: Map<string, Contact>;
|
|
441
|
+
mutations: {
|
|
442
|
+
tool: string;
|
|
443
|
+
args: unknown;
|
|
444
|
+
}[];
|
|
445
|
+
emails: {
|
|
446
|
+
to: string;
|
|
447
|
+
subject: string;
|
|
448
|
+
}[];
|
|
449
|
+
charges: {
|
|
450
|
+
customer_id: string;
|
|
451
|
+
amount_usd: number;
|
|
452
|
+
}[];
|
|
453
|
+
}
|
|
454
|
+
declare function seedState(): CrmState;
|
|
455
|
+
declare function crmTools(state: CrmState): ToolDef[];
|
|
456
|
+
declare function createCrmMcpServer(state?: CrmState): McpServer;
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* A scripted "agent" that misbehaves on purpose: reads, then writes, then loops, then bursts
|
|
460
|
+
* writes past the cap. Run it against the proxy to see dry-run diffs, LOOP_DETECTED and
|
|
461
|
+
* CAP_EXCEEDED in `agentguard report`.
|
|
462
|
+
*
|
|
463
|
+
* node dist/fixtures/demo-agent.js --config agentguard.yaml # spawns `agentguard proxy` over stdio
|
|
464
|
+
*/
|
|
465
|
+
|
|
466
|
+
interface DemoStep {
|
|
467
|
+
step: string;
|
|
468
|
+
tool: string;
|
|
469
|
+
ok: boolean;
|
|
470
|
+
code?: string;
|
|
471
|
+
dryRun?: boolean;
|
|
472
|
+
text?: string;
|
|
473
|
+
}
|
|
474
|
+
interface DemoOptions {
|
|
475
|
+
/** how many writes to burst at the end (default 60 — past a `writes: 50` cap) */
|
|
476
|
+
burst?: number;
|
|
477
|
+
/** how many times to repeat the identical update (default 5 — past `max_repeats: 3`) */
|
|
478
|
+
loop?: number;
|
|
479
|
+
runId?: string;
|
|
480
|
+
log?: (line: string) => void;
|
|
481
|
+
}
|
|
482
|
+
/** Drive a connected client through the scripted scenario. Returns every step's outcome. */
|
|
483
|
+
declare function runDemoAgent(client: Client, opts?: DemoOptions): Promise<DemoStep[]>;
|
|
484
|
+
|
|
485
|
+
declare const HELP = "agentguard \u2014 MCP policy proxy for agents that touch production\n\n npx @agentwares/agentguard init read your MCP config, write agentguard.yaml (dry-run), route every server through the proxy\n agentguard report [--run id|--all] what this run did / would have destroyed / spent, where it was halted\n agentguard diff [--run id] record-by-record mutation diff from a dry run\n agentguard verify [audit.jsonl] prove the hash-chained audit log was not edited\n\n agentguard proxy [--http --port 8788] [--agent name] [--run-id id] [--mode dry-run|enforce]\n agentguard tools [--json] the tools your agent will see, with class and why\n agentguard status [--run id] counters vs caps, kill state, pending approvals\n\n agentguard kill [reason] halt every run now (file + running HTTP proxy); agentguard resume\n agentguard approvals [--all] pending approvals; agentguard approve <id> | deny <id> [--note text]\n agentguard key create <agent> [--allow 'crm_get_*']... [--deny p] [--writes n] [--spend n] [--mode m]\n agentguard key list | revoke <agent>\n agentguard permission-diff [--base ref] [--head ref] [--paths a,b] [--format markdown|json] [--fail-on-widen]\n\nOptions: --config <agentguard.yaml> (or AGENTGUARD_CONFIG), --json, --help, --version\nDocs: https://github.com/agentwares/agentwares/tree/main/apps/agentguard-cli";
|
|
486
|
+
declare function main(argv: readonly string[], io?: Io): Promise<number>;
|
|
487
|
+
|
|
488
|
+
export { type CallContext, type ClientConfigFile, type CrmState, DEFAULT_PERMISSION_PATHS, type DemoOptions, type DemoStep, type DownstreamOptions, type DownstreamSession, type ExposedTool, type FileGuard, HELP, type HttpProxy, type HttpProxyOptions, type HttpRegistration, type Io, type PermissionDiffResult, type ProbeResult, type ProbedTool, ProxyRuntime, type RuntimeOptions, type ServerEntry, type UpstreamStatus, approvalSlackMessage, candidateConfigs, createAlerter, createCrmMcpServer, createDownstreamServer, createFileGuard, crmTools, detectClientConfigs, haltSlackMessage, loadPolicyFor, main, probeUpstreams, proxyEntry, readRegistration, readServers, registrationPath, renderStarterPolicy, restoreClientConfig, rewriteClientConfig, runDemoAgent, runIdFor, runPermissionDiff, seedState, serversToUpstreams, startHttpProxy, toCallToolResult };
|