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

@hackettai/appengine-editor-mcp

v0.5.3

Published

MCP server that lets Cursor / Claude Desktop / Claude Code / any MCP-capable agent connect to AppEngine generated applications and edit their files with full file-system-like tools.

Readme

AppEngine Editor MCP

npm version

A Model Context Protocol (MCP) server that lets Cursor, Claude Desktop, Claude Code, or any MCP-capable agent connect directly to AppEngine-generated applications and edit their source files — with the same power you get from a local code editor.

It talks to the same endpoint the DIAL UI uses (POST /chat/conversations/:id/save-files), so any change the agent makes shows up instantly in the /appengine/conversation/:id page.


Quick start

Remote (recommended — zero config)

Just add a URL. First connection opens your browser for login — no secrets, no tokens, no env vars.

{ "mcpServers": { "appengine-editor": { "url": "https://dev.dialhackett.digital/api/mcp" } } }

Works in Cursor, Claude Desktop, and Claude Code.

Local (stdio)

npx @hackettai/appengine-editor-mcp

When started without credentials, the agent calls mcp_auth at runtime and asks you for your Clerk secret key + session ID. No need to edit JSON configs.


What you get

31 tools exposed over MCP:

| Tool | What it does | | ---------------------- | ---------------------------------------------------------------------------------------- | | Authentication | | | mcp_auth | Provide Clerk credentials at runtime (stdio only — remote uses OAuth) | | Project lifecycle | | | list_projects | List AppEngine projects (my / accessible / shared-with-me / favorites / kainam / public) | | search_projects | Search by keyword in conversation messages | | get_project | Load a project into the session and list every file path it contains | | activate_project | Lock the session to a single project (required before any mutations) | | deactivate_project | Release the project lock | | get_active_project | Return the currently locked project id | | project_stats | File count, largest files, LOC summary | | save_project | Persist everything via /save-files (same endpoint the DIAL UI hits) | | delete_project | Delete the entire project (requires confirm: true) | | Reading | | | read_file | Return the full contents of one file | | read_file_range | Return a line range from a file | | read_all_files | Bulk read — return a JSON array with every file in the project in one call | | search_in_files | Regex or literal search across all project files | | Writing (staged) | | | write_file | Create or fully overwrite a file | | edit_file | Search-and-replace edit (unique match required unless replaceAll) | | delete_file | Remove a file | | rename_file | Rename or move a file to another path | | copy_file | Duplicate a file to a new path | | append_to_file | Append content to the end of a file | | prepend_to_file | Prepend content to the beginning of a file | | insert_at_line | Insert content at a specific line number | | replace_lines | Replace a range of lines | | regex_replace | Regex find-and-replace within a single file | | global_replace | Regex find-and-replace across all project files | | bulk_edit | Apply the same search-and-replace edit to multiple files | | bulk_write | Create or overwrite multiple files in one call | | CDN libraries | | | add_cdn_library | Add a CDN script/stylesheet to the project | | remove_cdn_library | Remove a CDN script/stylesheet from the project | | Staging | | | list_changes | Show what is staged for the next save | | discard_changes | Revert staged edits back to the last loaded/saved baseline |

The agent can edit every file in a project — no allowlist, no extension filter, no depth limit. Whatever is in the conversation (from App.tsx all the way down to pages/…, components/…, data/…, config files, mock data, .css, .svg, .yaml, etc.) is loaded into the working tree, and every tool operates on an arbitrary path string. save_project always sends the full file tree so new files and renames persist correctly.

All mutating operations (write_file, edit_file, delete_file, rename_file) are staged in memory so agents can run many small edits across dozens of files and commit them with a single save_project call — matching how the DIAL frontend persists manual edits.


1. Install

Quick start (npx — no repo needed)

npx @hackettai/appengine-editor-mcp

That's it. npx downloads, caches and runs the MCP server in one step. Use this in your Cursor / Claude Code config (see step 4).

From source (for contributors)

cd mcp-servers/appengine-editor
npm install
npm run build

This produces dist/index.js which is the executable MCP server.


2. Authentication

Remote mode (OAuth — recommended)

