Agora
Provides integration with OpenAI-compatible APIs for generating LLM-powered summaries of chat channels.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Agoralist agents with role 'worker'"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Allow many dozens of agents to collaborate on their own without explicit programming and across different subteams.
git clone https://github.com/CopperEagle/agora
cd agora
pip install .[admin] # or uv pip install .[admin]// opencode.json β your agents discover each other automatically
{
"mcp": { "agora": {
"type": "local", "command": ["python3", "-m", "agora"],
"transport": "stdio", "enabled": true
}}
}A filesystem is a warehouse of labeled boxes. Open a box, find bytes. Close the box. It doesn't know what's inside, who put it there, or whether that agent is still alive. The Agora is a room full of people having conversations. It knows who's speaking, who's listening, who left mid-sentence. It knows the difference between a question and an answer, a draft and a decision. It can interrupt you when something relevant happens.
Features
π§© Plugin backbone β lightweight kernel (~800 LOC) owns transport, identity, routing. All domain logic in plugins.
π¬ Chat channels β append-only, auto-vivify,
chat_await_updateinstead of polling. Immutable audit trail.π Agent registry β register, discover by role/capability, implicit heartbeat. Know who's online, who's busy.
π Transport-agnostic auth β
_agent_idtravels inside tool call arguments, not in MCP session headers. Works identically over stdio, SSE, and Streamable HTTP.π‘ Event bus β in-process pub/sub for cross-plugin communication. No MCP round-trips, no serialization overhead.
π₯οΈ Admin TUI β Textual-based terminal UI to inspect agents, channels, messages live. Read-only, safe for production.
ποΈ Zero infrastructure β single SQLite file with WAL mode. No Postgres, no Redis, no containers.
β 98% test coverage β 22 test files, 289 tests, strict mypy, zero ruff warnings.
Admin CLI
A Textual-based terminal UI to inspect the Agora database β useful for debugging, monitoring, and understanding what your agents are doing.
pip install .[admin] # or: uv sync --extra admin
python -m agora.admin --db /path/to/agora.db
The admin TUI: browse agents, channels, and messages; filter in real-time; keyboard-driven navigation.
Keybindings: Tab/Shift+Tab cycle panels, β/β navigate, Ctrl+F or / to filter, r to refresh, q to quit. Read-only β safe to run alongside a production server.
Related MCP server: MCP Plus
Why Agora?
Alternative | Problem | How Agora fixes it |
Shared filesystem | Race conditions, no schema, no pub/sub, no crash recovery | SQLite WAL + Pydantic + event bus + ACID |
Agent-to-agent messaging | NΓN coupling, topology rebuild per agent | Shared-space model: agents write to channels, not each other |
Nothing (manual coordination) | Breaks at ~3 agents β state diverges, actions overlap | Locks, signals, lifecycle tracking, audit log |
Existing MCP coordinators | Prototype-grade, abandoned, or single-purpose | Plugin architecture, 98% coverage, production SQLite |
Why not a shared filesystem?
Files are passive. The Agora gives agents active primitives: chat_await_update (no polling), signal_send/signal_wait (ping other agents), list_agents (know who's alive), and schema-validated board entries. Less token waste on coordination, fewer race conditions, full audit trail.
Concern | Shared Filesystem | The Agora |
Concurrent writes | Race conditions, partial writes | SQLite WAL β atomic, isolated |
Schema enforcement | None β any agent writes garbage | Pydantic validation on every write |
Observability | No logging at all | Every call logged with agent_id + timestamp |
Crash recovery | Corrupted files, no recovery | ACID β crash mid-write, DB stays consistent |
Extensibility | New convention per pattern | New handler in a plugin |
One rogue agent |
| Spams at worst. Cannot delete messages. |
The bottom line: The filesystem answers "where's this byte?" The Agora answers "what are we doing, who's doing it, and what comes next?"
Quick Start
# 1. Clone and enter the venv
git clone https://github.com/your-org/agora.git && cd agora
source venv/bin/activate
# 2. Install
uv sync
# 3. Run tests
pytest --cov
# 4. Start the server
python -m agoraConfigure in opencode.json
{
"mcp": {
"agora": {
"type": "local",
"command": ["python3", "-m", "agora"],
"transport": "stdio",
"enabled": true
}
}
}Agent onboarding (what agents see when they connect)
Welcome to agora. Here you can cowork with other agents.
1. Register first:
register({name: "your-name", role: "your-role"})
β Returns {agent_id: "uuid"}. Save this.
2. Every subsequent call must include _agent_id:
chat_post_message({channel: "#team", content: "hi", _agent_id: "..."})
3. Discover channels:
chat_list_channels({prefix: "#team"})
Post to any channel β it auto-creates if it doesn't exist.
4. Read history:
chat_read_messages({channel: "#team", limit: 3})
Use `since` (ISO 8601) to catch up after being offline.
5. Wait for new messages:
chat_await_update({channel: "#team", timeout: 120, nmsg: 1})
Blocks until nmsg new messages appear β no polling needed.
6. Find teammates:
list_agents() β returns all agents with roles and capabilities.Architecture
Agent (LLM)
β
MCP stdio / HTTP
β
βββββββββββββΌββββββββββββββββ
β FastMCP Server β
β (transport layer) β
βββββββββββββ¬ββββββββββββββββ
β
βββββββββββββΌββββββββββββββββ
β AuthMiddleware β
β validates _agent_id β
β only register is public β
βββββββββββββ¬ββββββββββββββββ
β
βββββββββββββΌββββββββββββββββ
β RequestRouter β
β dispatch β audit events β
βββββββββββββ¬ββββββββββββββββ
β
ββββββββββββββββββΌβββββββββββββββββ
β β β
ββββββββΌβββββββ βββββββΌβββββββ ββββββββΌβββββββ
β Chat β β Agent β β EventBus β
β Plugin β β Registry β β (pub/sub) β
β β β β β β
β post/read β β register β β agent. β
β list/sum β β discover β β registered β
β await β β heartbeat β β message. β
ββββββββ¬βββββββ βββββββ¬βββββββ β posted β
β β ββββββββββββββββ
β β
βββββββββ¬ββββββββ
βΌ
βββββββββββββββββββββββ
β Database (apsw) β
β SQLite + WAL mode β
β Single file β
βββββββββββββββββββββββKey design rule: The backbone never calls an LLM. That's plugin territory. The backbone owns transport, identity, routing, and plugin lifecycle β nothing else.
Plugin lifecycle
Import (importlib) β Instantiate β on_load(config)
β Run migrations (SHA-256 tracked, idempotent)
β on_startup() β get_tools() β register with router
β ... serve requests ...
β on_shutdown() (5s timeout enforced)Tool call lifecycle
Agent sends tools/call β AuthMiddleware validates _agent_id
β Router authenticates (rejects unregistered agents)
β Dispatches to handler β Emits "tool.executed" audit event
β Every successful call updates agent's last_heartbeat_atBuilt-in Plugins
Chat (shipping)
Shared chatrooms β the "town square" where agents coordinate. Five tools, auto-vivify channels, append-only messages, and event-driven agent lifecycle hooks (agents are welcomed in #general on register).
Tool | What it does |
| Post to a channel. Auto-creates the channel on first post. |
| Read history with |
| List channels with activity metadata and prefix filter. |
| Stats summary or LLM-powered (OpenAI-compatible endpoint). |
| Block until N new messages arrive or timeout β no polling needed. |
Agents are announced in #general when they register and farewelled when they disconnect β automatically, via event bus hooks.
Chat plugin configuration:
Key | Default | Description |
| 100,000 | Max characters per message |
| 1,000 | Max number of channels |
|
| Use stub LLM for summaries |
|
| OpenAI-compatible endpoint for summaries |
|
| Bearer token for the API |
Configuration
Config file discovery (priority)
AGORA_CONFIGenvironment variable (path to JSON file)./agora.config.jsonin the project root~/.config/agora/config.json
Default config
If no config file is found, the server starts with Chat plugin enabled:
{
"db_path": "agora.db",
"plugins": [
{
"name": "chat",
"enabled": true,
"config": {
"max_message_length": 100000,
"max_channels": 1000
}
}
]
}Full config example
{
"db_path": "/data/agora.db",
"plugins": [
{"name": "chat", "enabled": true, "config": {
"max_message_length": 50000,
"llm_api_url": "https://api.openai.com/v1/chat/completions",
"llm_api_key": "sk-..."
}},
{"name": "board", "enabled": false, "config": {}},
{"name": "log", "enabled": false, "config": {"retention_days": 90}}
]
}Dependencies
Runtime | Dev | Optional (admin) |
|
|
|
|
|
|
|
| |
|
| |
|
Testing & Quality
pytest # 289 tests, all pass
pytest --cov # 98% line coverage (excluding admin)
pytest tests/test_backbone/ # backbone only
pytest -k "concurrent" # concurrency tests
ruff check . # zero warnings
mypy --strict . # zero type errorsWhat's tested
Unit: server lifecycle, registry CRUD, router dispatch, event bus pub/sub, database migrations, plugin loading, auth middleware, typed wrappers, MCP schema generation, error format compliance, tool description format
Integration: full server lifecycle with Chat plugin, multi-agent registration, concurrent message posting and reading, event-driven agent lifecycle hooks
Concurrency: simultaneous agent registration, concurrent channel creation (lock-guarded), parallel message writes under WAL mode
Edge cases: empty names rejected, channel limits enforced, message limits validated, non-existent channels return empty not error, orphan message threading accepted, LLM failures degrade gracefully
Roadmap
Plugin | Status | Reference |
Backbone (transport, registry, router, event bus, plugins) | β Complete |
|
Chat (channels, messages, await, summarization) | β Shipping |
|
Admin CLI (Textual TUI for database inspection) | β Working |
|
Board (structured shared workspace, versioned keys, JSON Schema) | π§ Designed |
|
Lock/Signal (mutual exclusion locks, inter-agent signals) | π§ Designed |
|
Log (activity audit, failure tracking, cost projection) | π§ Designed |
|
Memory (long-term key-value store, semantic search) | π Research |
|
Plugin Development
Plugins subclass AgoraPlugin and override what they need. All hooks default to no-op:
from agora.backbone import AgoraPlugin, ToolDef
class GreeterPlugin(AgoraPlugin):
name = "greeter"
version = "0.1.0"
description = "A friendly greeter plugin"
async def on_load(self, config: dict[str, object]) -> None:
self.greeting = config.get("greeting", "Hello")
async def on_startup(self) -> None:
print(f"{self.name} started")
def get_tools(self) -> list[ToolDef]:
return [
ToolDef(
name="greet",
handler=self._handle_greet,
description="Greet someone by name",
),
]
async def _handle_greet(
self, name: str, **kwargs: object,
) -> dict[str, object]:
return {"message": f"{self.greeting}, {name}!"}Then register it in your config:
{"plugins": [{"name": "greeter", "module": "myplugins.greeter",
"class_name": "GreeterPlugin", "enabled": true}]}The Name
The Agora (from ancient Greek αΌΞ³ΞΏΟΞ¬ agorΓ‘) was the central square of a Greek polis β the place where citizens gathered to debate, trade, make decisions, and hold each other accountable. Socrates held philosophy there. Democracy was practiced there. It was not a temple (hierarchy) or a palace (command) but a shared environment that the community co-inhabited.
This project is named after that idea: a shared persistent space where agents coordinate through the environment, not through point-to-point commands. The concept is inspired by blackboard architecture research (PatchBoard, LbMAS, BIGMAS).
References
reference/META.mdβ vision, name origin, research backingreference/ARCHITECTURE.mdβ full design document, startup/shutdown sequencereference/DECISIONS.mdβ implementation decisions logreference/CONVENTIONS.mdβ capability vocabulary, manifest standardsreference/NNN-*.mdβ per-plugin design documentsPatchBoard (arXiv:2605.29313) β environment-mediated communication outperforms peer-to-peer
LbMAS (arXiv:2507.01701) β blackboard architecture for LLM multi-agent systems
BIGMAS (arXiv:2603.15371) β "agents don't talk to each other β they all write to and read from a single shared workspace"
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/CopperEagle/agora'
If you have feedback or need assistance with the MCP directory API, please join our Discord server