Skip to content

feat(chat): add embedded assistant and MCP workflows#5109

Open
rschlaefli wants to merge 70 commits into
v3-aifrom
codex/manage-assistant-mcp-v3-ai
Open

feat(chat): add embedded assistant and MCP workflows#5109
rschlaefli wants to merge 70 commits into
v3-aifrom
codex/manage-assistant-mcp-v3-ai

Conversation

@rschlaefli

@rschlaefli rschlaefli commented May 31, 2026

Copy link
Copy Markdown
Member

What This Adds

  • Adds embedded chat entry points for PWA course and microlearning flows, including scoped PWA embed auth, course chatbot drawer/context helpers, and no-login recovery handling.
  • Adds the Manage assistant surface and chat runtime integration for lecturer MCP tools: Manage context propagation, assistant route, proposal review cards, skill/tool rendering, and stateless streaming.
  • Adds apps/mcp-lecturer with auth, authorization, tool policy/error/capability patterns, smoke scripts, tests, and Helm/K8s deployment wiring.
  • Cleans the build setup for plain TypeScript packages by removing Rollup from grading, hatchet, markdown, prisma, and util; GraphQL keeps Rollup with a NodeNext-compatible emit override.
  • Merged latest v3 into v3-ai, then latest v3-ai into this branch; kept @assistant-ui/react-ai-sdk at 1.3.7 to match the existing @assistant-ui/react@0.12.10 runtime.

How It Works

  • Renders embedded chat frames with custom surface context parameters (?embed=true&surface=manage) to allow UI-context-aware assistance.
  • Employs a FastMCP server implementation under apps/mcp-lecturer and apps/mcp-student communicating over streamable HTTP.
  • Uses JWT-based authorization tokens for both lecturer and student MCP routes, signed with the local APP_SECRET.
  • Renamed the shared smoke client to util/mcpSmokeClient.mts to force Node.js to resolve imports as ES Modules under Node 24, avoiding ESM/CommonJS interop failures for standalone run scripts.

Branch Coverage

  • Base: v3 (via v3-ai)
  • Head: 8e0c851b9a
  • Reviewed: All commits on the branch since base branch.
  • Covered: apps/mcp-lecturer, apps/mcp-student, apps/chat integration, and build setup refactoring.

Verification

Current head (8e0c851b9a):

  • pnpm --filter @klicker-uzh/mcp-lecturer test -> 33/33 tests passed
  • pnpm --filter @klicker-uzh/mcp-student test -> 23/23 tests passed
  • pnpm --filter @klicker-uzh/mcp-lecturer smoke:local --dry-run -> successfully runs and prints config
  • pnpm --filter @klicker-uzh/mcp-student smoke:local --dry-run -> successfully runs and prints config

Earlier branch verification:

  • Full pnpm run build -> all 32 workspace packages built successfully
  • Standard check:all -> formatted and lint-checked

Security / Privacy

  • Review: Checked for sensitive logs, credentials, or leaks in tool implementations.
  • Result: No secrets or raw database payloads are logged during Timing/instrumentation.
  • Sensitive data: Secrets are injected strictly through Infisical dev environments; client tokens are generated dynamically for local runs.

Manual Verification Before Merge

  • Start the local dev dependency stack: ./_run_app_dependencies.sh local
  • Start the MCP servers via:
    • pnpm --filter @klicker-uzh/mcp-lecturer dev
    • pnpm --filter @klicker-uzh/mcp-student dev
  • Run local live smoke verification:
    • pnpm --filter @klicker-uzh/mcp-lecturer dev -- pnpm run smoke:local
    • pnpm --filter @klicker-uzh/mcp-student dev -- pnpm run smoke:local

ClickUp Links

@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a lecturer MCP service and deployment, Manage assistant runtime + widget with proposal confirmation, chat/manage context types/hooks/store integrated into chat routes and UI, PWA course chat drawer and GraphQL chatbot API, Helm/CI packaging, and tests/docs.

Changes

Complete PR checkpoint

