feat: add browser_console MCP tool for frontend error capture

This commit is contained in:
2026-05-07 12:45:30 -07:00
parent 87577e69a4
commit dc60e1fdf5
9 changed files with 22038 additions and 52 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

159
mcp-zed-adapter.js Executable file
View File

@@ -0,0 +1,159 @@
#!/usr/bin/env node
/**
* Vibn MCP Adapter for Zed
*
* This script runs locally as a standard stdio MCP server for Zed.
* It intercepts tool calls and forwards them over HTTP to the Vibn API
* using the proprietary format that Vibn expects.
*/
const { Server } = require("@modelcontextprotocol/sdk/server/index.js");
const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
const { CallToolRequestSchema, ListToolsRequestSchema } = require("@modelcontextprotocol/sdk/types.js");
// Configuration from environment variables
const VIBN_API_URL = process.env.VIBN_API_URL || "https://vibnai.com/api/mcp";
const VIBN_API_KEY = process.env.VIBN_API_KEY;
if (!VIBN_API_KEY) {
console.error("Missing VIBN_API_KEY environment variable.");
process.exit(1);
}
// Create the MCP server
const server = new Server(
{
name: "vibn-zed-adapter",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
let cachedTools = null;
// Fetch the tool list from the Vibn API
async function fetchTools() {
if (cachedTools) return cachedTools;
try {
const response = await fetch(VIBN_API_URL, {
method: "GET",
headers: {
Authorization: \`Bearer \${VIBN_API_KEY}\`,
},
});
if (!response.ok) {
throw new Error(\`Failed to fetch tools: \${response.statusText}\`);
}
const data = await response.json();
// We need to fetch the actual tool schemas since the GET endpoint
// only returns a string array of tool names.
// For this adapter, we define the schema passthrough.
// Note: Since Vibn's GET /api/mcp only returns an array of names:
// "available": ["workspace.describe", "gitea.credentials", ...]
// We will construct basic MCP tool definitions for them.
// In a production scenario, you would expose the JSON schemas on the GET endpoint.
const available = data.capabilities?.tools?.available || [];
cachedTools = available.map(name => ({
name: name,
description: \`Vibn workspace tool: \${name}\`,
inputSchema: {
type: "object",
properties: {
// Accept any parameters generically for the proxy
projectId: { type: "string", description: "Vibn project ID" },
},
additionalProperties: true
}
}));
return cachedTools;
} catch (error) {
console.error("Error fetching tools:", error);
return [];
}
}
// Handle List Tools Request
server.setRequestHandler(ListToolsRequestSchema, async () => {
const tools = await fetchTools();
return {
tools: tools,
};
});
// Handle Call Tool Request
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
// Forward the request to Vibn API
const response = await fetch(VIBN_API_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: \`Bearer \${VIBN_API_KEY}\`,
},
body: JSON.stringify({
tool: name, // Vibn's expected format
params: args || {},
}),
});
const data = await response.json();
if (!response.ok) {
return {
content: [
{
type: "text",
text: \`Error (\${response.status}): \${JSON.stringify(data.error || data)}\`,
},
],
isError: true,
};
}
return {
content: [
{
type: "text",
text: JSON.stringify(data.result || data, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: \`Internal Adapter Error: \${error.message}\`,
},
],
isError: true,
};
}
});
// Start the server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Vibn Zed MCP Adapter running on stdio");
}
main().catch((error) => {
console.error("Fatal error:", error);
process.exit(1);
});

29
mcp-zed.md Normal file
View File

@@ -0,0 +1,29 @@
local
{
/// Configure an MCP server that runs locally via stdin/stdout
///
/// The name of your MCP server
"some-mcp-server": {
/// The command which runs the MCP server
"command": ,
/// The arguments to pass to the MCP server
"args": [],
/// The environment variables to set
"env": {}
}
}
remote
{
/// Configure an MCP server that you connect to over HTTP
///
/// The name of your remote MCP server
"some-remote-server": {
/// The URL of the remote MCP server
"url": "https://example.com/mcp",
"headers": {
/// Any headers to send along
// "Authorization": "Bearer <token>
}
}
}

View File

@@ -1,13 +1,7 @@
# vibn-dev — per-project AI development container.
#
# Goal: a small, fast-pulling base image (~500 MB target) that gives the AI
# (and the user, eventually) a real shell with git, ripgrep, and the
# scaffolding to lazy-install language toolchains via mise on first use.
#
# Heavy toolchains (Node / Python / Go / Rust) are NOT baked in — they
# install on demand via `mise install` the first time the AI runs
# `npm`, `python`, `go`, etc. This keeps the base image lean and lets us
# bump toolchain versions without rebuilding the image.
# Ships with Node.js (LTS), Python 3.12, and Go 1.23 pre-installed so the AI
# can start running code immediately without a mise install step.
#
# Spec is in AI_PATH_B_EXECUTION_PLAN.md §3.
@@ -18,55 +12,50 @@ ENV DEBIAN_FRONTEND=noninteractive \
LC_ALL=C.UTF-8 \
TZ=UTC
# Core OS packages: shell, git, network, build essentials, ripgrep
# (powers fs.grep), tini (PID 1 reaper), supervisord (process supervisor
# for sshd + dev servers), curl/ca-certs (downloads), unzip (mise
# tarballs), sudo (toolchain installers expect it).
# Core OS packages + shell/git/ripgrep/tini/supervisor.
# Language toolchains installed below.
RUN apt-get update && apt-get install -y --no-install-recommends \
bash coreutils ca-certificates curl wget git openssh-client \
ripgrep jq nano vim less procps lsof net-tools dnsutils \
build-essential pkg-config \
sudo tini supervisor unzip xz-utils \
python3-minimal \
python3 python3-pip python3-venv \
&& rm -rf /var/lib/apt/lists/*
# Playwright System Dependencies (for headless Chromium)
RUN apt-get update && apt-get install -y --no-install-recommends \
libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 \
libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \
libgbm1 libasound2t64 libpangocairo-1.0-0 libpango-1.0-0 libcairo2 \
&& rm -rf /var/lib/apt/lists/*
# Node.js LTS (via NodeSource)
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# Go 1.23 — scrape latest patch version from go.dev/dl
RUN GO_TAR=$(curl -fsSL https://go.dev/dl/ | grep -oE 'go1\.23\.[0-9]+\.linux-amd64\.tar\.gz' | head -1) \
&& curl -fsSL "https://go.dev/dl/${GO_TAR}" | tar -C /usr/local -xz \
&& echo 'export PATH=/usr/local/go/bin:$PATH' >> /etc/profile.d/go.sh
# vibn user — the AI runs as this, NOT root.
# Ubuntu 24.04 base image preallocates a default `ubuntu` user at uid 1000;
# delete it first so we can claim 1000 for vibn (matches the docker exec
# `--user vibn` calls in lib/coolify-exec.ts and the workspace volume's
# default ownership in the compose template).
RUN userdel -r ubuntu 2>/dev/null || true \
&& useradd --create-home --shell /bin/bash --uid 1000 vibn \
&& mkdir -p /workspace /home/vibn/.cache /home/vibn/.local /var/log/vibn-dev \
&& chown -R vibn:vibn /workspace /home/vibn /var/log/vibn-dev \
&& echo 'vibn ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/vibn
# mise — polyglot version manager. Installs Node/Python/Go/Rust on demand.
# Pinned to a specific version for reproducibility; bump in this Dockerfile.
ENV MISE_VERSION=v2024.12.14
RUN curl -fsSL "https://mise.run" | MISE_VERSION=${MISE_VERSION} sh \
&& mv /root/.local/bin/mise /usr/local/bin/mise \
&& chmod +x /usr/local/bin/mise
# Hook mise into vibn's shell so `node`, `python` etc. resolve once
# installed via `mise install`.
RUN echo 'eval "$(/usr/local/bin/mise activate bash)"' >> /home/vibn/.bashrc \
# Toolchain env for vibn user
RUN echo 'export PATH=/usr/local/go/bin:$PATH' >> /home/vibn/.bashrc \
&& echo 'export PATH="$HOME/.local/bin:$PATH"' >> /home/vibn/.bashrc
# Default mise toolchain config — lazily materialised. The AI can
# override per-project by writing /workspace/.mise.toml.
COPY --chown=vibn:vibn mise.default.toml /home/vibn/.config/mise/config.toml
# supervisord runs sshd-less; we don't need ssh in the container because
# all exec happens via `docker exec` from the Coolify host. Supervisord
# is reserved for dev_server.* (Vite/Next/etc) once that ships.
COPY supervisord.conf /etc/supervisor/conf.d/vibn-dev.conf
WORKDIR /workspace
USER vibn
# Keep-alive process. The container's job is to exist; commands run via
# `docker exec`. tail -f /dev/null is the canonical "stay running, do
# nothing" pattern — cheaper than supervisord for the no-dev-server case.
# Keep-alive. Commands run via docker exec.
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["tail", "-f", "/dev/null"]

View File

@@ -1,7 +1,7 @@
# vibn-dev
Per-project AI development container. One of these runs in Coolify per
Vibn project; the AI agent (Gemini) drives it via `shell.exec` and
Vibn project; the AI agent drives it via `shell.exec` and
`fs.*` MCP tools.
See `/AI_PATH_B_EXECUTION_PLAN.md` for the architecture.
@@ -9,26 +9,36 @@ See `/AI_PATH_B_EXECUTION_PLAN.md` for the architecture.
## Build & publish
```bash
docker build -t registry.vibnai.com/vibn-dev:latest .
docker push registry.vibnai.com/vibn-dev:latest
docker buildx build --platform linux/amd64 -t ghcr.io/vibnai/vibn-dev:latest --push .
```
The image is pre-pulled on every Coolify host on deploy so first-use
spin-up stays under 5 seconds.
## Smoke test locally
## Smoke test locally (requires Docker with QEMU for cross-platform)
```bash
docker build -t vibn-dev .
docker buildx build --platform linux/amd64 -t vibn-dev --load .
docker run --rm -it -v "$PWD/scratch:/workspace" vibn-dev bash
# inside: mise install # pulls Node lts + Python 3.12 (~90s, one-time)
# inside: rg --version # ripgrep ships in the base image
# inside: node --version # Node LTS ships in the image
# inside: npm --version
# inside: python3 --version
# inside: go version
# inside: rg --version # ripgrep ships in the image
# inside: git --version
```
## What's in the image
- Node.js LTS (via NodeSource)
- Python 3.12 + pip + venv
- Go 1.23
- ripgrep, git, build-essential, jq, curl, nano, vim
- supervisord (reserved for future dev_server use)
- tini (PID 1 reaper)
## What's NOT in the image (by design)
- Node/Python/Go/Rust toolchains — lazy-installed via mise
- Coolify control-plane creds — never. The container has no route to
internal Vibn services (Docker network policy enforced at host level)
- SSH server — exec happens via `docker exec` from the Coolify host

View File

@@ -1,6 +0,0 @@
# Default toolchain hints for vibn-dev. Nothing is installed until the
# AI (or the user) runs `mise install`. Override per-project by writing
# /workspace/.mise.toml — mise auto-loads the closest config.
[tools]
node = "lts"
python = "3.12"

Submodule vibn-frontend updated: 19f284f464...fa9cfda712