@mhingston5/conduit 1.1.0 → 1.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 +15 -0
- package/package.json +1 -1
- package/src/gateway/gateway.service.ts +67 -2
- package/tests/gateway.service.test.ts +11 -1
package/README.md
CHANGED
|
@@ -175,6 +175,21 @@ By default, Conduit runs in **Permissive Mode** to allow easy exploration.
|
|
|
175
175
|
- permissive mode for exploration
|
|
176
176
|
- strict mode for production agents
|
|
177
177
|
|
|
178
|
+
## Code Mode Prompting Guide
|
|
179
|
+
|
|
180
|
+
To get the most out of Conduit, you should guide your LLM (agent) to prefer multi-tool scripts over individual tool calls.
|
|
181
|
+
|
|
182
|
+
**Recommended System Prompt Additions:**
|
|
183
|
+
> You are equipped with a "Code Mode" execution environment via Conduit.
|
|
184
|
+
>
|
|
185
|
+
> - **Prefer `mcp.executeTypeScript`**: Use this for any task requiring multiple steps, data transformation, or logical branching.
|
|
186
|
+
> - **Use `tools.*` SDK**: Within your scripts, access all upstream tools via the `tools` namespace (e.g., `await tools.github.create_issue(...)`).
|
|
187
|
+
> - **Avoid JSON tool-calling overhead**: Instead of making 5 separate tool calls and waiting for 5 round-trips, write one script that orchestrates the entire operation.
|
|
188
|
+
> - **Data Transformation**: Perform loops, filters, and aggregations directly in your code rather than asking the user (or yourself) to process large datasets in the chat context.
|
|
189
|
+
|
|
190
|
+
Example of a high-efficiency prompt:
|
|
191
|
+
*"Scan the last 50 emails for invoices, total their amounts by currency, and create a single summary ticket in Jira if the total exceeds $1000."*
|
|
192
|
+
|
|
178
193
|
---
|
|
179
194
|
|
|
180
195
|
## Design Principles
|
package/package.json
CHANGED
|
@@ -10,6 +10,66 @@ import { PolicyService, ToolIdentifier } from '../core/policy.service.js';
|
|
|
10
10
|
import { Ajv } from 'ajv';
|
|
11
11
|
import addFormats from 'ajv-formats';
|
|
12
12
|
|
|
13
|
+
const BUILT_IN_TOOLS: ToolSchema[] = [
|
|
14
|
+
{
|
|
15
|
+
name: 'mcp.executeTypeScript',
|
|
16
|
+
description: 'Executes TypeScript code in a secure sandbox with access to `tools.*` SDK.',
|
|
17
|
+
inputSchema: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
code: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'The TypeScript code to execute.'
|
|
23
|
+
},
|
|
24
|
+
allowedTools: {
|
|
25
|
+
type: 'array',
|
|
26
|
+
items: { type: 'string' },
|
|
27
|
+
description: 'Optional list of tools the script is allowed to call (e.g. ["github.*"]).'
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
required: ['code']
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'mcp.executePython',
|
|
35
|
+
description: 'Executes Python code in a secure sandbox with access to `tools.*` SDK.',
|
|
36
|
+
inputSchema: {
|
|
37
|
+
type: 'object',
|
|
38
|
+
properties: {
|
|
39
|
+
code: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
description: 'The Python code to execute.'
|
|
42
|
+
},
|
|
43
|
+
allowedTools: {
|
|
44
|
+
type: 'array',
|
|
45
|
+
items: { type: 'string' },
|
|
46
|
+
description: 'Optional list of tools the script is allowed to call (e.g. ["github.*"]).'
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
required: ['code']
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'mcp.executeIsolate',
|
|
54
|
+
description: 'Executes JavaScript code in a high-speed V8 isolate (no Deno/Node APIs).',
|
|
55
|
+
inputSchema: {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {
|
|
58
|
+
code: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
description: 'The JavaScript code to execute.'
|
|
61
|
+
},
|
|
62
|
+
allowedTools: {
|
|
63
|
+
type: 'array',
|
|
64
|
+
items: { type: 'string' },
|
|
65
|
+
description: 'Optional list of tools the script is allowed to call.'
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
required: ['code']
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
|
|
13
73
|
export class GatewayService {
|
|
14
74
|
private logger: Logger;
|
|
15
75
|
private clients: Map<string, UpstreamClient> = new Map();
|
|
@@ -110,8 +170,13 @@ export class GatewayService {
|
|
|
110
170
|
}
|
|
111
171
|
|
|
112
172
|
const parsed = this.policyService.parseToolName(toolId);
|
|
173
|
+
const toolName = parsed.name; // Use a new variable for the un-namespaced name
|
|
174
|
+
|
|
175
|
+
// Check for built-in tools
|
|
176
|
+
const builtIn = BUILT_IN_TOOLS.find(t => t.name === toolId); // Compare with the full toolId
|
|
177
|
+
if (builtIn) return builtIn;
|
|
178
|
+
|
|
113
179
|
const upstreamId = parsed.namespace;
|
|
114
|
-
const toolName = parsed.name;
|
|
115
180
|
|
|
116
181
|
// Ensure we have schemas for this upstream
|
|
117
182
|
if (!this.schemaCache.get(upstreamId)) {
|
|
@@ -132,7 +197,7 @@ export class GatewayService {
|
|
|
132
197
|
}
|
|
133
198
|
|
|
134
199
|
async discoverTools(context: ExecutionContext): Promise<ToolSchema[]> {
|
|
135
|
-
const allTools: ToolSchema[] = [];
|
|
200
|
+
const allTools: ToolSchema[] = [...BUILT_IN_TOOLS];
|
|
136
201
|
|
|
137
202
|
for (const [id, client] of this.clients.entries()) {
|
|
138
203
|
let tools = this.schemaCache.get(id);
|
|
@@ -31,11 +31,21 @@ describe('GatewayService', () => {
|
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
const tools = await gateway.discoverTools(context);
|
|
34
|
-
expect(tools).
|
|
34
|
+
expect(tools.length).toBeGreaterThanOrEqual(3);
|
|
35
|
+
expect(tools.find(t => t.name === 'mcp.executeTypeScript')).toBeDefined();
|
|
36
|
+
expect(tools.find(t => t.name === 'mcp.executePython')).toBeDefined();
|
|
37
|
+
expect(tools.find(t => t.name === 'mcp.executeIsolate')).toBeDefined();
|
|
35
38
|
expect(tools.find(t => t.name === 'u1__t1')).toBeDefined();
|
|
36
39
|
expect(tools.find(t => t.name === 'u2__t2')).toBeDefined();
|
|
37
40
|
});
|
|
38
41
|
|
|
42
|
+
it('should return schema for built-in tools', async () => {
|
|
43
|
+
const schema = await gateway.getToolSchema('mcp.executeTypeScript', context);
|
|
44
|
+
expect(schema).toBeDefined();
|
|
45
|
+
expect(schema?.name).toBe('mcp.executeTypeScript');
|
|
46
|
+
expect(schema?.inputSchema.required).toContain('code');
|
|
47
|
+
});
|
|
48
|
+
|
|
39
49
|
it('should route tool calls to correct upstream', async () => {
|
|
40
50
|
gateway.registerUpstream({ id: 'u1', url: 'http://u1' });
|
|
41
51
|
|