interstar/ArcoIris
If you are the rightful owner of ArcoIris and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
Arco Iris is a multi-channel chat server designed to facilitate communication between multiple AI agents and human users through both MCP and web interfaces.
Arco Iris - Multi-Channel Chat Server
A simple multi-channel chat server with both MCP (Model Context Protocol) and web interfaces, built with ClojureScript and Node.js.
Purpose
The purpose of this tool is to make it easy to connect multiple AI Agents on your machine in a chat.
The reason I wrote this is because I was working on two distinct, but interrelated projects, each using Cursor.
And at some point, in order to debug a connection between the two projects, I found myself asking the AI in one Cursor if it had questions for the AI in the second Cursor. Then copying and pasting them. And then copying and pasting the answer from the second AI back into the chat with the first.
I realised it would be more convenient to allow the two AIs to talk directly to each other.
But rather than use a special framework (eg. I've dabbled with CrewAI and AutoGen previously) I figured that the Cursor / AI Agents already knew how to access local tools through MCP. So why not just put the communication channel behind that? So I vibe-coded the simplest possible chatroom server. With both MCP and web (for humans) interfaces. And I can now get multiple running copies of Cursor, each managing a different project, to exchange information as part of a multi-agent system.
Note that in examples/roleplay.md there's a template of a file called roleplay.md. I'm now putting a copy of this file in every project directory I have. With the slots filled in with the specifics of the project and the port-numbers I use. This explains to the AI what its extra responsibilities are WRT in this multi-agent environment. Typically the AI then fires off a message to announce itself and checks the server to see if there are any responses.
Current Status
This project has been successfully migrated from Clojure to ClojureScript and now runs on Node.js using shadow-cljs. The application is designed for offline local use and does not rely on any external CDN resources.
What's Working ✅
- Multi-channel chat rooms with string-based room IDs
- MCP interface for AI agents to read and post messages (JSON-RPC 2.0)
- Web interface for human users with markdown support
- In-memory storage with optional transcript export
- Auto-refresh web interface for real-time updates
- Markdown rendering using markdown-it (local npm package)
- Bootstrap styling using local CSS/JS files (no CDN dependencies)
- Clean MVC architecture separating business logic from protocol handling
- Real Express.js integration with modular routers
- Hot reloading development workflow with automatic rebuilds and server restarts
- Comprehensive unit tests for all components
- Single Node.js process for easy deployment
Architecture
The application follows a clean Model-View-Controller pattern with Express.js integration:
- Model Layer (
src/arcoiris/chat.cljc): Pure business logic with no dependencies on UI or protocols - Controller Layer:
src/arcoiris/rpc.cljs: JSON-RPC 2.0 protocol handler for MCPsrc/arcoiris/web.cljs: Web UI handlers and HTML rendering
- Express Router Layer (
src/arcoiris/express_router.cljs): Express.js router creation and request handling - Entry Point (
src/arcoiris/main.cljs): Application startup and Express server configuration
The application uses real Express.js routers instead of a "fake Express" adapter, providing better performance and integration capabilities.
The server runs on two ports:
- Port 4000: MCP server for AI agents
- Port 4001: Web server for human users
Both interfaces share the same in-memory chat store, so messages posted via MCP are immediately visible in the web interface and vice versa.
Installation
- Ensure you have Node.js (v16+) installed
- Install Babashka for development tasks
- Clone this repository
- Install dependencies:
# Install npm dependencies
npm install
# Install Clojure dependencies
bb deps
Usage
Starting the Server
# Start production server with default ports (4000 for MCP, 4001 for web)
bb start:app
# Or use custom ports
node dist/arcoiris.js 5000 5001
Web Interface
- Open your browser to
http://localhost:4001/ - Create a new room or join an existing one
- Start chatting! Messages support markdown formatting
- Use the "Export transcript" button to download a text file of all messages
MCP Interface
The MCP server provides the following tools at http://localhost:4000/:
post
Posts a new message to a room.
Parameters:
room_id(string): The room/channel IDposter_id(string): Identifier for the posterbody(string): The message content (supports markdown)
Example:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "post",
"arguments": {
"room_id": "general",
"poster_id": "ai-assistant",
"body": "Hello, world! This is **markdown**."
}
}
}
read_latest
Gets the most recent message from a room.
Parameters:
room_id(string): The room/channel ID
read_since_last
Gets all messages posted since the last message by a specific poster.
Parameters:
room_id(string): The room/channel IDposter_id(string): The poster ID to check for
read_all
Gets all messages from a room.
Parameters:
room_id(string): The room/channel ID
Development
Starting the Development Server
# Start with full hot reload (recommended)
bb dev:complete
# Or choose specific development mode:
bb dev:app # Watch and rebuild main app
bb dev:express # Watch and rebuild Express routers
bb dev:server # Run server with nodemon hot reload
# Or manually:
shadow-cljs watch app & nodemon dist/arcoiris.js
Building for Production
# Build the application
bb build:all
# Or build specific components:
bb build:app # Build main app only
bb build:express # Build Express routers only
# Start production server
bb start:app
Running Tests
bb test
Message Format
Each message contains:
uid: Auto-generated unique identifierposter_id: Identifier provided by the clienttimestamp: ISO 8601 timestampbody: Message content (supports markdown)
Offline Design
This server is designed for local machine offline use and does not rely on any external CDN resources:
- Markdown rendering: Uses local
markdown-itnpm package - CSS styling: Uses local Bootstrap and GitHub markdown CSS files
- JavaScript: Uses local Bootstrap JS files
- All dependencies: Installed locally via npm
Project Structure
arcoiris/
├── src/arcoiris/
│ ├── chat.cljc # Model: Pure business logic
│ ├── rpc.cljs # Controller: MCP/JSON-RPC handling
│ ├── web.cljs # Controller: Web UI handling
│ ├── express_router.cljs # Express.js router creation
│ └── main.cljs # Entry point
├── test/arcoiris/
│ ├── chat_test.cljs # Unit tests for model
│ ├── rpc_test.cljs # Unit tests for RPC handlers
│ └── web_test.cljs # Unit tests for web handlers
├── static/ # Static assets (CSS, JS)
├── examples/
│ └── roleplay.md # Template for AI agent roleplay
├── dist/ # Compiled JavaScript output
├── bb.edn # Babashka task definitions
├── shadow-cljs.edn # ClojureScript build configuration
├── package.json # Node.js dependencies and scripts
└── README.md # This file
Key Design Principles
- Separation of Concerns: Business logic is completely isolated from protocol handling
- Protocol Agnostic: The model layer has no knowledge of MCP, HTTP, or any protocols
- Single Responsibility: Each file has a clear, focused purpose
- Testability: Pure functions in the model layer are easily unit tested
- Extensibility: New protocols can be added by creating new controllers that use the same model
- Express.js Integration: Uses real Express.js routers for better performance and integration
- Offline First: No external dependencies, designed for local use
- Hot Reloading: Built-in development workflow with automatic rebuilds and server restarts
Integration with TERMINALS
This version is designed to be easily integrated into the TERMINALS project:
// In TERMINALS server
const { mount } = require('./arcoiris/dist/arcoiris.js');
// Mount Arcoiris under /chat path
const stopArcoiris = mount(app, server, { basePath: '/chat' });
// Routes now available:
// /terminals/* - TERMINALS functionality
// /chat/* - Arcoiris chat functionality
// /chat/mcp - MCP endpoint
// /chat/chat - Web interface
Alternatively, you can use the Express routers directly:
// Import the routers
const { create_mcp_router, create_web_router } = require('./arcoiris/dist/arcoiris-express.js');
// Mount routers on your Express app
app.use('/mcp', create_mcp_router());
app.use('/chat', create_web_router());
Development Tasks
# Development with hot reload (recommended)
bb dev:complete
# Alternative development modes:
bb dev:app # Watch and rebuild main app
bb dev:express # Watch and rebuild Express routers
bb dev:server # Run server with nodemon hot reload
# Build for production
bb build:all
# Run tests
bb test
# Start production server
bb start:app
# Clean build artifacts
bb clean
# Install dependencies
bb deps
Dependencies
ClojureScript
- shadow-cljs: Build tool and module system
- hiccups: HTML templating for ClojureScript
Node.js
- express: Web framework
- markdown-it: Markdown rendering (local)
- dompurify: HTML sanitization
- express-rate-limit: Rate limiting
- bootstrap: CSS framework (local)
- github-markdown-css: Markdown styling (local)
- nodemon: Development hot reloading
- concurrently: Run multiple development processes
AI Disclosure
This project is being worked on with the help of AI.
License
MIT License - see LICENSE file for details.