@easynet/agent-tool 1.0.16 → 1.0.18

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.
Files changed (39) hide show
  1. package/README.md +11 -4
  2. package/dist/api/createAgentTools.d.ts.map +1 -1
  3. package/dist/api/main.cjs +14 -14
  4. package/dist/api/main.js +3 -3
  5. package/dist/api/runtimeFromConfig.d.ts +5 -0
  6. package/dist/api/runtimeFromConfig.d.ts.map +1 -1
  7. package/dist/{chunk-FYJ5VD3Q.js → chunk-7MRBWT2T.js} +3 -3
  8. package/dist/{chunk-FYJ5VD3Q.js.map → chunk-7MRBWT2T.js.map} +1 -1
  9. package/dist/{chunk-M2VNTQHS.js → chunk-7WI5VK5G.js} +28 -5
  10. package/dist/{chunk-M2VNTQHS.js.map → chunk-7WI5VK5G.js.map} +1 -1
  11. package/dist/{chunk-CDTLERB6.cjs → chunk-EMI67SPN.cjs} +11 -5
  12. package/dist/chunk-EMI67SPN.cjs.map +1 -0
  13. package/dist/{chunk-SIN5JHMP.js → chunk-ETWGKCOP.js} +3 -3
  14. package/dist/{chunk-SIN5JHMP.js.map → chunk-ETWGKCOP.js.map} +1 -1
  15. package/dist/{chunk-PVVUTEZP.cjs → chunk-OXTQULXH.cjs} +7 -7
  16. package/dist/{chunk-PVVUTEZP.cjs.map → chunk-OXTQULXH.cjs.map} +1 -1
  17. package/dist/{chunk-BNHLMLDH.js → chunk-RKN4PT7P.js} +10 -4
  18. package/dist/chunk-RKN4PT7P.js.map +1 -0
  19. package/dist/{chunk-F32XCT4U.cjs → chunk-YK2MQDNJ.cjs} +9 -9
  20. package/dist/{chunk-F32XCT4U.cjs.map → chunk-YK2MQDNJ.cjs.map} +1 -1
  21. package/dist/{chunk-UDGQSHEO.cjs → chunk-ZIFQWIN3.cjs} +42 -19
  22. package/dist/{chunk-UDGQSHEO.cjs.map → chunk-ZIFQWIN3.cjs.map} +1 -1
  23. package/dist/index.cjs +276 -59
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +222 -7
  28. package/dist/index.js.map +1 -1
  29. package/dist/security/sandbox.d.ts +9 -0
  30. package/dist/security/sandbox.d.ts.map +1 -0
  31. package/dist/security/ssrf.d.ts +24 -0
  32. package/dist/security/ssrf.d.ts.map +1 -0
  33. package/dist/tools/util/toolConfig.d.ts +7 -1
  34. package/dist/tools/util/toolConfig.d.ts.map +1 -1
  35. package/dist/utils/cli/index.cjs +17 -17
  36. package/dist/utils/cli/index.js +3 -3
  37. package/package.json +1 -1
  38. package/dist/chunk-BNHLMLDH.js.map +0 -1
  39. package/dist/chunk-CDTLERB6.cjs.map +0 -1
package/dist/index.js CHANGED
@@ -1,13 +1,228 @@
1
- export { LangChainToolsHub, createAgentTools } from './chunk-M2VNTQHS.js';
2
- import { loadMCPTool } from './chunk-FYJ5VD3Q.js';
3
- export { DirectoryScanner, DiscoveryError, SkillManifestError, buildFunctionToTool, buildMcpPackage, initProject, loadMCPTool, loadSkillDefinition, parseSkillMd, runGeneratedMCP, runMcpServer, scan, scanForTools, scanSkillResources, validateFrontmatter } from './chunk-FYJ5VD3Q.js';
1
+ export { LangChainToolsHub, createAgentTools } from './chunk-7WI5VK5G.js';
2
+ import { loadMCPTool } from './chunk-7MRBWT2T.js';
3
+ export { DirectoryScanner, DiscoveryError, SkillManifestError, buildFunctionToTool, buildMcpPackage, initProject, loadMCPTool, loadSkillDefinition, parseSkillMd, runGeneratedMCP, runMcpServer, scan, scanForTools, scanSkillResources, validateFrontmatter } from './chunk-7MRBWT2T.js';
4
+ import { MCP_KIND } from './chunk-RKN4PT7P.js';
5
+ export { BudgetManager, EventLog, Metrics, PTCRuntime, PolicyDeniedError, PolicyEngine, SchemaValidationError, SchemaValidator, Tracing, buildEvidence, createLogger, ensurePackageInCache, expandToolDescriptorsToRegistryNames, getPackageEntryPath, importFromCache, isNpmToolDescriptor, loadToolConfig, normalizeToolList, parseNpmToolDescriptor, resolveNpmToolDescriptor, resolveToolDescriptor, sanitizeForLog, summarizeForLog } from './chunk-RKN4PT7P.js';
4
6
  import { DEFAULT_OUTPUT_SCHEMA, DEFAULT_INPUT_SCHEMA } from './chunk-5SWSNVMI.js';
5
7
  export { DEFAULT_INPUT_SCHEMA, DEFAULT_OUTPUT_SCHEMA, createToolSpec } from './chunk-5SWSNVMI.js';
6
- import { MCP_KIND } from './chunk-BNHLMLDH.js';
7
- export { BudgetManager, EventLog, Metrics, PTCRuntime, PolicyDeniedError, PolicyEngine, SchemaValidationError, SchemaValidator, Tracing, buildEvidence, createLogger, ensurePackageInCache, expandToolDescriptorsToRegistryNames, getPackageEntryPath, importFromCache, isNpmToolDescriptor, loadToolConfig, normalizeToolList, parseNpmToolDescriptor, resolveNpmToolDescriptor, resolveToolDescriptor, sanitizeForLog, summarizeForLog } from './chunk-BNHLMLDH.js';
8
+ import { createTaggedError } from './chunk-AE6FSNGY.js';
8
9
  export { ToolRegistry, createTaggedError, isRetryable, withRetry } from './chunk-AE6FSNGY.js';
9
10
  import './chunk-FR2CXERF.js';
