Atlas / MCP servers / vexa-ai / Vexa

VexaBLOCK

mcp/vexa-ai/vexa

Open-source meeting transcription API for Google Meet, Microsoft Teams & Zoom. Auto-join bots, real-time WebSocket transcripts, MCP server for AI agents. Self-host or use hosted SaaS.

Verdict
BLOCK
Grade
F
Trust score
27 /100
Exposed tools
—
Transport
streamable-http
License
Apache-2.0
Stars
2,809
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

Open-source meeting bots and real-time transcription — cloud or fully self-hosted.

A bot joins your Google Meet, Microsoft Teams, and Zoom calls and streams speaker-attributed transcripts in real time — through our API or one you host — then feeds sandboxed agents that build a Markdown knowledge base your team owns. Apache-2.0, air-gap-ready. (Jitsi: join + capture offline-proven, live validation pending — #883.)

[](LICENSE) [](#️-status--roadmap) [](#-quickstart) [](https://discord.gg/Ga9duGkVz9)

[vexa.ai](https://vexa.ai) runs Vexa 0.12 for meeting bots and transcription. Sandboxed knowledge agents are self-hosted only — self-host Vexa to run the full stack.

[Connect your agent](https://vexa.ai/connect?utm_source=github&utm_medium=readme) · [Get an API key](https://vexa.ai/start?utm_source=github&utm_medium=readme) · [Talk to the founder](https://cal.com/dmitrygrankin/web)

Why Vexa

Every meeting-AI tool you can buy sends your conversations to their cloud and rents you access back. Vexa inverts that: run the stack yourself, point it at your own models, own what your meetings become.

No one else has all three:

  1. *Vexa is in the meeting.* A real bot joins Meet, Teams and Zoom — Jitsi offline-proven, live

validation pending — and streams speaker-attributed transcripts live. That bot fleet is the genuinely hard part — every "chat with your docs" tool starts after a transcript exists. Vexa produces it.

  1. Your knowledge is files you own. Meetings compile into
Read from source at commit 245ce1792c3eOBSERVED · 2026-09-22
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add transcript-rendering --env ADMIN_API_TOKEN=${ADMIN_API_TOKEN} --env ADMIN_TOKEN=${ADMIN_TOKEN} --env ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} --env ANTHROPIC_AUTH_TOKEN=${ANTHROPIC_AUTH_TOKEN} -- npx -y @vexaai/[email protected]
claude-desktop
{
  "mcpServers": {
    "transcript-rendering": {
      "command": "npx",
      "args": [
        "-y",
        "@vexaai/[email protected]"
      ],
      "env": {
        "ADMIN_API_TOKEN": "${ADMIN_API_TOKEN}",
        "ADMIN_TOKEN": "${ADMIN_TOKEN}",
        "ANTHROPIC_API_KEY": "${ANTHROPIC_API_KEY}",
        "ANTHROPIC_AUTH_TOKEN": "${ANTHROPIC_AUTH_TOKEN}"
      }
    }
  }
}
03

Trust audit

BLOCKgrade F · trust 27/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryWARN
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)WARN
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (10 observation(s))
Network
declared (13 observation(s))
Shell
declared (6 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
clients/terminal/src/canvas/runtime.tsx:64
const fn = new Function(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
MEDIUMInventory / provenance · inv.binary · CWE-1104
core/meetings/modules/zoom-capture/src/zoom-chat.ts
zoom-chat.ts
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
core/flows/src/flows_defs/production.py:557
mod = importlib.import_module(name)
MEDIUMCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
core/meetings/services/meeting-api/src/meeting_api/__init__.py:47
return importlib.import_module(f"{__name__}.{name}")
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
core/identity/src/identity_core/secrets.py:46
`repr`/`str` are redacted so an accidental `logger.info(secret)` or f-string leaks nothing.
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
core/meetings/services/transcription/src/transcription/main.py:148
logger.warning(f"Invalid or missing API token - X-API-Key: {api_key is not None}, Authorization: {bool(auth_header)}")
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
core/meetings/services/meeting-api/src/meeting_api/bot_spawn/invocation.py:215
callback_url: Optional[str] = None,
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
core/meetings/services/meeting-api/src/meeting_api/bot_spawn/invocation.py:235
if callback_url:
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
core/meetings/services/meeting-api/src/meeting_api/bot_spawn/invocation.py:236
spec["callbackUrl"] = callback_url
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
core/meetings/services/meeting-api/src/meeting_api/bot_spawn/service.py:799
callback_url=f"{meeting_api_url}/runtime/callback",
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
clients/slim/vexa_slim/config.py:11
DEFAULT_GATEWAY = "http://127.0.0.1:18056"
MEDIUMObfuscation / stealth · obf.base64_blob · CWE-506, CWE-94
core/meetings/eval/replay-fixture/session.captured-signal.jsonl:2
{"seq":0,"ts":1718000000000,"speakerIndex":0,"speakerName":"Alice","pcm":"zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzE
MEDIUMObfuscation / stealth · obf.base64_blob · CWE-506, CWE-94
core/meetings/eval/replay-fixture/session.captured-signal.jsonl:3
{"seq":1,"ts":1718000000200,"speakerIndex":0,"speakerName":"Alice","pcm":"zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzE
MEDIUMObfuscation / stealth · obf.base64_blob · CWE-506, CWE-94
core/meetings/eval/replay-fixture/session.captured-signal.jsonl:4
{"seq":2,"ts":1718000000400,"speakerIndex":0,"speakerName":"Alice","pcm":"zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzE
MEDIUMObfuscation / stealth · obf.base64_blob · CWE-506, CWE-94
core/meetings/eval/replay-fixture/session.captured-signal.jsonl:5
{"seq":3,"ts":1718000000600,"speakerIndex":0,"speakerName":"Alice","pcm":"zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzE
MEDIUMObfuscation / stealth · obf.base64_blob · CWE-506, CWE-94
core/meetings/eval/replay-fixture/session.captured-signal.jsonl:6
{"seq":4,"ts":1718000000800,"speakerIndex":0,"speakerName":"Alice","pcm":"zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzEw9zcxMPc3MTD3NzE
MEDIUMObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
core/meetings/modules/join/src/googlemeet/admission.ts:390
log("🧑⚖️ Gemini consent prompt detected — bot is behind a consent gate (not admitted). Escalating to needs_human_help; not auto-consenting.");
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
core/agent/tests/test_github_vcs.py:21
TOKEN = "ghp_SUPERSECRETtoken1234567890"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
core/agent/tests/test_meeting_postprocess_offline.py:292
base_url="https://openrouter.ai/api", token="sk-ant-api03-deadbeef",
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
core/agent/tests/test_meeting_postprocess_offline.py:305
base_url="https://api.anthropic.com", token="sk-ant-api03-deadbeef",
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
core/agent/tests/test_workspace_git_sync.py:23
TOKEN = "ghp_SECRET_token_123"
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
core/agent/tests/test_workspace_publish.py:24
TOKEN = "ghp_SECRET_token_123"
MEDIUMPrompt injection · prompt.conditional_escalation · CWE-94, CWE-1427
core/agent/workspace-seeds/default/skills/scheduling/SKILL.md:8
When the user asks for ANYTHING that should run on a schedule or repeat over time
MEDIUMPrompt injection · prompt.conditional_escalation · CWE-94, CWE-1427
core/agent/workspace-seeds/finos/skills/scheduling/SKILL.md:8
When the user asks for ANYTHING that should run on a schedule or repeat over time
LOWInventory / provenance · inv.hidden_file · CWE-1104
.dependency-cruiser.cjs
.dependency-cruiser.cjs
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose

Gates applied: no_behavioural_pass.

Audited 2026-09-22 · audit v0.4.1 · source sha 245ce1792c3efull audit observations/trust-audit/mcp-server/vexa-ai__vexa.json · Report an issue / request a re-scan
04

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-09-22245ce1792c3eBLOCKF27source changed, verdict held
05

Questions

What is the Vexa MCP server?

Open-source meeting transcription API for Google Meet, Microsoft Teams & Zoom. Auto-join bots, real-time WebSocket transcripts, MCP server for AI agents. Self-host or use hosted SaaS.

Is Vexa safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (27/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on.

What credentials does Vexa need?

It reads ADMIN_API_TOKEN, ADMIN_TOKEN, ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, API_TOKEN, AUTHORITY_SECRET, AUTH_PLATFORM, AUTH_PROFILE, BOT_S3_ACCESS_KEY, BOT_S3_SECRET_KEY, DB_PASSWORD and DG_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does Vexa run?

It speaks streamable-http, so it runs as a service you connect to over the network. It is published on npm as @vexaai/transcript-rendering at 0.4.1.

How current is this page?

The grade is for one exact copy of the source (245ce1792c3e), read on 2026-09-22. The repository is watched and re-audited when it changes.

Advertisement