Skip to main content
Glama
README.md
<p align="center">
  <img src="icon.jpg" alt="DevMCP" width="96" />
</p>

# DevMCP

A single-file [MCP](https://modelcontextprotocol.io) server that turns any folder on your machine into a workspace an AI agent can work in: read and edit files, search code, run shell commands, manage background jobs, test HTTP endpoints, browse pages in headless Chromium, extract PDFs, and capture the screen.

It speaks streamable HTTP, so any remote MCP client can connect through an ngrok tunnel.

## How it works

1. `dev_server.py` runs an MCP server on `127.0.0.1:8787`. The folder it is **launched from** becomes the workspace root — file tools are sandboxed to it; shell tools are not.
2. `ngrok` exposes the port publicly so your MCP client can reach it.
3. The client calls the tools to read/edit files, run commands, and inspect images or screenshots.

## Tools

| Tool | Purpose |
| --- | --- |
| `workspace_info` | Project path plus system details: OS, architecture, shell, Python |
| `project_overview` | Manifests (package.json, pyproject.toml, ...) and README head |
| `project_tree` | Depth-limited directory tree |
| `view_dir` | Single-directory listing with sizes |
| `list_files` | Recursive file list (capped, junk dirs skipped) |
| `read_file` | Read a file slice with line numbers |
| `file_outline` | Class/function/export lines with line numbers |
| `write_file` | Create or overwrite a file (UTF-8) |
| `edit_file` | Exact-match single replacement |
| `search_code` | ripgrep search with a pure-Python fallback |
| `run_cmd` | Shell command in the project folder (blocking) |
| `run_powershell` | PowerShell in the project folder (blocking) |
| `git` | Git wrapper (status, diff, log, commit, ...) |
| `start_process` | Run a long command in the background, returns a job id |
| `check_process` | Job status plus the tail of its output |
| `stop_process` | Kill a background job's process tree |
| `http_request` | Test HTTP/API endpoints, including localhost |
| `fetch_page` | Load a URL in headless Chromium (JS-rendered text or HTML) |
| `browser_screenshot` | Screenshot of a URL rendered in headless Chromium |
| `view_image` | Send an image file from the project to the client |
| `screenshot` | Capture a monitor |
| `read_pdf` | Extract text from a PDF |
| `view_pdf_page` | Render one PDF page as an image |
| `restart_server` | Restart to pick up `dev_server.py` changes |
| `stop_server` | Shut down; the launcher cleans up ngrok |

## Requirements

- Python 3.11+
- [ngrok](https://ngrok.com) (a free account with a reserved domain is recommended)
- Optional, for faster code search: ripgrep (e.g. `winget install BurntSushi.ripgrep.MSVC`)

Launchers: `devmcp.ps1` / `devmcp.bat` (Windows) and `devmcp.sh` (Linux; run `chmod +x devmcp.sh` after cloning).

## Setup

1. Clone the repository and install dependencies:

   ```
   pip install -r requirements.txt
   playwright install chromium
   ```

2. Reserve a domain in the ngrok dashboard and point the launcher at it:

   ```
   setx DEVMCP_NGROK_URL "https://your-domain.ngrok-free.dev"
   ```

   If unset, ngrok assigns a random URL each run (check the inspector at `http://127.0.0.1:4040`).

3. Add this folder to your `PATH` so `devmcp` works from anywhere.

4. Start it from a project folder:

   ```
   cd path/to/project
   devmcp
   ```

5. In your MCP client, add a server with:
   - URL: `https://your-domain.ngrok-free.dev/mcp` (the path must end in `/mcp`)
   - Transport: streamable HTTP
   - Auth: bearer token with any value (the server does no authentication itself)

`Ctrl+C` stops the server and the tunnel.

## Configuration

| Variable | Default | Meaning |
| --- | --- | --- |
| `DEVMCP_NGROK_URL` | (unset) | Reserved ngrok domain used by the launcher |
| `DEVMCP_PORT` | `8787` | Local port for the server and tunnel |
| `DEVMCP_HOST` | `127.0.0.1` | Bind address for the server |

All variables are optional — the server runs fine with the defaults. Instead of setting them globally, you can copy `.env.example` to `.env` next to the launcher and edit it there; both launchers load it automatically (`.env` is gitignored).

Output caps, ignored directories, and the browser user agent are constants at the top of `dev_server.py`.

## Security

- File tools reject paths that escape the launch folder. Shell tools are **not** sandboxed — they run arbitrary commands with your user's privileges.
- There is no real authentication. Anyone with the tunnel URL can control your machine: keep the URL private and stop the tunnel when not in use.

## Notes

- Commands that may run longer than ~60 seconds (dev servers, builds) should use `start_process` + `check_process`, not a blocking `run_cmd`.
- Every tool returns a readable `ERROR (...)` string instead of raising; a transport-level connection failure means the server or tunnel is down.
- After editing `dev_server.py`, call `restart_server` and retry tools after ~10 seconds.
- Most MCP clients cache the tool list at connect time — refresh the connection after adding or renaming tools.

## Troubleshooting

| Symptom | Fix |
| --- | --- |
| `421` error on connect | ngrok is missing `--host-header=localhost:<port>` (the launcher sets it) |
| "Failed to connect" / timeouts | Server or tunnel not running (or mid-restart); wait ~10 s and retry, or rerun `devmcp` |
| Stray ngrok process | `taskkill /F /IM ngrok.exe` |
| Editor import warnings | Wrong Python interpreter selected, not a real error |