MCP: connect any AI to the board
Chalkmind is an MCP server. With it, claude.ai, Claude Desktop, Claude Code or any other MCP client (agent) can teach on the board live, as one of its tenant's teachers.
- Hosted: the board server speaks MCP over HTTP at
/v1/mcp(Streamable HTTP). A client needs only the address and its key. - On a computer:
server/bin/mcp.tsspeaks MCP over stdio, one message per line. - One connection, both ways:
server/src/mcp.tsis one connection either way (JSON-RPC 2.0, no SDK). It sends each tool call to the board's HTTP API with the client's key, so a tool does exactly what that key may do.
Connecting to the hosted board
claude mcp add --transport http chalkmind https://HOST/v1/mcp --header "Authorization: Bearer cm_…"
Other clients take the same address and header. How a session works:
- It starts with
initialize. The answer'sMcp-Session-Idgoes with every later message. - It is bound to its key. The same session id sent with another key is answered 404.
- It ends. A
DELETE /v1/mcpwith the session id ends it, and a session nobody used for 2 hours is dropped. - It is not for web pages. A browser call from another site's page (its
Origin) is refused.
A key that may manage its tenant also gets teacher_save and teacher_book_add.
Connecting on a computer (stdio)
The client's machine needs Node 22 (for --experimental-transform-types) and this project.
Claude Code:
claude mcp add liveboard -- node --experimental-transform-types --no-warnings /abs/path/liveboard/server/bin/mcp.ts --board http://127.0.0.1:4620
Claude Desktop and other clients (mcpServers in their config):
{
"mcpServers": {
"liveboard": {
"command": "node",
"args": ["--experimental-transform-types", "--no-warnings", "/abs/path/liveboard/server/bin/mcp.ts", "--board", "http://127.0.0.1:4620"]
}
}
}
| Option | Default | Meaning |
|---|---|---|
--board URL | http://127.0.0.1:4620 | the board server |
--channel NAME | demo | the channel the students watch (board_start can change it) |
--wait SECONDS | 20 | how long board_write waits for its lines to be laid out |
--key KEY | LIVEBOARD_API_KEY | the board's API key for this channel's tenant; a board started with keys refuses calls without it (401) |
--manage | off | also list teacher_save and teacher_book_add (the key must be one that may manage its tenant) |
Resources
liveboard://guide: AI_GUIDE.md, what the board can do and every command.liveboard://teaching: the teaching skill, how a good teacher teaches with it.
board_start carries both (and the library's names) in its reply, because many clients do not read resources.
Tools
src/mcp.ts has one TOOLS table: an entry per tool (name, description, input schema, HTTP route), so a new tool is one new entry. The lesson routes are under /board/:channel.
| Tool | Input | HTTP | What it does |
|---|---|---|---|
board_start | channel?, title?, guide?, learner?, lang?, teacher? | POST /session | A new lesson on a clean board, as one of the tenant's teachers (teacher), in its language unless lang names one. The reply carries the board's instructions, taken from the board server (GET /guide): the guide, the tool rules with the library's names, the teacher's instructions, and the teaching skill (unless guide: false), because many clients do not read resources. It also gives the students' link, with a viewer token. |
board_teachers | id? | GET /teachers, GET /teachers/:id | The teachers the key may teach as; with id, one teacher's subject, learners, style, book and library. |
board_book | chapter?, search? | GET /teachers/:id/book | The lesson's teacher's book: a chapter whole, or the passages with a word. |
teacher_save | id, name?, subject?, level?, lang?, style?, notes?, std?, library?, from? | PATCH /teachers/:id, else POST /teachers | Makes a teacher of the tenant's own, or changes the fields given (a manage key only). |
teacher_book_add | id, chapter, title, text, lang? | POST /teachers/:id/book | A chapter of a teacher's book (a manage key only). |
board_write | lines | POST /lines | Sends lines and waits (up to --wait) for them to be laid out. It returns any refused line with its reason and hint, so the AI fixes it at once, how much lesson is queued, the free lines left and what is on the board with its ids. It also returns the students' questions asked on their screens since the last call (GET /doubts?take=1), to answer at this step. |
board_library | kind?, category?, search? | GET /library/search (this project's copy if the server cannot be asked) | The ready stamps, labelled diagrams, formulas and lesson patterns (LIBRARY.md): what each is, a diagram's part ids and labels, found by kind, category or a word. board_start already lists the names. |
board_state | GET /state | What is on the board now: every item's id, kind, box [x, y, w, h], line and text; figure points (fig.A); the cursor, the text column and the free lines; how far the board is behind the voice; hold; problems. | |
board_status | GET /problems, GET /film | How many lines came, how many seconds of lesson are laid out and where the students are, the steps, every problem. | |
board_hold | POST /hold | Pauses the lesson on every screen (chalk and voice). | |
board_resume | POST /resume | Continues a held lesson from where it stopped. | |
board_teach | problem, lang? | POST /teach | The board server's own Claude teaches the problem. |
board_command | text, lang?, fresh? | POST /command | An instruction for the board's own teacher on the board as it is ("explain the second step again", a student's question), or on a fresh board. |
board_end | POST /end | Ends the lesson. |
Order:
board_start,board_write,board_status,board_teachandboard_endrun one after another, in the order they came, so lines reach the board in order.board_state,board_holdandboard_resumenever wait behind them, so a lesson can be held even during a longboard_teach.
Descriptions tell the AI to read the guide first, and to send lines in small pieces as it thinks of them (a say and the few lines it explains), never the whole lesson in one block.
Resource and prompt
| Name | What | |
|---|---|---|
| Resource | liveboard://guide | AI_GUIDE.md, the board language |
| Prompt | teach {problem} | the guide, how to use the tools, and the problem to teach (the same request as bin/teach.ts) |
How a lesson goes
board_start {title}: the board is cleaned and the guide comes back.board_write, again and again:board 0.1, then asayand its lines, in small pieces.- The result lists refused lines, for example
did you mean "write"?forwrte:, or "left side is 6, right side is 7" for a wrong calculation. Those lines are not on the board, so the AI sends only the corrected lines and goes on. - When needed:
board_state: before pointing at or erasing an item, or to decide when toclear;board_holdandboard_resume.
board_end.
Notes:
- Line numbers count from the start of the lesson.
- With DamruVani, a
sayline waits for its clip, so problems found after--waitcome with the nextboard_writeorboard_status. - Each problem is reported once;
board_statusshows them all again.
Test
server/test/mcp.test.ts (part of npm test):
- It runs the real
serve.tson a free port (estimated narration, no keys) and drivesmcp.tsover stdio. It covers:initialize,tools/list, the guide resource and the prompt- protocol errors
- a whole lesson: refused lines with hints, corrections, an open calc block,
board_end, and writing to a finished lesson - a closed board
- A small stand-in board serves
/state,/hold,/resumeand/teach. The test checks that each tool calls its route, and thatboard_holddoes not wait behind a slowboard_teach.