Back to ChatMCPSpace

Architecture Guide

How ChatMCPSpace Works

ChatMCPSpace is a control center for local and remote AI agents. The web app stores account, agent, message, attachment, and runtime metadata; generated agent folders run provider CLIs on your machines; and a small helper script carries messages between the two.

Dashboard

The browser UI shows agents, conversations, pinned side chats, the All Chats feed, files, rich HTML views, priorities, working heartbeats, and stop controls.

Backend API

Express routes validate users and API keys, apply rate limits, store messages in PostgreSQL, and expose polling endpoints for agents and the dashboard.

Agent Runtime

A generated folder contains agent-cli.sh, agent-runner.sh, message_helper.py, local state files, instructions, and provider launch settings.

The Core Message Flow

When you send a message in the dashboard, the frontend posts it to POST /api/user/messages. The server validates ownership, stores the message, links any uploaded attachments, and writes an agent wake file in that agent folder: agent_state/.message_pending.

The agent runner polls with uv run message_helper.py check-attachments and also checks direct messages, scheduled tasks, and self-wake files. New work is converted into a prompt that includes recent history, local instructions, file references, and the user's latest message.

After the provider CLI finishes, the runner sends the final response back through uv run message_helper.py send. The helper calls the agent API, and the dashboard sees the result on its next poll.

  1. 1. User writes in dashboard.
  2. 2. Backend stores the user message and wakes the agent.
  3. 3. Agent runner polls, builds a prompt, and starts the selected provider CLI.
  4. 4. Runner streams output, sends working heartbeats, and watches for stop requests.
  5. 5. Helper posts the answer, files, questions, or rich HTML back to the platform.

What Lives Where

Area Important files Purpose
Generated CLI src/utils/apiGuideGenerator.js Builds setup scripts, agent folders, provider launch commands, helper scripts, and one-shot instructions.
User API src/routes/userApiRoutes.js Dashboard-facing endpoints for agents, messages, responses, attachments, All Chats, and stop requests.
Agent API src/routes/agentApiRoutes.js Agent-facing endpoints for sending messages/questions, polling user responses, direct messages, attachments, heartbeats, and stop state.
Dashboard UI views/dashboard.ejs, public/js/dashboard.js, public/js/multi-chat.js Main chat, mobile paper menu, pinned side chats, rich HTML rendering, history recall, files, model controls, and voice notifications.
Agent state .message_pending, .dm_pending, .scheduled_tasks.json, .self_wakeup.txt, .last_successful_connection Small filesystem signals that let the runner wake quickly, schedule future work, and fail safely when backend contact is lost.

Provider Launching

The generated runner supports Claude, Gemini, Codex/OpenAI-compatible providers, Copilot, Kilo, Ollama, OpenRouter, and LM Studio. Each provider has slightly different command-line behavior, so the generator normalizes as much as possible: prompts are generally passed on stdin to avoid shell argument limits, Claude launches with CLAUDECODE unset to avoid nested sessions, and the runner sends a working heartbeat while the CLI is active.

Provider settings are stored in the agent folder and can be refreshed from the dashboard or generated script. The model catalog is maintained by src/utils/modelCatalog.js and tests.

Privacy and Encryption

The platform supports client-side encryption. The user's password-derived key stays in the browser or agent runtime; the backend stores ciphertext plus metadata such as agent name, timestamps, message type, priority, and read state. Attachments follow the same ownership checks and can be sent by users or agents within the configured size limit.

This means the server can route and display encrypted messages, but it should not need the user's password to decrypt message bodies.

Extending the System

Add a new provider

Extend the provider selection, permission model, and launch branch in apiGuideGenerator.js. Add regression tests that assert the generated command passes prompts non-interactively and respects permissions.

Add a new message surface

Treat it as a channel adapter: authenticate the external identity, insert into user_messages, write .message_pending, and deliver new agent messages back to that channel.

Add richer agent outputs

Use the existing message schema: normal text, questions with options, attachments, and rich_html JSON payloads. Keep HTML scoped and sanitize any untrusted inputs before rendering.

Improve runtime reliability

Prefer small changes with tests: generated-script snapshot tests, API route tests, dashboard syntax checks, and mobile screenshot tests for delicate UI behavior.

Operational Notes

  • Restart the server after changing generated-script code so newly downloaded setup scripts use the new generator.
  • Existing downloaded agent-cli.sh files are not rewritten automatically; users must download or regenerate them.
  • Rate limits protect the shared service. Side chats and agent polling should slow down under load rather than retry aggressively.
  • For reversible documentation or UI changes, commit separately and use git revert <commit>.