npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@techprofessor/mcp

v0.7.0

Published

MCP server to create, read, and update TechProfessor artifacts (quizzes, tours, flashcards, playgrounds, exams, syllabi), courses, and code challenges from any MCP client — you author the content, this persists it.

Readme

TechProfessor MCP server

A push-based CRUD surface over TechProfessor artifacts (quizzes, tours, flashcards, playgrounds, exams, syllabi, showcases) for any MCP client (Claude Desktop, Cursor, other agents). This server never generates content — you (the client) author the artifact, and the MCP persists, reads, and updates it. Create and Update just push what you made: no server-side AI, no provider key, no serverless time limit.

The flow for every type is the same: call get_artifact_schema for the exact shape, author the artifact, push_artifact to save it, then read it back with get_artifact / list_artifacts and edit it with update_artifact. Optionally group existing artifacts into a course with the course tools.

Tools

| Tool | What it does | |------|--------------| | push_artifact | Create / full-replace — upload one artifact you authored, or pass artifact_id (the API session_id) to rewrite an existing one in place. Always set audience + level (ask if unspecified; defaults technical + mixed). | | push_artifacts | Create (bulk) — upload authored artifact JSON files (a directory or single file). Local package only. | | get_artifact | Read — fetch one artifact in full. Tours return narratives[].groups[].snippets[]; other types return items[]. | | list_artifacts | Read (list) — list your artifacts and their artifact_id (the API session_id). Filter by type, team_id, repo_id, q, source_ref, or lifecycle (active | archived | all, default active). | | update_artifact | Update — edit an artifact in place: title/description/audience/level and/or content rows by id. | | archive_artifact | Hide / restore — take an artifact out of the default listing, or put it back. Reversible; changes no content. Prefer this over deleting. | | delete_artifact | Delete (permanent) — remove an artifact for good. Also drops it from any course referencing it. | | get_artifact_schema | Return the exact package shape (+ example) for a type, so an authored artifact validates on the first upload. | | list_repos | List your repositories and their repo_id (to attach a pushed artifact to a repo). | | list_teams | List your teams and their team_id (target for pushes). | | list_folders | List folders inside a repo (folder_id for move/create). | | create_folder | Create a folder in a repo (optional parent_id to nest). | | rename_folder | Rename a folder or update its description. | | move_artifact | Move an artifact into a folder, or pass folder_id: null to unfile it. | | list_courses | List your courses and their course_id. | | create_course | Create a new (empty) course. | | get_course | Fetch one course's items, each with the artifact it points to. | | update_course | Update a course's title, description, and/or status (active | archived). | | add_course_item | Add an existing artifact (by artifact_id, the API session_id) as a step in a course. | | remove_course_item | Remove a step by its course item_id (from get_course). The artifact it pointed at is not deleted. | | reorder_course_items | Reorder every step — pass the full permutation of item ids. | | delete_course | Delete (permanent) — remove a course and its steps. The artifacts the steps pointed at are not deleted. | | list_code_challenges | List the code challenges you authored and their challenge_id. Templates only. | | create_code_challenge | Create a code challenge — a brief plus ordered tasks, each graded by its own checks. | | get_code_challenge | Fetch one challenge in full: brief, workspace file, and every task with its checks and reference solution. | | update_code_challenge | Edit the brief and/or patch existing tasks (by task_id or 0-based sort_order). |

Create an artifact (push)

You author the artifact; this server persists it. Steps:

  1. get_artifact_schema({ type }) — get the exact package shape (+ an example) for quiz / tour / flashcards / playground / exam / syllabus / showcase.
  2. Author the package JSON yourself (one artifact per package).
  3. push_artifact({ artifact, repo_id?, team_id?, artifact_id? }) — save it. repo_id attaches it to a repo (from list_repos); omit for a standalone artifact. team_id (from list_teams) saves to a team space instead of your private one. Pass artifact_id (the API session_id, from list_artifacts) to full-replace a known artifact in place — including empty UI/generate tours. source_ref alone upserts only prior ingest/MCP packages that own that key (not generate-created sessions).

push_artifacts does the same from .json files — a directory or a single file. The response includes a web_link you can open to study or share. The link is placement-aware: root artifacts use their flat type home, while repo-backed artifacts use the nested repository/view home. All links returned by push, list, get, and update are canonical browser links.

To read and patch existing artifacts, follow the flow list_artifacts → get_artifact → update_artifact. Call list_artifacts to find an artifact_id, then get_artifact to fetch the current content and ids. Non-Tours retain the flat items[] update shape. Empty Tour groups need push_artifact with artifact_id (full replace), not update_artifact. A Tour has no parallel top-level items: read and patch it through narratives[]: set Narrative diagram (Mermaid), references (source links), concepts (Concept slugs), and/or groups[].snippets[] with the existing Narrative/Group ids for containment and only the changed Snippet fields. Group patches may also set description and diagram. Group title and importance stay read-only. Snippet why is Markdown. Also copy the Tour's tour_revision into expected_revision; if the update conflicts, reload the Tour before retrying. For example:

{
  "artifact_id": "...",
  "expected_revision": 4,
  "narratives": [{
    "id": "narrative-id",
    "diagram": "flowchart TD\n  A --> B",
    "groups": [{
      "id": "group-id",
      "snippets": [{ "id": "snippet-id", "why": "Updated explanation" }]
    }]
  }]
}

Edits happen in place (no new version is created) and are strictly owner-scoped — you only ever see or edit artifacts you own.

