Bildungly Mein NOW MCP

Bildungly Mein NOW MCP

An AI-native Weiterbildung discovery layer over Mein NOW course data, providing tools for course search, profile matching, and fit explanation via MCP.

Category
访问服务器

README

Bildungly Mein NOW MCP

An AI-native Weiterbildung discovery layer over Mein NOW course data. The project keeps source ingestion, the independent Supabase intelligence layer, MCP, and the browser experience separate so the same capabilities can later serve Bildungly, hackathon clients, and partners.

Mein NOW API
    ↓ admin-only background sync
Independent Supabase / Postgres
    ↓ normalized providers, runs, chunks, pgvector + full-text search
MCP server (Streamable HTTP or stdio)
    ├── search_courses
    ├── get_course
    ├── match_courses_for_profile
    └── explain_course_fit
    ↓
Bildungly chat UI / MCP clients / future partners

What is included

  • A production-oriented Node/TypeScript MCP server using the stable @modelcontextprotocol/sdk v1 line.
  • Stateless Streamable HTTP at POST /mcp, plus a stdio entry point.
  • Four narrow domain tools, course:// and provider:// resources, and the recommend_weiterbildung_path prompt.
  • A responsive German-first React chat UI with profile context, tool activity, course cards, details, content-level fit evidence, loading, retry, and mobile states.
  • An MCP-backed /api/chat host. It uses a deterministic advisor flow, so an LLM key is not required for the MVP; a generative host can be added later without changing the MCP tools.
  • An independent Supabase schema with private tables, normalized course runs, content chunks, pgvector HNSW indexes, full-text/trigram indexes, and bounded hybrid-search RPCs.
  • Protected Supabase Edge Functions for source sync and gte-small embedding jobs.
  • A six-course demo repository that starts automatically until a complete independent Supabase configuration is present.
  • Tests for ranking, fit evidence, MCP discovery, structured tool results, resources, and prompts.

Quick start

Requirements: Node.js 20.12 or newer.

npm install
npm run dev

Open http://localhost:5173. The UI proxies its API and MCP requests to the server on http://127.0.0.1:8787.

The existing .env is intentionally ignored by Git. The app safely starts in demo mode whenever the independent Supabase URL or secret is absent. Check the current mode at GET /health.

If you add a project URL before applying the migrations, temporarily set DEMO_MODE=true; live mode expects search_courses_hybrid and the rest of the schema to already exist.

Useful commands:

npm test
npm run typecheck
npm run build
npm start
npm run mcp:stdio

Connect the independent Supabase project

Copy the missing settings from .env.example into .env:

SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co
SUPABASE_SECRET=sb_secret_your_server_only_key
SYNC_SECRET=a-long-random-machine-to-machine-secret
DEMO_MODE=false

SUPABASE_SECRET and SYNC_SECRET are server-only. Never expose either through Vite variables or browser code.

Apply and deploy the Supabase layer from this repository:

npx supabase link --project-ref YOUR_PROJECT_REF
npx supabase db push
npx supabase secrets set SYNC_SECRET=YOUR_SYNC_SECRET
npx supabase functions deploy sync-courses --no-verify-jwt
npx supabase functions deploy embed-pending --no-verify-jwt

The functions disable gateway JWT verification because they use their own machine-to-machine SYNC_SECRET and fail closed without it. Invoke the source sync without filters or user-supplied keywords:

curl -X POST "https://YOUR_PROJECT_REF.supabase.co/functions/v1/sync-courses" \
  -H "Authorization: Bearer YOUR_SYNC_SECRET" \
  -H "Content-Type: application/json" \
  -d '{}'

Then process pending course embeddings in bounded batches:

curl -X POST "https://YOUR_PROJECT_REF.supabase.co/functions/v1/embed-pending" \
  -H "Authorization: Bearer YOUR_SYNC_SECRET" \
  -H "Content-Type: application/json" \
  -d '{}'

Set EMBED_BATCH_SIZE (1–10) and EMBED_MAX_SECTIONS_PER_COURSE as Edge Function secrets/configuration when you need different bounded worker batches; callers cannot override those limits.

For semantic query vectors, point the Node server at that same protected function:

EMBEDDING_API_URL=https://YOUR_PROJECT_REF.supabase.co/functions/v1/embed-pending

Without EMBEDDING_API_URL, the database RPCs deliberately fall back to full-text/trigram ranking. Indexed course and section embeddings remain ready for semantic search once the query endpoint is configured.

Source sync behavior

The new sync-courses function is deployed into the independent Supabase project. It does not call the old Lovable database or accept public search filters. It:

  • crawls a server-owned keyword catalog;
  • validates and sanitizes upstream records;
  • deduplicates repeated courses across keywords;
  • upserts providers and courses using stable source keys;
  • normalizes schedules into course_runs, prioritizing future dates;
  • stores raw provenance and content hashes;
  • marks changed content for re-embedding;
  • records partial failures without treating a partial crawl as authoritative deletion.

Before a large production crawl, confirm Mein NOW usage terms and rate limits for scheduled ingestion.

MCP usage

Remote client configuration (exact field names vary by host):

{
  "mcpServers": {
    "bildungly-courses": {
      "url": "http://127.0.0.1:8787/mcp"
    }
  }
}

Local stdio configuration:

{
  "mcpServers": {
    "bildungly-courses": {
      "command": "npm",
      "args": ["run", "mcp:stdio"],
      "cwd": "/absolute/path/to/bildungly-mcp"
    }
  }
}

Set MCP_API_KEY before exposing the HTTP endpoint publicly. Clients then send Authorization: Bearer .... A partner-grade deployment should replace the shared key with MCP OAuth protected-resource metadata.

Tools

Tool Purpose
search_courses General hybrid course discovery with bounded, structured constraints.
get_course Canonical course, provider, schedule, and optional section details.
match_courses_for_profile Profile-aware ranking with evidence-backed match reasons.
explain_course_fit Relevant stored sections, gaps, and provider questions; never invents modules.

The server does not expose raw SQL, arbitrary upstream API calls, or public refresh actions.

Resources and prompt

  • course://{courseId}
  • provider://{providerId}
  • recommend_weiterbildung_path

Every tool supplies both MCP structuredContent and a JSON text fallback. All tools are annotated read-only and idempotent.

Chat API

The browser calls POST /api/chat:

{
  "messages": [
    { "role": "user", "content": "Ich möchte als Quereinsteiger Data Analyst werden" }
  ],
  "profile": {
    "goal": "Data Analyst",
    "location": "Berlin",
    "remote": true,
    "language": "de",
    "startTiming": "3_months"
  }
}

The chat host connects to /mcp with the official MCP client, invokes a domain tool, and maps its structured output to cards/evidence. Conversation state stays in the host; the MCP server receives only validated tool arguments.

Security and guidance boundaries

  • Supabase tables have RLS enabled and no anon or authenticated policies. Only the server-side secret role can access them.
  • Inputs are bounded with Zod, request bodies are size-limited, and /api/chat and /mcp are rate-limited.
  • MCP validates allowed hosts/origins to reduce DNS-rebinding exposure. Set ALLOWED_HOSTS and PUBLIC_ORIGIN for deployment.
  • Raw HTML from course sources is sanitized before display and embedding.
  • Logs include request metadata, not learner profiles or secrets.
  • The UI and tools say a course is marked as funding-eligible in source data. They never claim that a learner qualifies; approval remains with Agentur für Arbeit or Jobcenter.

Deployment

Build and run directly with npm run build && npm start, or use the included Dockerfile:

docker build -t bildungly-mcp .
docker run --rm -p 8787:8787 --env-file .env \
  -e ALLOWED_HOSTS=localhost:8787 \
  -e PUBLIC_ORIGIN=http://localhost:8787 \
  bildungly-mcp

For a public host, terminate TLS at the platform, set its public hostname/origin, protect /mcp, and keep the Supabase secret in the platform secret store.

Project layout

src/server/domain/       Course contracts, repositories, ranking and fit evidence
src/server/mcp/          Tools, resources and prompt registration
src/server/chat/         Browser-host MCP client and deterministic orchestration
src/server/http/         HTTP transport, API, security and static UI hosting
src/web/                 React chat UI
supabase/migrations/     Independent catalog, vector search and security
supabase/functions/      Source sync and embedding pipeline

The production MCP wire protocol follows the current stable specification (2025-11-25) and the stable TypeScript SDK v1 line; the SDK v2 line targets a newer, not-yet-stable spec.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选