10
- import { join, dirname, basename } from 'path';
11
+ import { lookup } from 'dns/promises';
12
+ import { resolve, normalize, dirname, basename, join } from 'path';
13
+ import { realpath, access } from 'fs/promises';
14
+
15
+ async function validateUrl(url, options) {
16
+ let parsed;
17
+ try {
18
+ parsed = new URL(url);
19
+ } catch {
20
+ throw createTaggedError(
21
+ "HTTP_DISALLOWED_HOST",
22
+ `Invalid URL: ${url}`,
23
+ { url }
24
+ );
25
+ }
26
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
27
+ throw createTaggedError(
28
+ "HTTP_DISALLOWED_HOST",
29
+ `Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,
30
+ { url, protocol: parsed.protocol }
31
+ );
32
+ }
33
+ const hostname = parsed.hostname;
34
+ if (!isHostAllowed(hostname, options.allowedHosts)) {
35
+ throw createTaggedError(
36
+ "HTTP_DISALLOWED_HOST",
37
+ `Host "${hostname}" is not in the allowed hosts list`,
38
+ { url, hostname, allowedHosts: options.allowedHosts }
39
+ );
40
+ }
41
+ if (isHostBlocked(hostname, options.blockedHosts)) {
42
+ throw createTaggedError(
43
+ "HTTP_DISALLOWED_HOST",
44
+ `Host "${hostname}" is in the blocked hosts list`,
45
+ { url, hostname, blockedHosts: options.blockedHosts }
46
+ );
47
+ }
48
+ try {
49
+ const { address } = await lookup(hostname);
50
+ if (isIpInBlockedCidrs(address, options.blockedCidrs)) {
51
+ throw createTaggedError(
52
+ "HTTP_DISALLOWED_HOST",
53
+ `Host "${hostname}" resolves to blocked IP: ${address}`,
54
+ { url, hostname, resolvedIp: address }
55
+ );
56
+ }
57
+ } catch (err) {
58
+ if (err instanceof Error && err.kind === "HTTP_DISALLOWED_HOST") {
59
+ throw err;
60
+ }
61
+ throw createTaggedError(
62
+ "HTTP_DISALLOWED_HOST",
63
+ `DNS resolution failed for host "${hostname}": ${err instanceof Error ? err.message : String(err)}`,
64
+ { url, hostname }
65
+ );
66
+ }
67
+ return parsed;
68
+ }
69
+ function isHostAllowed(hostname, allowedHosts) {
70
+ for (const pattern of allowedHosts) {
71
+ if (pattern === "*") {
72
+ return true;
73
+ }
74
+ if (pattern.startsWith("*.")) {
75
+ const suffix = pattern.slice(1);
76
+ if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {
77
+ return true;
78
+ }
79
+ } else if (hostname === pattern) {
80
+ return true;
81
+ }
82
+ }
83
+ return false;
84
+ }
85
+ function isHostBlocked(hostname, blockedHosts) {
86
+ for (const pattern of blockedHosts) {
87
+ if (pattern === "*") {
88
+ return true;
89
+ }
90
+ if (pattern.startsWith("*.")) {
91
+ const suffix = pattern.slice(1);
92
+ if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {
93
+ return true;
94
+ }
95
+ } else if (hostname === pattern) {
96
+ return true;
97
+ }
98
+ }
99
+ return false;
100
+ }
101
+ function isIpInBlockedCidrs(ip, cidrs) {
102
+ const normalizedIp = normalizeIp(ip);
103
+ if (!normalizedIp) return false;
104
+ for (const cidr of cidrs) {
105
+ if (cidr.includes(":")) {
106
+ if (!ip.includes(":")) continue;
107
+ if (isIpv6InCidr(ip, cidr)) return true;
108
+ } else {
109
+ if (isIpv4InCidr(normalizedIp, cidr)) return true;
110
+ }
111
+ }
112
+ return false;
113
+ }
114
+ function normalizeIp(ip) {
115
+ if (ip.startsWith("::ffff:")) {
116
+ return ip.slice(7);
117
+ }
118
+ if (/^\d+\.\d+\.\d+\.\d+$/.test(ip)) {
119
+ return ip;
120
+ }
121
+ return null;
122
+ }
123
+ function isIpv4InCidr(ip, cidr) {
124
+ const [cidrIp, prefixStr] = cidr.split("/");
125
+ if (!cidrIp || !prefixStr) return false;
126
+ const prefix = parseInt(prefixStr, 10);
127
+ if (isNaN(prefix) || prefix < 0 || prefix > 32) return false;
128
+ const ipNum = ipv4ToNum(ip);
129
+ const cidrNum = ipv4ToNum(cidrIp);
130
+ if (ipNum === null || cidrNum === null) return false;
131
+ const mask = prefix === 0 ? 0 : -1 << 32 - prefix >>> 0;
132
+ return (ipNum & mask) === (cidrNum & mask);
133
+ }
134
+ function ipv4ToNum(ip) {
135
+ const parts = ip.split(".");
136
+ if (parts.length !== 4) return null;
137
+ let num = 0;
138
+ for (const part of parts) {
139
+ const n = parseInt(part, 10);
140
+ if (isNaN(n) || n < 0 || n > 255) return null;
141
+ num = num << 8 | n;
142
+ }
143
+ return num >>> 0;
144
+ }
145
+ function isIpv6InCidr(ip, cidr) {
146
+ const [cidrIp, prefixStr] = cidr.split("/");
147
+ if (!cidrIp || !prefixStr) return false;
148
+ const prefix = parseInt(prefixStr, 10);
149
+ if (isNaN(prefix)) return false;
150
+ const ipBytes = expandIpv6(ip);
151
+ const cidrBytes = expandIpv6(cidrIp);
152
+ if (!ipBytes || !cidrBytes) return false;
153
+ const fullBytes = Math.floor(prefix / 8);
154
+ for (let i = 0; i < fullBytes && i < 16; i++) {
155
+ if (ipBytes[i] !== cidrBytes[i]) return false;
156
+ }
157
+ const remainingBits = prefix % 8;
158
+ if (remainingBits > 0 && fullBytes < 16) {
159
+ const mask = -1 << 8 - remainingBits & 255;
160
+ if ((ipBytes[fullBytes] & mask) !== (cidrBytes[fullBytes] & mask)) return false;
161
+ }
162
+ return true;
163
+ }
164
+ function expandIpv6(ip) {
165
+ const zoneIdx = ip.indexOf("%");
166
+ if (zoneIdx !== -1) ip = ip.slice(0, zoneIdx);
167
+ const parts = ip.split("::");
168
+ if (parts.length > 2) return null;
169
+ const bytes = new Array(16).fill(0);
170
+ const expandGroup = (group) => {
171
+ if (!group) return [];
172
+ return group.split(":").flatMap((hex) => {
173
+ const val = parseInt(hex || "0", 16);
174
+ return [val >> 8 & 255, val & 255];
175
+ });
176
+ };
177
+ if (parts.length === 1) {
178
+ const expanded = expandGroup(parts[0]);
179
+ if (expanded.length !== 16) return null;
180
+ return expanded;
181
+ }
182
+ const left = expandGroup(parts[0]);
183
+ const right = expandGroup(parts[1]);
184
+ if (left.length + right.length > 16) return null;
185
+ for (let i = 0; i < left.length; i++) bytes[i] = left[i];
186
+ for (let i = 0; i < right.length; i++) bytes[16 - right.length + i] = right[i];
187
+ return bytes;
188
+ }
189
+ async function resolveSandboxedPath(inputPath, sandboxRoot) {
190
+ let normalizedRoot;
191
+ try {
192
+ normalizedRoot = await realpath(resolve(sandboxRoot));
193
+ } catch {
194
+ normalizedRoot = normalize(resolve(sandboxRoot));
195
+ }
196
+ const resolved = resolve(normalizedRoot, inputPath);
197
+ let real;
198
+ try {
199
+ await access(resolved);
200
+ real = await realpath(resolved);
201
+ } catch {
202
+ const parentDir = dirname(resolved);
203
+ let realParent;
204
+ try {
205
+ await access(parentDir);
206
+ realParent = await realpath(parentDir);
207
+ } catch {
208
+ realParent = normalize(parentDir);
209
+ }
210
+ real = resolve(realParent, basename(resolved));
211
+ }
212
+ if (!isWithinRoot(real, normalizedRoot)) {
213
+ throw createTaggedError(
214
+ "PATH_OUTSIDE_SANDBOX",
215
+ `Path "${inputPath}" resolves to "${real}" which is outside sandbox "${normalizedRoot}"`,
216
+ { inputPath, resolvedPath: real, sandboxRoot: normalizedRoot }
217
+ );
218
+ }
219
+ return real;
220
+ }
221
+ function isWithinRoot(path, root) {
222
+ const normalizedPath = normalize(path);
223
+ const normalizedRoot = normalize(root);
224
+ return normalizedPath === normalizedRoot || normalizedPath.startsWith(normalizedRoot + "/");
225
+ }
11
226
 
12
227
  // src/tools/mcp/MCPClientAdapter.ts
13
228
  function textFromCallToolResult(result) {
@@ -118,6 +333,6 @@ async function registerMCPToolsFromConfig(runtime, registry, options = {}) {
118
333
  return { transport };
119
334
  }
120
335
 
121
- export { MCPClientAdapter, MCPProcessManager, connectMCP, mcpToolsToSpecs, registerMCPToolsFromConfig };
336
+ export { MCPClientAdapter, MCPProcessManager, connectMCP, isIpInBlockedCidrs, mcpToolsToSpecs, registerMCPToolsFromConfig, resolveSandboxedPath, validateUrl };
122
337
  //# sourceMappingURL=index.js.map
123
338
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tools/mcp/MCPClientAdapter.ts","../src/tools/mcp/connectMCP.ts","../src/tools/mcp/MCPProcessManager.ts","../src/tools/mcp/registerMCPTools.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * ToolAdapter for MCP tools: holds SDK Client reference, invoke() calls client.callTool.\n * Framework-level support so scripts use registerMCPToolsFromConfig instead of inline MCP logic.\n */\n\nimport type { ToolAdapter, ToolSpec } from \"../../core/types/ToolSpec.js\";\nimport type { ExecContext } from \"../../core/types/ToolIntent.js\";\nimport { MCP_KIND } from \"./types.js\";\n\n/** SDK Client type (avoid hard typing on @modelcontextprotocol/sdk in this file for optional dep). */\nexport interface MCPClientLike {\n callTool(params: { name: string; arguments: Record<string, unknown> }): Promise<CallToolResult>;\n}\n\nexport interface CallToolResult {\n content?: Array<{ type: string; text?: string }>;\n toolResult?: unknown;\n}\n\nfunction textFromCallToolResult(result: CallToolResult): string {\n if (result.content?.length) {\n const parts = result.content\n .filter((c) => c.type === \"text\" && c.text != null)\n .map((c) => c.text);\n if (parts.length) return parts.join(\"\\n\");\n }\n if (result.toolResult !== undefined) return JSON.stringify(result.toolResult);\n return JSON.stringify(result);\n}\n\n/**\n * Adapter that invokes MCP tools via the SDK Client (callTool).\n * Register with runtime after connecting and listing tools; specs must have kind MCP_KIND.\n */\nexport class MCPClientAdapter implements ToolAdapter {\n readonly kind = MCP_KIND;\n\n constructor(private readonly client: MCPClientLike) {}\n\n async invoke(\n spec: ToolSpec,\n args: unknown,\n _ctx: ExecContext\n ): Promise<{ result: unknown; raw?: unknown }> {\n const params = args != null && typeof args === \"object\" && !Array.isArray(args)\n ? (args as Record<string, unknown>)\n : {};\n const result = await this.client.callTool({ name: spec.name, arguments: params });\n const text = textFromCallToolResult(result);\n let resultValue: unknown = text;\n try {\n resultValue = JSON.parse(text) as unknown;\n } catch {\n // keep as string\n }\n return { result: resultValue, raw: result };\n }\n}\n","/**\n * Connect to an MCP server via stdio using MCPConnectionInfo.\n * Framework-level: uses @modelcontextprotocol/sdk Client + StdioClientTransport.\n */\n\nimport type { MCPConnectionInfo } from \"./MCPProcessManager.js\";\nimport type { ToolSpec } from \"../../core/types/ToolSpec.js\";\nimport { DEFAULT_INPUT_SCHEMA, DEFAULT_OUTPUT_SCHEMA } from \"../../core/types/ToolSpec.js\";\nimport { MCP_KIND } from \"./types.js\";\n\nexport interface MCPConnectResult {\n /** SDK Client; use listTools() and callTool(). */\n client: MCPClientLike;\n /** Transport; call close() when done. */\n transport: MCPTransportLike;\n}\n\nexport interface MCPClientLike {\n connect(transport: MCPTransportLike): Promise<void>;\n listTools(params?: unknown): Promise<{ tools: MCPToolDef[] }>;\n callTool(params: { name: string; arguments: Record<string, unknown> }): Promise<CallToolResult>;\n}\n\nexport interface MCPTransportLike {\n close(): Promise<void>;\n}\n\nexport interface MCPToolDef {\n name: string;\n description?: string;\n inputSchema?: object;\n}\n\nexport interface CallToolResult {\n content?: Array<{ type: string; text?: string }>;\n toolResult?: unknown;\n}\n\n/**\n * Connect to MCP server via stdio. Only stdio is supported; url/SSE not implemented here.\n * Requires @modelcontextprotocol/sdk. Returns client and transport; caller must call transport.close() when done.\n */\nexport async function connectMCP(connectionInfo: MCPConnectionInfo): Promise<MCPConnectResult> {\n if (connectionInfo.type !== \"stdio\" || !connectionInfo.command) {\n throw new Error(\n `MCP stdio requires connectionInfo.type \"stdio\" and command; got type=${connectionInfo.type}`\n );\n }\n\n const { Client } = await import(\"@modelcontextprotocol/sdk/client\");\n const { StdioClientTransport } = await import(\n \"@modelcontextprotocol/sdk/client/stdio.js\"\n );\n\n const serverParams = {\n command: connectionInfo.command,\n args: connectionInfo.args ?? [],\n env: connectionInfo.env,\n cwd: connectionInfo.cwd,\n };\n const transport = new StdioClientTransport(serverParams);\n const client = new Client({ name: \"agent-tool\", version: \"1.0.0\" });\n await client.connect(transport);\n return {\n client: client as unknown as MCPClientLike,\n transport: transport as unknown as MCPTransportLike,\n };\n}\n\n/**\n * Convert MCP listTools() result to ToolSpec[] (kind MCP_KIND) for registry.\n */\nexport function mcpToolsToSpecs(tools: MCPToolDef[]): ToolSpec[] {\n return tools.map((t) => ({\n name: t.name,\n version: \"1.0.0\",\n kind: MCP_KIND,\n description: t.description ?? `MCP tool: ${t.name}`,\n inputSchema: t.inputSchema ?? DEFAULT_INPUT_SCHEMA,\n outputSchema: DEFAULT_OUTPUT_SCHEMA,\n capabilities: [],\n }));\n}\n","import type { MCPServerConfig } from \"../discoveryFactory.js\";\n\n/**\n * Connection info for an MCP server.\n */\nexport interface MCPConnectionInfo {\n /** Transport type: \"url\" for SSE/HTTP, \"stdio\" for command-based */\n type: \"url\" | \"stdio\";\n /** SSE/HTTP URL (when type=\"url\") */\n url?: string;\n /** Command to spawn (when type=\"stdio\") */\n command?: string;\n /** Command arguments (when type=\"stdio\") */\n args?: string[];\n /** Environment variables (when type=\"stdio\") */\n env?: Record<string, string>;\n /** Working directory when spawning (when type=\"stdio\") */\n cwd?: string;\n}\n\n/**\n * Manages MCP server connection information extracted from directory discovery.\n */\nexport class MCPProcessManager {\n private readonly connections = new Map<string, MCPConnectionInfo>();\n\n getConnectionInfo(toolName: string, config: MCPServerConfig): MCPConnectionInfo {\n const cached = this.connections.get(toolName);\n if (cached) return cached;\n const info: MCPConnectionInfo = config.url\n ? { type: \"url\", url: config.url }\n : {\n type: \"stdio\",\n command: config.command!,\n args: config.args,\n env: config.env,\n cwd: config.cwd,\n };\n this.connections.set(toolName, info);\n return info;\n }\n\n remove(toolName: string): boolean {\n return this.connections.delete(toolName);\n }\n\n getToolNames(): string[] {\n return [...this.connections.keys()];\n }\n\n dispose(): void {\n this.connections.clear();\n }\n}\n","/**\n * High-level API: load mcp.json, connect to MCP server, register tools with runtime.\n * Framework-level so scripts call registerMCPToolsFromConfig() instead of inline MCP logic.\n */\n\nimport { basename, dirname, join } from \"node:path\";\nimport type { PTCRuntime } from \"../../core/runtime/PTCRuntime.js\";\nimport type { ToolRegistry } from \"../../core/registry/ToolRegistry.js\";\nimport { MCP_KIND } from \"./types.js\";\nimport { loadMCPTool } from \"./MCPLoader.js\";\nimport { MCPProcessManager } from \"./MCPProcessManager.js\";\nimport { connectMCP, mcpToolsToSpecs } from \"./connectMCP.js\";\nimport { MCPClientAdapter } from \"./MCPClientAdapter.js\";\n\nexport interface RegisterMCPToolsOptions {\n /** Path to mcp.json (or dir containing it). Default: process.env.MCP_CONFIG_PATH or \"mcp.json\" in cwd. */\n configPath?: string;\n /** Tool name for getConnectionInfo (default \"mcp\"). */\n toolName?: string;\n}\n\nexport interface RegisterMCPToolsResult {\n /** Transport; caller must call transport.close() when done. */\n transport: { close(): Promise<void> };\n}\n\n/**\n * Load mcp config (from configPath or MCP_CONFIG_PATH), connect via stdio, list tools,\n * register ToolSpec[] with registry and MCPClientAdapter with runtime. Returns transport for cleanup.\n */\nexport async function registerMCPToolsFromConfig(\n runtime: PTCRuntime,\n registry: ToolRegistry,\n options: RegisterMCPToolsOptions = {}\n): Promise<RegisterMCPToolsResult> {\n const configPath = options.configPath ?? process.env.MCP_CONFIG_PATH ?? join(process.cwd(), \"mcp.json\");\n const dirPath = dirname(configPath);\n const entryPoint = basename(configPath);\n const toolName = options.toolName ?? MCP_KIND;\n\n const loaded = await loadMCPTool(dirPath, { kind: MCP_KIND, name: toolName, entryPoint });\n if (!loaded.mcpConfig) {\n throw new Error(\"mcp.json must have command or url\");\n }\n const manager = new MCPProcessManager();\n const connectionInfo = manager.getConnectionInfo(toolName, loaded.mcpConfig);\n\n const { client, transport } = await connectMCP(connectionInfo);\n const { tools } = await client.listTools();\n const specs = mcpToolsToSpecs(tools);\n registry.bulkRegister(specs);\n runtime.registerAdapter(new MCPClientAdapter(client));\n\n return { transport };\n}\n"]}
1
+ {"version":3,"sources":["../src/security/ssrf.ts","../src/security/sandbox.ts","../src/tools/mcp/MCPClientAdapter.ts","../src/tools/mcp/connectMCP.ts","../src/tools/mcp/MCPProcessManager.ts","../src/tools/mcp/registerMCPTools.ts"],"names":["dirname","basename"],"mappings":"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","file":"index.js","sourcesContent":["import { lookup } from \"node:dns/promises\";\nimport { createTaggedError } from \"../core/runtime/Retry.js\";\n\n/**\n * Options for validateUrl. Unified rule: allow iff host is in allowedHosts AND not in blockedHosts.\n * - \"Default allow all + blocklist\": allowedHosts: [\"*\"], blockedHosts: [\"*.internal\", ...]\n * - \"Default disallow all + allowlist\": allowedHosts: [\"api.github.com\", ...], blockedHosts: []\n */\nexport interface ValidateUrlOptions {\n /** Allow only these hosts. Use [\"*\"] for allow-all. Supports \"*.example.com\", exact host. */\n allowedHosts: string[];\n /** Block these hosts even if allowed. Supports \"*.internal\", exact host. Merged with allowlist. */\n blockedHosts: string[];\n /** CIDR ranges to block (resolved IP). */\n blockedCidrs: string[];\n}\n\n/**\n * Validate a URL: allow iff (host in allowedHosts) AND (host not in blockedHosts). Then check blockedCidrs on resolved IP.\n *\n * @throws HTTP_DISALLOWED_HOST if the URL is blocked\n */\nexport async function validateUrl(url: string, options: ValidateUrlOptions): Promise<URL> {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Invalid URL: ${url}`,\n { url },\n );\n }\n\n // Only allow http/https\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,\n { url, protocol: parsed.protocol },\n );\n }\n\n const hostname = parsed.hostname;\n\n if (!isHostAllowed(hostname, options.allowedHosts)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" is not in the allowed hosts list`,\n { url, hostname, allowedHosts: options.allowedHosts },\n );\n }\n if (isHostBlocked(hostname, options.blockedHosts)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" is in the blocked hosts list`,\n { url, hostname, blockedHosts: options.blockedHosts },\n );\n }\n\n // DNS resolve and check against blocked CIDRs\n try {\n const { address } = await lookup(hostname);\n if (isIpInBlockedCidrs(address, options.blockedCidrs)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" resolves to blocked IP: ${address}`,\n { url, hostname, resolvedIp: address },\n );\n }\n } catch (err) {\n // Re-throw our tagged errors\n if (err instanceof Error && (err as any).kind === \"HTTP_DISALLOWED_HOST\") {\n throw err;\n }\n // DNS resolution failure — block by default\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `DNS resolution failed for host \"${hostname}\": ${err instanceof Error ? err.message : String(err)}`,\n { url, hostname },\n );\n }\n\n return parsed;\n}\n\n/**\n * Check if a hostname matches any entry in the allowed hosts list.\n * Supports: exact \"*\" (allow any host), wildcard prefix (e.g. \"*.github.com\"), or exact host.\n */\nfunction isHostAllowed(hostname: string, allowedHosts: string[]): boolean {\n for (const pattern of allowedHosts) {\n if (pattern === \"*\") {\n return true;\n }\n if (pattern.startsWith(\"*.\")) {\n const suffix = pattern.slice(1); // \".github.com\"\n if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {\n return true;\n }\n } else if (hostname === pattern) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if a hostname matches any entry in the blocked hosts list (same pattern rules as allowlist).\n */\nfunction isHostBlocked(hostname: string, blockedHosts: string[]): boolean {\n for (const pattern of blockedHosts) {\n if (pattern === \"*\") {\n return true;\n }\n if (pattern.startsWith(\"*.\")) {\n const suffix = pattern.slice(1);\n if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {\n return true;\n }\n } else if (hostname === pattern) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an IPv4 address falls within any blocked CIDR range.\n */\nexport function isIpInBlockedCidrs(ip: string, cidrs: string[]): boolean {\n // Handle IPv4-mapped IPv6\n const normalizedIp = normalizeIp(ip);\n if (!normalizedIp) return false;\n\n for (const cidr of cidrs) {\n if (cidr.includes(\":\")) {\n // IPv6 CIDR — skip for IPv4 addresses\n if (!ip.includes(\":\")) continue;\n if (isIpv6InCidr(ip, cidr)) return true;\n } else {\n if (isIpv4InCidr(normalizedIp, cidr)) return true;\n }\n }\n return false;\n}\n\nfunction normalizeIp(ip: string): string | null {\n // Handle IPv4-mapped IPv6 (e.g. \"::ffff:127.0.0.1\")\n if (ip.startsWith(\"::ffff:\")) {\n return ip.slice(7);\n }\n // Pure IPv4\n if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(ip)) {\n return ip;\n }\n return null;\n}\n\nfunction isIpv4InCidr(ip: string, cidr: string): boolean {\n const [cidrIp, prefixStr] = cidr.split(\"/\");\n if (!cidrIp || !prefixStr) return false;\n\n const prefix = parseInt(prefixStr, 10);\n if (isNaN(prefix) || prefix < 0 || prefix > 32) return false;\n\n const ipNum = ipv4ToNum(ip);\n const cidrNum = ipv4ToNum(cidrIp);\n if (ipNum === null || cidrNum === null) return false;\n\n const mask = prefix === 0 ? 0 : (~0 << (32 - prefix)) >>> 0;\n return (ipNum & mask) === (cidrNum & mask);\n}\n\nfunction ipv4ToNum(ip: string): number | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) return null;\n let num = 0;\n for (const part of parts) {\n const n = parseInt(part, 10);\n if (isNaN(n) || n < 0 || n > 255) return null;\n num = (num << 8) | n;\n }\n return num >>> 0;\n}\n\nfunction isIpv6InCidr(ip: string, cidr: string): boolean {\n // Simplified IPv6 CIDR matching for common cases (::1, fc00::, fe80::)\n const [cidrIp, prefixStr] = cidr.split(\"/\");\n if (!cidrIp || !prefixStr) return false;\n\n const prefix = parseInt(prefixStr, 10);\n if (isNaN(prefix)) return false;\n\n const ipBytes = expandIpv6(ip);\n const cidrBytes = expandIpv6(cidrIp);\n if (!ipBytes || !cidrBytes) return false;\n\n // Compare prefix bits\n const fullBytes = Math.floor(prefix / 8);\n for (let i = 0; i < fullBytes && i < 16; i++) {\n if (ipBytes[i] !== cidrBytes[i]) return false;\n }\n\n const remainingBits = prefix % 8;\n if (remainingBits > 0 && fullBytes < 16) {\n const mask = (~0 << (8 - remainingBits)) & 0xff;\n if ((ipBytes[fullBytes]! & mask) !== (cidrBytes[fullBytes]! & mask)) return false;\n }\n\n return true;\n}\n\nfunction expandIpv6(ip: string): number[] | null {\n // Remove zone ID\n const zoneIdx = ip.indexOf(\"%\");\n if (zoneIdx !== -1) ip = ip.slice(0, zoneIdx);\n\n const parts = ip.split(\"::\");\n if (parts.length > 2) return null;\n\n const bytes: number[] = new Array(16).fill(0);\n\n const expandGroup = (group: string): number[] => {\n if (!group) return [];\n return group.split(\":\").flatMap((hex) => {\n const val = parseInt(hex || \"0\", 16);\n return [(val >> 8) & 0xff, val & 0xff];\n });\n };\n\n if (parts.length === 1) {\n const expanded = expandGroup(parts[0]!);\n if (expanded.length !== 16) return null;\n return expanded;\n }\n\n const left = expandGroup(parts[0]!);\n const right = expandGroup(parts[1]!);\n\n if (left.length + right.length > 16) return null;\n\n for (let i = 0; i < left.length; i++) bytes[i] = left[i]!;\n for (let i = 0; i < right.length; i++) bytes[16 - right.length + i] = right[i]!;\n\n return bytes;\n}\n","import { resolve, normalize, dirname, basename } from \"node:path\";\nimport { realpath, access } from \"node:fs/promises\";\nimport { createTaggedError } from \"../core/runtime/Retry.js\";\n\n/**\n * Resolve an input path to an absolute path within the sandbox.\n * Throws PATH_OUTSIDE_SANDBOX if the resolved path escapes the sandbox root.\n *\n * For existing files: uses realpath to resolve symlinks.\n * For non-existing files (write targets): resolves the parent directory.\n */\nexport async function resolveSandboxedPath(\n inputPath: string,\n sandboxRoot: string,\n): Promise<string> {\n // Resolve the sandbox root itself with realpath to handle platform symlinks\n // (e.g. macOS /var -> /private/var)\n let normalizedRoot: string;\n try {\n normalizedRoot = await realpath(resolve(sandboxRoot));\n } catch {\n normalizedRoot = normalize(resolve(sandboxRoot));\n }\n\n // Resolve against sandbox root\n const resolved = resolve(normalizedRoot, inputPath);\n\n let real: string;\n try {\n // Try to resolve symlinks for existing paths\n await access(resolved);\n real = await realpath(resolved);\n } catch {\n // Path does not exist — resolve parent to check containment\n const parentDir = dirname(resolved);\n let realParent: string;\n try {\n await access(parentDir);\n realParent = await realpath(parentDir);\n } catch {\n // Parent also doesn't exist — use normalized resolved path\n // (will fail at actual FS operation if truly invalid)\n realParent = normalize(parentDir);\n }\n real = resolve(realParent, basename(resolved));\n }\n\n if (!isWithinRoot(real, normalizedRoot)) {\n throw createTaggedError(\n \"PATH_OUTSIDE_SANDBOX\",\n `Path \"${inputPath}\" resolves to \"${real}\" which is outside sandbox \"${normalizedRoot}\"`,\n { inputPath, resolvedPath: real, sandboxRoot: normalizedRoot },\n );\n }\n\n return real;\n}\n\nfunction isWithinRoot(path: string, root: string): boolean {\n const normalizedPath = normalize(path);\n const normalizedRoot = normalize(root);\n return normalizedPath === normalizedRoot || normalizedPath.startsWith(normalizedRoot + \"/\");\n}\n","/**\n * ToolAdapter for MCP tools: holds SDK Client reference, invoke() calls client.callTool.\n * Framework-level support so scripts use registerMCPToolsFromConfig instead of inline MCP logic.\n */\n\nimport type { ToolAdapter, ToolSpec } from \"../../core/types/ToolSpec.js\";\nimport type { ExecContext } from \"../../core/types/ToolIntent.js\";\nimport { MCP_KIND } from \"./types.js\";\n\n/** SDK Client type (avoid hard typing on @modelcontextprotocol/sdk in this file for optional dep). */\nexport interface MCPClientLike {\n callTool(params: { name: string; arguments: Record<string, unknown> }): Promise<CallToolResult>;\n}\n\nexport interface CallToolResult {\n content?: Array<{ type: string; text?: string }>;\n toolResult?: unknown;\n}\n\nfunction textFromCallToolResult(result: CallToolResult): string {\n if (result.content?.length) {\n const parts = result.content\n .filter((c) => c.type === \"text\" && c.text != null)\n .map((c) => c.text);\n if (parts.length) return parts.join(\"\\n\");\n }\n if (result.toolResult !== undefined) return JSON.stringify(result.toolResult);\n return JSON.stringify(result);\n}\n\n/**\n * Adapter that invokes MCP tools via the SDK Client (callTool).\n * Register with runtime after connecting and listing tools; specs must have kind MCP_KIND.\n */\nexport class MCPClientAdapter implements ToolAdapter {\n readonly kind = MCP_KIND;\n\n constructor(private readonly client: MCPClientLike) {}\n\n async invoke(\n spec: ToolSpec,\n args: unknown,\n _ctx: ExecContext\n ): Promise<{ result: unknown; raw?: unknown }> {\n const params = args != null && typeof args === \"object\" && !Array.isArray(args)\n ? (args as Record<string, unknown>)\n : {};\n const result = await this.client.callTool({ name: spec.name, arguments: params });\n const text = textFromCallToolResult(result);\n let resultValue: unknown = text;\n try {\n resultValue = JSON.parse(text) as unknown;\n } catch {\n // keep as string\n }\n return { result: resultValue, raw: result };\n }\n}\n","/**\n * Connect to an MCP server via stdio using MCPConnectionInfo.\n * Framework-level: uses @modelcontextprotocol/sdk Client + StdioClientTransport.\n */\n\nimport type { MCPConnectionInfo } from \"./MCPProcessManager.js\";\nimport type { ToolSpec } from \"../../core/types/ToolSpec.js\";\nimport { DEFAULT_INPUT_SCHEMA, DEFAULT_OUTPUT_SCHEMA } from \"../../core/types/ToolSpec.js\";\nimport { MCP_KIND } from \"./types.js\";\n\nexport interface MCPConnectResult {\n /** SDK Client; use listTools() and callTool(). */\n client: MCPClientLike;\n /** Transport; call close() when done. */\n transport: MCPTransportLike;\n}\n\nexport interface MCPClientLike {\n connect(transport: MCPTransportLike): Promise<void>;\n listTools(params?: unknown): Promise<{ tools: MCPToolDef[] }>;\n callTool(params: { name: string; arguments: Record<string, unknown> }): Promise<CallToolResult>;\n}\n\nexport interface MCPTransportLike {\n close(): Promise<void>;\n}\n\nexport interface MCPToolDef {\n name: string;\n description?: string;\n inputSchema?: object;\n}\n\nexport interface CallToolResult {\n content?: Array<{ type: string; text?: string }>;\n toolResult?: unknown;\n}\n\n/**\n * Connect to MCP server via stdio. Only stdio is supported; url/SSE not implemented here.\n * Requires @modelcontextprotocol/sdk. Returns client and transport; caller must call transport.close() when done.\n */\nexport async function connectMCP(connectionInfo: MCPConnectionInfo): Promise<MCPConnectResult> {\n if (connectionInfo.type !== \"stdio\" || !connectionInfo.command) {\n throw new Error(\n `MCP stdio requires connectionInfo.type \"stdio\" and command; got type=${connectionInfo.type}`\n );\n }\n\n const { Client } = await import(\"@modelcontextprotocol/sdk/client\");\n const { StdioClientTransport } = await import(\n \"@modelcontextprotocol/sdk/client/stdio.js\"\n );\n\n const serverParams = {\n command: connectionInfo.command,\n args: connectionInfo.args ?? [],\n env: connectionInfo.env,\n cwd: connectionInfo.cwd,\n };\n const transport = new StdioClientTransport(serverParams);\n const client = new Client({ name: \"agent-tool\", version: \"1.0.0\" });\n await client.connect(transport);\n return {\n client: client as unknown as MCPClientLike,\n transport: transport as unknown as MCPTransportLike,\n };\n}\n\n/**\n * Convert MCP listTools() result to ToolSpec[] (kind MCP_KIND) for registry.\n */\nexport function mcpToolsToSpecs(tools: MCPToolDef[]): ToolSpec[] {\n return tools.map((t) => ({\n name: t.name,\n version: \"1.0.0\",\n kind: MCP_KIND,\n description: t.description ?? `MCP tool: ${t.name}`,\n inputSchema: t.inputSchema ?? DEFAULT_INPUT_SCHEMA,\n outputSchema: DEFAULT_OUTPUT_SCHEMA,\n capabilities: [],\n }));\n}\n","import type { MCPServerConfig } from \"../discoveryFactory.js\";\n\n/**\n * Connection info for an MCP server.\n */\nexport interface MCPConnectionInfo {\n /** Transport type: \"url\" for SSE/HTTP, \"stdio\" for command-based */\n type: \"url\" | \"stdio\";\n /** SSE/HTTP URL (when type=\"url\") */\n url?: string;\n /** Command to spawn (when type=\"stdio\") */\n command?: string;\n /** Command arguments (when type=\"stdio\") */\n args?: string[];\n /** Environment variables (when type=\"stdio\") */\n env?: Record<string, string>;\n /** Working directory when spawning (when type=\"stdio\") */\n cwd?: string;\n}\n\n/**\n * Manages MCP server connection information extracted from directory discovery.\n */\nexport class MCPProcessManager {\n private readonly connections = new Map<string, MCPConnectionInfo>();\n\n getConnectionInfo(toolName: string, config: MCPServerConfig): MCPConnectionInfo {\n const cached = this.connections.get(toolName);\n if (cached) return cached;\n const info: MCPConnectionInfo = config.url\n ? { type: \"url\", url: config.url }\n : {\n type: \"stdio\",\n command: config.command!,\n args: config.args,\n env: config.env,\n cwd: config.cwd,\n };\n this.connections.set(toolName, info);\n return info;\n }\n\n remove(toolName: string): boolean {\n return this.connections.delete(toolName);\n }\n\n getToolNames(): string[] {\n return [...this.connections.keys()];\n }\n\n dispose(): void {\n this.connections.clear();\n }\n}\n","/**\n * High-level API: load mcp.json, connect to MCP server, register tools with runtime.\n * Framework-level so scripts call registerMCPToolsFromConfig() instead of inline MCP logic.\n */\n\nimport { basename, dirname, join } from \"node:path\";\nimport type { PTCRuntime } from \"../../core/runtime/PTCRuntime.js\";\nimport type { ToolRegistry } from \"../../core/registry/ToolRegistry.js\";\nimport { MCP_KIND } from \"./types.js\";\nimport { loadMCPTool } from \"./MCPLoader.js\";\nimport { MCPProcessManager } from \"./MCPProcessManager.js\";\nimport { connectMCP, mcpToolsToSpecs } from \"./connectMCP.js\";\nimport { MCPClientAdapter } from \"./MCPClientAdapter.js\";\n\nexport interface RegisterMCPToolsOptions {\n /** Path to mcp.json (or dir containing it). Default: process.env.MCP_CONFIG_PATH or \"mcp.json\" in cwd. */\n configPath?: string;\n /** Tool name for getConnectionInfo (default \"mcp\"). */\n toolName?: string;\n}\n\nexport interface RegisterMCPToolsResult {\n /** Transport; caller must call transport.close() when done. */\n transport: { close(): Promise<void> };\n}\n\n/**\n * Load mcp config (from configPath or MCP_CONFIG_PATH), connect via stdio, list tools,\n * register ToolSpec[] with registry and MCPClientAdapter with runtime. Returns transport for cleanup.\n */\nexport async function registerMCPToolsFromConfig(\n runtime: PTCRuntime,\n registry: ToolRegistry,\n options: RegisterMCPToolsOptions = {}\n): Promise<RegisterMCPToolsResult> {\n const configPath = options.configPath ?? process.env.MCP_CONFIG_PATH ?? join(process.cwd(), \"mcp.json\");\n const dirPath = dirname(configPath);\n const entryPoint = basename(configPath);\n const toolName = options.toolName ?? MCP_KIND;\n\n const loaded = await loadMCPTool(dirPath, { kind: MCP_KIND, name: toolName, entryPoint });\n if (!loaded.mcpConfig) {\n throw new Error(\"mcp.json must have command or url\");\n }\n const manager = new MCPProcessManager();\n const connectionInfo = manager.getConnectionInfo(toolName, loaded.mcpConfig);\n\n const { client, transport } = await connectMCP(connectionInfo);\n const { tools } = await client.listTools();\n const specs = mcpToolsToSpecs(tools);\n registry.bulkRegister(specs);\n runtime.registerAdapter(new MCPClientAdapter(client));\n\n return { transport };\n}\n"]}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolve an input path to an absolute path within the sandbox.
3
+ * Throws PATH_OUTSIDE_SANDBOX if the resolved path escapes the sandbox root.
4
+ *
5
+ * For existing files: uses realpath to resolve symlinks.
6
+ * For non-existing files (write targets): resolves the parent directory.
7
+ */
8
+ export declare function resolveSandboxedPath(inputPath: string, sandboxRoot: string): Promise<string>;
9
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/security/sandbox.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CA0CjB"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Options for validateUrl. Unified rule: allow iff host is in allowedHosts AND not in blockedHosts.
3
+ * - "Default allow all + blocklist": allowedHosts: ["*"], blockedHosts: ["*.internal", ...]
4
+ * - "Default disallow all + allowlist": allowedHosts: ["api.github.com", ...], blockedHosts: []
5
+ */
6
+ export interface ValidateUrlOptions {
7
+ /** Allow only these hosts. Use ["*"] for allow-all. Supports "*.example.com", exact host. */
8
+ allowedHosts: string[];
9
+ /** Block these hosts even if allowed. Supports "*.internal", exact host. Merged with allowlist. */
10
+ blockedHosts: string[];
11
+ /** CIDR ranges to block (resolved IP). */
12
+ blockedCidrs: string[];
13
+ }
14
+ /**
15
+ * Validate a URL: allow iff (host in allowedHosts) AND (host not in blockedHosts). Then check blockedCidrs on resolved IP.
16
+ *
17
+ * @throws HTTP_DISALLOWED_HOST if the URL is blocked
18
+ */
19
+ export declare function validateUrl(url: string, options: ValidateUrlOptions): Promise<URL>;
20
+ /**
21
+ * Check if an IPv4 address falls within any blocked CIDR range.
22
+ */
23
+ export declare function isIpInBlockedCidrs(ip: string, cidrs: string[]): boolean;
24
+ //# sourceMappingURL=ssrf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf.d.ts","sourceRoot":"","sources":["../../src/security/ssrf.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,6FAA6F;IAC7F,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mGAAmG;IACnG,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,0CAA0C;IAC1C,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,GAAG,CAAC,CA8DxF;AA2CD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAevE"}
@@ -2,12 +2,18 @@
2
2
  * Load tool.yaml: tools config (sandboxedPath + list) or legacy top-level tools + sandboxedPath.
