Problem
Three document read tools make a document reader, and nobody adds a connector for that. The chat room per heading is the one docs.plus feature no competitor has, and the connector cannot reach it.
There is no chat route in apps/hocuspocus.server. The OpenAPI spec carries 49 paths and zero chat paths.
The address already exists, so no schema change is needed. channel_id is the heading toc-id (apps/webapp/src/services/openHeadingChatroom.ts:142), and channels.workspace_id is the documentId. So one messages row names both a document and a section.
What to do
Add three chat tools to the MCP server:
list_chat_rooms — the rooms in a document.
read_chat_thread — the messages under one heading.
post_chat_message — a reply in one room, posted as the signed-in person.
Each reads from an existing Supabase table or RPC, but none of them may call Supabase first. A chat room carries no document-privacy rule, so each tool must resolve the slug to its document row and run resolvePrivateAccess in the application tier BEFORE it touches Supabase. That gate is new server work. Treat Row Level Security as the second gate, never the only one.
Acceptance
Notes
Chat rooms are created lazily. A heading nobody has opened chat on has no channels row. So a room list is always a subset of the outline, never a superset. A tool that treats them as interchangeable reports rooms as missing when they are merely unborn. Say this in the tool description.
messages already carries a unique client_id index, so a retried post is safe. It also carries a monotonic seq, which is a resume cursor.
Chat content is untrusted text from anyone who can open the document, and it flows into the model. Mark these tools accordingly, and do not let a chat message drive a write in this issue.
Promote the shared gate from denyRead and denyWrite at apps/hocuspocus.server/src/modules/document-conversion/http/controller.ts:47-71, which already run resolvePrivateAccess correctly.
Blocked by #226.
Problem
Three document read tools make a document reader, and nobody adds a connector for that. The chat room per heading is the one docs.plus feature no competitor has, and the connector cannot reach it.
There is no chat route in
apps/hocuspocus.server. The OpenAPI spec carries 49 paths and zero chat paths.The address already exists, so no schema change is needed.
channel_idis the headingtoc-id(apps/webapp/src/services/openHeadingChatroom.ts:142), andchannels.workspace_idis thedocumentId. So onemessagesrow names both a document and a section.What to do
Add three chat tools to the MCP server:
list_chat_rooms— the rooms in a document.read_chat_thread— the messages under one heading.post_chat_message— a reply in one room, posted as the signed-in person.Each reads from an existing Supabase table or RPC, but none of them may call Supabase first. A chat room carries no document-privacy rule, so each tool must resolve the slug to its document row and run
resolvePrivateAccessin the application tier BEFORE it touches Supabase. That gate is new server work. Treat Row Level Security as the second gate, never the only one.Acceptance
list_chat_roomsreturns the rooms of a document the caller can read.read_chat_threadreturns messages for one heading, newest last, and truncates at the same limit Mount a stateless MCP server at /api/mcp with the document read tools #226 sets. It says in its result that it truncated, and returns aseqcursor for the next call.post_chat_messageposts under the caller's own identity, never a shared one.post_chat_message.read_chat_threadmarks its result as untrusted content, because anyone who can open the document can write into the room.Notes
Chat rooms are created lazily. A heading nobody has opened chat on has no
channelsrow. So a room list is always a subset of the outline, never a superset. A tool that treats them as interchangeable reports rooms as missing when they are merely unborn. Say this in the tool description.messagesalready carries a uniqueclient_idindex, so a retried post is safe. It also carries a monotonicseq, which is a resume cursor.Chat content is untrusted text from anyone who can open the document, and it flows into the model. Mark these tools accordingly, and do not let a chat message drive a write in this issue.
Promote the shared gate from
denyReadanddenyWriteatapps/hocuspocus.server/src/modules/document-conversion/http/controller.ts:47-71, which already runresolvePrivateAccesscorrectly.Blocked by #226.