When using the remote endpoint (https://dev.dialhackett.digital/api/mcp), authentication is handled automatically via Clerk OAuth. The MCP client opens your browser, you sign in with your DIAL account, and tokens are managed transparently. No credentials to manage.

Local stdio mode

The local MCP needs to authenticate against the Mirador backend. Three options are supported:

Option A: Runtime mcp_auth tool (recommended for stdio)

No credentials in the JSON config at all. When the agent tries to use a tool, it gets a 401 error and knows to call mcp_auth first. The agent asks the user for their Clerk secret key and session id, passes them to mcp_auth, and the MCP authenticates on the fly.

  1. Get your Clerk secret key from the Clerk dashboard → API Keys (starts with sk_test_ or sk_live_).

  2. Get your session id from the browser console:

    copy(window.Clerk.session.id);

    (starts with sess_)

  3. When the agent asks, provide both values. The agent calls mcp_auth({ clerkSecretKey, clerkSessionId }) and you're authenticated.

If your session expires mid-conversation, the agent can call mcp_auth again with a fresh session id — no need to restart anything.

Option B: Env vars (auto-refresh, for unattended use)

Pass CLERK_SECRET_KEY + CLERK_SESSION_ID as env vars in the MCP config. The MCP mints and rotates JWTs automatically via the Clerk Backend API. Useful for CI or unattended workflows where interactive prompts are not available.

Option C: Static token (quick, short-lived)

  1. Open the browser JS console on any DIAL page.
  2. Run: copy(await window.Clerk.session.getToken());
  3. Paste the JWT into APPENGINE_API_TOKEN. Tokens expire in ~5 minutes.

3. Configure environment (stdio only)

Remote mode does not need any env vars — skip to section 4.

| Variable | Default | Required | Notes | | ------------------------------ | ----------------------- | :------: | ------------------------------------------------------------------------- | | APPENGINE_API_URL | http://localhost:3000 | ✓ | Same value DIAL uses for NEXT_PUBLIC_API_BASE_URL. | | APPENGINE_TENANT_ID | — | | Clerk org id, sent as X-Tenant-ID (matches the DIAL proxy behaviour). | | APPENGINE_REQUEST_TIMEOUT_MS | 60000 | | Per-request timeout in ms. | | APPENGINE_MCP_DEBUG | 0 | | Set to 1 for verbose logs on stderr. | | CLERK_SECRET_KEY | — | | Clerk secret key (sk_test_…). Optional — can use mcp_auth instead. | | CLERK_SESSION_ID | — | | Active Clerk session id (sess_…). Optional — can use mcp_auth instead.| | APPENGINE_API_TOKEN | — | | Static Clerk JWT. Short-lived fallback for quick one-off use. |

Authentication priority: mcp_auth (runtime) > env vars > static token. If no credentials are configured at startup, the agent must call mcp_auth before using any other tool.


4. Register the MCP with your client

Remote (recommended — no secrets needed)

Just provide the URL. The first connection opens a browser window for Clerk OAuth login, and tokens are managed automatically.

Cursor (~/.cursor/mcp.json):

{
  "mcpServers": {
    "appengine-editor": {
      "url": "https://dev.dialhackett.digital/api/mcp"
    }
  }
}

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "appengine-editor": {
      "url": "https://dev.dialhackett.digital/api/mcp"
    }
  }
}

Claude Code:

claude mcp add --transport http appengine-editor https://dev.dialhackett.digital/api/mcp

Prerequisite: The DIAL app must be deployed with the MCP route enabled, and Clerk must have OAuth + Dynamic Client Registration configured.

Local stdio (alternative — for offline/dev use)

If you prefer running the MCP locally (offline, dev, or when the remote endpoint is unavailable), use the stdio transport with npx:

Cursor (via npx)

Open Cursor settings → MCPAdd new global MCP server (or edit ~/.cursor/mcp.json) and add:

{
  "mcpServers": {
    "appengine-editor": {
      "command": "npx",
      "args": ["-y", "@hackettai/appengine-editor-mcp"],
      "env": {
        "APPENGINE_API_URL": "https://your-api-host.example.com/api",
        "APPENGINE_TENANT_ID": "org_your_clerk_org_id",
        "CLERK_SECRET_KEY": "sk_test_your_clerk_secret_key",
        "CLERK_SESSION_ID": "sess_your_active_session_id",
        "APPENGINE_MCP_DEBUG": "1"
      }
    }
  }
}

Reload Cursor, open the MCP panel, and you should see appengine-editor listed with 31 tools.

Claude Code (CLI)

Run this single command to register the MCP:

claude mcp add appengine-editor \
  -e APPENGINE_API_URL=https://your-api-host.example.com/api \
  -e CLERK_SECRET_KEY=sk_test_your_clerk_secret_key \
  -e CLERK_SESSION_ID=sess_your_active_session_id \
  -e APPENGINE_MCP_DEBUG=1 \
  -- npx -y @hackettai/appengine-editor-mcp

