Skip to content

mcp: import-by-entrypoint tool execution and injected workspace param#55

Merged
congwang-mk merged 11 commits into
mainfrom
mcp-import-entrypoint
May 22, 2026
Merged

mcp: import-by-entrypoint tool execution and injected workspace param#55
congwang-mk merged 11 commits into
mainfrom
mcp-import-entrypoint

Conversation

@congwang-mk
Copy link
Copy Markdown
Contributor

@congwang-mk congwang-mk commented May 22, 2026

Summary

  • Import-by-entrypoint execution. Replace the inspect.getsource + f-string source-paste in McpSandbox._call_local with a stdlib-only worker (_worker.py) that imports each tool's module and calls the function in place. Same per-call isolation (Landlock + seccomp, clean_env, deny-by-default), but tools can now use normal module-level imports, helpers, constants, and state. Lambdas, methods, and nested functions are rejected at add_tool with a clear error instead of failing cryptically in a subprocess. The worker is invoked by absolute path so it never drags the sandlock package (or its FFI cdylib) into the jail.
  • Injected workspace parameter. A tool that declares a parameter named workspace receives the sandbox workspace path automatically (injected at call time, hidden from the LLM schema, and not overridable by the model). Removes the SANDLOCK_WORKSPACE magic string and all manual {"env": {...}} wiring; the env capability stays for real vars.
  • Lighter built-in server. Move the five built-in tools into a stdlib-only sandlock/mcp/_builtins.py and make create_server lazy, so the per-call worker no longer re-imports the mcp framework. Measured per-call import cost for sandlock-mcp drops from ~450ms to ~60ms.

Test Plan

  • cd python && pytest tests/ -q (294 passing locally)
  • New coverage: module-level-state tool runs under the worker; lambda/method/nested rejection; workspace injection and override-prevention; built-in module imports without pulling in mcp; create_server lazily importable.

Notes

  • Known limitation (dev-only): executing the bundled built-in tools from an editable/source checkout fails in-jail because the dev cdylib lives in target/ (unreadable inside the sandbox). Wheel installs are unaffected; fully removing it would require lazy-loading the cdylib in sandlock core.

🤖 Generated with Claude Code

Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
@congwang-mk congwang-mk force-pushed the mcp-import-entrypoint branch from 3ef3ba1 to fa4038f Compare May 22, 2026 03:21
@congwang-mk congwang-mk merged commit add7c37 into main May 22, 2026
8 checks passed
@congwang-mk congwang-mk deleted the mcp-import-entrypoint branch May 22, 2026 03:25
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.

1 participant