Skip to content

feat(mcp): Week 3-ready — cohort defaults, transcripts, update_profile, retire stdio bridge - #45

Merged
unforced merged 1 commit into
mainfrom
feat/mcp-week3-ready
May 4, 2026
Merged

feat(mcp): Week 3-ready — cohort defaults, transcripts, update_profile, retire stdio bridge#45
unforced merged 1 commit into
mainfrom
feat/mcp-week3-ready

Conversation

@unforced

@unforced unforced commented May 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Sharpens the LVB MCP for tonight's Week 3 (Connectors) session. Students will drop the MCP into Claude.ai via the browser-OAuth flow and play with it — this PR makes that landing soft.

Changes

Retire stdio bridge (mcp-server/ directory deleted)

The HTTP MCP at /mcp + Claude.ai's browser-OAuth integration is the standard path; stdio (npm install @learnvibe/mcp-server + env var) was a parallel surface whose tool names had drifted from the HTTP MCP (get_lessons vs list_lessons, read_lesson vs get_lesson, etc.). One canonical surface now, one set of names.

Smart cohort defaults on list_lessons + get_lesson

New resolveActiveCohortSlug(db, userId) helper picks the latest non-dropped enrollment. Demo-ergonomic: a student can ask "what did we cover in weeks 1 and 2" without naming a cohort, and Claude doesn't need to chain through get_my_profile first. Tool descriptions tightened to make the natural chain obvious (list → get).

list_lessons now also returns a hasTranscript flag per lesson so Claude can know up-front whether get_lesson will give it transcript content for that week.

Surface transcripts on get_lesson

Bug catch. get_lesson previously returned contentMarkdown only — the recordingUrl and transcriptMarkdown columns existed (populated by the transcribe-week.sh pipeline from #20) but the tool didn't expose them. Now both are in the response. This is what makes lessons into living context (the recording is what actually happened in the room, not just the plan), and makes queries like "summarize what I missed from week 2" land well.

update_my_profile (new tool)

Lets students fill out name/bio/location/website/github via MCP. A lot of folks haven't set names yet; this becomes a natural Week 3 "try it on your own data" moment.

  • Email + role are read-only (email = Clerk source-of-truth; role = admin-only)
  • Pass only the fields you want to change; empty string clears, undefined leaves alone
  • Returns the updated profile + which fields actually changed

Demo questions for tonight (curated set)

These exercise the new behavior end-to-end:

  1. "What did we cover in weeks 1 and 2 of LVB?" — exercises cohort default + list_lessons + get_lesson chain
  2. "Pull the week 2 transcript and ask me 5 reflection questions about my living document" — exercises the new transcript surface
  3. "Summarize the three-relationships frame from week 1" — deep-dive single lesson
  4. "What's my progress in the cohort?" — list_lessons completion flags
  5. "Update my profile — set my bio to '<…>' and github to '<…>'" — write-action via update_my_profile
  6. "Show me other students' artifacts from week 2" — list_artifacts
  7. "Mark week 2 as complete for me" — toggle_lesson_complete (write action, low risk)

Test plan

  • npx tsc --noEmit clean (CI runs too)
  • After deploy + Aaron's live test in Claude.ai:
    • "What did we cover in weeks 1 and 2?" → list + 2× get_lesson, both responses include transcript
    • "Update my profile name to 'X'" → returns updated profile, name persists in /admin/accounts
    • Listing without cohortSlug returns Cohort 1 lessons (Aaron's enrolled cohort if testing as admin… actually, Aaron may not be in enrollments for cohort-1 since he's a facilitator; if so, the resolver returns null and the tool errors with a clear "pass cohortSlug explicitly" message — that's the right fallback. Worth verifying as a test of the error path.)

Notes

  • No DB schema changes — pure code + a directory deletion.
  • No migration.
  • First PR exercising CI since feat: link interests to users + funnel continuity (#44) #44 — typecheck job should run.
  • Aaron's users row may not have an enrollments record for cohort-1 (he's the facilitator). If the cohort-default returns null on his account, the tool prompts for cohortSlug explicitly. Easy demo flow either way: pass cohortSlug: 'cohort-1' once at the start and Claude will reuse it.

Setup-guide block for Week 3 lesson body

Aaron — drop this into the Week 3 lesson markdown via the admin UI. Adjust copy to taste:

## Connect the Learn Vibe Build MCP to your Claude

This week you'll connect your Claude to LVB itself — your cohort, your lessons, your progress, your profile — and let Claude work with that data on your behalf. This is what a Connector feels like in practice.

### One-time setup

1. Open Claude.ai → **Settings → Integrations** (or "Connectors" in the sidebar)
2. Click **Add custom MCP server**
3. Name: `Learn Vibe Build`
4. URL: `https://learnvibe.build/mcp`
5. Click through the authorization flow — you'll sign in with the same email you use for LVB
6. Done. Open a new chat; you should see "Learn Vibe Build" in the integrations panel.

### Try these prompts

- "What did we cover in weeks 1 and 2 of LVB?"
- "Pull the week 2 transcript and ask me 5 reflection questions about my living document."
- "Update my profile — set my name to <your name> and bio to <a sentence about you>."
- "Show me other students' artifacts from week 2."
- "What's my progress in the cohort? What's left to do?"
- "Mark week 2 as complete for me."

Notice the shape: you ask in your own words; Claude figures out which tool to call, calls it, and uses the response. You don't think about endpoints or auth — you think about what you want.

That's the point of Connectors.

🤖 Generated with Claude Code

…e, retire stdio bridge

Tonight's Cohort 1 Week 3 session is on Connectors. The teaching artifact
is the LVB MCP itself — students drop it into their Claude.ai and play.
This sharpens the MCP for that demo:

## Retire stdio bridge

Delete mcp-server/ entirely. The HTTP MCP at /mcp + Claude.ai's
browser-OAuth integration is the standard path; stdio (npm install +
env var) was a parallel surface that kept drifting from the HTTP
tool names. One canonical surface, one set of names.

## Smart cohort defaults

list_lessons and get_lesson previously required cohortSlug. Now both
fall back to the caller's "active enrolled cohort" when omitted —
new resolveActiveCohortSlug() helper picks the latest non-dropped
enrollment. Demo-ergonomic: students can ask "what did we cover in
weeks 1 and 2" without naming a cohort, and Claude doesn't need to
chain through get_my_profile first.

Tool descriptions tightened to make the chain obvious to Claude:
list_lessons returns titles/dates and a hasTranscript flag; the
description points at get_lesson(weekNumber=N) as the natural
follow-up for deep content.

## Surface transcripts on get_lesson

Previously get_lesson returned contentMarkdown only — recordingUrl
and transcriptMarkdown columns existed but the tool didn't expose
them. Now both are in the response. This is what makes the lesson
into living context (the recording is what *actually happened*
versus the lesson plan), and is what makes "summarize what I missed
from week 2" land well.

## update_my_profile (new tool)

Lets students fill out name/bio/location/website/github via MCP.
A lot of folks haven't set names yet; this becomes a natural Week 3
"try it on your own data" moment. Email and role are read-only
(email = Clerk source-of-truth; role = admin-only). Pass only the
fields you want to change; empty string clears, undefined leaves
alone. Returns the updated profile + which fields changed.

Closes the Week 3 readiness work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@unforced
unforced merged commit b05e16b into main May 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant