Visual Loop MCP Server
by IqbalHere
README.md
<div align="center">
<!-- Animated Header Banner -->
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:6C63FF,50:A855F7,100:EC4899&height=220§ion=header&text=Visual%20Loop%20MCP&fontSize=50&fontColor=FFFFFF&fontAlignY=35&desc=Execute%20%E2%80%A2%20Render%20%E2%80%A2%20Verify&descSize=20&descAlignY=55&animation=fadeIn" width="100%" alt="Visual Loop MCP Header"/>
<br/>
<!-- Badges -->
[](https://modelcontextprotocol.io)
[](https://www.typescriptlang.org/)
[](https://playwright.dev/)
[](https://judge0.com/)
[](LICENSE)
[](https://nodejs.org/)
<br/>
<p align="center">
<strong>A production-ready MCP server that combines <em>secure code execution</em> with <em>visual rendering</em> β giving multimodal AI clients the power to write, run, and <em>see</em> code in one seamless loop.</strong>
</p>
<br/>
[π Quick Start](#-quick-start) β’
[π Documentation](#-how-it-works) β’
[π§ Configuration](#-configuration) β’
[π€ Claude Desktop](#-claude-desktop-integration) β’
[π‘ API Reference](#-tool-reference)
<br/>
---
</div>
## β¨ Why Visual Loop?
Most AI coding assistants can *write* code β but they can't *see* the result. **Visual Loop MCP** closes that gap by providing a single tool that:
<table>
<tr>
<td width="60" align="center">β‘</td>
<td><strong>Executes code securely</strong> via Judge0/Codebox sandboxed runtime</td>
</tr>
<tr>
<td align="center">πΌοΈ</td>
<td><strong>Renders visual output</strong> using Playwright headless Chromium</td>
</tr>
<tr>
<td align="center">πΈ</td>
<td><strong>Returns screenshots</strong> alongside console output in a single multimodal response</td>
</tr>
<tr>
<td align="center">π</td>
<td><strong>Enables iterative UI development</strong> β AI sees its own output and self-corrects</td>
</tr>
</table>
> [!TIP]
> Think of it as **giving your AI eyes** β it can now verify layouts, catch visual bugs, and iterate on designs without human intervention.
---
## ποΈ Architecture
```
ββββββββββββββββββββββββββββββββ
β AI Client β
β (Claude Desktop / Cursor) β
ββββββββββββββββ¬ββββββββββββββββ
β
stdio (JSON-RPC 2.0)
β
ββββββββββββββββΌββββββββββββββββ
β Visual Loop MCP Server β
β β
β βββββββββββββββββββββββββ β
β β Phase A: Execute β β ββββββββββββββββββββ
β β Code Validation βββββΌβββββΆβ Judge0/Codebox β
β β β β β (Sandboxed API) β
β βββββββββββββββββββββββββ β ββββββββββββββββββββ
β β
β βββββββββββββββββββββββββ β
β β Phase B: Render β β ββββββββββββββββββββ
β β Visual Screenshot βββββΌβββββΆβ Playwright β
β β β β β (Headless Chrome) β
β βββββββββββββββββββββββββ β ββββββββββββββββββββ
β β
β βββββββββββββββββββββββββ β
β β Phase C: Cleanup β β Temp files removed
β β Resource Disposal β β Browser closed
β βββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββ
```
<div align="center">
```mermaid
graph LR
A[π€ AI Client] -->|stdio JSON-RPC| B[π Visual Loop MCP]
B -->|POST /submissions| C[β‘ Judge0 Codebox]
B -->|file:// render| D[π Playwright]
C -->|stdout / stderr| B
D -->|base64 PNG| B
B -->|multimodal response| A
style A fill:#6C63FF,stroke:#4F46E5,color:#fff,stroke-width:2px
style B fill:#A855F7,stroke:#9333EA,color:#fff,stroke-width:2px
style C fill:#F59E0B,stroke:#D97706,color:#fff,stroke-width:2px
style D fill:#10B981,stroke:#059669,color:#fff,stroke-width:2px
```
</div>
---
## π¦ Prerequisites
| Requirement | Version | Purpose |
|:---:|:---:|:---|
| <img src="https://img.shields.io/badge/-Node.js-339933?logo=node.js&logoColor=white&style=flat-square" /> | `β₯ 20.0` | Runtime environment |
| <img src="https://img.shields.io/badge/-npm-CB3837?logo=npm&logoColor=white&style=flat-square" /> | `β₯ 10.0` | Package management |
| <img src="https://img.shields.io/badge/-Docker-2496ED?logo=docker&logoColor=white&style=flat-square" /> | Any | Judge0 container hosting |
---
## π Quick Start
### 1οΈβ£ Start the Judge0 Sandbox
```bash
# Pull and run Judge0 CE in Docker
docker run -d -p 2358:2358 --name judge0 judge0/judge0-ce
```
### 2οΈβ£ Install & Build
```bash
# Clone the repository
git clone https://github.com/IqbalHere/-Visual-Loop-MCP-Server.git
cd -Visual-Loop-MCP-Server
# Install dependencies
npm install
# Install Playwright Chromium (minimal footprint)
npx playwright install chromium
# Build the TypeScript project
npm run build
```
### 3οΈβ£ Run the Server
<details>
<summary><strong>π§ macOS / Linux</strong></summary>
```bash
CODEBOX_URL=http://localhost:2358 CODEBOX_TOKEN=your_token npm start
```
</details>
<details>
<summary><strong>πͺ Windows (PowerShell)</strong></summary>
```powershell
$env:CODEBOX_URL = "http://localhost:2358"
$env:CODEBOX_TOKEN = "your_token"
npm start
```
</details>
---
## π§ Configuration
| Variable | Required | Description |
|:---|:---:|:---|
| `CODEBOX_URL` | β
| Base URL of your Judge0/Codebox instance |
| `CODEBOX_TOKEN` | β | Auth token for the Codebox API *(omit if no auth)* |
> [!NOTE]
> If `CODEBOX_URL` is unset, the server gracefully skips code execution and only performs visual rendering. No crash, no fuss.
---
## π€ Claude Desktop Integration
Add this to your Claude Desktop configuration file:
| Platform | Config Path |
|:---|:---|
| **macOS** | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| **Windows** | `%APPDATA%\Claude\claude_desktop_config.json` |
```jsonc
{
"mcpServers": {
"visual-loop": {
"command": "node",
"args": ["C:/absolute/path/to/visual-loop-mcp/build/index.js"],
"env": {
"CODEBOX_URL": "http://localhost:2358",
"CODEBOX_TOKEN": "your_token_here" // optional
}
}
}
}
```
> [!IMPORTANT]
> Replace the path in `args` with the **absolute path** to your cloned project. Use forward slashes (`/`) even on Windows.
After saving, **restart Claude Desktop**. The `execute_and_render` tool will appear in the tool picker. π
---
## π‘ Tool Reference
### `execute_and_render`
The single, powerful tool exposed by this server.
```
AI writes code β Codebox validates logic β Playwright renders visuals β AI sees the result
```
#### Parameters
| Parameter | Type | Required | Default | Description |
|:---|:---:|:---:|:---:|:---|
| `source_code` | `string` | β
| β | Raw HTML/CSS/JS source code to execute and render |
| `language_id` | `number` | β
| β | Judge0 language ID (see table below) |
| `viewport_width` | `number` | β | `1280` | Browser viewport width in pixels |
| `viewport_height` | `number` | β | `720` | Browser viewport height in pixels |
#### Response Format
The tool returns a **multimodal MCP content array** containing both text and image:
```json
{
"content": [
{
"type": "text",
"text": "[Codebox] Status: Accepted (id: 3)\nββ stdout ββ\nHello, world!\n\nExecution time: 0.012s | Memory: 3456 KB"
},
{
"type": "image",
"data": "<base64-encoded-PNG-screenshot>",
"mimeType": "image/png"
}
]
}
```
---
## ποΈ Supported Languages
| Language | ID | Language | ID |
|:---|:---:|:---|:---:|
| π¨ JavaScript (Node.js) | `63` | π Python 3 | `71` |
| π· TypeScript | `74` | β Java | `62` |
| βοΈ C++ (GCC) | `54` | π Ruby | `72` |
| πΉ Go | `60` | π HTML/CSS | `82` |
> [!TIP]
> For a complete list of 60+ supported languages, query your Judge0 instance: `GET /languages`
---
## π‘οΈ Error Handling
The server is engineered to **never crash** from tool-level errors. Every failure is caught and returned gracefully:
| Scenario | Behavior |
|:---|:---|
| π Codebox timeout / network error | Error details in text response; screenshot still attempted |
| π₯οΈ Playwright crash | Codebox results returned with rendering error note |
| π₯ Both fail | Descriptive error text returned; no image block |
| β οΈ Missing `CODEBOX_URL` | Codebox phase skipped with warning; rendering proceeds |
---
## π§° Development
```bash
# Build and run in one step
npm run dev
# Watch mode with tsx (great for iterating)
npx tsx watch src/index.ts
```
### Project Structure
```
visual-loop-mcp/
βββ π src/
β βββ index.ts # Main server β Codebox + Playwright + MCP
βββ π build/ # Compiled JavaScript output
βββ π¦ package.json # Dependencies & scripts
βββ βοΈ tsconfig.json # TypeScript configuration
βββ π README.md # You are here!
```
---
## π οΈ Tech Stack
<div align="center">
| Technology | Role |
|:---:|:---|
| <img src="https://img.shields.io/badge/-TypeScript-3178C6?logo=typescript&logoColor=white&style=for-the-badge" height="28" /> | Core language with strict type safety |
| <img src="https://img.shields.io/badge/-MCP%20SDK-6C63FF?style=for-the-badge" height="28" /> | Model Context Protocol server framework |
| <img src="https://img.shields.io/badge/-Playwright-2EAD33?logo=playwright&logoColor=white&style=for-the-badge" height="28" /> | Headless browser automation & screenshots |
| <img src="https://img.shields.io/badge/-Judge0-E34F26?style=for-the-badge" height="28" /> | Sandboxed multi-language code execution |
| <img src="https://img.shields.io/badge/-Axios-5A29E4?logo=axios&logoColor=white&style=for-the-badge" height="28" /> | HTTP client for Codebox API |
| <img src="https://img.shields.io/badge/-Zod-3E67B1?logo=zod&logoColor=white&style=for-the-badge" height="28" /> | Runtime schema validation |
</div>
---
## π€ Contributing
Contributions are welcome! Here's how to get started:
1. **Fork** the repository
2. **Create** a feature branch (`git checkout -b feature/amazing-feature`)
3. **Commit** your changes (`git commit -m 'Add amazing feature'`)
4. **Push** to the branch (`git push origin feature/amazing-feature`)
5. **Open** a Pull Request
---
## π License
This project is licensed under the **MIT License** β see the [LICENSE](LICENSE) file for details.
---
<div align="center">
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:6C63FF,50:A855F7,100:EC4899&height=120§ion=footer&animation=fadeIn" width="100%" alt="Footer"/>
<br/>
**Built with β€οΈ by [Iqbal](https://github.com/IqbalHere)**
<br/>
<a href="https://github.com/IqbalHere/-Visual-Loop-MCP-Server/stargazers">
<img src="https://img.shields.io/github/stars/IqbalHere/-Visual-Loop-MCP-Server?style=social" alt="GitHub Stars" />
</a>
<a href="https://github.com/IqbalHere/-Visual-Loop-MCP-Server/network/members">
<img src="https://img.shields.io/github/forks/IqbalHere/-Visual-Loop-MCP-Server?style=social" alt="GitHub Forks" />
</a>
<a href="https://github.com/IqbalHere/-Visual-Loop-MCP-Server/issues">
<img src="https://img.shields.io/github/issues/IqbalHere/-Visual-Loop-MCP-Server?style=social" alt="GitHub Issues" />
</a>
<br/><br/>
β **Star this repo if you found it useful!** β
</div>
TDQS
A4.1/5.0
Scored across 1 tool
Disambiguation5/5
Only one tool exists, so there is no possibility of ambiguity or confusion with other tools.
Naming Consistency5/5
With a single tool, naming consistency is not a concern; the name 'execute_and_render' clearly describes its function.
Tool Count3/5
One tool is on the lower end of reasonable count, but it serves a specific combined purpose of execution and rendering, which may justify the minimal surface.
Completeness3/5
The single tool covers both code execution and visual rendering, but lacks separate tools for execution-only or rendering-only tasks, limiting flexibility.
Maintenance
ActivityStale
ResponsivenessNo issues