Composable orchestration platform for conversational AI with voice agent runtime, backend API, and frontend UI. Includes LiveKit-based voice agent with STT, LLM, and TTS orchestration.
This is NOT an MCP server, it is a FastAPI/Next.js/LiveKit voice agent framework. The 13 listed 'tools' are Python functions and TypeScript helpers spread across agent/, backend/, and frontend/ code, NOT MCP tool definitions. No MCP tool registration is visible in the source. Tool descriptions are present but highly domain-specific (voice STT/LLM/TTS orchestration) and lack LLM-optimized guidance for when/why an agent should invoke them. Several tools expose context objects and complex async patterns that do not follow Arcade's 54 agentic tool patterns. Parameter schemas are partially documented but inconsistently; many lack type constraints, enums, and validation rules. Error handling is minimal. The 'server' is architected as a containerized voice agent runtime (LiveKit + FastAPI backend + Next.js frontend), not an MCP protocol server exposing tools for remote consumption.
Tools (13)
ResembleTTS.synthesizeread onlyauth40/100
Synthesize text to speech using Resemble AI streaming.
Fetch API keys from backend (async). Safe to call inside the entrypoint.
getServerAuthHeadersread onlyauth42/100
Server-side helper: get auth headers for backend API calls. Reads session token + activeOrganizationId from the request. Use in server components and API routes.
NOT an MCP SERVER, this is a FastAPI/Next.js voice agent framework. The 13 items listed are Python functions and TypeScript helpers, NOT MCP tool definitions. No evidence of MCP protocol implementation, tool registration via MCP messages, or stateless request handling.
If creating an actual MCP server wrapper: define tools as JSON Schema with explicit tool registration via tools/list_changed messages. Each tool must have name (snake_case verb_noun), description (50 - 200 chars), and inputSchema (typed, with enum constraints where applicable).
Document all output schemas. For fetch_agent_config, define: { agent_id, config: {...}, created_at, updated_at }. For lookup_agent_by_phone, define: { agent_id, phone_number, status } or empty object + error guidance.
Add enums to provider parameters: provider in [deepgram, assemblyai, elevenlabs, resemble, google, openai] instead of free-form strings.
Replace generic 'object' parameters. For resolve_agent_id_from_metadata, define ctx schema: { room_id (string), metadata (object), retry_count (integer, 0 - 5) }. For download_agent_files, define client schema with required methods (list_objects, get_object).
Add validation constraints to numeric parameters: audio_duration must be positive; input_tokens and output_tokens must be >= 0; character_count must be > 0. Specify max bounds (e.g., audio_duration <= 3600 seconds for a single call).
Add format constraints: phone_number should state 'E.164 format (e.g., +1-555-0123)' and include a regex pattern or validation example.
Implement error handling for all WRITE tools. Example for install_extra_requirements: 'Return { success: boolean, duration_ms: integer, stderr: string (if failed), stdout: string (if partial success) }. On failure, return actionable error like 'Dependency conflict in requirements.txt: pydantic 2.0 incompatible with livekit-agents 1.5.0. Review and retry with pinned versions.'
Score history
Overall score trend
First recorded score · v2 rubric
38/100
Scored
Grade
Overall
Spec posture
Rubric
2026-09-23
F
38
2026-07-28+
v2
Import workspace/agent.py and return the AgentServer instance. Looks for a module-level `server` variable first (preferred pattern). Falls back to calling `create_agent()` if `server` is not found.
Log tools (log_stt_usage, log_llm_usage, log_tts_usage) are fire-and-forget with no error handling guidance. If backend URL is unreachable or session_id is invalid, what does the agent see? No recovery path documented.
Parameter descriptions lack format constraints, enums, and validation rules. E.g., phone_number in lookup_agent_by_phone has no format guidance (E.164? raw digits?). provider in log_stt_usage should be an enum, not free-form string.
Naming inconsistencies: getServerAuthHeaders uses camelCase instead of snake_case (get_server_auth_headers). ResembleTTS.synthesize uses class notation instead of flat name (resemble_synthesize or synthesize_tts). These prevent LLM name-based tool selection.
Tool descriptions are inconsistently detailed. Some (e.g., resolve_agent_id_from_sip at 26 chars) are too brief to guide LLM decision-making. Others mention internal implementation (retries, cloud latency) rather than user-facing behavior.
No idempotency declarations. Multi-call patterns (resolve_agent_id_from_*) mention retries but do not document whether repeated calls with same input are safe. Agents may retry and create duplicate side effects.
Backend URL, session_id, and agent_id are passed as parameters in logging tools. These should be injected server-side or read from request context. Exposing them as parameters risks logging credentials.
log_stt_usagelog_llm_usagelog_tts_usage
Add confirmation patterns for destructive operations. Before download_agent_files or install_extra_requirements, ask the agent: 'Confirm: overwrite /app/workspace/ contents? (yes/no)'. Use MRTR (Multi-Round-Trip Request) with input_required result type if implementing in MCP.
Rename tools to follow verb_noun snake_case convention: getServerAuthHeaders → get_server_auth_headers. ResembleTTS.synthesize → resemble_synthesize or synthesize_tts.
For phone lookup and agent resolution tools, add 'did you mean' error responses. If lookup_agent_by_phone('+1-555-0199') fails, return: { error: 'Phone not found', available_phones: ['+1-555-0100', '+1-555-0199'] } to enable agent self-correction.
Add idempotency declarations to all write tools: 'This tool is idempotent, repeated calls with the same input produce the same result (no duplicate log entries).' For fire-and-forget logging tools, include deduplication guidance (e.g., log once per (session_id, provider, event_type) tuple).
Move backend_url from parameters to server-side injection (env var BACKEND_API_URL). Pass session_id and user_id via authenticated request headers instead of tool parameters. This prevents credential leakage into logs.
Expand tool descriptions to 50 - 150 chars. Example: fetch_agent_config → 'Fetch the complete agent configuration (model, providers, system prompt, tool list) from the backend. Call this once at agent startup to set up the voice pipeline. Returns null if agent ID not found.'
Document retry semantics explicitly. For resolve_agent_id_from_metadata: 'Retries up to 3 times with exponential backoff. Safe to call multiple times (idempotent). Returns null if metadata never settles; check room status separately.'
Add composition hints. For example, after lookup_agent_by_phone succeeds and returns agent_id, the agent can immediately call fetch_agent_config(agent_id), document this expected flow in descriptions.