Skip to main content

MCP server + CLI (gdn) that lets any agent harness submit a NUST LMS lab by harvesting another account's submission and re-skinning it under the user's identity.

Project description

grabdeeznust

gdn for short. MCP server + CLI that lets any agent harness submit a NUST LMS lab by harvesting a friend's already-submitted work and re-skinning it under the user's own identity.

The "agent" is whatever LLM is driving the harness — Claude Code, OpenCode, Cursor, Cline, Continue, Zed, the Anthropic SDK, etc. grabdeeznust only provides the deterministic plumbing: log into the LMS, download submitted files, re-render a styled report.docx, log back in as the user and upload it.

Two LMS accounts are involved:

  • Account 1 — the user's own account; submissions are uploaded here
  • Account 2 — a friend's account; their already-submitted files are harvested here

NUST LMS assignment URLs are the same on both accounts, so the user supplies the URL once and the tool reuses it.

Install

pipx install grabdeeznust
gdn setup

gdn setup walks you through a one-time onboarding:

  1. Prompts for both LMS account credentials (passwords are hidden).
  2. Prompts for the identity values (IDENTITY_NAME, IDENTITY_ROLL, IDENTITY_TERMINAL) that get stamped into every report.
  3. Saves it all to ~/.gdn/.env with mode 0600.
  4. Downloads Playwright's Chromium (~150 MB, one-time).
  5. Prints the MCP config block to paste into your agent harness.

Run gdn doctor any time to check that everything's still in place.

From source (dev)

git clone https://github.com/ZaynIkhlaq/grabdeeznust
cd grabdeeznust
uv sync
uv run gdn setup

A .env in the repo root takes precedence over ~/.gdn/.env, so dev work doesn't pollute your real config.

Use it as an MCP server (recommended)

Add one block to your harness's MCP config.

Claude Code (~/.claude/mcp.json or per-project .mcp.json):

{
  "mcpServers": {
    "gdn": {
      "command": "gdn",
      "args": ["mcp"]
    }
  }
}

Or via the CLI: claude mcp add gdn -- gdn mcp.

OpenCode, Cursor, Cline, Continue, Zed, Claude Desktop — same shape, in their respective MCP settings file. Any MCP-aware client works.

The agent now has these tools:

Tool Purpose
gdn_harvest(url) Login as account 2, download every submitted file at URL
gdn_extract(source_path) Dump docx/pdf/zip/code as plain text
gdn_render(plan, out_path) Render plan dict → styled docx (auto-verified)
gdn_verify(docx_path) Identity check on an existing docx
gdn_submit(url, files) Login as account 1, remove old draft, upload files

And these resources for the agent to fetch context:

  • gdn://briefing — full operator briefing (CLAUDE.md content)
  • gdn://schema — plan dict schema + tone rules (prompts/system.md)

Use it as a plain CLI

If you'd rather drive each step manually:

gdn harvest <URL>                          # account 2 downloads files
gdn extract <source-file>                  # source → plain text
# write work/<slug>/plan.json (schema in prompts/system.md)
gdn render plan.json --out report.docx     # plan → styled docx + verify
gdn submit <URL> <file1> <file2> ...       # account 1 uploads

Browser is visible by default so you can watch. Pass --headless before the subcommand to hide it.

How the report is generated

The browser side is fully deterministic. The "thinking" step — read the source, write a plan that re-skins the report under the user's identity in a student-tone voice — is performed by the LLM driving the harness, not by any baked-in API call. That keeps grabdeeznust provider-neutral: no Anthropic key, no OpenAI key, nothing to configure beyond the LMS creds and the identity values.

The plan is just a JSON dict matching the schema in prompts/system.md. The renderer is pure Python (python-docx) and styles the docx to match the format Claude.ai's web app produces:

  • Arial 11pt body
  • Courier New 9pt code blocks on dark #1E1E2E (the "fake terminal" look)
  • Courier New 9pt output blocks on light green #F0FFF0
  • Section headings (Introduction / Task N / Conclusion) bold 17pt with bottom rule
  • Italic captions on light-blue #EBF3FB panel with a thin blue border

Anything that looks like an AI tell (Claude, Anthropic, as an AI, language model) trips the verifier and blocks render.

Layout

agent.py             # CLI dispatcher
browser.py           # Playwright NUST LMS driver (selectors pinned at top)
report.py            # source extraction + docx rendering + verification
mcp_server.py        # FastMCP wrapper exposing the above as MCP tools/resources
prompts/system.md    # plan-schema + tone guide for whichever LLM is driving
CLAUDE.md            # operator briefing (read by Claude Code)
AGENTS.md            # pointer to CLAUDE.md (read by OpenCode and others)
work/<slug>/         # per-run scratch (source, plan.json, report.docx, error.png on failure)

Notes

  • Selectors live in one block at the top of browser.py. Tweak there if NUST LMS changes its DOM.
  • "Screenshots" in the report are styled text captions ending in (${IDENTITY_TERMINAL}). No code execution, no real images.
  • GDN_WORK_DIR env var overrides where harvest writes scratch files (default: ./work).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

grabdeeznust-0.1.1.tar.gz (18.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

grabdeeznust-0.1.1-py3-none-any.whl (18.1 kB view details)

Uploaded Python 3

File details

Details for the file grabdeeznust-0.1.1.tar.gz.

File metadata

  • Download URL: grabdeeznust-0.1.1.tar.gz
  • Upload date:
  • Size: 18.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for grabdeeznust-0.1.1.tar.gz
Algorithm Hash digest
SHA256 4107540aefb65d98c0f8290324b9df07c952f44560140287ce0f1f6a1742a66e
MD5 2e348ecbd7d81687268da6fb8ffd9276
BLAKE2b-256 842e06cfd7e4d129872952149b7d4645e810d3a3089289983d40d0e222c637f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for grabdeeznust-0.1.1.tar.gz:

Publisher: publish.yml on ZaynIkhlaq/grabdeeznust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file grabdeeznust-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: grabdeeznust-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 18.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for grabdeeznust-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d060d8c0f0f16d9888687fb31cdb878381bb4497177e72eb5bf9eba7dc5a54eb
MD5 d30964b9c705e5f98569ef708275b4bc
BLAKE2b-256 e54261b41bf1d6d2d196ead78bbeb66c7c68a1e5ac625f55a01cff2a6711b28b

See more details on using hashes here.

Provenance

The following attestation bundles were made for grabdeeznust-0.1.1-py3-none-any.whl:

Publisher: publish.yml on ZaynIkhlaq/grabdeeznust

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page