Layer / File(s) Summary
CI workflows & Dockerfiles
.github/workflows/*, apps/mcp-lecturer/Dockerfile, apps/frontend-manage/Dockerfile
New GitHub Actions to build/push mcp-lecturer images and Dockerfiles/ARGs for mcp-lecturer and frontend-manage.
Manage assistant API routes & runtime
apps/chat/src/app/api/manage/*, apps/chat/src/services/manageAssistant*, apps/chat/src/services/manageProposals.ts
Adds manage chat streaming POST route, proposal confirmation API, manage assistant system prompt/model selection, skills, and manage-proposal GraphQL request/confirmation helpers.
Frontend Manage widget & embedding
apps/frontend-manage/src/components/assistant/*, apps/chat/src/app/manage/page.tsx, apps/chat/src/components/manage-assistant.tsx
Adds ManageAssistant widget, iframe handshake, manageContext builders, embedded manage hook, and a Manage page with runtime provider wiring.
Chat context types, hooks, store, and integration
packages/types/src/chatContext.ts, apps/chat/src/services/*, apps/chat/src/hooks/*, apps/chat/src/stores/*, apps/chat/src/app/api/chatbots/*
Defines Klicker chat/manage context types and sanitizers, embedded chat/manage hooks and store, integrates chatContext into chat route and useChatResponse payloads.
Thread UI, avatars, tool labels, and manage proposal UI
apps/chat/src/components/thread.tsx, apps/chat/src/components/chatbot-avatar.tsx, apps/chat/src/components/tool-labels.ts, apps/chat/src/components/manage-proposal-card.tsx, apps/chat/src/components/tool-fallback.tsx
Extends Thread props/welcome/suggestions, adds ChatbotAvatar, tool label formatter, renders ManageProposalCard for proposal results, and updates composer/button sizing for embedded mode.
PWA Course chat drawer & practice-quiz integration
apps/frontend-pwa/src/components/chatbot/*, apps/frontend-pwa/src/pages/course/*, apps/frontend-pwa/.env.stg
Adds CourseChatDrawer with iframe postMessage/context ack retry, SSR chatbot entry page with participation gating, practice-quiz chatContext generation, and staging env var.
GraphQL: chatbot public type & service
packages/graphql/src/schema/*, packages/graphql/src/services/chatbots.ts
Adds ChatbotPublic GraphQL type, courseChatbots query, and service that returns public chatbot fields for active participants.
mcp-lecturer service, auth, JWT, server, and read service
apps/mcp-lecturer/*
Implements lecturer MCP package: package.json, JWT sign/verify, auth/authorization, RuntimeSettings, FastMCP server, read service with Zod schemas and Prisma wiring, Dockerfile, tsconfigs, Vitest config, and tests.
Helm charts, values, and deployment templates
deploy/charts/klicker-uzh-v3/templates/*, deploy/*/values.yaml
Adds mcp-lecturer Helm templates (ConfigMap, Deployment, Service, HPA, PDB), updates cm-chat to include MCP_LECTURER entries, and adds values for staging/production.
Tests: vitest suites and test updates across modules
apps/chat/test/*, apps/mcp-lecturer/test/*, packages/graphql/test/*, various test harness updates`
Adds many unit/integration tests for chat context, manage proposals, mcpAuthMint, manage assistant runtime/skills, mcp-lecturer server/service/auth, GraphQL service, and adjusts existing test mocks.
i18n, docs, plans, and tooling updates
packages/i18n/*, AGENTS.md, project/plans_wip/*, turbo.json
Adds translations for chatbot/manage assistant, AGENTS.md learnings, new project plans for lecturer/manage assistant, and extends globalEnv allowlist.

Estimated code review effort
🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.84% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title 'feat(chat): add embedded assistant and MCP workflows' clearly and concisely summarizes the main changes: adding embedded assistants and MCP (Model Context Protocol) workflows to the chat system, which is the primary focus across the changeset.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@rschlaefli rschlaefli force-pushed the codex/manage-assistant-mcp-v3-ai branch from cb96071 to a35778a Compare May 31, 2026 07:25
@greptile-apps

greptile-apps Bot commented May 31, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

Safe to merge after addressing the open items from previous review threads and validating cookie sharing between the manage and chat subdomains in staging.

The core auth flows (session verification, MCP JWT minting, proposal token sign-and-verify, APQ-only mutation forwarding) are implemented defensively and tested. The postMessage bridges are correctly origin-validated on both ends. The one new finding — the 'open in new tab' link using the embed URL — is a minor UX edge case that does not affect the main assistant functionality.

apps/frontend-manage/src/components/assistant/ManageAssistantWidget.tsx — the new-tab href should use a non-embedded URL to preserve the full login-recovery UI.

Important Files Changed

Filename Overview
apps/chat/src/app/api/manage/chat/route.ts New POST route for the Manage assistant: validates auth, sanitizes context, loads MCP tools, streams AI responses. MCP tool loading failure is handled gracefully with a silent fallback.
apps/chat/src/app/api/manage/proposals/confirm/route.ts Proposal confirmation route: verifies user identity, JWT proposal token, and forwards APQ mutation to GraphQL with proper CSRF headers. getGraphqlEndpoint() has a silent localhost fallback when APP_ORIGIN_API is missing (flagged in a previous review thread).
apps/chat/src/services/manageProposals.ts Builds APQ-only GraphQL requests (no inline query body), verifies signed proposal tokens, and executes confirmation mutations. All errors are normalized to a generic token error to prevent leaking verification details.
apps/chat/src/lib/server/manageAuth.ts Reads the next-auth session cookie and verifies it with APP_SECRET to authenticate manage lecturers in the chat app.
apps/mcp-lecturer/src/server.ts FastMCP server with bearer-token auth, read/draft tool separation, and signed proposal generation. Error normalization prevents leaking authorization details to the model.
apps/mcp-lecturer/src/service.ts Read service backed by Prisma with userId-scoped DerivedPermission filters on every query; double-checked with requireDerivedPermission after data retrieval. Content fields are capped to prevent token blowout.
apps/frontend-manage/src/components/assistant/ManageAssistantWidget.tsx Iframe-based Manage assistant widget with postMessage context bridge, ack retry, and keyboard/focus management. The 'open in new tab' link reuses the embed URL; a non-embedded URL should be derived separately (see comment).
apps/frontend-pwa/src/components/chatbot/CourseChatDrawer.tsx Course chatbot drawer with origin-validated postMessage context bridge; correctly separates embedded iframe URL from non-embedded new-tab href.

Sequence Diagram

sequenceDiagram
    participant Manage as Manage App
    participant ChatApp as Chat App
    participant MCP as mcp-lecturer
    participant GQL as GraphQL API

    Note over Manage,ChatApp: Embedded assistant (iframe)
    Manage->>ChatApp: "iframe src=/manage?embed=true"
    Manage->>ChatApp: postMessage klicker:manage-context
    ChatApp-->>Manage: postMessage klicker:manage-context-ack

    Note over ChatApp,MCP: Chat request
    Manage->>ChatApp: POST /api/manage/chat (session cookie)
    ChatApp->>ChatApp: getAuthenticatedManageUserId()
    ChatApp->>ChatApp: mintLecturerMcpJwt(userId)
    ChatApp->>MCP: Bearer JWT
    MCP->>MCP: verifyLecturerSession()
    MCP-->>ChatApp: MCP tool list
    ChatApp-->>Manage: SSE stream

    Note over ChatApp,GQL: Proposal confirmation
    Manage->>ChatApp: POST /api/manage/proposals/confirm
    ChatApp->>ChatApp: verifyManageProposalToken()
    ChatApp->>GQL: POST /api/graphql (APQ)
    GQL-->>ChatApp: manipulateChoicesQuestion
    ChatApp-->>Manage: element created
Loading

Fix All in Codex Fix All in Claude Code

Reviews (7): Last reviewed commit: "fix(security): avoid test url hotspots" | Re-trigger Greptile

Comment thread apps/chat/src/services/manageProposals.ts
Comment thread apps/chat/src/app/api/manage/proposals/confirm/route.ts Outdated
Comment thread packages/graphql/src/services/chatbots.ts Outdated
@greptile-apps

greptile-apps Bot commented Jun 18, 2026

Copy link
Copy Markdown

Too many files changed for review. (168 files found, 100 file limit)

Bypass the limit by tagging @greptile-apps to review.

@dosubot dosubot Bot added size:XS This PR changes 0-9 lines, ignoring generated files. and removed size:XXL This PR changes 1000+ lines, ignoring generated files. labels Jun 18, 2026
@gitguardian

gitguardian Bot commented Jun 18, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 2 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
14050276 Triggered Generic Password db1c87b .github/workflows/playwright-testing.yml View secret
1509424 Triggered Generic Password db1c87b .github/workflows/playwright-testing.yml View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@rschlaefli rschlaefli changed the title feat(chat): add embedded assistants with MCP support feat(chat): add embedded assistant and MCP workflows Jun 18, 2026
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
6 Security Hotspots
4.3% Duplication on New Code (required ≤ 3%)
D Reliability Rating on New Code (required ≥ A)
D Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@dosubot dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Jun 30, 2026
@rschlaefli

Copy link
Copy Markdown
Member Author

Production readiness review pushed to the branch: project/2026-07-07-pr-5109-production-readiness-review.md (commit 9008f49).

TL;DR: solid merge candidate for v3-ai, not yet production-ready. 2 small confirmed fixes (turbo.json globalEnv gap for MCP_*_SCHEME, any-typed Prisma delegates), 161 tests pass with 0 assertion failures, auth design verified sound at code level. Remaining gap = runtime verification: browser pass over the new drawers/embed flows, staging smoke incl. SSE-through-ingress, kill-switch + rate-limit decisions. The review file contains an ordered, junior-executable checklist with exact commands.

@rschlaefli

Copy link
Copy Markdown
Member Author

Junior runtime feedback verified and incorporated into the review file (commit 109dbf7, findings F5–F9):

  • F5 (high): empty course list confirmed — model passes query: ".*", service does a literal contains match (service.ts:687), and the param has no .describe(). Fix: describe all tool params + treat .*/*/% as no-filter. Plus a staging check for legacy courses without DerivedPermission rows (potential backfill needed).
  • F6: raw course UUIDs in prose — the system prompt literally asks for "names and IDs" (manageAssistantRuntime.ts:14). One-line reword.
  • F7: no chat persistence confirmed — drawer unmounts the iframe on close (CourseChatDrawer.tsx:194); staged fix (CSS-hide, sessionStorage thread id, new-chat button).
  • F8: missing answer context confirmed — context is deliberately answer-safe pre-submission; fix is post-submission context fields via the existing postMessage path, no Prisma change needed.
  • F9: direct-save already exists (confirmManageProposal + proposal card) — the model just routes to the draft-only tools; fix is prompt/tool-description steering.

Checklist steps 1, 5, 7 updated accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature size:XXL This PR changes 1000+ lines, ignoring generated files.

Development

Successfully merging this pull request may close these issues.

4 participants