Dirextalk Message Server is Dirextalk's backend contract authority. It combines a Matrix-compatible homeserver, the ProductCore action API, product policy, projections, Native Agent, external MCP access, and PostgreSQL-backed runtime storage in one Go monolith.
It is based on Element Dendrite, but this repository is maintained as a Dirextalk product server rather than a general-purpose Matrix homeserver distribution.

Each personal node keeps one contract boundary for Matrix, ProductCore, and Native Agent:
- Matrix is the source of truth for rooms, membership, ordinary messages, media, history, search, unread state, and redaction.
- ProductCore actions provide the authenticated product facade for validation, remote forwarding, Matrix write orchestration, and projection reads.
- PostgreSQL-backed P2P tables are projection/read models unless a current contract explicitly makes a record authoritative.
- Native Agent and
POST /mcpare backend-owned capabilities. They are not installed, configured, or invoked through the plugin lifecycle. BYOK web search accepts a Tavily key only in the request-scopedtool_credentials.web_searchobject and never persists it.
- Production entry point:
cmd/dirextalk-message-server - Compatibility entry point:
cmd/dendrite - Docker image:
dirextalk/message-server:latest - Default config path in Docker:
/etc/dirextalk-message-server/message-server.yaml - Default data path in Docker:
/var/dirextalk-message-server - Go module:
github.com/YingSuiAI/dirextalk-message-server - Go version:
1.26.5 - Server database: PostgreSQL only; SQLite and file DSNs are unsupported.
- Docker development database: PostgreSQL 18
Matrix protocol routes remain under:
/_matrix/*/_synapse/*/_dendrite/*/.well-known/matrix/*
Dirextalk product APIs use the body-action surface:
GET /_p2p/healthPOST /_p2p/queryPOST /_p2p/commandGET /_p2p/wsGET /.well-known/portal/owner.json
The generated ProductCore action metadata is
client.request/server.response over the realtime WebSocket
and use HTTP query/command fallback when realtime is not ready. External MCP
clients use JSON-RPC over POST /mcp with an agent_token.
Authentication and transport boundaries:
- Owner ProductCore actions use
Authorization: Bearer <access_token>. realtime.ws_ticket.createissues a short-lived single-use owner ticket;GET /_p2p/wsaccepts that ticket, not a bearer token.agent_tokenis limited toagent.matrix_session.createand the standardPOST /mcpendpoint; it cannot create an owner WebSocket ticket or call owner actions.
Product requests use this envelope:
{
"action": "channels.public.get",
"params": {
"room_id": "!room:dendrite-a:8448",
"remote_node_base_url": "https://dendrite-a:8448/_p2p"
}
}