Skip to main content

Generative AI/UI sandbox for Python

Project description

Belgie: Generative AI/UI Sandbox for Python

Belgie is a sandboxed TypeScript environment for Python that lets you build React MCP Apps and have agents write code in a sandbox.

  • MCP Apps: Attach React widgets to Python MCP tools in one project.
  • AI agents: Sandboxed run_code so Pydantic AI and LangChain can run TypeScript and TSX.
  • Inline React widgets: Return self-contained HTML from run_code with @belgie/render.
  • Sandbox: Deno is bundled, so you do not need to install Node.js.

Installation

uv add belgie
uvx library-skills install  # optional: install the use-belgie skill for Cursor, Codex, Claude, etc.

For MCP Apps, install the MCP and CLI extras:

uv add "belgie[mcp,cli]"

MCP Apps

Skip the second package manager. Attach a React widget to a Python MCP tool. BelgieExtension starts Vite in the background for development and runs a one-time production build.

from datetime import UTC, datetime
from pathlib import Path

from mcp.server import MCPServer

from belgie.mcp import BelgieExtension

belgie = BelgieExtension(project=".")


@belgie.tool(
    widget=Path("src/widgets/get-time/widget.tsx"),
    name="get-time",
    title="Get Time",
    description="Get the current server time in ISO 8601 format.",
)
def get_time() -> dict[str, str]:
    return {"time": datetime.now(tz=UTC).isoformat()}


mcp = MCPServer(name="Get Time Server", extensions=[belgie])

The widget is a normal React entry. @belgie/mcp connects the MCP Apps host and surfaces the opening tool result:

import { Widget, useToolResult } from "@belgie/mcp";
import { getTime } from "@widgets/tools";

function AppView() {
  const { data, isLoading, execute } = useToolResult(getTime);
  return (
    <main>
      <p>{data?.time ?? (isLoading ? "Waiting..." : "No time returned.")}</p>
      <button onClick={() => void execute()}>Refresh</button>
    </main>
  );
}

export default function GetTime() {
  return (
    <Widget metadata={{ name: "Get Time", version: "1.0.0" }}>
      <AppView />
    </Widget>
  );
}

Declare JS deps under [tool.belgie.dependencies], then:

uv run belgie lock
uv run belgie install
# start your MCP server; Belgie starts Vite with widget HMR

Pass build=False to BelgieExtension when Vite is managed separately or production assets are already built.

Runnable projects:

  • mcp: Minimal MCP Apps widget.
  • shadcn: Same pattern with Tailwind CSS and shadcn/ui.
  • tanstack: TanStack Start SPA and MCP widget served together through FastAPI.

AI agents

When an agent needs an npm package, a browser-style API, or a JS-side transform, give it run_code. Belgie executes the TypeScript, JavaScript, or TSX in the embedded Deno sandbox. No separate Node install.

Pydantic AI

Install with uv add "belgie[pydantic-ai]", set OPENAI_API_KEY, then:

from pydantic_ai import Agent

from belgie.pydantic_ai import BelgieCapability

agent = Agent("openai:gpt-5", capabilities=[BelgieCapability()])

result = agent.run_sync(
    "Convert 'foo-bar' to camelCase using TypeScript and the camelcase npm package.",
)
print(result.output)

See examples/ai/pydantic-ai.

LangChain

Install with uv add "belgie[langchain]", set OPENAI_API_KEY, then:

from langchain.agents import create_agent

from belgie.langchain import BelgieMiddleware

agent = create_agent(
    model="openai:gpt-5",
    tools=[],
    middleware=[BelgieMiddleware()],
    system_prompt="You can execute JS/TS in a Deno sandbox with run_code.",
)

result = agent.invoke(
    {
        "messages": [
            (
                "user",
                "Convert 'foo-bar' to camelCase using TypeScript and the camelcase npm package.",
            ),
        ],
    },
)
print(result["messages"][-1].content)

See examples/ai/langchain.

Under the hood: Deno in Python

MCP Apps and agent run_code both use Belgie’s embedded Deno runtime. Call it directly when you need JS/TS from Python without MCP or an agent framework:

  • Scripts: Inline or file-based JS/TS with Runtime and Script, sync or async.
  • Inline dependencies: Import npm, JSR, and URL modules from source.
  • Environments: Lockfiles, custom cache/options, local packages, and Command for npm binaries (Vite, esbuild, etc.).
  • Data bridge: Pass JSON-safe dicts, lists, and primitives across the boundary.
import asyncio

from belgie import Runtime, Script

script = Script[[str], str](
    """
import camelcase from "npm:camelcase@8.0.0";

export default function run(input: string): string {
  return camelcase(input);
}
"""
)


async def main() -> None:
    async with Runtime() as run:
        print(await run(script)("foo-bar"))  # prints: fooBar


asyncio.run(main())

Inline widget rendering

Pydantic AI and LangChain agents can return a complete inline React widget through the same run_code tool. The agent writes one TSX module and imports the standalone renderer:

import { render } from "npm:@belgie/render";

function Widget() {
  return <main>Hello from Belgie</main>;
}

export default function run() {
  return render({
    widget: <Widget />,
    plugins: [],
  });
}

render() runs Vite inside the active Deno worker and returns one self-contained HTML string with inline JavaScript, CSS, and assets. Package imports are supported. Relative host-file imports are intentionally unavailable, and Vite plugins run only during the server build before their expressions and plugin-only imports are removed from the browser bundle. This API is independent from @belgie/mcp and its path-based widget.tsx development and production flow.

