toolgate 1.0.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
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,342 @@
1
+ # 🛡️ ToolGate
2
+
3
+ **Optimistic execution middleware for autonomous agents.**
4
+
5
+ Let your agent run freely — reads execute instantly, every other action (writes, deletes, sends, deploys) is silently intercepted, recorded, and held for human approval. The agent never knows the difference.
6
+
7
+ ```
8
+ Agent calls tool ──▶ ToolGate classifies ──▶ READ? ──▶ Execute for real
9
+
10
+ └──▶ ACTION? ──▶ Return phantom result
11
+ Save params to queue
12
+
13
+ Agent finishes ──▶ Human reviews all actions
14
+
15
+ Approve ──▶ Execute for real
16
+ Reject ──▶ Discard
17
+ Edit ──▶ Execute with new params
18
+ ```
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ npm install toolgate
24
+ ```
25
+
26
+ ## Quick Start — 5 Lines
27
+
28
+ ```typescript
29
+ import { ToolGate, cliApproval } from "toolgate";
30
+
31
+ // Your real tool executor (what the agent normally calls)
32
+ async function execute(tool: string, params: Record<string, unknown>) {
33
+ // call your APIs, MCP servers, SDKs, whatever
34
+ }
35
+
36
+ const gate = new ToolGate(execute, {
37
+ agentName: "my-agent",
38
+ onApprovalNeeded: cliApproval, // interactive terminal approval
39
+ });
40
+
41
+ // Give your agent gate.proxy instead of the real executor
42
+ await myAgent.run({
43
+ tools: gate.proxy,
44
+ task: "Organize my inbox and draft replies",
45
+ });
46
+
47
+ // When done, finalize — triggers the approval flow
48
+ await gate.finalize();
49
+ ```
50
+
51
+ That's it. Your agent runs as normal. Reads pass through. Actions are queued. You approve at the end.
52
+
53
+ ## How Classification Works
54
+
55
+ ToolGate uses a multi-layer classifier to determine if a tool call is a **read** (passthrough) or an **action** (intercept):
56
+
57
+ 1. **Explicit overrides** — `readTools: ["getUser"]` / `actionTools: ["deleteUser"]`
58
+ 2. **Custom classifier** — provide your own function
59
+ 3. **Name pattern matching** — `get*`, `list*`, `search*` → read. `create*`, `send*`, `delete*` → action
60
+ 4. **MCP description analysis** — parses tool descriptions for read vs. mutate signals
61
+ 5. **HTTP method hints** — if params contain `method: "GET"` → read, `method: "POST"` → action
62
+ 6. **Safe default** — unknown tools are intercepted (never accidentally executes a write)
63
+
64
+ ## Explicit Tool Lists
65
+
66
+ ```typescript
67
+ const gate = new ToolGate(execute, {
68
+ readTools: ["getEmails", "searchContacts", "listFiles"],
69
+ actionTools: ["sendEmail", "deleteFile", "createIssue"],
70
+ });
71
+ ```
72
+
73
+ ## Custom Classifier
74
+
75
+ ```typescript
76
+ const gate = new ToolGate(execute, {
77
+ classifier: (toolName, params) => {
78
+ if (toolName.startsWith("db.query")) {
79
+ return { intent: "read", isPassthrough: true, confidence: 1, reason: "DB query" };
80
+ }
81
+ // fall through to default
82
+ return classifyTool(toolName, params);
83
+ },
84
+ });
85
+ ```
86
+
87
+ ## MCP Integration
88
+
89
+ ToolGate auto-classifies MCP tools by analyzing their names and descriptions:
90
+
91
+ ```typescript
92
+ import { mcpToolGate, autoConfigFromMCP } from "toolgate";
93
+
94
+ // Option 1: Provide tool definitions upfront
95
+ const gate = mcpToolGate(mcpExecutor, {
96
+ mcpServers: [
97
+ {
98
+ name: "gmail",
99
+ url: "https://gmail.mcp.example.com/sse",
100
+ tools: [
101
+ { name: "gmail_listMessages", description: "List messages in the inbox" },
102
+ { name: "gmail_sendMessage", description: "Send a new email message" },
103
+ { name: "gmail_trashMessage", description: "Move a message to trash" },
104
+ ],
105
+ },
106
+ ],
107
+ });
108
+
109
+ // Option 2: Auto-discover from running MCP servers
110
+ const config = await autoConfigFromMCP([
111
+ { name: "gmail", url: "https://gmail.mcp.example.com/sse" },
112
+ { name: "github", url: "https://github.mcp.example.com/sse" },
113
+ ]);
114
+ const gate = new ToolGate(mcpExecutor, config);
115
+ ```
116
+
117
+ ## Wrapping an Existing Tool Map
118
+
119
+ If your agent uses a `{ toolName: function }` map:
120
+
121
+ ```typescript
122
+ const realTools = {
123
+ getUser: async (p) => db.users.find(p.id),
124
+ createUser: async (p) => db.users.insert(p),
125
+ sendEmail: async (p) => mailer.send(p),
126
+ };
127
+
128
+ const gate = new ToolGate(
129
+ async (name, params) => realTools[name](params),
130
+ { agentName: "user-manager" }
131
+ );
132
+
133
+ // Or use the convenience wrapper:
134
+ const proxiedTools = gate.wrapTools(realTools);
135
+ await agent.run({ tools: proxiedTools });
136
+ await gate.finalize();
137
+ ```
138
+
139
+ ## Phantom Responses
140
+
141
+ When an action is intercepted, the agent receives a convincing phantom response so it continues working normally:
142
+
143
+ | Intent | Default Phantom Response |
144
+ |----------|-------------------------------------------------------|
145
+ | `create` | `{ success: true, id: "phantom_abc123" }` |
146
+ | `update` | `{ success: true, message: "Updated successfully" }` |
147
+ | `delete` | `{ success: true, message: "Deleted successfully" }` |
148
+ | `send` | `{ success: true, messageId: "msg_xyz789" }` |
149
+
150
+ Custom phantom responses:
151
+
152
+ ```typescript
153
+ const gate = new ToolGate(execute, {
154
+ phantomResponse: (tool) => {
155
+ if (tool.name === "createIssue") {
156
+ return { id: 99999, url: "https://github.com/org/repo/issues/99999", title: tool.params.title };
157
+ }
158
+ return { ok: true };
159
+ },
160
+ });
161
+ ```
162
+
163
+ ## Approval Methods
164
+
165
+ ### 1. CLI (built-in)
166
+
167
+ ```typescript
168
+ import { cliApproval } from "toolgate";
169
+ const gate = new ToolGate(execute, { onApprovalNeeded: cliApproval });
170
+ ```
171
+
172
+ ### 2. Programmatic
173
+
174
+ ```typescript
175
+ const gate = new ToolGate(execute);
176
+ await agent.run({ tools: gate.proxy });
177
+ const request = await gate.finalize();
178
+
179
+ // Inspect what the agent wants to do
180
+ console.log(gate.summary());
181
+
182
+ // Approve everything
183
+ await gate.approveAll();
184
+
185
+ // Or reject everything
186
+ await gate.rejectAll();
187
+
188
+ // Or decide per-action
189
+ await gate.executeApproval({
190
+ sessionId: gate.sessionId,
191
+ approvedAt: Date.now(),
192
+ decisions: new Map([
193
+ ["action-id-1", { action: "approve" }],
194
+ ["action-id-2", { action: "reject" }],
195
+ ["action-id-3", { action: "edit", actionId: "action-id-3", newParams: { to: "corrected@example.com" } }],
196
+ ]),
197
+ });
198
+ ```
199
+
200
+ ### 3. Dashboard (Next.js + Supabase)
201
+
202
+ See the **Dashboard** section below.
203
+
204
+ ## Supabase Persistence
205
+
206
+ Pass your Supabase credentials and sessions are automatically persisted:
207
+
208
+ ```typescript
209
+ const gate = new ToolGate(execute, {
210
+ supabaseUrl: process.env.SUPABASE_URL,
211
+ supabaseKey: process.env.SUPABASE_ANON_KEY,
212
+ agentName: "inbox-agent",
213
+ });
214
+ ```
215
+
216
+ ## Inspection
217
+
218
+ ```typescript
219
+ gate.reads; // all reads that were executed
220
+ gate.pending; // all intercepted actions
221
+ gate.currentSession; // full session snapshot
222
+ gate.summary(); // pretty-printed CLI summary
223
+ ```
224
+
225
+ ---
226
+
227
+ # Dashboard Setup
228
+
229
+ The dashboard is a Next.js app that shows all ToolGate sessions in real time.
230
+
231
+ ## 1. Supabase Setup
232
+
233
+ 1. Create a project at [supabase.com](https://supabase.com)
234
+ 2. Go to **SQL Editor** and run the contents of `sql/schema.sql` (included in this repo)
235
+ 3. Copy your **Project URL** and **anon public key** from Settings → API
236
+
237
+ ## 2. Dashboard Setup
238
+
239
+ ```bash
240
+ cd dashboard
241
+ cp .env.example .env.local
242
+ # Edit .env.local with your Supabase URL and key
243
+ npm install
244
+ npm run dev
245
+ ```
246
+
247
+ Open `http://localhost:3000`. Sessions appear in real time as your agents run.
248
+
249
+ ## 3. Use Together
250
+
251
+ ```typescript
252
+ import { ToolGate } from "toolgate";
253
+
254
+ const gate = new ToolGate(execute, {
255
+ agentName: "deploy-bot",
256
+ supabaseUrl: "https://xxx.supabase.co",
257
+ supabaseKey: "eyJ...",
258
+ });
259
+
260
+ gate.describe("Deploy v2.3.1 to production");
261
+
262
+ await agent.run({ tools: gate.proxy });
263
+ await gate.finalize();
264
+
265
+ // Now open the dashboard — the session is there with approve/reject/edit buttons
266
+ ```
267
+
268
+ ---
269
+
270
+ # Full Example: Autonomous Email Agent
271
+
272
+ ```typescript
273
+ import { ToolGate, cliApproval } from "toolgate";
274
+
275
+ // Simulated tool executor
276
+ async function execute(tool: string, params: Record<string, unknown>) {
277
+ switch (tool) {
278
+ case "listEmails": return [{ id: 1, from: "boss@co.com", subject: "Q3 Report" }];
279
+ case "readEmail": return { id: 1, body: "Please review the Q3 numbers." };
280
+ case "sendEmail": return { messageId: "real_123" };
281
+ case "archiveEmail": return { success: true };
282
+ default: return { error: "unknown tool" };
283
+ }
284
+ }
285
+
286
+ const gate = new ToolGate(execute, {
287
+ agentName: "email-assistant",
288
+ onApprovalNeeded: cliApproval,
289
+ });
290
+
291
+ gate.describe("Read inbox, draft replies, archive processed emails");
292
+
293
+ // Simulate what an autonomous agent would do:
294
+ const emails = await gate.proxy("listEmails", {}); // ✅ READ — executes
295
+ const detail = await gate.proxy("readEmail", { id: 1 }); // ✅ READ — executes
296
+ const sent = await gate.proxy("sendEmail", { // 🛑 SEND — intercepted
297
+ to: "boss@co.com",
298
+ subject: "Re: Q3 Report",
299
+ body: "Reviewed — numbers look solid. Ship it.",
300
+ });
301
+ const archived = await gate.proxy("archiveEmail", { id: 1 }); // 🛑 DELETE — intercepted
302
+
303
+ // Agent thinks both worked. Now finalize:
304
+ await gate.finalize();
305
+ // → CLI shows: 2 reads executed, 2 actions pending approval
306
+ // → You approve/reject/edit each one
307
+ ```
308
+
309
+ ---
310
+
311
+ # API Reference
312
+
313
+ ### `new ToolGate(executor, config?)`
314
+
315
+ | Config Field | Type | Description |
316
+ |-------------------|----------------------------------------------|------------------------------------------|
317
+ | `classifier` | `(name, params) => ToolClassification` | Custom classification function |
318
+ | `readTools` | `string[]` | Always-passthrough tool names |
319
+ | `actionTools` | `string[]` | Always-intercept tool names |
320
+ | `phantomResponse` | `(tool: ToolCall) => unknown` | Custom phantom result generator |
321
+ | `onApprovalNeeded`| `(req: ApprovalRequest) => Promise<Result>` | Callback when agent finishes |
322
+ | `supabaseUrl` | `string` | Supabase project URL |
323
+ | `supabaseKey` | `string` | Supabase anon key |
324
+ | `agentName` | `string` | Display name for the agent |
325
+ | `mcpServers` | `MCPServerDef[]` | MCP server + tool definitions |
326
+
327
+ ### Instance Methods
328
+
329
+ | Method | Returns | Description |
330
+ |----------------------|----------------------------|----------------------------------------------|
331
+ | `.proxy` | `RealExecutor` | The proxied executor to give to your agent |
332
+ | `.wrapTools(map)` | Same tool map shape | Wraps a `{ name: fn }` tool map |
333
+ | `.describe(text)` | `this` | Set task description |
334
+ | `.finalize()` | `Promise<ApprovalRequest>` | End session, trigger approval |
335
+ | `.approveAll()` | `Promise<Map>` | Approve + execute all pending actions |
336
+ | `.rejectAll()` | `void` | Reject all pending actions |
337
+ | `.executeApproval()` | `Promise<Map>` | Execute with per-action decisions |
338
+ | `.summary()` | `string` | Pretty-printed session summary |
339
+
340
+ ## License
341
+
342
+ MIT
@@ -0,0 +1,165 @@
1
+ type ToolIntent = "read" | "write" | "delete" | "create" | "update" | "execute" | "send" | "unknown";
2
+ interface ToolClassification {
3
+ intent: ToolIntent;
4
+ isPassthrough: boolean;
5
+ confidence: number;
6
+ reason: string;
7
+ }
8
+ interface ToolCall {
9
+ id: string;
10
+ name: string;
11
+ params: Record<string, unknown>;
12
+ timestamp: number;
13
+ classification: ToolClassification;
14
+ }
15
+ interface ExecutedRead extends ToolCall {
16
+ result: unknown;
17
+ }
18
+ interface PendingAction extends ToolCall {
19
+ phantomResult: unknown;
20
+ approved?: boolean;
21
+ editedParams?: Record<string, unknown>;
22
+ }
23
+ type SessionStatus = "running" | "pending_approval" | "approved" | "rejected" | "partial";
24
+ interface Session {
25
+ id: string;
26
+ agentName: string;
27
+ taskDescription: string;
28
+ startedAt: number;
29
+ completedAt?: number;
30
+ status: SessionStatus;
31
+ reads: ExecutedRead[];
32
+ pendingActions: PendingAction[];
33
+ metadata?: Record<string, unknown>;
34
+ }
35
+ interface ApprovalRequest {
36
+ sessionId: string;
37
+ agentName: string;
38
+ taskDescription: string;
39
+ reads: ExecutedRead[];
40
+ pendingActions: PendingAction[];
41
+ createdAt: number;
42
+ }
43
+ type ActionDecision = {
44
+ action: "approve";
45
+ } | {
46
+ action: "reject";
47
+ } | {
48
+ action: "edit";
49
+ actionId: string;
50
+ newParams: Record<string, unknown>;
51
+ };
52
+ interface ApprovalResult {
53
+ sessionId: string;
54
+ decisions: Map<string, ActionDecision>;
55
+ approvedAt: number;
56
+ }
57
+ interface ToolGateConfig {
58
+ /** Custom classifier — override the built-in heuristic */
59
+ classifier?: (toolName: string, params: Record<string, unknown>) => ToolClassification;
60
+ /** Explicit read tool names (always passthrough) */
61
+ readTools?: string[];
62
+ /** Explicit write/action tool names (always intercept) */
63
+ actionTools?: string[];
64
+ /** What to return to the agent when an action is intercepted */
65
+ phantomResponse?: (tool: ToolCall) => unknown;
66
+ /** Called when session completes and needs approval */
67
+ onApprovalNeeded?: (request: ApprovalRequest) => Promise<ApprovalResult>;
68
+ /** Supabase URL for dashboard persistence (optional) */
69
+ supabaseUrl?: string;
70
+ /** Supabase anon key (optional) */
71
+ supabaseKey?: string;
72
+ /** Agent display name */
73
+ agentName?: string;
74
+ /** MCP server definitions for auto-classification */
75
+ mcpServers?: MCPServerDef[];
76
+ }
77
+ interface MCPToolDef {
78
+ name: string;
79
+ description: string;
80
+ inputSchema?: Record<string, unknown>;
81
+ }
82
+ interface MCPServerDef {
83
+ name: string;
84
+ url: string;
85
+ tools?: MCPToolDef[];
86
+ }
87
+ type RealExecutor = (toolName: string, params: Record<string, unknown>) => Promise<unknown>;
88
+
89
+ declare class ToolGate {
90
+ private config;
91
+ private executor;
92
+ private session;
93
+ private mcpToolIndex;
94
+ private readSet;
95
+ private actionSet;
96
+ private persistence;
97
+ constructor(executor: RealExecutor, config?: ToolGateConfig);
98
+ /** Set a human-readable description for this task/session */
99
+ describe(taskDescription: string): this;
100
+ /** The proxy function you hand to the agent instead of the real executor */
101
+ get proxy(): RealExecutor;
102
+ /** Wrap an existing tool map (name → function) into a proxied tool map */
103
+ wrapTools<T extends Record<string, (...args: any[]) => Promise<unknown>>>(tools: T): T;
104
+ /** Core: classify and either passthrough or intercept */
105
+ private handle;
106
+ private classify;
107
+ private defaultPhantom;
108
+ /** Call when agent is done. Returns the approval request. */
109
+ finalize(): Promise<ApprovalRequest>;
110
+ /** Execute approved actions for real */
111
+ executeApproval(result: ApprovalResult): Promise<Map<string, unknown>>;
112
+ /** Approve all pending actions at once */
113
+ approveAll(): Promise<Map<string, unknown>>;
114
+ /** Reject all pending actions */
115
+ rejectAll(): Promise<void>;
116
+ get sessionId(): string;
117
+ get reads(): ExecutedRead[];
118
+ get pending(): PendingAction[];
119
+ get currentSession(): Session;
120
+ /** Pretty-print a summary for CLI / logging */
121
+ summary(): string;
122
+ }
123
+
124
+ /**
125
+ * Interactive CLI approval flow.
126
+ * Pass this as `onApprovalNeeded` in ToolGateConfig to get a
127
+ * terminal-based approval UI.
128
+ */
129
+ declare function cliApproval(request: ApprovalRequest): Promise<ApprovalResult>;
130
+
131
+ declare function classifyTool(toolName: string, params: Record<string, unknown>, mcpToolDef?: MCPToolDef): ToolClassification;
132
+
133
+ /**
134
+ * Create a ToolGate specifically for MCP-based agents.
135
+ *
136
+ * Pass your MCP server definitions (with tool lists) and ToolGate will
137
+ * auto-classify every tool by analyzing its name + description.
138
+ *
139
+ * Usage:
140
+ * const gate = mcpToolGate(mcpExecutor, {
141
+ * mcpServers: [
142
+ * { name: "gmail", url: "https://gmail.mcp.example.com/sse", tools: [...] },
143
+ * { name: "github", url: "https://github.mcp.example.com/sse", tools: [...] },
144
+ * ],
145
+ * });
146
+ *
147
+ * // Hand gate.proxy to your agent as the tool executor
148
+ * await agent.run({ execute: gate.proxy });
149
+ * const approval = await gate.finalize();
150
+ */
151
+ declare function mcpToolGate(executor: RealExecutor, config?: ToolGateConfig): ToolGate;
152
+ /**
153
+ * Fetch MCP tool definitions from a running MCP server.
154
+ * Calls the standard `tools/list` JSON-RPC method.
155
+ */
156
+ declare function discoverMCPTools(serverUrl: string): Promise<MCPToolDef[]>;
157
+ /**
158
+ * Auto-discover tools from all MCP servers and return a fully configured ToolGateConfig.
159
+ */
160
+ declare function autoConfigFromMCP(servers: Array<{
161
+ name: string;
162
+ url: string;
163
+ }>, overrides?: Partial<ToolGateConfig>): Promise<ToolGateConfig>;
164
+
165
+ export { type ActionDecision, type ApprovalRequest, type ApprovalResult, type ExecutedRead, type MCPServerDef, type MCPToolDef, type PendingAction, type RealExecutor, type Session, type SessionStatus, type ToolCall, type ToolClassification, ToolGate, type ToolGateConfig, type ToolIntent, autoConfigFromMCP, classifyTool, cliApproval, discoverMCPTools, mcpToolGate };
@@ -0,0 +1,165 @@
1
+ type ToolIntent = "read" | "write" | "delete" | "create" | "update" | "execute" | "send" | "unknown";
2
+ interface ToolClassification {
3
+ intent: ToolIntent;
4
+ isPassthrough: boolean;
5
+ confidence: number;
6
+ reason: string;
7
+ }
8
+ interface ToolCall {
9
+ id: string;
10
+ name: string;
11
+ params: Record<string, unknown>;
12
+ timestamp: number;
13
+ classification: ToolClassification;
14
+ }
15
+ interface ExecutedRead extends ToolCall {
16
+ result: unknown;
17
+ }
18
+ interface PendingAction extends ToolCall {
19
+ phantomResult: unknown;
20
+ approved?: boolean;
21
+ editedParams?: Record<string, unknown>;
22
+ }
23
+ type SessionStatus = "running" | "pending_approval" | "approved" | "rejected" | "partial";
24
+ interface Session {
25
+ id: string;
26
+ agentName: string;
27
+ taskDescription: string;
28
+ startedAt: number;
29
+ completedAt?: number;
30
+ status: SessionStatus;
31
+ reads: ExecutedRead[];
32
+ pendingActions: PendingAction[];
33
+ metadata?: Record<string, unknown>;
34
+ }
35
+ interface ApprovalRequest {
36
+ sessionId: string;
37
+ agentName: string;
38
+ taskDescription: string;
39
+ reads: ExecutedRead[];
40
+ pendingActions: PendingAction[];
41
+ createdAt: number;
42
+ }
43
+ type ActionDecision = {
44
+ action: "approve";
45
+ } | {
46
+ action: "reject";
47
+ } | {
48
+ action: "edit";
49
+ actionId: string;
50
+ newParams: Record<string, unknown>;
51
+ };
52
+ interface ApprovalResult {
53
+ sessionId: string;
54
+ decisions: Map<string, ActionDecision>;
55
+ approvedAt: number;
56
+ }
57
+ interface ToolGateConfig {
58
+ /** Custom classifier — override the built-in heuristic */
59
+ classifier?: (toolName: string, params: Record<string, unknown>) => ToolClassification;
60
+ /** Explicit read tool names (always passthrough) */
61
+ readTools?: string[];
62
+ /** Explicit write/action tool names (always intercept) */
63
+ actionTools?: string[];
64
+ /** What to return to the agent when an action is intercepted */
65
+ phantomResponse?: (tool: ToolCall) => unknown;
66
+ /** Called when session completes and needs approval */
67
+ onApprovalNeeded?: (request: ApprovalRequest) => Promise<ApprovalResult>;
68
+ /** Supabase URL for dashboard persistence (optional) */
69
+ supabaseUrl?: string;
70
+ /** Supabase anon key (optional) */
71
+ supabaseKey?: string;
72
+ /** Agent display name */
73
+ agentName?: string;
74
+ /** MCP server definitions for auto-classification */
75
+ mcpServers?: MCPServerDef[];
76
+ }
77
+ interface MCPToolDef {
78
+ name: string;
79
+ description: string;
80
+ inputSchema?: Record<string, unknown>;
81
+ }
82
+ interface MCPServerDef {
83
+ name: string;
84
+ url: string;
85
+ tools?: MCPToolDef[];
86
+ }
87
+ type RealExecutor = (toolName: string, params: Record<string, unknown>) => Promise<unknown>;
88
+
89
+ declare class ToolGate {
90
+ private config;
91
+ private executor;
92
+ private session;
93
+ private mcpToolIndex;
94
+ private readSet;
95
+ private actionSet;
96
+ private persistence;
97
+ constructor(executor: RealExecutor, config?: ToolGateConfig);
98
+ /** Set a human-readable description for this task/session */
99
+ describe(taskDescription: string): this;
100
+ /** The proxy function you hand to the agent instead of the real executor */
101
+ get proxy(): RealExecutor;
102
+ /** Wrap an existing tool map (name → function) into a proxied tool map */
103
+ wrapTools<T extends Record<string, (...args: any[]) => Promise<unknown>>>(tools: T): T;
104
+ /** Core: classify and either passthrough or intercept */
105
+ private handle;
106
+ private classify;
107
+ private defaultPhantom;
108
+ /** Call when agent is done. Returns the approval request. */
109
+ finalize(): Promise<ApprovalRequest>;
110
+ /** Execute approved actions for real */
111
+ executeApproval(result: ApprovalResult): Promise<Map<string, unknown>>;
112
+ /** Approve all pending actions at once */
113
+ approveAll(): Promise<Map<string, unknown>>;
114
+ /** Reject all pending actions */
115
+ rejectAll(): Promise<void>;
116
+ get sessionId(): string;
117
+ get reads(): ExecutedRead[];
118
+ get pending(): PendingAction[];
119
+ get currentSession(): Session;
120
+ /** Pretty-print a summary for CLI / logging */
121
+ summary(): string;
122
+ }
123
+
124
+ /**
125
+ * Interactive CLI approval flow.
126
+ * Pass this as `onApprovalNeeded` in ToolGateConfig to get a
127
+ * terminal-based approval UI.
128
+ */
129
+ declare function cliApproval(request: ApprovalRequest): Promise<ApprovalResult>;
130
+
131
+ declare function classifyTool(toolName: string, params: Record<string, unknown>, mcpToolDef?: MCPToolDef): ToolClassification;
132
+
133
+ /**
134
+ * Create a ToolGate specifically for MCP-based agents.
135
+ *
136
+ * Pass your MCP server definitions (with tool lists) and ToolGate will
137
+ * auto-classify every tool by analyzing its name + description.
138
+ *
139
+ * Usage:
140
+ * const gate = mcpToolGate(mcpExecutor, {
141
+ * mcpServers: [
142
+ * { name: "gmail", url: "https://gmail.mcp.example.com/sse", tools: [...] },
143
+ * { name: "github", url: "https://github.mcp.example.com/sse", tools: [...] },
144
+ * ],
145
+ * });
146
+ *
147
+ * // Hand gate.proxy to your agent as the tool executor
148
+ * await agent.run({ execute: gate.proxy });
149
+ * const approval = await gate.finalize();
150
+ */
151
+ declare function mcpToolGate(executor: RealExecutor, config?: ToolGateConfig): ToolGate;
152
+ /**
153
+ * Fetch MCP tool definitions from a running MCP server.
154
+ * Calls the standard `tools/list` JSON-RPC method.
155
+ */
156
+ declare function discoverMCPTools(serverUrl: string): Promise<MCPToolDef[]>;
157
+ /**
158
+ * Auto-discover tools from all MCP servers and return a fully configured ToolGateConfig.
159
+ */
160
+ declare function autoConfigFromMCP(servers: Array<{
161
+ name: string;
162
+ url: string;
163
+ }>, overrides?: Partial<ToolGateConfig>): Promise<ToolGateConfig>;
164
+
165
+ export { type ActionDecision, type ApprovalRequest, type ApprovalResult, type ExecutedRead, type MCPServerDef, type MCPToolDef, type PendingAction, type RealExecutor, type Session, type SessionStatus, type ToolCall, type ToolClassification, ToolGate, type ToolGateConfig, type ToolIntent, autoConfigFromMCP, classifyTool, cliApproval, discoverMCPTools, mcpToolGate };