NOTE: The progress on this project has been halted. The main goals I had in mind for this system has already been achieved by OpenClaw, so I've moved on to other projects. Check out my other recent work:
A full-stack web application for managing AI conversations with dynamic, modular system prompts. The system allows system prompts to be composed from reusable modules that can execute Python scripts, call AI models, and maintain state across conversations.
MDCS addresses the problem of system prompts becoming lost or diluted in long conversations by treating them as executable, stateful components rather than static text. System prompts are built from modules that can:
- Execute sandboxed Python scripts with access to conversation data
- Call AI models for self-reflection or generation tasks
- Persist state between conversations
- Execute conditionally based on triggers or keywords
The system uses a 5-stage execution pipeline to control when modules run relative to the main AI response, enabling pre-processing, post-processing, and background analysis.
Golden ration layout with 4 areas, the main chat interface with markdown rendering, a navigation/management area connected to the control panel area, and an additional smaller information display area
Alternate expanded display for navigation/management + control panel areas, currently showing the advanced module editor with Python scripting, trigger patterns, and test functionality
Same alternate display, currently showing persona configuration with template system and available modules suggest box
Module management (on the right), chat controls, and expandable thinking process from reasoning models (on the left)
- API Layer: REST endpoints and WebSocket for real-time chat
- Module System: Simple (text) and Advanced (Python script) modules
- Plugin System: ~60 functions available to module scripts (
ctx.*) - Execution Pipeline: 5-stage system for controlled module execution
- Script Engine: RestrictedPython sandbox for safe script execution
- Provider Abstraction: Support for Ollama and OpenAI-compatible APIs
- Database: PostgreSQL with SQLAlchemy ORM
- Chat Interface: Real-time streaming with WebSocket
- Module Editor: Create and edit modules with Python scripting
- Persona Management: Configure AI personalities with modular templates
- Code Editor: CodeMirror integration for script editing
- Markdown Rendering: Full GFM support with custom styling
Backend:
- FastAPI 0.104.1
- Python 3.10+
- SQLAlchemy 2.0.23
- PostgreSQL 12+
- RestrictedPython 7.0
- uvicorn (ASGI server)
Frontend:
- Vue 3.5.18 (Composition API)
- TypeScript 5.8
- Vite 7.0.6 (build tool)
- Pinia (state management)
- CodeMirror 6 (code editor)
- marked 16.2.0 (markdown parser)
Deployment:
- Docker + Docker Compose
- Nginx (frontend reverse proxy)
- PostgreSQL 14
Simple Modules: Static text that gets inserted into the system prompt.
Advanced Modules: Python scripts with access to:
- Conversation history and metadata
- Time/date functions
- AI generation and reflection capabilities
- Memory storage and retrieval
- JSON manipulation utilities
Execution Contexts:
IMMEDIATE: Executes before the main AI responsePOST_RESPONSE: Executes after the main AI responseON_DEMAND: Only executes when explicitly referenced
Trigger Patterns: Modules can execute based on keywords, regex patterns, or always (*).
- Stage 1 - Template Preparation: Load persona template, resolve module references, execute simple modules and non-AI immediate modules
- Stage 2 - Pre-response AI: Execute immediate modules that require AI inference
- Stage 3 - Main Response: AI generates the response using the resolved system prompt
- Stage 4 - Post-response Non-AI: Fast post-processing modules (logging, analytics)
- Stage 5 - Post-response AI: Background AI analysis and reflection
Stages 4 and 5 save their outputs to the database, which are then injected into Stage 1 of the next conversation. This enables persistent, evolving context.
- WebSocket Communication: Bidirectional real-time messaging
- Streaming: Token-by-token response streaming
- Cancellation: Sub-100ms cancellation latency
- Provider Support: Ollama (local models) and OpenAI-compatible APIs
- Reasoning Models: Support for models with thinking/reasoning output (e.g., gpt-oss)
- Message Editing: Edit and regenerate messages
- Markdown Rendering: Full GitHub Flavored Markdown support
Modules have access to plugin functions via the ctx object:
Time:
ctx.get_current_time(format)- Current time with formattingctx.get_relative_time(offset)- Time with offsetctx.is_business_hours()- Business hours checkctx.get_day_of_week()- Day name
Conversation:
ctx.get_message_count()- Total messagesctx.get_recent_messages(limit)- Message historyctx.get_conversation_summary()- Metadatactx.get_persona_info()- Persona details
AI:
ctx.generate(instructions)- On-demand AI generationctx.reflect(instructions)- AI self-reflection with current system prompt
Memory:
ctx.should_compress_buffer()- Check if compression neededctx.get_buffer_messages(start, end)- Message windowctx.store_memory(content)- Save compressed memoryctx.get_recent_memories(limit)- Retrieve memories
Utilities:
ctx.to_json(),ctx.from_json()- JSON operationsctx.join_strings(),ctx.count_words()- String utilities
- RestrictedPython Sandbox: No file system or network access from modules
- Whitelisted Imports: Only safe modules (datetime, math, json, re)
- Reflection Depth Limiting: Maximum 3 levels to prevent infinite nesting
- Circular Reference Detection: Prevents infinite module loops
- SQL Injection Prevention: Parameterized queries via SQLAlchemy
- External Link Security: Automatic
rel="noopener noreferrer"on links
Prerequisites:
- Docker Engine 20.10+
- Docker Compose V2
- 2GB free disk space
Steps:
# Clone repository
git clone https://github.com/IdentityOverflow/MDCS.git
cd MDCS
# Configure environment
cp .env.docker .env
# Edit .env and set a strong DB_PASSWORD
# Start services
docker compose up -d
# View logs
docker compose logs -fAccess:
- Frontend: http://localhost:5173
- Backend API: http://localhost:8000
- API Docs: http://localhost:8000/docs
Using Ollama on Host (Linux):
For the Docker backend to connect to Ollama running on your host machine, you need to configure Ollama to listen on all network interfaces:
-
Edit the Ollama systemd service:
sudo systemctl edit ollama.service
-
Add the following configuration:
[Service] Environment="OLLAMA_HOST=0.0.0.0:11434"
-
Reload and restart Ollama:
sudo systemctl daemon-reload sudo systemctl restart ollama
-
Verify Ollama is listening on all interfaces:
ss -tlnp | grep 11434 # Should show: 0.0.0.0:11434
Once configured, you can use this connection URL in the settings for accessing Ollama:
http://host.docker.internal:11434
Backend:
# Install PostgreSQL
sudo apt install postgresql postgresql-contrib
# Create database
sudo -u postgres psql
CREATE USER mdcs WITH PASSWORD 'password';
CREATE DATABASE mdcs OWNER mdcs;
GRANT ALL PRIVILEGES ON DATABASE mdcs TO mdcs;
\q
# Initialize schema
psql -U mdcs -d mdcs -f backend/init_db.sql
# Install backend
cd backend
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
# Configure
cp .env.example .env
# Edit .env with database credentials
# Run
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reloadFrontend:
cd frontend
npm install
npm run devAI Provider:
- Install Ollama:
curl -fsSL https://ollama.com/install.sh | sh - Or use OpenAI API / LM Studio / compatible API
- Navigate to Settings → Ollama connection or OpenAI connection
- Ensure the connection enpoint is available and set correctly, primarily BASE URL and API KEY (this can be a random string in case of local providers like LM Studio)
- Navigate to Personas → + NEW
- Set name and description
- Write template with module references:
You are a helpful assistant. @greeting_module Current time: @time_module Conversation context: ${conversation_history} - Select mode: REACTIVE (chat) or AUTONOMOUS (experimental)
- Optionally upload avatar image
Simple Module:
- Navigate to Modules → + NEW
- Select Type: Simple
- Enter static text content
- Set execution context: IMMEDIATE
Advanced Module:
- Select Type: Advanced
- Write Python script:
conversation_history = ctx.get_recent_messages(30)
- Set trigger pattern (optional): keyword, regex, or
*for always - Set execution context IMMEDIATE or POST_RESPONSE
- Test script with TEST SCRIPT button
The script analyzer automatically detects if the module requires AI inference based on calls to ctx.generate() or ctx.reflect().
@module_name- Insert module output${variable}- Insert variable from module script
- Select persona from sidebar
- Choose AI provider and model in chat controls
- Adjust temperature, top-p, max tokens as needed
- Enable markdown rendering for formatted output
- Reasoning models show expandable "Thinking Process" section
- Edit messages by hovering and clicking edit icon
- Debug panel shows resolved system prompts and execution stages
mdcs/
├── backend/
│ ├── app/
│ │ ├── api/ # REST and WebSocket endpoints
│ │ ├── core/ # Script engine, plugins, analyzers
│ │ ├── models/ # SQLAlchemy database models
│ │ ├── services/ # Business logic, providers
│ │ ├── plugins/ # Plugin function implementations
│ │ └── database/ # Connection and migrations
│ ├── tests/ # Backend tests
│ ├── init_db.sql # Database schema
│ └── requirements.txt # Python dependencies
├── frontend/
│ ├── src/
│ │ ├── components/ # Vue components
│ │ ├── views/ # Page views
│ │ ├── composables/ # Vue composables (logic)
│ │ ├── types/ # TypeScript type definitions
│ │ └── assets/ # CSS, images
│ └── package.json # Node dependencies
├── docker-compose.yml # Docker orchestration
└── screenshots/ # UI screenshots
Backend Type Checking:
cd backend
mypy app/Frontend Type Checking:
cd frontend
npm run type-checkRun Tests:
cd backend
pytest -vDatabase Migrations:
Migrations are SQL files in backend/app/database/migrations/. Apply them manually:
psql -U mdcs -d mdcs -f backend/app/database/migrations/NNN_migration.sqlAdding Plugin Functions:
- Create file in
backend/app/plugins/ - Use decorator:
from app.core.script_plugins import plugin_registry @plugin_registry.register("my_function") def my_function(param: str, db_session=None, _script_context=None): """Function description.""" return result
- Function auto-loads on startup
- Available as
ctx.my_function()in module scripts
- Memory compression is functional but still experimental and higly dependatnt on the model
- Autonomous mode is not fully implemented
- Vector database / semantic search planned but not yet implemented
- No multi-modal support yet (images, audio, video)
- Tool use/MCP support not fully impemented
- Chat rooms not implemented
- No rate limiting
- No user authentication system (single-user)
# View logs
docker compose logs -f
docker compose logs -f backend
docker compose logs -f frontend
# Restart services
docker compose restart
# Rebuild after code changes
docker compose up -d --build
# Stop and remove (keeps data)
docker compose down
# Stop and remove including data
docker compose down -v
# Check health
docker compose psEnvironment Variables (.env):
# Database
DB_HOST=localhost
DB_PORT=5432
DB_NAME=mdcs
DB_USER=mdcs
DB_PASSWORD=your_password
DATABASE_URL=postgresql://mdcs:your_password@localhost:5432/mdcs
# Application
# Add other config as neededAI Provider Settings (stored in browser localStorage):
- Ollama: host URL, model
- OpenAI: API key, model, base URL
MIT License - see LICENSE file for details.
Copyright (c) 2025 Paul Panțiru
This is a solo development project in early stages. Contributions are welcome but please note:
- Follow existing code style
- Write tests for new features
- Update documentation
- Keep commits focused
- FastAPI for the backend framework
- Vue.js team for the frontend framework
- Marked.js for markdown parsing
- RestrictedPython for safe script execution
- Anthropic, Google, Mistral and OpenAI for the AI models / coding agents
- Ollama and LM Studio for local inference