board-clerk
Click on "Deploy 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., "@board-clerkIngest this board meeting transcript and show what was decided."
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.
Board Clerk MCP
Streamable-HTTP MCP server for the MinutesDesk board-clerk loop: ingest a clean transcript, list what the board decided, confirm a mover or seconder, and approve minutes. It keeps that state per board across sessions. Protocol 2025-11-25. Server name board-clerk, version 0.3.0.
Judge walkthrough: docs/JUDGES.md. Assistant instructions: skills/board-clerk/SKILL.md.
All meetings, names, and organizations in this repo are synthetic and fictional. The server does not call a model and does not send email.
Judge quick start
MCP:
https://lumegrid-board-clerk-v02.lumegridai.workers.dev/mcpSimulated Alexa+ page:
https://lumegrid-board-clerk-v02.lumegridai.workers.dev/demo
npx @modelcontextprotocol/inspector --cli https://lumegrid-board-clerk-v02.lumegridai.workers.dev/mcp --transport http --method tools/listThe /demo page is a simulated Alexa+ experience, not an Alexa device. It calls /mcp (initialize 2025-11-25, then tools/call). Speech recognition, when the browser has it, is input only. The page does not speak.
On first load the page calls start_demo_board with a random judge- id stored in localStorage (boardClerkDemoBoardId), so a judge is not writing on the shared demo board. ?board=<id> reuses a board. ?reset=1 starts a fresh isolated board. Judge boards are isolated by board_id.
Live: https://lumegrid-board-clerk-v02.lumegridai.workers.dev (MCP at /mcp, demo at /demo) was redeployed Sun Oct 11 ~10:25 PM MDT from commit d2ec60c with round 4 (16 tools, read-only shared board, prepare_board_packet, decision card, Agent Skill). Remote smoke and Inspector tools/list (16 tools) passed after deploy; a write to juniper-hollow-demo returns the read-only error. npx wrangler dev serves this checkout locally.
wrangler.toml name is lumegrid-board-clerk-v02, the judge worker. A future deploy of this file would publish onto that host, not onto the old lumegrid-board-clerk-mcp worker. That old host still answered GET / as version 0.1.0 on the same check, and its health JSON still carries the old withdrawal sentence. This checkout did not deploy, so both live workers are unchanged.
Local worker (does not deploy):
npx wrangler devHealth: GET / and GET /health. MCP: /mcp. Demo: /demo. Transcript: GET /demo/transcript.txt.
Related MCP server: personal-meeting
Tests
npm test # node --test test/
npm run test:engine # offline fixture smoke
npm run test:mcp-local # in-process MCP smokenpm run test:remote -- <baseUrl> runs the same ingest, confirm, and approve flow over HTTP against that URL, using a random board id, then calls reset_board. It is not part of the offline suite.
Tools
Tool | What it does |
| Meetings on this board |
| Motions and attribution status |
| One motion |
| Short decision card |
| Search; |
| Motions on one topic across meetings, approved dollar total, open confirmations, tabled items |
| Mover or seconder still unconfirmed |
| Store a roster name for a later session |
| Markdown draft; approval is still required |
| Rule-based extract of a |
| Record a pending approval; nothing is emailed |
| Recorded approval requests |
| Approve, or refuse while a name is unconfirmed |
| Who did what, and when |
| Clear layered state for this board |
| Copy the two Juniper fixtures onto a new board |
Resources: board://{board_id}/roster, board://{board_id}/meetings, and ui://board-clerk/decision-card (text/html;profile=mcp-app). Prompt: ask_the_board.
get_decision and what_did_we_decide set _meta.ui.resourceUri to that card. Text and structuredContent are still returned for clients that do not render UI. Installed @modelcontextprotocol/server 2.3.1 copies tool _meta onto tools/list and can register a static resource at a ui:// URI. It does not export registerAppTool or registerAppResource, and this server does not advertise io.modelcontextprotocol/ui. No MCP Apps host was run. The in-process tests check the resource bytes and the tool link only, not an iframe.
Every tool has a title and annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint: false). Pass board_id when you have one. The pattern is ^[a-z0-9-]{3,40}$. Omitted, it is juniper-hollow-demo, which is read-only for writes.
State
BoardState is a SQLite Durable Object, one instance per board id (BOARD_STATE). It stores ingested meetings, confirmations, approval requests, and an audit log. MemoryStore speaks the same POST /op JSON RPC for tests and for a worker with no binding.
Fixtures are not stored. Reads of juniper-hollow-demo layer them under any meetings already stored and set demo_board: true. ingest_meeting, confirm_mover_seconder, request_minutes_approval, approve_minutes, and reset_board return isError on that id and tell the caller to use start_demo_board with their own id. start_demo_board deep-copies juniper-2026-08-20 and juniper-2026-09-17 onto that id and refuses juniper-hollow-demo.
A new handler that shares the same store sees earlier confirms and ingested meetings. A different board_id does not.
Guardrails
approve_minutesreturnsisErrorwhile any mover or seconder on that meeting isNEEDS CONFIRMATION.confirm_mover_seconderaccepts a roster full name, first name, or last name (case-insensitive), stores the full name, and otherwise returnsisErrorwith the roster. The value is at most 80 characters. The engine helper used by the offline tests stays permissive; the MCP tool is what normalizes.Transcripts are capped at 200 KB, ingested meetings at 25 per board, approval requests at 40, and audit entries at 200.
approver_nameandconfirmed_byare capped at 80 characters./mcprejects a presentOriginthat is nothttp://localhost(any port),http://127.0.0.1(any port), or the worker's ownhttps://*.workers.devorigin. A missingOriginis allowed.https://localhostandOrigin: nullare rejected. The error body does not echoOrigin. Any other path thanGET /,GET /health,GET /demo,GET /demo/transcript.txt, and/mcpis 404, so the checks cannot be skipped.POST /mcpbodies over 256 KB get 413.Tool failures are tool results with
isErrorand a message that names the board, the roster, the limit, or the next call to make.
Accuracy
A name is marked SPOKEN only when it is said within −45s to +30s of the motion. Otherwise the field is NEEDS CONFIRMATION and a person confirms it in one step. That window is unit-tested on synthetic lines in test/namerule.test.mjs. The rule-based extractor covers clean synthetic [HH:MM:SS] Speaker: transcripts only. This server does not call a model.
A separate Gemini MinutesDesk pipeline test, not this extractor, reported 24/24 motions and outcomes, movers 16/24, and seconders 14/24 on 5 public meetings. This repository does not compute those ratios and does not call Gemini. An outside note did not accept that run as checked against the recordings. Do not treat the ratios as recording-verified, and do not treat them as this server's score.
ingest_meeting runs crosscheck only when the caller passes second_pass_motions. A disagreement whose flag starts with passes disagree on mover: or passes disagree on seconder: sets that attribution to NEEDS CONFIRMATION. The server still does not call Gemini.
what_did_we_decide answers in at most two sentences, with dates like "August 20th" and amounts as written in the motion (not rewritten as dollars). If the mover or seconder is unconfirmed, the answer says so. If a topic word is not in any motion, the first sentence says that and the second sentence is the closest match. It does not pretend the closest match is the thing that was asked. prepare_board_packet uses the same topic score. Approved dollar totals are parsed from motion text only, and only for a passed motion that is not a tabling motion. A missing topic word is named in the spoken summary.
This server cannot be deployed
Maintenance
Related MCP Connectors
- AlignOAuthcom.meet-align
Your team's meetings, decisions and tasks: ask what was decided, who owns what, what's due.
Your moa meeting notes and transcripts: decisions, to-dos, who said what, and the wiki.
1The context layer for your company's AI: your team's decisions, meetings and plans, with sources.
- mcpOAuthcom.attendmeet
Bring meeting decisions, tasks and user stories into your AI editor (Claude, Cursor, Copilot).
Related MCP Servers
- FlicenseNot gradedqualityAmaintenanceProvides organizational memory for AI agents, enabling shared company memory, decision recall, artifact management, approval review, task delegation, and initiative tracking.2-
- AlicenseAqualityCmaintenanceEnables creating meeting minutes from unstructured meeting memos with validation, grounding checks, and user-approved saving.11MIT
- AlicenseAqualityCmaintenanceEnables reading unstructured meeting notes, generating meeting minutes drafts, validating them against source text, and saving approved versions through a local MCP server.11MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to track session lifecycles, persist context notes and transcripts, and manage a human-gated memory-promotion pipeline with an append-only audit trail.1 npm1MIT