push_artifacts takes a path (a directory of artifact JSON files or a single .json file; defaults to .techprof) and an optional team_id. It POSTs each file to the ingest endpoint and reports one line per file. The server caps ingests at 30/min; larger batches may be rate-limited (429).

Exams and syllabi

push_artifact/push_artifacts also accept type: "exam" and type: "syllabus" — call get_artifact_schema({ type: "exam" }) or get_artifact_schema({ type: "syllabus" }) for the exact shape before authoring one:

  • An exam's items[] interleaves questions and coding exercises in one ordered list, each keyed by kind: "question" | "playground". Exam questions support multiple_choice/freeform only — no fill_blank.
  • A syllabus's materials[] holds html/mermaid content — the field is body (not content). PDF materials are upload-only (not supported via push_artifact).

Both are editable with update_artifact the same way as any other artifact: get_artifact returns each exam item's kind and each syllabus material's fields, and you patch them by id (an exam question edits like a quiz question, an exam playground edits like a playground spec, a syllabus material edits title/body/sort_order).

Showcase

A showcase is marketing/positioning copy, not a learning artifact — one shared brief re-told as audience-shaped content. push_artifact/ push_artifacts accept type: "showcase"; call get_artifact_schema({ type: "showcase" }) for the exact shape before authoring one.

  • showcase_format is "explainer" (cold web visitor, landing-page style), "one_pager" (customer/partner/press, dense one-page sheet), or "posts" (followers/subscribers, ready-to-post blog + email copy). "pitch_deck" is a real format value but Phase 2 (slide model + .pptx export) — not yet pushable.
  • sections[] holds the content, each { kind, heading, body } in order. kind is per-format convention (not schema-enforced): explainer uses hero | problem | how | benefits | faq | cta; one_pager uses header | problem | what | benefit | who | proof | cta; posts uses blog | email.
  • Either inline a new brief (one_liner, who_for, problem, how_it_works, why_different, proof, business_model, team, cta, tone) or link an existing one you own with brief_id — the two are mutually exclusive.

Like exam/syllabus, showcase is author-only (no generate_showcase tool). update_artifact edits a section's heading/body/sort_order by id; its kind remains read-only.

Courses

A course groups existing artifacts (by artifact_id, the API session_id) into an ordered sequence — it is not an artifact type itself and is never pushed via push_artifact. Typical flow: push the pieces you want (a tour, an exam, a syllabus, …) with push_artifact, create_course to make the container, then add_course_item once per piece with its artifact_id. Use list_courses / get_course to review what's already in a course; update_course, remove_course_item, and reorder_course_items to maintain it.

Code challenges

A code challenge is a guided build: one brief, one workspace file, and an ordered set of tasks that each narrow the goal and are graded by their own acceptance checks. Learners fork a challenge; their copy carries their own code buffer and progress. It is not an artifact type — push_artifact does not create one.

Author with create_code_challenge (brief + ordered tasks). Read one back with get_code_challenge before editing, then update_code_challenge to change the brief or patch a task. A task patch identifies its target by task_id or the 0-based sort_order, and carries only the fields to change; tests replaces that task's checks wholesale. Tasks cannot be added, removed or reordered through the API — that stays in the challenge editor.

Two things to know:

  • get_code_challenge returns the gated reference solutions. It is owner-only for that reason. Never paste a solution to someone working the challenge.
  • Every acceptance check needs both a name and a code. A check with a blank code would grade as an automatic pass, so it is rejected rather than saved.

Setup

  1. In TechProfessor, open Settings → Developer & MCP and create a token (tp_pat_…). Copy it — it is shown only once. No AI provider key is needed — this server never generates content, it only stores what you author.
  2. Add the server to your MCP client (below). Prefer the hosted HTTP endpoint (https://tech-professor.com/api/mcp) — no clone or build needed.

Configure your MCP client

Hosted HTTP (recommended)

No local Node/npx required. Point any MCP client at the hosted Streamable HTTP endpoint and pass your token as a Bearer header — same shape as GitHub Copilot's remote MCP. The endpoint speaks MCP protocol 2026-07-28 (stateless) and still serves 2025-era clients:

claude mcp add-json techprofessor \
  '{"type":"http","url":"https://tech-professor.com/api/mcp","headers":{"Authorization":"Bearer tp_pat_xxx"}}'
claude mcp add --transport http techprofessor https://tech-professor.com/api/mcp \
  --header "Authorization: Bearer tp_pat_xxx"

Cursor / Claude Desktop / .mcp.json:

{
  "mcpServers": {
    "techprofessor": {
      "type": "http",
      "url": "https://tech-professor.com/api/mcp",
      "headers": { "Authorization": "Bearer tp_pat_xxx" }
    }
  }
}

Settings → Developer & MCP also shows a ready-made add-json command with your freshly created token filled in.

Local stdio (npx) — optional

Prefer HTTP above. Use the published package when you need filesystem push_artifacts (bulk upload from a directory):

claude mcp add techprofessor -s user \
  -e TECHPROF_API_TOKEN=tp_pat_xxx \
  -- npx -y @techprofessor/mcp
claude mcp add-json techprofessor \
  '{"type":"stdio","command":"npx","args":["-y","@techprofessor/mcp"],"env":{"TECHPROF_API_TOKEN":"tp_pat_xxx"}}'

-s user registers it for every project; drop it to add only the current one.

TECHPROF_BASE_URL defaults to https://tech-professor.com (the hosted app); set it only to point at your own deployment.