@evercam/mcp
v0.0.7
Published
MCP server + CLI for Evercam — cameras, AI, copilot, analytics
Readme
evercam-mcp
MCP (Model Context Protocol) server + CLI for the Evercam platform.
Talk to your cameras, AI analytics, copilot, and gate reports — from Claude, Cursor, scripts, or any MCP client.
What is this?
@evercam/mcp exposes the full Evercam platform as AI-callable tools via the Model Context Protocol. It wraps three Evercam backends through a single interface:
| Backend | URL | Features |
| ------------------- | --------------------- | -------------------------------------------------------- |
| evercam-backend | media.evercam.io/v2 | Cameras, projects, snapshots, BIM, timelapses, media hub |
| evercam-labs | labs.evercam.io | AI Copilot, presence detection, luminance, heatmaps |
| evercam-ai | data.evercam.io | ANPR, gate reports, smart search, site analytics |
Built on @evercam/sdk — no custom HTTP clients, no vendored types.
Table of Contents
- Installation
- Authentication
- Quickstart (HTTP + REST tools)
- CLI Reference
- Use with Claude Desktop
- Use with Claude Code
- Use with Codex
- Use with Cursor
- Use with Windsurf
- Use with Zed
- Use with Continue.dev
- Use with Cline
- Use with Goose
- Streamable HTTP Server
- Use as a Node.js Library
- All Tools
- Profiles & Multi-environment
- Environment Variables
- Architecture
- Development
- Publishing
Installation
Global install (recommended):
npm install -g @evercam/mcp
# or
pnpm add -g @evercam/mcpWithout installing (npx):
npx @evercam/mcp <command>Note: npx evercam-mcp <command> will not work unless an unscoped evercam-mcp package is published.
From source:
git clone [email protected]:evercam/evercam-mcp.git
cd evercam-mcp
pnpm install
pnpm -C packages/evercam-mcp buildAuthentication
Login with your Evercam credentials:
evercam-mcp auth login
# Username or email: [email protected]
# Password: ••••••••
# ✓ Logged in successfully (profile: default)Token is stored securely in ~/.evercam/tokens.json (chmod 0600) and reused on every subsequent command.
For local Claude/ChatGPT MCP usage, EVERCAM_TOKEN is not required after auth login on the same machine.
Note: the SDK currently has no token refresh endpoint; when a token expires, run evercam-mcp auth relogin.
evercam-mcp auth status # Check current login state
evercam-mcp auth logout # Clear stored token
evercam-mcp auth relogin # Re-authenticate and replace stored tokenAlternatively, skip the login flow entirely using an environment variable:
EVERCAM_TOKEN=your-token evercam-mcp serveUse EVERCAM_TOKEN when running in CI, Docker, remote hosts, or shared machines where ~/.evercam/tokens.json is unavailable.
Quickstart (HTTP + REST tools)
# 1) Authenticate once (or set EVERCAM_TOKEN)
npx @evercam/mcp auth login
# 2) Start the HTTP server
npx @evercam/mcp serve --transport http --port 4004
# 3) List tools
curl http://localhost:4004/tools
# 4) Call a tool directly
curl -X POST http://localhost:4004/tools/list-cameras \
-H "Content-Type: application/json" \
-d '{}'CLI Reference
evercam-mcp <command> [options]auth
evercam-mcp auth login [--profile <name>] # Log in (prompts username + password)
evercam-mcp auth logout [--profile <name>] # Log out
evercam-mcp auth relogin [--profile <name>] # Re-authenticate and replace token
evercam-mcp auth status [--profile <name>] # Show login state + masked tokenprofile
evercam-mcp profile list # List all profiles (active marked ●)
evercam-mcp profile add <name> [options] # Add a new profile
--base-url <url> # Override backend URL
--ai-url <url> # Override AI API URL
--labs-url <url> # Override Labs URL
--ingest-url <url> # Override Ingest URL
evercam-mcp profile switch <name> # Switch active profiletools
evercam-mcp tools list # Show all tools grouped by domainrun
Call any tool directly from the shell. Arguments are passed as key=value pairs.
evercam-mcp run <tool-name> [key=value ...] [--profile <name>]Examples:
evercam-mcp run list-cameras
evercam-mcp run get-camera cameraExid=roof-cam
evercam-mcp run list-projects
evercam-mcp run get-gate-report-events \
projectExid=site-abc \
fromDate=2024-01-01T00:00:00Z \
toDate=2024-01-31T23:59:59Z
evercam-mcp run list-anpr-events projectExid=site-abc plate=ABC123
evercam-mcp run smart-search projectExid=site-abc labels='["person","car"]'
evercam-mcp run list-copilot-conversations page=1 limit=10
evercam-mcp run get-presence-intervals \
cameraExid=roof-cam \
fromDate=2024-01-15T00:00:00Z \
toDate=2024-01-15T23:59:59Zserve
Start the MCP server.
evercam-mcp serve # stdio transport (default)
evercam-mcp serve --transport http # Streamable HTTP transport
evercam-mcp serve --transport http --port 4004
evercam-mcp serve --profile staging # Use a specific profile
evercam-mcp serve --allowed-origins https://app.example.com
evercam-mcp serve --timeout 60000 # Tool timeout in ms
evercam-mcp serve --api-key $MCP_API_KEY # Require ApiKey auth on HTTP endpoints
evercam-mcp serve --allowed-tools list-cameras,get-camera
evercam-mcp serve --denied-tools delete-progress-photo
evercam-mcp serve --enable-rate-limit # Enable HTTP REST rate limiting (disabled by default)
evercam-mcp serve --enable-rate-limit --rate-limit 120
evercam-mcp serve --enable-mutations # Allow create/update/delete/action toolsUse with Claude Desktop
1. Log in:
npx @evercam/mcp auth login2. Add to Claude Desktop config:
- Linux:
~/.config/Claude/claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"evercam": {
"command": "npx",
"args": ["-y", "@evercam/mcp", "serve"]
}
}
}Or with an explicit token (useful for CI or shared machines):
{
"mcpServers": {
"evercam": {
"command": "npx",
"args": ["-y", "@evercam/mcp", "serve"],
"env": {
"EVERCAM_TOKEN": "your-token-here"
}
}
}
}3. Restart Claude Desktop.
You can now ask Claude things like:
"Which cameras are offline right now?"
"Show gate report events for project abc from last week"
"How many vehicles were detected at the main gate yesterday?"
"Create a timelapse for camera roof-cam for all of January"
"Search for persons in project abc between 9am and 5pm today"
"List my last Copilot conversations"
"What days in March had recordings on camera roof-cam?"
Claude will call the right tools, chain results, and reason over them.
Use with Claude Code
1. Log in:
npx @evercam/mcp auth login2. Add the MCP server via CLI:
claude mcp add evercam -- npx -y @evercam/mcp serveOr add manually to ~/.claude/settings.json:
{
"mcpServers": {
"evercam": {
"command": "npx",
"args": ["-y", "@evercam/mcp", "serve"]
}
}
}With an explicit token:
{
"mcpServers": {
"evercam": {
"command": "npx",
"args": ["-y", "@evercam/mcp", "serve"],
"env": {
"EVERCAM_TOKEN": "your-token-here"
}
}
}
}3. Verify tools are loaded:
claude mcp list
# evercam: npx -y @evercam/mcp serveClaude Code can now call all Evercam tools while you code — pull real camera exids, fetch live API shapes for type generation, or check gate report data without leaving the terminal.
Use with Codex
1. Log in:
npx @evercam/mcp auth login2. Add to ~/.codex/config.toml:
[[mcp_servers]]
name = "evercam"
command = "npx"
args = ["-y", "@evercam/mcp", "serve"]With an explicit token:
[[mcp_servers]]
name = "evercam"
command = "npx"
args = ["-y", "@evercam/mcp", "serve"]
[mcp_servers.env]
EVERCAM_TOKEN = "your-token-here"Use with Cursor
Add to .cursor/mcp.json at your project root:
{
"mcpServers": {
"evercam": {
"command": "npx",
"args": ["-y", "@evercam/mcp", "serve"]
}
}
}While coding, Cursor can:
- Pull real camera/project exids to use in tests instead of fake placeholders
- Fetch actual API response shapes to generate correct TypeScript types
- Verify fixes against real gate report data without leaving the editor
Use with Windsurf
1. Log in:
npx @evercam/mcp auth login2. Add to Windsurf MCP config:
Global (~/.windsurf/mcp.json) or project-level (.windsurf/mcp.json):
{
"mcpServers": {
"evercam": {
"command": "npx",
"args": ["-y", "@evercam/mcp", "serve"]
}
}
}3. Reload Windsurf. The Evercam tools will appear in the Cascade agent tool list.
Use with Zed
1. Log in:
npx @evercam/mcp auth login2. Add to ~/.config/zed/settings.json:
{
"context_servers": {
"evercam": {
"command": {
"path": "npx",
"args": ["-y", "@evercam/mcp", "serve"]
},
"settings": {}
}
}
}With an explicit token:
{
"context_servers": {
"evercam": {
"command": {
"path": "npx",
"args": ["-y", "@evercam/mcp", "serve"],
"env": {
"EVERCAM_TOKEN": "your-token-here"
}
},
"settings": {}
}
}
}3. Evercam tools become available as slash commands and in the Agent panel.
Use with Continue.dev
1. Log in:
npx @evercam/mcp auth login2. Add to ~/.continue/config.yaml:
mcpServers:
- name: evercam
command: npx
args:
- -y
- "@evercam/mcp"
- serveWith an explicit token:
mcpServers:
- name: evercam
command: npx
args:
- -y
- "@evercam/mcp"
- serve
env:
EVERCAM_TOKEN: your-token-here3. Reload VS Code / JetBrains. The @evercam context provider and tools will be available in the Continue chat panel.
Use with Cline
1. Log in:
npx @evercam/mcp auth login2. Open VS Code → Cline extension → click MCP Servers → Edit MCP Settings.
Add to the settings JSON:
{
"evercam": {
"command": "npx",
"args": ["-y", "@evercam/mcp", "serve"],
"disabled": false,
"autoApprove": []
}
}With an explicit token:
{
"evercam": {
"command": "npx",
"args": ["-y", "@evercam/mcp", "serve"],
"env": {
"EVERCAM_TOKEN": "your-token-here"
},
"disabled": false,
"autoApprove": []
}
}3. The server connects automatically. You'll see a green indicator next to evercam in the MCP Servers list.
Use with Goose
1. Log in:
npx @evercam/mcp auth login2. Add to ~/.config/goose/config.yaml:
extensions:
evercam:
name: evercam
type: stdio
cmd: npx
args:
- -y
- "@evercam/mcp"
- serve
enabled: trueWith an explicit token:
extensions:
evercam:
name: evercam
type: stdio
cmd: npx
args:
- -y
- "@evercam/mcp"
- serve
envs:
EVERCAM_TOKEN: your-token-here
enabled: trueOr via CLI:
goose mcp add evercam --command "npx -y @evercam/mcp serve"Streamable HTTP Server
Run as a persistent HTTP server instead of a stdio subprocess. This is useful for:
- Remote deployments (server, Docker)
- Connecting multiple clients simultaneously
- Integrating with evercam-labs or other services over the network
evercam-mcp serve --transport http --port 4004
# Evercam MCP server listening on http://localhost:4004
# MCP endpoint: ALL http://localhost:4004/mcpHTTP endpoints
| Endpoint | Method | Description |
| ----------------------- | ------ | ----------------------------------------------- |
| /health | GET | Health check { status: "ok", tools: <count> } |
| /tools | GET | List all tools (name, description, inputSchema) |
| /tools/:toolName | POST | Call a tool directly with JSON args |
| /snapshot/:cameraExid | GET | Authenticated latest snapshot proxy |
| /mcp | ALL | Streamable HTTP MCP endpoint |
Authorization header: For REST tool calls, you can pass Authorization: Bearer <token> to override the server token for that request.
How it works
Client evercam-mcp HTTP server
│ │
├── POST /mcp (initialize) ───────────────►│ Creates session
│◄── sessionId ───────────────────────────┤ Server returns sessionId
│ │
├── GET /mcp (SSE stream) ────────────────►│ Opens persistent SSE stream
│ │
├── POST /mcp (tool call) ────────────────►│ Send tool call
│◄── result (via SSE stream) ─────────────┤ Server streams response backConnect Claude Desktop to a remote server
{
"mcpServers": {
"evercam": {
"url": "http://your-server:4004/mcp"
}
}
}Connect from Node.js (evercam-labs / custom service)
import { Client } from "@modelcontextprotocol/sdk/client/index.js"
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"
const client = new Client({ name: "my-app", version: "1.0.0" })
const transport = new StreamableHTTPClientTransport(new URL("http://localhost:4004/mcp"))
await client.connect(transport)
// Call any evercam-mcp tool
const result = await client.callTool("list-cameras", {})
const cameras = await client.callTool("smart-search", {
projectExid: "site-abc",
labels: ["person", "car"],
fromDate: "2024-01-15T09:00:00Z",
toDate: "2024-01-15T17:00:00Z",
})Call a tool without MCP
curl -X POST http://localhost:4004/tools/get-camera \
-H "Content-Type: application/json" \
-d '{"cameraExid":"roof-cam"}'Docker
FROM node:22-alpine
RUN npm install -g @evercam/mcp
EXPOSE 4004
CMD ["evercam-mcp", "serve", "--transport", "http", "--port", "4004"]docker run -e EVERCAM_TOKEN=your-token -p 4004:4004 evercam-mcpMultiple environments simultaneously
EVERCAM_TOKEN=$PROD_TOKEN evercam-mcp serve --transport http --port 4004
EVERCAM_TOKEN=$STAGING_TOKEN evercam-mcp serve --transport http --port 4002Note: MCP sessions share the server’s base Evercam identity. REST tool calls can override per-request using the
Authorizationheader.
Use as a Node.js Library
Install as a dependency:
pnpm add @evercam/mcpWith a token:
import { createEvercamMcpServer, startHttp } from "@evercam/mcp"
const { server, evercam } = await createEvercamMcpServer({
credentials: { token: process.env.EVERCAM_TOKEN },
})
await startHttp(server, evercam, 4004)With username/password:
import { createEvercamMcpServer, startStdio } from "@evercam/mcp"
const { server } = await createEvercamMcpServer({
credentials: {
username: "[email protected]",
password: "your-password",
},
})
await startStdio(server)With custom URLs (staging, local dev):
import { createEvercamMcpServer } from "@evercam/mcp"
const { server, evercam } = await createEvercamMcpServer({
credentials: { token: process.env.EVERCAM_TOKEN },
baseUrls: {
baseUrl: "https://staging.evercam.io/v2",
aiApiUrl: "https://staging-data.evercam.io",
evercamLabsUrl: "https://staging-labs.evercam.io",
},
})All Tools
Cameras
| Tool | Description | Required | Optional |
| --------------- | --------------------------- | ------------ | ------------------------------ |
| list-cameras | List all accessible cameras | — | projectExid, page, limit |
| get-camera | Get camera details | cameraExid | — |
| update-camera | Update camera properties | cameraExid | name, isOnline, timezone |
Snapshots
| Tool | Description | Required | Optional |
| ----------------------- | ------------------------------------ | ----------------------------- | -------- |
| get-live-snapshot-url | Get live snapshot URL | cameraExid | — |
| get-snapshot-at | Get snapshot nearest to timestamp | cameraExid, timestamp | — |
| get-latest-snapshot | Get most recent snapshot | cameraExid | — |
| get-oldest-snapshot | Get oldest snapshot | cameraExid | — |
| list-available-days | List days with recordings in a month | cameraExid, year, month | — |
Projects
| Tool | Description | Required | Optional |
| ---------------------- | ---------------------------- | ------------- | -------- |
| list-projects | List all accessible projects | — | — |
| list-project-cameras | List cameras in a project | projectExid | — |
| list-project-users | List users in a project | projectExid | — |
| list-project-members | List members with roles | projectExid | — |
Media
| Tool | Description | Required | Optional |
| ------------------ | ---------------------------- | ------------------------------------------------- | --------------- |
| list-timelapses | List timelapses for a camera | cameraExid, fromDate, toDate | — |
| create-timelapse | Create a timelapse | projectExid, cameraExid, fromDate, toDate | title |
| list-media-hub | List clips in the media hub | projectExid | page, limit |
BIM
| Tool | Description | Required | Optional |
| ------------------ | ----------------------------- | ------------------------- | -------- |
| list-bim-layers | List BIM layers for a camera | cameraExid | — |
| get-bim-snapshot | Get BIM snapshot at timestamp | cameraExid, timestamp | — |
| get-bim-model | Get BIM model info | cameraExid | — |
Copilot
| Tool | Description | Required | Optional |
| ---------------------------- | ------------------------------- | --------------------------------------- | -------------------------------------------- |
| list-copilot-conversations | List AI Copilot conversations | — | page, limit, projectExid, cameraExid |
| get-copilot-conversation | Get a conversation by ID | conversationId | — |
| list-copilot-messages | List messages in a conversation | conversationId | page, limit |
| send-copilot-message | Send a message | conversationId, message | — |
| submit-copilot-feedback | Submit message feedback | conversationId, messageId, rating | comment |
rating accepts "positive" or "negative".
Detections
| Tool | Description | Required | Optional |
| -------------------------------------- | ---------------------------- | ---------------------------------- | --------------------------- |
| get-presence-intervals | Presence detection intervals | cameraExid, fromDate, toDate | — |
| get-luminance-readings | Light level readings | cameraExid, fromDate, toDate | — |
| get-site-analytics-processing-status | Processing status | — | projectExid, cameraExid |
| get-heatmap-intersections | Heatmap intersection data | cameraExid, fromDate, toDate | — |
ANPR / Gate Report
| Tool | Description | Required | Optional |
| ------------------------ | -------------------------------- | ----------------------------------- | ------------------------------------------------------------ |
| list-anpr-events | License plate recognition events | projectExid | fromDate, toDate, cameraExid, plate, page, limit |
| get-gate-report-events | Gate report events | projectExid, fromDate, toDate | cameraExid, page, limit |
| list-verified-days | Verified gate report days | projectExid | fromDate, toDate |
| list-rois | ROI configurations | projectExid | cameraExid |
Site Analytics
| Tool | Description | Required | Optional |
| --------------------------- | ----------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------- |
| smart-search | Semantic/visual search over footage | projectExid | cameraExid, query, labels, fromDate, toDate, page, pageSize |
| list-smart-search-queries | Saved smart search queries | projectExid | — |
| get-detections-heatmap | Detection heatmap data | projectExid, cameraExid, fromDate, toDate, labels | — |
| get-gate-report-counts | Event count statistics | projectExid, fromDate, toDate | cameraExid |
Profiles & Multi-environment
Profiles let you switch between production, staging, and local environments without changing env vars.
# Add a staging profile
evercam-mcp profile add staging \
--base-url https://staging.evercam.io/v2 \
--ai-url https://staging-data.evercam.io \
--labs-url https://staging-labs.evercam.io
# Log in on staging
evercam-mcp auth login --profile staging
# List all profiles
evercam-mcp profile list
# ● default
# staging
# Switch active profile
evercam-mcp profile switch staging
# Or pass --profile to any command without switching
evercam-mcp run list-cameras --profile staging
evercam-mcp serve --profile stagingProfile config is stored in ~/.evercam/config.json. Tokens per profile in ~/.evercam/tokens.json.
Environment Variables
Environment variables take highest priority — they override both profile config and SDK defaults.
EVERCAM_BASE_URL, EVERCAM_AI_URL, EVERCAM_LABS_URL, and EVERCAM_INGEST_URL are optional. If omitted, the SDK uses production defaults.
| Variable | Default | Description |
| -------------------- | ----------------------------- | -------------------------------------- |
| EVERCAM_TOKEN | — | Auth token (skips login flow entirely) |
| EVERCAM_BASE_URL | https://media.evercam.io/v2 | Evercam backend URL |
| EVERCAM_AI_URL | https://data.evercam.io | Evercam AI API URL |
| EVERCAM_LABS_URL | https://labs.evercam.io | Evercam Labs URL |
| EVERCAM_INGEST_URL | https://ingest.evercam.io | Evercam Ingest URL |
| EVERCAM_PROFILE | default | Active profile name |
Copy .env.example to .env — it's loaded automatically on startup.
Architecture
┌─────────────────────────────────────┐
MCP Client │ evercam-mcp │
(Claude, Cursor, │ │
custom app) │ McpServer │
│ │ tools/cameras.ts │
│ MCP │ tools/snapshots.ts │
│ protocol │ tools/projects.ts │
▼ │ tools/media.ts │
┌─────────┐ │ tools/bim.ts │
│ stdio │ │ tools/copilot.ts │
│ or │ │ tools/detections.ts │
│ HTTP │ │ tools/anpr.ts │
│ stream │ │ tools/siteAnalytics.ts │
└────┬────┘ │ │ │
│ │ @evercam/sdk — Evercam class │
│ │ evercam.api ────────────────────►│──► media.evercam.io/v2
│ │ evercam.ai ────────────────────►│──► data.evercam.io
│ │ evercam.axios ───────────────────►│──► labs.evercam.io
└────────────┘ │
└──────────────────────Config resolution order
For each setting, priority is:
EVERCAM_TOKEN env var
→ ~/.evercam/tokens.json[activeProfile]
→ @evercam/sdk DEFAULT_BASE_URLSAuth flow
evercam-mcp auth login
1. Prompts username + password
2. new Evercam({ credentials: { username, password } }).connect()
→ POST media.evercam.io/v2/users/login
3. Stores returned token in ~/.evercam/tokens.json (chmod 0600)
On serve/run:
1. Reads EVERCAM_TOKEN env var OR ~/.evercam/tokens.json[profile]
2. new Evercam({ credentials: { token } }); evercam.setToken(token)Labs API note
EvercamLabsApi from @evercam/api references window.location.href internally (browser-only). Copilot and detection tools bypass this by calling evercam.axios directly with evercam.axios.env.evercamLabsUrl.
Development
git clone [email protected]:evercam/evercam-mcp.git
cd evercam-mcp
pnpm install
pnpm -C packages/evercam-mcp build # Compile TypeScript → dist/
pnpm -C packages/evercam-mcp dev # Watch mode (tsx watch)Adding a new tool
- Find the method in
evercam-frontend/packages/api/api/ - Add to the relevant
packages/evercam-mcp/src/tools/<domain>.tsfile:
server.tool(
"tool-name",
"Human description shown to the AI",
{
requiredArg: z.string().describe("What this is"),
optionalArg: z.number().optional().describe("Page number"),
},
async ({ requiredArg, optionalArg }) => {
const data = await evercam.api.namespace.method(requiredArg, { optionalArg })
return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }] }
}
)- Register in
packages/evercam-mcp/src/tools/index.ts - Add to
TOOL_DESCRIPTIONSinpackages/evercam-mcp/src/cli/tools.ts - Run
pnpm -C packages/evercam-mcp build— must compile with zero errors
SDK namespace map
| What you want | Use |
| ---------------------------------------------- | ----------------------------------------------------------------- |
| Cameras, projects, recordings, BIM, media | evercam.api.* |
| ANPR, gate report, ROIs, smart search, heatmap | evercam.ai.* |
| Copilot, luminance, presence, labs heatmap | evercam.axios.get(\${evercam.axios.env.evercamLabsUrl}/...`)` |
Publishing
# Monorepo release scripts (repo root)
pnpm mcp:publish:patch
pnpm mcp:publish:minor
pnpm mcp:publish:major
pnpm mcp:publish:patch:commit
pnpm mcp:publish:patch:push
pnpm mcp:publish:dry-run
# Or direct:
node ci-scripts/mcp-release.js patch
node ci-scripts/mcp-release.js patch --mutate --commit
node ci-scripts/mcp-release.js patch --mutate --push
node ci-scripts/mcp-release.js patch --dry-runRelease types:
patch:x.y.z -> x.y.(z+1)minor:x.y.z -> x.(y+1).0major:x.y.z -> (x+1).0.0
The package prepublishOnly script still runs pnpm -C packages/evercam-mcp build before packaging. Only the dist/ folder is included in the published package.
After publishing:
npm install -g @evercam/mcp # global install → evercam-mcp command in PATH
npx @evercam/mcp serve # no install required
# npx evercam-mcp serve # won't work unless an unscoped package existsRelated
@evercam/sdk— TypeScript SDK this is built onevercam-frontend— Source of API typesevercam-labs— AI copilot backendevercam-ai— ML analytics backend- Model Context Protocol — MCP specification
License
ISC © Evercam