Claude Desktop

Edit the Claude Desktop config file:

  • Windows (standalone): %APPDATA%\Claude\claude_desktop_config.json
  • Windows (Microsoft Store): %LOCALAPPDATA%\Packages\Claude_<id>\LocalCache\Roaming\Claude\claude_desktop_config.json
  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

Add the appengine-editor entry inside mcpServers:

{
  "mcpServers": {
    "appengine-editor": {
      "command": "npx",
      "args": ["-y", "@hackettai/appengine-editor-mcp"],
      "env": {
        "APPENGINE_API_URL": "https://your-api-host.example.com/api",
        "CLERK_SECRET_KEY": "sk_test_your_clerk_secret_key",
        "CLERK_SESSION_ID": "sess_your_active_session_id",
        "APPENGINE_MCP_DEBUG": "1"
      }
    }
  }
}

Windows tip: If Claude Desktop doesn't find npx, use the full path instead: "command": "C:\\Program Files\\nodejs\\npx.cmd".

Microsoft Store version: The Store (MSIX) build reads its config from a sandboxed path under AppData\Local\Packages\Claude_*\LocalCache\Roaming\Claude\. Use Settings → Developer → Edit Config to find the exact path.

Fully restart Claude Desktop after editing — changes are not hot-reloaded. Verify by checking Settings → Developer for the server status, or click the + button in the chat → Connectors to see available tools.

From source (local development)

If you have the DIAL repo cloned and prefer running from the built files:

{
  "mcpServers": {
    "appengine-editor": {
      "command": "node",
      "args": [
        "/path/to/HackettAnalyticsLab/mcp-servers/appengine-editor/dist/index.js"
      ],
      "env": {
        "APPENGINE_API_URL": "http://localhost:3000",
        "CLERK_SECRET_KEY": "sk_test_your_clerk_secret_key",
        "CLERK_SESSION_ID": "sess_your_active_session_id"
      }
    }
  }
}

Windows note

If Windows rejects spawning .js directly, use the platform-specific node.exe absolute path (find it with where node in PowerShell):

"command": "C:/Program Files/nodejs/node.exe"

5. Typical agent session

> list_projects({ "scope": "my", "limit": 20 })
• 665f1c… — "Auto-match QA dashboard" — 42 msgs — updated 2026-05-01…
• 665dab… — "Interactive hierarchy explorer" — 18 msgs — …

> get_project({ "projectId": "665f1c..." })
{
  "projectId": "665f1c...",
  "flowType": "analytical_dashboard",
  "fileCount": 24,
  "files": [
    "App.tsx",
    "components/Chart.tsx",
    ...
  ]
}

> read_all_files({ "projectId": "665f1c..." })    # agent ingests full codebase

> edit_file({
    "projectId": "665f1c...",
    "path": "pages/MyTasksPage.tsx",
    "oldString": "const REFRESH_MS = 30000;",
    "newString": "const REFRESH_MS = 5000;"
  })

> save_project({
    "projectId": "665f1c...",
    "instruction": "Refresh rate tuning"
  })
Saved 1 change (24 total files sent): …

Reload /appengine/conversation/665f1c... in DIAL and the UI will rebuild against the new file tree immediately (the same way it does for manual edits made in the built-in editor).


6. Safety model

  • Staged, not live. write_file / edit_file / delete_file only mutate an in-memory snapshot. The backend does not see a single byte until save_project is called. That keeps agent exploration cheap and reversible via discard_changes.
  • Full-tree save. Just like the DIAL UI, save_project always sends the full set of files currently in the working tree. This matches the backend's expectation and prevents drift from partial writes.
  • No HAL / AI side-channel. This MCP is purely the file-persistence surface. It does not trigger backend LLM runs or consume model budget. The agent doing the editing is whatever agent the user runs the MCP from (Cursor, Claude Code, etc.).
  • Token scope. The server uses whatever bearer you pass. Give it a token with the same permissions the DIAL UI would have — nothing more.

7. Development

# Type-check without emitting
npm run typecheck

# Watch mode (runs against TS directly via tsx)
npm run dev

# Clean build output
npm run clean

Useful APPENGINE_MCP_DEBUG=1 prints every outbound HTTP call, tool registration, and shutdown event on stderr — MCP clients show stderr in their logs panel.