3
3
  * Normalized shape: tools (array of descriptors) and sandboxedPath.
4
4
  */
5
- /** Normalized shape returned by loadToolConfig: tools list and optional sandboxedPath. */
5
+ /** Normalized shape returned by loadToolConfig: tools list, sandbox, and security. */
6
6
  export interface ToolYamlShape {
7
7
  /** List of tool descriptors (npm:@scope/pkg#path or plain names). */
8
8
  tools?: string[];
9
9
  /** Root path for fs sandbox; tools can only access under this path. Resolved relative to tool.yaml dir. */
10
10
  sandboxedPath?: string;
11
+ /** Allowed hosts (e.g. ["*"] or ["api.github.com"]). Merged with programmatic config. */
12
+ allowedHosts?: string[];
13
+ /** Block these hosts even if allowed (e.g. ["*.internal"]). Merged with programmatic config. */
14
+ blockedHosts?: string[];
15
+ /** CIDR ranges to block for HTTP (SSRF). When set, overrides builtin default. */
16
+ blockedCidrs?: string[];
11
17
  }
12
18
  /**
13
19
  * Load tool.yaml and return normalized shape (tools array + sandboxedPath).
@@ -1 +1 @@
1
- {"version":3,"file":"toolConfig.d.ts","sourceRoot":"","sources":["../../../src/tools/util/toolConfig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,0FAA0F;AAC1F,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,2GAA2G;IAC3G,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAcD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAiBlE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CASxF;AAED,oEAAoE;AACpE,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKnF;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAU1F"}
1
+ {"version":3,"file":"toolConfig.d.ts","sourceRoot":"","sources":["../../../src/tools/util/toolConfig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,2GAA2G;IAC3G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,gGAAgG;IAChG,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,iFAAiF;IACjF,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAoBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CA0BlE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CASxF;AAED,oEAAoE;AACpE,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKnF;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAU1F"}
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
3
 
4
- var chunkF32XCT4U_cjs = require('../../chunk-F32XCT4U.cjs');
4
+ var chunkYK2MQDNJ_cjs = require('../../chunk-YK2MQDNJ.cjs');
5
+ var chunkOXTQULXH_cjs = require('../../chunk-OXTQULXH.cjs');
6
+ var chunkEMI67SPN_cjs = require('../../chunk-EMI67SPN.cjs');
5
7
  require('../../chunk-SOFUWEZ6.cjs');
6
- var chunkPVVUTEZP_cjs = require('../../chunk-PVVUTEZP.cjs');
7
- var chunkCDTLERB6_cjs = require('../../chunk-CDTLERB6.cjs');
8
8
  require('../../chunk-ZNJBRLKN.cjs');
9
9
  var chunk6F5JHLZ7_cjs = require('../../chunk-6F5JHLZ7.cjs');
10
10
  var path = require('path');
@@ -24,10 +24,10 @@ async function getRuntimeWithTools(pathOpt, verbose = false) {
24
24
  const stepLog = verbose ? (msg) => process.stderr.write(`[agent-tool] ${msg}
25
25
  `) : void 0;
26
26
  if (stepLog) stepLog(`Loading tool config from ${searchDir}`);
27
- const config = chunkCDTLERB6_cjs.findAndLoadToolConfig(searchDir);
27
+ const config = chunkEMI67SPN_cjs.findAndLoadToolConfig(searchDir);
28
28
  let sandboxRoot = cwd;
29
29
  if (config.sandboxedPath && typeof config.sandboxedPath === "string" && config.configPath) {
30
- sandboxRoot = chunkCDTLERB6_cjs.resolveSandboxedPath(config.configPath, config.sandboxedPath);
30
+ sandboxRoot = chunkEMI67SPN_cjs.resolveSandboxedPath(config.configPath, config.sandboxedPath);
31
31
  }
32
32
  if (stepLog) {
33
33
  if (config.configPath) {
@@ -38,7 +38,7 @@ async function getRuntimeWithTools(pathOpt, verbose = false) {
38
38
  }
39
39
  }
40
40
  const coreConfig = { sandboxRoot, allowedHosts: [] };
41
- const result = await chunkCDTLERB6_cjs.createRuntimeFromConfig({
41
+ const result = await chunkEMI67SPN_cjs.createRuntimeFromConfig({
42
42
  coreTools: coreConfig,
43
43
  configFilePath: config.configPath,
44
44
  stepLog
@@ -165,7 +165,7 @@ For agent run (ReAct + agent.yaml): npx @easynet/agent-orchestra run "task" -c a
165
165
  }
166
166
  async function cmdInit(pathOpt) {
167
167
  try {
168
- const { targetPath, filesCreated } = await chunkF32XCT4U_cjs.initProject({ targetPath: pathOpt || void 0 });
168
+ const { targetPath, filesCreated } = await chunkYK2MQDNJ_cjs.initProject({ targetPath: pathOpt || void 0 });
169
169
  process.stdout.write(`Initialized project at ${targetPath}
170
170
  Created: ${filesCreated.join(", ")}
171
171
  Next: npm install && npm run build
@@ -179,7 +179,7 @@ Next: npm install && npm run build
179
179
  }
180
180
  async function cmdBuild(pathOpt, outDir, include, includeN8n) {
181
181
  try {
182
- const result = await chunkF32XCT4U_cjs.buildMcpPackage({
182
+ const result = await chunkYK2MQDNJ_cjs.buildMcpPackage({
183
183
  projectPath: pathOpt || void 0,
184
184
  outDir: outDir || void 0,
185
185
  include: include.length > 0 ? include : void 0,
@@ -200,7 +200,7 @@ mcp.json: ${result.mcpJsonPath}
200
200
  }
201
201
  async function cmdServe(pathOpt) {
202
202
  try {
203
- const { process: child } = await chunkF32XCT4U_cjs.runMcpServer({ path: pathOpt || void 0 });
203
+ const { process: child } = await chunkYK2MQDNJ_cjs.runMcpServer({ path: pathOpt || void 0 });
204
204
  child.stdin?.pipe(process.stdin);
205
205
  child.stdout?.pipe(process.stdout);
206
206
  process.stdin?.unref();
@@ -218,7 +218,7 @@ var LS_DESC_MAX = 72;
218
218
  function formatLsOutput(specs) {
219
219
  const rows = specs.map((spec) => {
220
220
  const { name } = parseToolName(spec.name);
221
- const scope = chunkCDTLERB6_cjs.getDisplayScope(spec.name, spec.kind, spec.version);
221
+ const scope = chunkEMI67SPN_cjs.getDisplayScope(spec.name, spec.kind, spec.version);
222
222
  const desc = (spec.description ?? "").replace(/\n/g, " ").trim().slice(0, LS_DESC_MAX);
223
223
  return { scope, name, description: desc || "(no description)" };
224
224
  });
@@ -245,7 +245,7 @@ function formatLsOutput(specs) {
245
245
  }
246
246
  function formatDescribeOutput(spec) {
247
247
  const { name: localName } = parseToolName(spec.name);
248
- const scope = chunkCDTLERB6_cjs.getDisplayScope(spec.name, spec.kind, spec.version);
248
+ const scope = chunkEMI67SPN_cjs.getDisplayScope(spec.name, spec.kind, spec.version);
249
249
  const sections = [];
250
250
  sections.push("\u250C\u2500 Tool");
251
251
  sections.push(`\u2502 name: ${spec.name}`);
@@ -281,7 +281,7 @@ async function cmdLs(pathOpt, verbose = false) {
281
281
  process.stdout.write("No tools registered.\n");
282
282
  const cwd = process.cwd();
283
283
  const searchDir = path__default.default.resolve(cwd, pathOpt ?? ".");
284
- const config = chunkCDTLERB6_cjs.findAndLoadToolConfig(searchDir);
284
+ const config = chunkEMI67SPN_cjs.findAndLoadToolConfig(searchDir);
285
285
  const hasNpmTools = Array.isArray(config.tools) && config.tools.some((t) => typeof t === "string" && t.startsWith("npm:"));
286
286
  if (hasNpmTools) {
287
287
  process.stdout.write("Tip: Install builtin tools in this directory: npm init -y && npm install @easynet/agent-tool-buildin\n");
@@ -304,7 +304,7 @@ async function cmdDescribe(toolName, pathOpt, verbose = false) {
304
304
  }
305
305
  try {
306
306
  const { registry } = await getRuntimeWithTools(pathOpt, verbose);
307
- const registryName = chunkCDTLERB6_cjs.resolveToolDescriptor(toolName.trim());
307
+ const registryName = chunkEMI67SPN_cjs.resolveToolDescriptor(toolName.trim());
308
308
  const spec = registry.get(registryName);
309
309
  if (!spec) {
310
310
  process.stderr.write(`Tool not found: ${toolName}
@@ -353,7 +353,7 @@ async function cmdRun(toolName, toolArgsJson, pathOpt, verbose = false) {
353
353
  }
354
354
  try {
355
355
  const { runtime, registry } = await getRuntimeWithTools(pathOpt, verbose);
356
- const registryName = chunkCDTLERB6_cjs.resolveToolDescriptor(toolName.trim());
356
+ const registryName = chunkEMI67SPN_cjs.resolveToolDescriptor(toolName.trim());
357
357
  if (!registry.get(registryName)) {
358
358
  process.stderr.write(`Tool not found: ${toolName}
359
359
  `);
@@ -381,10 +381,10 @@ async function cmdStartMcp(pathOpt, verbose = false, stdio = false, port = 3e3,
381
381
  try {
382
382
  const { runtime } = await getRuntimeWithTools(pathOpt, verbose);
383
383
  if (stdio) {
384
- await chunkPVVUTEZP_cjs.runMCPServerOverStdio(runtime);
384
+ await chunkOXTQULXH_cjs.runMCPServerOverStdio(runtime);
385
385
  return 0;
386
386
  }
387
- const streamable = await chunkPVVUTEZP_cjs.createMCPServerStreamableHttp(runtime, { port, host, path: "/mcp" });
387
+ const streamable = await chunkOXTQULXH_cjs.createMCPServerStreamableHttp(runtime, { port, host, path: "/mcp" });
388
388
  const { url, port: actualPort } = await streamable.listen(port, host);
389
389
  process.stdout.write(`MCP Streamable HTTP: ${url}
390
390
  `);
@@ -400,7 +400,7 @@ async function cmdStartMcp(pathOpt, verbose = false, stdio = false, port = 3e3,
400
400
  async function cmdStartHttp(port, host, pathOpt, verbose = false) {
401
401
  try {
402
402
  const { runtime } = await getRuntimeWithTools(pathOpt, verbose);
403
- const http = await chunkPVVUTEZP_cjs.createHttpService(runtime);
403
+ const http = await chunkOXTQULXH_cjs.createHttpService(runtime);
404
404
  const { port: actualPort, host: actualHost } = await http.listen({ port, host });
405
405
  const base = `http://${actualHost}:${actualPort}`;
406
406
  process.stdout.write(`API: ${base}/invoke (POST), ${base}/tools (GET)
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { initProject, buildMcpPackage, runMcpServer } from '../../chunk-FYJ5VD3Q.js';
2
+ import { initProject, buildMcpPackage, runMcpServer } from '../../chunk-7MRBWT2T.js';
3
+ import { runMCPServerOverStdio, createMCPServerStreamableHttp, createHttpService } from '../../chunk-ETWGKCOP.js';
4
+ import { findAndLoadToolConfig, resolveToolDescriptor, resolveSandboxedPath, createRuntimeFromConfig, getDisplayScope } from '../../chunk-RKN4PT7P.js';
3
5
  import '../../chunk-5SWSNVMI.js';
4
- import { runMCPServerOverStdio, createMCPServerStreamableHttp, createHttpService } from '../../chunk-SIN5JHMP.js';
5
- import { findAndLoadToolConfig, resolveToolDescriptor, resolveSandboxedPath, createRuntimeFromConfig, getDisplayScope } from '../../chunk-BNHLMLDH.js';
6
6
  import '../../chunk-AE6FSNGY.js';
7
7
  import { enrichSpecWithCanonicalSchema } from '../../chunk-FR2CXERF.js';
8
8
  import path from 'path';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easynet/agent-tool",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "description": "MCP build: init → build → run. Turn your project (@tool, SKILL, n8n) into a standalone MCP npm server (no framework embedding, no package conflict).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",