Package Exports
- @everkers/agent-eyes
- @everkers/agent-eyes/vite
Readme
AgentEyes
Give your AI coding agent eyes into your running app.
AgentEyes streams console logs, network requests, DOM snapshots, errors, performance metrics, React component renders, and screenshots from your browser — directly to your coding agent over MCP.
Dev-only by default. In production, AgentEyes is completely inert — no monkey-patching, no WebSocket connections, zero overhead.
How it works
┌──────────────┐ WebSocket ┌──────────────┐ stdio/MCP ┌──────────────┐
│ Your App │ ──────────────> │ AgentEyes │ <────────────> │ Any Agent │
│ (browser) │ events stream │ MCP Server │ tools/queries │ (Kiro, │
│ │ │ :9960 │ │ Cursor...) │
└──────────────┘ └──────────────┘ └──────────────┘Quick start
1. Add to your app
React (Provider component)
import { AgentEyesProvider } from '@everkers/agent-eyes';
function App() {
return (
<AgentEyesProvider config={{ mcpBridge: true }}>
<YourApp />
</AgentEyesProvider>
);
}Vite (Plugin — zero app code)
// vite.config.ts
import { agentEyesPlugin } from '@everkers/agent-eyes/vite';
export default defineConfig({ plugins: [agentEyesPlugin()] });Next.js (Client component wrapper)
// app/agent-eyes-provider.tsx
"use client";
import { AgentEyesProvider } from "@everkers/agent-eyes";
export default function AgentEyesWrapper({ children }: { children: React.ReactNode }) {
return (
<AgentEyesProvider config={{ mcpBridge: true }}>
{children}
</AgentEyesProvider>
);
}
// app/layout.tsx
import AgentEyesWrapper from "./agent-eyes-provider";
export default function RootLayout({ children }) {
return (
<html><body><AgentEyesWrapper>{children}</AgentEyesWrapper></body></html>
);
}Vanilla (no framework)
import { AgentEyes } from '@everkers/agent-eyes';
const eyes = new AgentEyes({ mcpBridge: true });
eyes.start();2. Configure your agent's MCP
Add to your MCP config (.kiro/settings/mcp.json, .cursor/mcp.json, claude_desktop_config.json):
{
"mcpServers": {
"agent-eyes": {
"command": "npx",
"args": ["@everkers/agent-eyes"]
}
}
}That's it. Your agent can now see your app.
Examples
See the examples/ directory for complete working apps:
| Example | Setup | Description |
|---|---|---|
examples/react |
AgentEyesProvider |
React app using the provider component |
examples/vite |
agentEyesPlugin() |
Vite app with zero-config plugin auto-injection |
examples/nextjs |
"use client" wrapper |
Next.js App Router with client component provider |
To run any example:
cd examples/react # or vite, nextjs
npm install
npm run devMCP Tools
| Tool | Description |
|---|---|
get_console_logs |
Console log/warn/error/debug/info with args and stack traces. Filter by level. |
get_network_requests |
Fetch & XHR with headers, bodies, status, timing. Filter by method, status, URL. |
get_errors |
Runtime errors and unhandled promise rejections with stack traces. |
get_dom_snapshot |
Simplified DOM snapshot with semantic attributes (id, class, role, aria-label, data-testid). |
get_performance_metrics |
Core Web Vitals (FCP, LCP), load timing, memory usage. |
get_react_components |
Component names, props, and render counts. Filter by name. |
get_snapshot |
Full state dump — everything at once. |
get_failed_requests |
All failed network requests (status >= 400 or errors). |
take_screenshot |
Visual screenshot of the running app. Supports CSS selector targeting. |
get_status |
Connection status — connected browsers, event counts by type. |
clear_events |
Clear the event buffer. |
Production Safety
agent-eyes auto-detects the environment and is completely inert in production:
- Checks
import.meta.env.DEV(Vite),process.env.NODE_ENV(CRA/Next.js), and localhost hostname - No console/fetch/XHR monkey-patching in production
- No WebSocket connections
- All methods return empty data — zero runtime overhead
Configuration
Basic
const eyes = new AgentEyes({
maxBufferSize: 500, // max events in memory (default: 500)
enabled: true, // force enable/disable (auto-detects by default)
mcpBridge: true, // connect to MCP server at ws://localhost:9960
redactPatterns: ['authorization', 'cookie', 'token', 'password'],
filter: (event) => true, // drop events before they enter the buffer
onEvent: (event) => {}, // callback for every captured event
collectors: {
console: true,
network: true,
errors: true,
dom: true,
performance: true,
reactComponents: false, // opt-in (needs React DevTools hook)
},
});Granular Collector Options
const eyes = new AgentEyes({
mcpBridge: true,
// Console
console: {
levels: ['warn', 'error'], // only capture these levels
maxArgLength: 5000, // truncate serialized args
stackTraceAll: false, // stack traces for all levels, not just errors
},
// Network
network: {
methods: ['GET', 'POST'], // only capture these HTTP methods
captureRequestHeaders: true,
captureResponseHeaders: true,
captureRequestBody: true,
captureResponseBody: true,
maxBodySize: 10000, // truncate large bodies
ignorePatterns: ['/analytics', /hot-update/],
},
// DOM
dom: {
maxDepth: 8, // how deep to traverse the tree
debounceMs: 1000, // debounce mutation-triggered snapshots
disableAutoSnapshot: false, // disable auto-snapshots on mutations
extraAttributes: ['data-cy', 'data-automation-id'],
},
// Performance
performance: {
disableLCP: false,
disableMemory: false,
},
// React Components (opt-in)
reactComponents: {
includeNames: [/^App/, 'Header'], // only track matching components
excludeNames: [/^Styled/], // skip these
captureProps: true,
maxPropsDepth: 2,
},
});Vite Plugin Options
agentEyesPlugin({
devOnly: true, // only inject in dev mode (default: true)
inject: true, // auto-inject script tag (default: true)
mcpBridge: true, // connect to MCP bridge (default: true)
redactPatterns: ['authorization', 'cookie'],
})Environment Variables
| Variable | Default | Description |
|---|---|---|
AGENT_EYES_PORT |
9960 |
WebSocket port for the MCP server |
Set it in your MCP config:
{
"mcpServers": {
"agent-eyes": {
"command": "npx",
"args": ["@everkers/agent-eyes"],
"env": {
"AGENT_EYES_PORT": "8888"
}
}
}
}Then point the client to the same port:
const eyes = new AgentEyes({ mcpBridge: 'ws://localhost:8888' });Security
- Sensitive headers and body fields are redacted when
redactPatternsis set - Patterns match against header names and JSON keys (case-insensitive)
- The WebSocket server only binds to localhost — not accessible from the network
- No data leaves your machine. Everything stays between browser ↔ MCP server ↔ agent
- In production, nothing runs at all
React Hooks
import { useAgentEyes, useAgentEvents, useAgentSnapshot } from '@everkers/agent-eyes';
function DevPanel() {
const eyes = useAgentEyes(); // the AgentEyes instance
const errors = useAgentEvents('error'); // live-updating error list
const snapshot = useAgentSnapshot(); // full state snapshot
return <pre>{JSON.stringify(snapshot, null, 2)}</pre>;
}How It Works
AgentEyesmonkey-patchesconsole.*,fetch, andXMLHttpRequestto capture events- A
MutationObserverwatches the DOM for structural changes PerformanceObservertracks Core Web Vitals and memory- Events stream over WebSocket to the MCP server process
- The MCP server exposes tools over stdio that any agent can call
- Screenshots use
html2canvas— the MCP server sends a request to the browser, which renders and returns the image
License
MIT