MCP Server for per-user JupyterLab server management on the ATLAS AF Kubernetes cluster
Wellknown found it in public sources; nobody has proven control of it yet. Claiming takes one click if the repository is under your GitHub account, or a small file on your domain otherwise. Verified owners get the badge, 15-minute checks, status alerts, edits that outrank crawled data, and a ranking boost.
Agents can do it too: POST https://wellknown.network/api/v1/claims with {"agent":"af-jupyterlab-mcp","method":"well_known_file"} — machine-readable steps at claim.json, guide at /docs/claim.
Everything here was measured by our prober or read from a registry. Nothing is self-reported.
Attributed to the source that supplied each field. Treated as claims, not facts.
# af-jupyterlab-mcp <!-- --8<-- [start:intro] --> MCP server that lets AF users create, inspect, and delete their own per-user JupyterLab servers on the UChicago ATLAS Analysis Facility Kubernetes cluster — the same notebooks [af-portal](https://github.com/maniaclab/af-portal) deploys today, exposed as tools for LLMs. <!-- --8<-- [end:intro] --> <!-- --8<-- [start:architecture] --> ## Architecture ``` LLM <--MCP/HTTP--> af-jupyterlab-mcp <--k8s API--> notebook namespace (Pod/Service/Secret/Ingress) ^ | Authorization: Bearer <broker-issued JWT> | af-mcp-platform credential broker ``` Phase 1 (this repo, today) ships six tools that manage the Pod/Service/ Secret/Ingress quadruple for a notebook, ported from af-portal's `portal/jupyterlab.py` and its four Jinja templates. Phase 2 (tracked, not yet built) adds a typed proxy to the Datalayer `jupyter-mcp-server` running inside the notebook itself — see [maniaclab/af-mcp-platform#189](https://github.com/maniaclab/af-mcp-platform/issues/189). <!-- --8<-- [end:architecture] --> ## Project layout ``` src/af_jupyterlab_mcp/ ├── cli.py # argparse: `af-jupyterlab-mcp serve` (HTTP only) ├── config.py # env-driven Settings: namespace, domain, image allowlist, quotas ├── server.py # FastMCP setup, lifespan (k8s client + broker verifier), tool registration ├── auth/ │ └── broker.py # extract_bearer(), get_broker_claims() -- broker-issued JWT verification ├── k8s/ │ ├── errors.py # GuardrailError, NameConflictError, NotFoundOrNotYoursError, ... │ ├── guardrails.py # CPU/memory/duration range + image allowlist validation │ ├── names.py # sanitize_k8s_pod_name, name availability, name generation │ ├── templates.py # Jinja rendering of the four ported manifests │ ├── notebooks.py # create/get/list/delete notebook (ported portal logic) │ ├── gpu.py …
Mapped onto the structured taxonomy from declared text and observed tool names. Confidence shown for derived entries.
Every source is kept verbatim. Field changes are logged as events.