Examples

Small, runnable projects. Each focuses on one capability.

UI

  • mcp: MCP Apps extension with a React widget built through Belgie.
  • shadcn: MCP Apps widget styled with Tailwind CSS and shadcn/ui.
  • tanstack: TanStack Start SPA and MCP widget served together through FastAPI.

AI

  • pydantic-ai: Pydantic AI agent with BelgieCapability() for sandboxed JS/TS/TSX execution.
  • langchain: LangChain agent with BelgieMiddleware() for sandboxed JS/TS/TSX execution.

Basic

  • simple: Async Runtime with a TypeScript file on disk.
  • inline-deps: Direct npm:, jsr:, and URL imports in a script.
  • jsr-deps: JSR packages declared through an explicit Environment.
  • pyproject: Manage project package dependencies with belgie[cli] and [tool.belgie.dependencies].
  • environment: Sync and async Environment setup with path.
  • commands: npm package binaries via Runtime and Command.

For deeper integration guidance, optionally install the use-belgie skill with uvx library-skills install.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

belgie-0.36.0.tar.gz (801.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

belgie-0.36.0-cp312-abi3-win_amd64.whl (54.0 MB view details)

Uploaded CPython 3.12+Windows x86-64

belgie-0.36.0-cp312-abi3-manylinux_2_28_x86_64.whl (61.0 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ x86-64

belgie-0.36.0-cp312-abi3-manylinux_2_28_aarch64.whl (64.6 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ ARM64

belgie-0.36.0-cp312-abi3-macosx_11_0_arm64.whl (55.1 MB view details)

Uploaded CPython 3.12+macOS 11.0+ ARM64

belgie-0.36.0-cp312-abi3-macosx_10_12_x86_64.whl (57.2 MB view details)

Uploaded CPython 3.12+macOS 10.12+ x86-64

File details

Details for the file belgie-0.36.0.tar.gz.

File metadata

  • Download URL: belgie-0.36.0.tar.gz
  • Upload date:
  • Size: 801.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for belgie-0.36.0.tar.gz
Algorithm Hash digest
SHA256 03ab8a4d69726e45515d9da21eb760769c7c0d1a94f05200418915d7e5dd6d61
MD5 a73e7e19faded33365047e3f154db23c
BLAKE2b-256 b67b3f38e191d379d95527555ebdcf0623d559c729ba1ffb9b3d20c31f71f46d

See more details on using hashes here.

File details

Details for the file belgie-0.36.0-cp312-abi3-win_amd64.whl.

File metadata

  • Download URL: belgie-0.36.0-cp312-abi3-win_amd64.whl
  • Upload date:
  • Size: 54.0 MB
  • Tags: CPython 3.12+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for belgie-0.36.0-cp312-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 725703e48ffb4381c2850b6c9543a2420dfca70c5e027ddae79cdd2a14567918
MD5 051b3a29c2e68a9d92081021e833b7af
BLAKE2b-256 ff2cf4aa284bf0244fde9b0a54bead71d723bb2e964cdf79f885af7bb1d48566

See more details on using hashes here.

File details

Details for the file belgie-0.36.0-cp312-abi3-manylinux_2_28_x86_64.whl.

File metadata

  • Download URL: belgie-0.36.0-cp312-abi3-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 61.0 MB
  • Tags: CPython 3.12+, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for belgie-0.36.0-cp312-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c7bf25c29b785deb5ef6a28cb7b738757287eadbaae50361451bd8d026da4e99
MD5 297001dcaf98954a3cb345c426a123fa
BLAKE2b-256 c71d358c20aaa641e79bed64e73075b9e7368585a9aa354e7b0c2d3ad1b86ffb

See more details on using hashes here.

File details

Details for the file belgie-0.36.0-cp312-abi3-manylinux_2_28_aarch64.whl.

File metadata

  • Download URL: belgie-0.36.0-cp312-abi3-manylinux_2_28_aarch64.whl
  • Upload date:
  • Size: 64.6 MB
  • Tags: CPython 3.12+, manylinux: glibc 2.28+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for belgie-0.36.0-cp312-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 5f290d9844752d1603e9b796f96c7eab0a9da09ce4a09592665d4cb1c1350d93
MD5 a4b39da9a2a9385c04e25048c6dd637d
BLAKE2b-256 36c67fceaef41f9a84ba1d3645c08ea6132bf8d15f6ad7233e1996d69c9ade74

See more details on using hashes here.

File details

Details for the file belgie-0.36.0-cp312-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: belgie-0.36.0-cp312-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 55.1 MB
  • Tags: CPython 3.12+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for belgie-0.36.0-cp312-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 55e04d4d10a9bf07d773256124f52a6092444463527e343cf2bb18a5fa4e281d
MD5 9bc6f57a4bac39d71a115a82065db25a
BLAKE2b-256 b84d4b6163ac706bb4c30ab13cc01c33c311ecec35c34b8a980ac89fa64a72a9

See more details on using hashes here.

File details

Details for the file belgie-0.36.0-cp312-abi3-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: belgie-0.36.0-cp312-abi3-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 57.2 MB
  • Tags: CPython 3.12+, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for belgie-0.36.0-cp312-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 f3c011b5dbd9aca3e72d90fcb83d6efe4e0ecf2179ad11ae0cbd671eb55a25e1
MD5 ccf47b802dfe6cb652d3e88a572b43ce
BLAKE2b-256 5fd3708af4f216e1a2ac02a0a1289119d0850f65279f7613e3fa1cdd03459700

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page