Skip to content
This repository was archived by the owner on Apr 22, 2026. It is now read-only.

Commit 6ced81a

Browse files
committed
fix: inject project assets as Docker volume mounts in execute_hub_tool
1 parent b975d28 commit 6ced81a

3 files changed

Lines changed: 38 additions & 4 deletions

File tree

fuzzforge-common/src/fuzzforge_common/hub/client.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,15 @@ async def execute_tool(
176176
arguments: dict[str, Any],
177177
*,
178178
timeout: int | None = None,
179+
extra_volumes: list[str] | None = None,
179180
) -> dict[str, Any]:
180181
"""Execute a tool on a hub server.
181182
182183
:param server: Hub server to execute on.
183184
:param tool_name: Name of the tool to execute.
184185
:param arguments: Tool arguments.
185186
:param timeout: Execution timeout (uses default if None).
187+
:param extra_volumes: Additional Docker volume mounts to inject.
186188
:returns: Tool execution result.
187189
:raises HubClientError: If execution fails.
188190
@@ -199,7 +201,7 @@ async def execute_tool(
199201
)
200202

201203
try:
202-
async with self._connect(config) as (reader, writer):
204+
async with self._connect(config, extra_volumes=extra_volumes) as (reader, writer):
203205
# Initialise MCP session (skip for persistent — already done)
204206
if not self._persistent_sessions.get(config.name):
205207
await self._initialize_session(reader, writer, config.name)
@@ -248,6 +250,7 @@ async def execute_tool(
248250
async def _connect(
249251
self,
250252
config: HubServerConfig,
253+
extra_volumes: list[str] | None = None,
251254
) -> AsyncGenerator[tuple[asyncio.StreamReader, asyncio.StreamWriter], None]:
252255
"""Connect to an MCP server.
253256
@@ -256,6 +259,7 @@ async def _connect(
256259
ephemeral per-call connection logic.
257260
258261
:param config: Server configuration.
262+
:param extra_volumes: Additional Docker volume mounts to inject.
259263
:yields: Tuple of (reader, writer) for communication.
260264
261265
"""
@@ -268,7 +272,7 @@ async def _connect(
268272

269273
# Ephemeral connection (original behaviour)
270274
if config.type == HubServerType.DOCKER:
271-
async with self._connect_docker(config) as streams:
275+
async with self._connect_docker(config, extra_volumes=extra_volumes) as streams:
272276
yield streams
273277
elif config.type == HubServerType.COMMAND:
274278
async with self._connect_command(config) as streams:
@@ -284,10 +288,12 @@ async def _connect(
284288
async def _connect_docker(
285289
self,
286290
config: HubServerConfig,
291+
extra_volumes: list[str] | None = None,
287292
) -> AsyncGenerator[tuple[asyncio.StreamReader, asyncio.StreamWriter], None]:
288293
"""Connect to a Docker-based MCP server.
289294
290295
:param config: Server configuration with image name.
296+
:param extra_volumes: Additional volume mounts to inject (e.g. project assets).
291297
:yields: Tuple of (reader, writer) for stdio communication.
292298
293299
"""
@@ -302,10 +308,14 @@ async def _connect_docker(
302308
for cap in config.capabilities:
303309
cmd.extend(["--cap-add", cap])
304310

305-
# Add volumes
311+
# Add volumes from server config
306312
for volume in config.volumes:
307313
cmd.extend(["-v", os.path.expanduser(volume)])
308314

315+
# Add extra volumes (e.g. project assets injected at runtime)
316+
for volume in (extra_volumes or []):
317+
cmd.extend(["-v", os.path.expanduser(volume)])
318+
309319
# Add environment variables
310320
for key, value in config.environment.items():
311321
cmd.extend(["-e", f"{key}={value}"])

fuzzforge-common/src/fuzzforge_common/hub/executor.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,14 @@ async def execute_tool(
180180
arguments: dict[str, Any] | None = None,
181181
*,
182182
timeout: int | None = None,
183+
extra_volumes: list[str] | None = None,
183184
) -> HubExecutionResult:
184185
"""Execute a hub tool.
185186
186187
:param identifier: Tool identifier (hub:server:tool or server:tool).
187188
:param arguments: Tool arguments.
188189
:param timeout: Execution timeout.
190+
:param extra_volumes: Additional Docker volume mounts to inject.
189191
:returns: Execution result.
190192
191193
"""
@@ -232,6 +234,7 @@ async def execute_tool(
232234
tool_name_to_use or tool_name,
233235
arguments,
234236
timeout=timeout,
237+
extra_volumes=extra_volumes,
235238
)
236239
return HubExecutionResult(
237240
success=True,
@@ -268,6 +271,7 @@ async def execute_tool(
268271
tool.name,
269272
arguments,
270273
timeout=timeout,
274+
extra_volumes=extra_volumes,
271275
)
272276
return HubExecutionResult(
273277
success=True,

fuzzforge-mcp/src/fuzzforge_mcp/tools/hub.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from fastmcp.exceptions import ToolError
1717
from fuzzforge_common.hub import HubExecutor, HubServerConfig, HubServerType
1818

19-
from fuzzforge_mcp.dependencies import get_settings
19+
from fuzzforge_mcp.dependencies import get_project_path, get_settings, get_storage
2020

2121
mcp: FastMCP = FastMCP()
2222

@@ -180,10 +180,30 @@ async def execute_hub_tool(
180180
try:
181181
executor = _get_hub_executor()
182182

183+
# Inject project assets as Docker volume mounts if configured.
184+
# Mounts the assets directory at the standard paths used by hub tools:
185+
# /app/uploads — binwalk, and other tools that use UPLOAD_DIR
186+
# /app/samples — yara, capa, and other tools that use SAMPLES_DIR
187+
extra_volumes: list[str] = []
188+
try:
189+
storage = get_storage()
190+
project_path = get_project_path()
191+
assets_path = storage.get_project_assets_path(project_path)
192+
if assets_path:
193+
assets_str = str(assets_path)
194+
extra_volumes = [
195+
f"{assets_str}:/app/uploads:ro",
196+
f"{assets_str}:/app/samples:ro",
197+
]
198+
except Exception:
199+
# Never block tool execution because of asset injection failure
200+
extra_volumes = []
201+
183202
result = await executor.execute_tool(
184203
identifier=identifier,
185204
arguments=arguments or {},
186205
timeout=timeout,
206+
extra_volumes=extra_volumes or None,
187207
)
188208

189209
return result.to_dict()

0 commit comments

Comments
 (0)