Skip to content

Add file upload support to /api/exec and run_js file-path reads#167

Open
r33drichards wants to merge 1 commit into
mainfrom
claude/peaceful-dirac-esj097
Open

Add file upload support to /api/exec and run_js file-path reads#167
r33drichards wants to merge 1 commit into
mainfrom
claude/peaceful-dirac-esj097

Conversation

@r33drichards

Copy link
Copy Markdown
Owner

Summary

This PR adds two complementary features for JavaScript execution:

  1. Multipart file upload to /api/exec: The REST endpoint now accepts multipart/form-data requests, allowing clients to upload script files directly instead of embedding code in JSON strings.

  2. File-path execution for run_js: Both the MCP run_js tool and REST /api/exec endpoint now support a file parameter to read and execute scripts from the server's own filesystem, with optional policy-based access control.

Key Changes

  • New module server/src/engine/run_js_file.rs: Implements policy-gated file reading for the run_js tool. Files are canonicalized before policy evaluation to prevent ../ escape attacks. Supports two modes:

    • AllowAll: Allow reading any path the server process can access (--allow-run-js-file)
    • Policy: Gate reads behind an OPA/Rego policy chain (run_js_file in --policies-json)
  • Updated /api/exec handler (server/src/api.rs):

    • Detects request encoding via Content-Type header
    • Parses multipart/form-data requests with file or code parts
    • Supports optional form fields: heap, session, heap_memory_max_mb, execution_timeout_secs, tags
    • Maintains backward compatibility with existing JSON requests
  • Extended Engine and RunJsRequest (server/src/engine/mod.rs):

    • Added run_js_file_policy field to Engine
    • Added file() and maybe_file() builder methods to RunJsRequest
    • Updated run_js_inner() to handle file-path reads with policy evaluation
  • Updated MCP run_js tool (server/src/mcp.rs):

    • Made code parameter optional (defaults to empty string)
    • Added optional file parameter
    • Passes file path through to engine with policy enforcement
  • CLI enhancements (server/src/cli.rs, mcp-v8-client/src/main.rs):

    • Added --allow-run-js-file flag for the server
    • Added --file / -f option to the CLI client's exec command
  • Comprehensive integration tests (server/tests/exec_upload_e2e.rs):

    • Tests multipart file upload execution
    • Tests multipart with additional form fields
    • Tests error handling for missing code/file parts
    • Regression test for JSON encoding
  • Documentation updates:

    • Updated API reference, how-to guides, and policy documentation
    • Added examples for both file-path execution and multipart uploads
    • Documented the run_js_file policy input schema

Implementation Details

  • Path canonicalization: File paths are canonicalized (symlinks and .. resolved) before policy evaluation, preventing directory escape attacks
  • Multipart parsing: Uses axum's Multipart extractor; unknown form parts are silently ignored
  • Backward compatibility: JSON requests continue to work unchanged; multipart is opt-in via Content-Type
  • Error handling: Clear error messages distinguish between missing files, policy denials, and I/O errors
  • Policy integration: Reuses existing OPA/Rego policy chain infrastructure with a new run_js_file policy category

https://claude.ai/code/session_01DGrcRNsCvv6QvGxn71MmhR

The run_js MCP tool gains an optional `file` parameter that reads the
script from a path on the server's own filesystem instead of inline
`code`. It is off by default and unlocked by either `--allow-run-js-file`
(allow any server-readable path) or a new `run_js_file` OPA/Rego policy
category in `--policies-json` (authorize per path). Paths are
canonicalized before policy evaluation, so `..` cannot escape an allowed
directory. Supplying both `code` and `file` is an error.

POST /api/exec now also accepts multipart/form-data: clients can upload
the script as a `file` (or `code`) part, with the optional heap/session/
tags/limit fields as sibling parts. The JSON body still works. Unlike the
tool's `file` parameter, uploads carry content from the client and need
no server flag or policy.

The mcp-v8-cli `exec` command gains `--file <PATH>` to read and submit a
local script.

Tests: unit tests for the policy-gated reader and the new policy config;
stateless-shell tests for the tool `file` path (allow-all / disabled /
conflict); an e2e test for multipart uploads (and a JSON regression).

Docs: regenerated CLI-flags, MCP-tools, OpenAPI, and HTTP-API references;
updated the js-execution and policies reference/how-to/concept pages, the
embedded README and llms.txt, and the run_js tool descriptions.

https://claude.ai/code/session_01DGrcRNsCvv6QvGxn71MmhR
@github-actions

Copy link
Copy Markdown

🦀 mcp-v8-client Built Successfully

Package: mcp-v8-client
Version: 0.1.0-beta.167.d93b53c

Add as dependency

[dependencies]
mcp-v8-client = { git = "https://github.com/r33drichards/mcp-js", branch = "claude/peaceful-dirac-esj097" }

CLI (from this branch)

cargo install --git https://github.com/r33drichards/mcp-js --branch claude/peaceful-dirac-esj097 mcp-v8-client

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants