GLU Web Development MCP
Follows GitHub links found on Notion pages: retrieves a repository's file listing and README, and reads the source code of individual GitHub files.
Reads and searches the public GLU Web Development Notion site via Notion's own (unofficial) public-page API. Renders entire pages as compact markdown β text, headings, lists, to-dos, code, tables, columns, tabs, callouts, synced blocks and databases β lists all assignments per study year, follows subpages and cross-page links to arbitrary depth, and exposes images to Claude. Includes caching of every page plus a background crawler that builds a full-text search index over ~1000 pages, with long pages split into parts and per-section reads.
Resolves YouTube links embedded in Notion pages, returning the video's title and channel.
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., "@GLU Web Development MCPWat zijn de eisen van de Hoveniers Website?"
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.
GLU Web Development MCP
Een MCP-server waarmee Claude de complete GLU Web Development Notion-site kan lezen en doorzoeken. Dat zijn alle opdrachten per leerjaar, elke subpagina, databases, afbeeldingen en de links die erin staan: GitHub-repo's, YouTube-video's en documentatie.
Je vraagt Claude bijvoorbeeld "Wat zijn de eisen van de Hoveniers Website?". Claude zoekt dan zelf de juiste pagina op, volgt de links en geeft antwoord.
Dit is een onofficieel hulpmiddel van een student. Het leest alleen pagina's die openbaar op internet staan en heeft geen banden met het Grafisch Lyceum Utrecht.
Wat kan het?
π Alle opdrachten per leerjaar: modules en ontwikkelweken met periode, plus losse pagina's zoals Stage en Loopbaan.
π Elke pagina volledig lezen: tekst, koppen, lijsten, to-do's, code, tabellen, kolommen, tabs, callouts, synced blocks en databases.
π Links volgen, eindeloos diep: subpagina's, links naar andere Notion-pagina's en links naar externe websites.
πΌοΈ Afbeeldingen bekijken: Claude krijgt de afbeelding echt te zien, bijvoorbeeld een wireframe of infographic.
π Externe bronnen:
GitHub-repo's: bestandslijst en README.
GitHub-bestanden: de broncode.
YouTube: titel en kanaal.
Overige websites: de hoofdtekst, zonder menu's en reclame.
π Zoeken in alles: full-text zoeken in ruim 1000 pagina's, met per treffer de opdracht waar hij bij hoort.
πͺ Zuinig met tokens: compacte markdown, korte verwijzingen en lange pagina's in delen. Zie Tokens besparen.
β‘ Snel en zonder installatie: alleen Python nodig, geen
pip install. Pagina's worden gecachet en de zoekindex wordt op de achtergrond bijgewerkt.
Related MCP server: mcp-webscraper
Installatie
1. Wat je nodig hebt
Python 3.10 of nieuwer. Check het met
python --version. Installeer je Python op Windows via python.org? Vink dan "Add python.exe to PATH" aan.Claude Code of Claude Desktop.
2. Downloaden
git clone https://github.com/TomsProgramming/glu-webdev-mcp.gitGeen git? Download dan de ZIP via de groene knop Code β Download ZIP en pak hem uit.
3. Toevoegen aan Claude
Gebruik in de voorbeelden het pad naar jouw map. In de voorbeelden staat de repo in C:\Users\jij\glu-webdev-mcp.
Claude Code (CLI, VS Code of de Code-tab in de Claude-app)
claude mcp add glu-webdev --scope user -- python "C:\Users\jij\glu-webdev-mcp\server.py"Op macOS/Linux gebruik je python3 en een pad zoals ~/glu-webdev-mcp/server.py. Met --scope user werkt hij in al je projecten. Start daarna een nieuwe sessie.
Claude Desktop
Open Settings β Developer β Edit Config. Dat opent
claude_desktop_config.json.Voeg de server toe. Staat er al een
mcpServers-blok? Voeg dan alleenglu-webdevtoe.
{
"mcpServers": {
"glu-webdev": {
"command": "python",
"args": ["C:\\Users\\jij\\glu-webdev-mcp\\server.py"]
}
}
}Sluit Claude Desktop helemaal af (ook in het systeemvak) en start hem opnieuw.
Tip (Windows): krijg je de melding dat de server niet kan starten? Vul dan bij
commandhet volledige pad naar Python in. Dat pad krijg je metwhere python, bijvoorbeeldC:\\Users\\jij\\AppData\\Local\\Programs\\Python\\Python313\\python.exe.
Alternatief: installeren als pakket
Wil je niet clonen? Met pipx of uv kan het ook:
pipx install git+https://github.com/TomsProgramming/glu-webdev-mcp.gitclaude mcp add glu-webdev --scope user -- glu-webdev-mcpMet uv kun je in Claude Desktop ook "command": "uvx" gebruiken, met "args": ["--from", "git+https://github.com/TomsProgramming/glu-webdev-mcp.git", "glu-webdev-mcp"].
4. Controleren
Claude Code:
claude mcp listmoetglu-webdevtonen metβ Connected. In een sessie kan het ook met/mcp.Claude Desktop: onder het π§-icoon in het chatvenster staat
glu-webdevmet drie tools.
Bij de eerste start haalt de server op de achtergrond alle Β±1000 pagina's op. Dat duurt ongeveer 6 minuten, omdat Notion snelle requests blokkeert. Lezen werkt meteen, zoeken is na die eerste keer compleet. Je kunt dit ook vooraf doen:
python server.py warmGebruik
Stel gewoon je vraag; Claude kiest zelf de tools. Een paar voorbeelden:
"Welke opdrachten zijn er in leerjaar 2?"
"Wat moet ik doen voor 4.2 Hoveniers Website en hoe word ik beoordeeld?"
"Lees de CBR Challenge en bekijk de GitHub-repo met de aangeleverde data."
"Waar wordt uitgelegd hoe migrations in Laravel werken?"
"Maak een planning voor 9.2 Berlins Best! op basis van de opdracht."
"Wat staat er op de afbeelding bij de Berlins Best-opdracht?"
Tools
Tool | Wat het doet |
| Alle opdrachten per leerjaar ( |
| Leest een Notion-pagina, afbeelding of webpagina als compacte markdown. |
| Zoekt in de tekst van alle pagina's en geeft per treffer de opdracht en een fragment. |
target van read mag het volgende zijn:
een @ref uit eerdere output, bijvoorbeeld
@920ee7f3;een opdrachtnaam of periode, bijvoorbeeld
hoveniersof4.1 module;een Notion-URL of -id;
een gewone URL, bijvoorbeeld
https://laravel.com/docs/migrations.
Links in de output zien eruit als [Titel](@ref) en afbeeldingen als [img: naam](@ref). Claude volgt ze door die @ref te lezen, en zo kan hij steeds dieper. Gewone web-links op Notion-pagina's blijven volledige URL's, zodat Claude ze ook aan jou kan geven.
Een lange pagina komt in delen. Het eerste deel bevat een overzicht van de koppen. Claude kan dan part=2 lezen, of met section="beoordeling" alleen het stuk dat hij nodig heeft.
Tokens besparen
Elke token in een tool-antwoord kost context, en dus geld of gebruikslimiet. Daarom:
Maatregel | Effect |
Drie compacte tools, korte beschrijvingen | Β±350 tokens per gesprek voor de tooldefinities |
| Β±20 tokens minder per link |
Markdown zonder opmaak die niets toevoegt (kleuren, lege regels, scheidingslijnen, ID's) | gemiddelde pagina Β±800 tokens |
Externe sites: alleen de hoofdinhoud, menu's eruit, links als ref | W3Schools-pagina: 90.000 β 3.500 tekens |
Lange pagina's in delen, of één sectie | Claude leest alleen wat nodig is |
Afbeeldingen verkleind tot 1000 px breed | genoeg om te lezen, niet onnodig groot |
Instellingen
Alle instellingen zijn optioneel en gaan via omgevingsvariabelen.
Variabele | Standaard | Betekenis |
|
| Hoe lang pagina's in de cache geldig blijven. |
|
| Maximale lengte van één antwoord; langere pagina's worden opgedeeld. |
|
| Gelijktijdige requests naar Notion. Hoger is sneller, maar dan krijg je eerder een rate limit. |
| zie hieronder | Map voor de cache. |
| GLU Web Development | Andere openbare Notion-site gebruiken. |
De cache staat standaard in %LOCALAPPDATA%\glu-webdev-mcp (Windows), ~/Library/Caches/glu-webdev-mcp (macOS) of ~/.cache/glu-webdev-mcp (Linux).
Een instelling meegeven:
claude mcp add glu-webdev --scope user -e GLU_CACHE_HOURS=24 -- python "C:\Users\jij\glu-webdev-mcp\server.py"In Claude Desktop gebruik je "env": { "GLU_CACHE_HOURS": "24" } naast command en args.
Zelf testen zonder Claude
python server.py list 2python server.py read "hoveniers"python server.py search "laravel migration"python server.py warmProblemen oplossen
Probleem | Oplossing |
Server start niet / | Gebruik het volledige pad naar |
Inhoud is verouderd | Verwijder de cachemap, of verlaag |
Zoeken geeft "index nog bezig" | De eerste crawl loopt nog. Wacht een paar minuten, of draai |
Fouten in Claude Desktop | Bekijk de logs via Settings β Developer, of |
"pagina niet gevonden of niet openbaar" | Die pagina staat niet openbaar op Notion. Dat kan de server niet omzeilen. |
Hoe werkt het?
Kort samengevat:
De server gebruikt dezelfde (niet-officiΓ«le) API als de Notion-website zelf, om openbare pagina's op te halen.
Hij zet de Notion-blokken om naar compacte markdown en vervangt lange id's door korte
@refs.Elke pagina wordt gecachet. Een crawler bouwt op de achtergrond een zoekindex over alle pagina's.
Het volledige verhaal staat in docs/hoe-het-werkt.md: architectuur, gebruikte endpoints, caching, rate limiting en de keuzes daarachter.
Ontwikkelen
glu_webdev_mcp/
βββ server.py MCP-protocol (JSON-RPC via stdio) en CLI
βββ tools.py de drie tools en hun definities
βββ notion.py pagina's ophalen via de Notion-API
βββ render.py Notion-blokken β markdown, opdrachtenlijst
βββ store.py cache van gerenderde pagina's
βββ search.py crawler en zoekindex
βββ web.py externe websites, GitHub, YouTube, afbeeldingen
βββ paging.py lange pagina's opdelen, secties
βββ refs.py korte @refs
βββ net.py HTTP met throttling en retries
βββ config.py instellingen
βββ util.py hulpfuncties
server.py starter, zodat het zonder installatie werkt
tests/ offline tests (geen netwerk nodig)De tests draaien zonder netwerk en zonder dependencies:
python -m unittest discover -s tests -t . -vVerandert de markdown-output? Verhoog dan RENDER_VERSION in config.py. Bestaande caches worden dan automatisch vernieuwd.
Licentie
MIT Β© Tom Tiedemann. De inhoud van de Notion-site is van het Grafisch Lyceum Utrecht en de docenten die hem schrijven.
Available Tools
3 toolslist_assignmentsBRead-only
List GLU Web Development assignments per leerjaar, plus other top-level pages. Lines: 'periode type: naam @ref'.
| Name | Required | Description | Default |
|---|---|---|---|
| leerjaar | No | 1, 2 or 3; omit for all |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=true, so the safety profile is covered. The description adds genuinely useful behavioral context with the return line format ('periode type: naam @ref'), which matters because there is no output schema, but it says nothing about pagination, ordering, or auth.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with the primary purpose front-loaded and no filler. The output-format fragment is terse to the point of being slightly cryptic, but it still earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With one fully documented parameter, no output schema, and annotations covering the safety profile, the description supplies the missing piece an agent would want: the shape of the returned lines. Only pagination/ordering behavior is unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already states '1, 2 or 3; omit for all'. The description's 'per leerjaar' merely echoes the parameter rather than adding syntax or default behavior, so the baseline 3 is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('List') and a specific resource ('GLU Web Development assignments') with scope ('per leerjaar, plus other top-level pages'), so the agent knows exactly what comes back. It does not explicitly contrast with the siblings 'read' and 'search', which keeps it short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this tool versus the siblings 'read' or 'search', and no prerequisites or exclusions. Usage is only weakly implied by the tool name and the phrase 'per leerjaar'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
readARead-only
Read a Notion page, image or any web URL as compact markdown. target: @ref, Notion URL/id, assignment name/period ('4.1 module', 'hoveniers') or http(s) URL. Links appear as text (pages, web links) or img: ..; read the @ref to follow. Long pages: use part or section (heading text).
| Name | Required | Description | Default |
|---|---|---|---|
| part | No | ||
| target | Yes | ||
| section | No | only this heading and its subsections |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. Beyond that the description adds real behavioral context: content is returned as compact markdown, links are rendered as [text](@ref) or [img: ..](@ref), and @refs must be followed to retrieve linked content β details an agent cannot infer from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four dense sentences, purpose front-loaded first, then target forms, then link rendering, then long-page handling β no filler. The telegraphic style keeps it short, though the parenthetical examples and semicolon-joined clauses make it slightly run-on.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description supplies the return shape (compact markdown with @ref links) plus the long-page escape hatch. Combined with annotations covering read-only and open-world behavior, an agent has everything needed to call it correctly; only the missing search-first routing is a minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33% (just `section`), so the description carries most of the burden and does so well for `target`: @ref, Notion URL/id, assignment name/period with examples, or http(s) URL. `part` is only weakly explained ('use part or section' for long pages), leaving its integer semantics and relationship to `section` partly implicit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb (read) plus the exact resource types (Notion page, image, any web URL) and the output form (compact markdown). Against siblings search and list_assignments, the fetch-content role is unambiguous without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives operational guidance for a given call (which target forms are accepted, follow @ref links, use part/section for long pages) but never states when to pick this tool over search or list_assignments, nor any prerequisite such as needing a @ref found via search. Usage is implied rather than framed against alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchBRead-only
Full-text search across all pages (assignments, subpages, databases). Returns pages with @ref, assignment and snippet. All words must match.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover readOnlyHint and openWorldHint, so the safety profile is handled. The description adds genuinely useful behavior beyond that: it discloses the AND matching semantics ('All words must match') and the return payload ('pages with @ref, assignment and snippet'), the latter being especially valuable since no output schema exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with the purpose front-loaded, followed by return shape and matching rule. No filler; each sentence carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple 2-parameter read tool with no output schema, the description covers purpose, result fields, and matching semantics. It omits any mention of the limit/pagination behavior, which an agent needs to reason about result counts.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% for both parameters. The description adds meaning to query via the AND matching rule, but says nothing about limit (default 8), so half the parameters remain undocumented in both schema and description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (full-text search) and resource (pages), and enumerates the scope: assignments, subpages, databases. This differentiates it from list_assignments (enumerate) and read (fetch one), though it does not name those siblings explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance is given. It does not tell the agent to reach for this tool when the page ID is unknown, nor when to prefer list_assignments or read instead. The scope of 'all pages' implies usage but no explicit selection criteria are offered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
list_assignments - First observed
read - First observed
search
TDQS
Scored across 3 tools
The three tools have mostly distinct purposes: list_assignments browses top-level pages, read fetches a specific page/URL, and search performs full-text queries. There is minor overlap because list_assignments and search both return page references, but the descriptions make their primary roles clear.
All names are lowercase and use snake_case where multiword, but the pattern is mixed: list_assignments is verb_noun, while read and search are bare verbs. It remains readable, but the convention is not fully predictable.
Three tools are concise and well-scoped for a read-only Notion content access server. The count is slightly minimal, but each tool earns its place and there is no evidence of bloat.
The surface covers the core read-only workflow: browsing assignments, reading pages/URLs, and searching across content. Minor gaps exist, such as dedicated subpage or database listing beyond search/read, but agents can work around them by following references.
Maintenance
Related MCP Connectors
Web search, URL content extraction to Markdown, site mapping, and recursive web crawler.
Checks whether a website is readable and citable by AI systems (ChatGPT, Claude, Perplexity, etc.)
Shared copies of public web pages for AI agents. Search stored pages or fetch a URL.
Build & publish sites β or a game, a calendar, a report β by chatting with Claude. Live in seconds.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables Claude and other LLMs to read and parse web content, with smart fallback strategies to bypass access restrictions (e.g., paywalls, Cloudflare) and output Markdown.518 npm46MIT
- FlicenseAqualityDmaintenanceEnables Claude Desktop to perform advanced web scraping and crawling operations, extracting structured data, analyzing website architectures, and discovering content relationships through natural conversation.54-
- FlicenseNot gradedqualityBmaintenanceEnables Claude to navigate, screenshot, read console/network, and crawl links in HTML documentation via a co-located headless Chromium and VSCode webview pane.12 npm-
- AlicenseAqualityBmaintenanceEnables Claude to access JW.org public materials including Bible verses, Watchtower articles, meeting workbooks, video captions, and lesson books through natural language conversation.1168 npmMIT