Self-hosted Python and Node tool workspace

A small workspace. A useful connection.

Your scripts.
Your AI’s tools.

Turn your Python and Node scripts into tools for your AI.

Bring the logic you already know. Give it a name, test the saved code, then let a compatible MCP client discover it—all from one self-hosted workspace.

Trusted LAN only. Not an internet-facing service. Know the boundaries

OMNIFORGE / WORKSPACE01—03
summarise_orders.pyPYTHON
# A small script. A clear contract.
import json, sys

orders = json.load(sys.stdin)
print(json.dumps({
  "total": sum(orders["amounts"])
}))
SAVED VERSION → TEST RESULT stdout{"total": 42}Illustrative script and output
Ready for discoveryEnabled tools → tools/list
Python + NodeJSON in. Useful output out.
01 Write ordinary scripts02 Inspect real results03 Keep control locally

From an idea to a callable tool

A short path.
No hidden steps.

Creation, saving and execution are separate actions. You see what runs before you put it in an assistant’s hands.

01 / CREATE

Make one thing useful.

Write Python or Node, or begin with a template. Name the tool, describe its purpose and declare the packages it needs.

Your logic, not a new framework.
02 / TEST SAVED CODE

Know what comes back.

Save first, then run with JSON inputs. Inspect stdout, stderr, exit status and timing. Retained results are labelled when the code or inputs change.

A test runs the saved tool—not a draft.
03 / DISCOVER

Connect on your terms.

Enable the tool and refresh tools/list in a compatible client. Calls pass a JSON object on stdin and return the script’s printed output.

Limited HTTP JSON-RPC at /mcp.
Create a Python or Node script, test the saved version with JSON, then discover enabled tools through limited HTTP JSON-RPC.
A deliberately small contract: a named script, JSON input and printed output.

Inside the workspace

Less setup.
More making.

A library when you need to find something. A studio when you need to focus. Connection details when you are ready.

THE WORKSPACELocal demo · light theme
OmniForge Overview with saved-tool counts and the create, test and connect journey.
Start with the next useful action, not a wall of configuration.
/01

Scripts stay familiar

Python and Node with JSON on stdin. Per-tool pip and npm requirements install on first use and remain cached for later calls.

/02

Results have context

Explicit save and test controls, visible errors and previous-version labels help distinguish a current result from an earlier run.

/03

Your library, organised

Search by name or description. Filter by runtime or enabled state. Choose which saved tools appear in discovery.

/04

A calmer everyday workspace

Light, dark and system themes, a phone layout and PWA support on HTTPS or localhost. Saving and execution still require the server online.

OmniForge Overview on a phone with labelled bottom navigation.

Same workspace. Smaller screen.

Keep the next step
within reach.

The interface adapts to a phone without turning into a different product. Labelled navigation, readable controls and the same saved-tool workflow.

Screenshots use local demo data, not a live service. The app supports light and dark themes; captures here show the documented workspace.

PWA and theme notes

A clear connection contract

Bring a client.
Check the transport.

Local or cloud model choice belongs to your MCP client. It does not imply a cloud service can reach—or safely expose—OmniForge.

Small, explicit HTTP surface

POST /mcp accepts one JSON-RPC request at a time for initialize, tools/list, tools/call and ping.

This is limited HTTP JSON-RPC, not full Streamable HTTP. There is no OAuth, session tracking or working SSE channel. Third-party client compatibility has not been live-verified; a client must accept this limited transport.

Read the exact protocol support

DISCOVERY REQUEST / ILLUSTRATIVE

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}

Refresh discovery after enabling a tool. Do not assume automatic client compatibility.

Before you run it

Local control.
Honest boundaries.

For trusted people running trusted code. Not a hosted multi-user service, not a sandbox and not safe for public exposure.

Keep access private

The dashboard and management API are unauthenticated. Anyone who can reach them can read, edit and run tools. Bind locally or restrict access to a trusted LAN. Do not port-forward or expose a public reverse proxy.

A key is not dashboard auth

Set OMNIFORGE_API_KEY to require a Bearer key on POST /mcp. That key does not protect the dashboard, management API or GET /mcp. No OAuth is provided.

Scripts share the container

Scripts inherit the app’s environment, including its MCP key, and can access its writable data and network. Only run trusted scripts and packages. Do not place unrelated secrets in the environment.

Execution and hosting constraints

Runs and dependency installs block the single worker. Output is not capped, per-script memory limits are not enforced and timeouts do not kill descendant processes. There are no CSRF, Origin or Host checks.

Container hardening is not per-script isolation. PWA installation requires HTTPS or localhost; its offline screen cannot execute or save tools. Public-safe hosting and security gaps are not solved by this page.

Full security model and checklist

Start on your machine

One container.
Your first useful tool.

Use Docker on an amd64 host. Keep the published port bound to localhost, and require a key for MCP POST requests.

Pull the image

Start with the image on Docker Hub. Review the constraints above before starting the container.

TERMINAL
docker pull dbzocchi/omniforge:latest

Use a digest when you need a reproducible image. This page previews the documented workspace; a pulled image may differ.

Image and tags on Docker Hub

Run with local-only access

The shell check below requires your key to be set first. It does not add authentication to the dashboard.

POSIX SHELL
# Set OMNIFORGE_API_KEY to a strong random value first.
: "${OMNIFORGE_API_KEY:?Set a strong random key first}"
export OMNIFORGE_API_KEY
docker run -d --name omniforge \
  -p 127.0.0.1:8000:8000 \
  -e OMNIFORGE_API_KEY \
  -v omniforge_data:/opt/omniforge/data \
  -v omniforge_lib:/opt/omniforge/lib \
  --restart unless-stopped \
  dbzocchi/omniforge:latest

Open http://localhost:8000. Create a tool, save it, then choose Run / Test.

Need LAN access or hardening?

The local bind above intentionally prevents other machines connecting. Review network restrictions, container permissions and resource limits before changing it.

Installation guide