DevTools MCP Server
Provides live web search via DuckDuckGo, returning titles, links, and snippets for queries without requiring an API key.
Allows running read-only SQL SELECT queries against PostgreSQL databases using connection strings.
Allows running read-only SQL SELECT queries against local SQLite database files, returning results as dictionaries.
Provides read-only SQL querying of Supabase's hosted PostgreSQL databases via connection strings.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@DevTools MCP ServerSearch the web for 'Model Context Protocol' spec"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
π οΈ DevTools MCP Server
A lightweight Model Context Protocol (MCP) server that gives any MCP-compatible LLM client (Claude Desktop, Claude Code, Cursor, etc.) a developer toolbox: web scraping, log inspection, live web search, and read-only SQL querying against SQLite or Postgres/Supabase β all through one server.
π Live Playground: Glama MCP Link β try the tools directly in the browser once listed (see Deployment).
π Overview
DevTools MCP exposes four tools over MCP so an LLM assistant can:
Pull clean, readable text from any webpage
Tail your local log files to debug errors
Search the live web for current documentation before writing code
Run read-only
SELECTqueries against a local SQLite file or a live Postgres/Supabase database
Every tool is a plain, testable Python function β nothing here depends on paid APIs except your own optional Supabase project.
Related MCP server: FireScrape MCP Server
β¨ Features
Tool | Description |
π | Fetches a webpage, strips |
π | Reads the last N lines of a local file β surfaces recent stack traces or error output. |
π | Searches the live web via DuckDuckGo ( |
ποΈ | Runs a read-only |
ποΈ Architecture
ββββββββββββββββββββββββ
β MCP Client β (Claude Desktop / Claude Code / Cursor / etc.)
ββββββββββββ¬βββββββββββββ
β MCP protocol (stdio)
ββββββββββββΌβββββββββββββ
β DevTools MCP Server β FastMCP("DevTools") β server.py
β β
β ββββββββββββββββββββ β
β β fetch_markdown β ββββΆ requests + BeautifulSoup βββΆ any URL
β ββββββββββββββββββββ€ β
β β read_log β ββββΆ local filesystem
β ββββββββββββββββββββ€ β
β β search_web β ββββΆ DDGS (DuckDuckGo, key-free)
β ββββββββββββββββββββ€ β
β β query_database β ββββΆ _is_safe_select() (SQL safety gate)
β β β β β
β β β β ββββΆ _query_sqlite() βββΆ local .db file
β β β β ββββΆ _query_postgres() βββΆ Postgres / Supabase
β ββββββββββββββββββββ β
ββββββββββββββββββββββββββHow query_database decides where to send a query
query_database(db_path_or_url, sql_query, limit)
β
βΌ
_is_safe_select(sql_query)?
β
ββββββ΄βββββ
NO YES
β β
reject does db_path_or_url start with
query "postgres://" or "postgresql://" ?
β
βββββββ΄ββββββ
YES NO
β β
_query_postgres() _query_sqlite()_is_safe_select is a hard gate that only allows single, plain SELECT statements β no INSERT/UPDATE/DELETE/DROP/ALTER/etc., and no stacked queries chained with ;. This matters because the SQL text is generated by an LLM, not typed by hand β the gate is there so a hallucinated or manipulated query can't mutate or destroy your data.
Stack:
fastmcpβ MCP server framework; turns Python functions into MCP tools via@mcp.toolrequests+beautifulsoup4β web scrapingddgsβ key-free live web search (formerlyduckduckgo-search)sqlite3β built into Python, used for local database queriespsycopg2β Postgres/Supabase client, imported lazily only when a Postgres URL is usedpython-dotenvβ loads local.envvariablespytest+pytest-mockβ test suite
π Project Structure
.
βββ venv/ # Local virtual environment (not committed)
βββ .env # Local secrets β real keys/paths, never committed
βββ .gitignore
βββ README.md
βββ requirements.txt # Runtime + dev/test dependencies
βββ server.py # Main MCP server β all 4 tools live here
βββ test_server.py # Pytest suite covering all 4 tools
βββ Dockerfile # Optional β only needed for Glama's hosted deployment
βββ glama.json # Optional β repo attribution for Glama's listing
βββ smithery.yaml # Optional β only relevant if also listing on Smitheryπ Getting Started
1. Clone the repo
git clone https://github.com/YOUR_USERNAME/YOUR_REPO.git
cd YOUR_REPO2. Create a virtual environment & install dependencies
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt3. Configure environment variables (optional)
server.py calls load_dotenv() on startup, so any variables in a local .env file are picked up automatically. None of the current tools require env vars β query_database takes its connection info as a direct parameter β but you may still want a .env for local convenience:
# Only needed if you want a default connection string handy locally.
# Real credentials should live here and nowhere else.
SUPABASE_DB_URL=postgresql://postgres:your-password@db.xxxxxxxx.supabase.co:5432/postgresβ οΈ Never commit your
.envfile. It's already excluded via.gitignore.Note: this is different from a Supabase project's
SUPABASE_URL/SUPABASE_KEY(used by the REST/JS client).query_databasetalks to Postgres directly viapsycopg2, so it needs the Postgres connection string from your Supabase dashboard under Settings β Database β Connection string, not the API URL/key pair.
4. Run the server locally
python server.pyThis starts the MCP server over stdio, ready to be connected to any MCP client.
π Connecting to Claude Desktop / Claude Code
Add the server to your MCP client config (e.g. claude_desktop_config.json):
{
"mcpServers": {
"devtools": {
"command": "python",
"args": ["/absolute/path/to/server.py"]
}
}
}Restart your client β the four tools (fetch_markdown, read_log, search_web, query_database) will appear as functions the assistant can call.
π§° Tool Reference
fetch_markdown(url: str) -> str
Fetches a webpage, strips <script>, <style>, <nav>, and <footer> tags, and returns cleaned plain text (capped at 8,000 characters).
fetch_markdown("https://docs.python.org/3/library/asyncio.html")read_log(file_path: str, lines: int = 50) -> str
Reads the last lines lines of a local text/log file.
read_log("/var/log/app/error.log", lines=100)search_web(query: str, max_results: int = 3) -> str
Searches DuckDuckGo for the given query and returns title, link, and snippet for each result.
search_web("fastapi background tasks example")query_database(db_path_or_url: str, sql_query: str, limit: int = 50) -> str
Runs a read-only SELECT against:
a local SQLite file (pass a file path), or
a Postgres/Supabase database (pass a connection string starting with
postgres://orpostgresql://)
Results are returned as a list of {column: value} dictionaries, capped at limit rows.
query_database("app.db", "SELECT * FROM users WHERE status = 'active'", limit=5)
query_database("postgresql://user:pass@host:5432/db", "SELECT id, email FROM users", limit=10)Safety guarantees:
Only queries starting with
SELECTare allowedQueries containing
INSERT,UPDATE,DELETE,DROP,ALTER,TRUNCATE,GRANT,REVOKE,CREATE, orATTACHanywhere are rejectedStacked queries (
SELECT ...; DROP TABLE ...) are rejectedKnown limitation: the check is a substring match, not a full SQL parser β a harmless query like
SELECT * FROM updates_logwill also be rejected, since it contains the substringupdate. This is a deliberate false-positive-over-false-negative tradeoff.
π§ͺ Testing
The project ships with a 27-test pytest suite covering all four tools, run fully offline via mocked network calls and throwaway tmp_path fixtures β nothing touches a real file, database, or website.
pip install -r requirements.txt
pytest test_server.py -vWhat's covered:
_is_safe_selectβ 10+ cases across valid selects, every forbidden keyword, stacked queries, and known false-positive behaviorquery_database(SQLite) β basic select,limit,WHEREfiltering, blocked unsafe queries, missing file, missing table, empty result set, and Postgres URL routing (mocked)read_logβ tail behavior, missing file, default line countfetch_markdownβ HTML stripping and error handling (network mocked)search_webβ result formatting, empty results, error handling (network mocked)
_query_postgresitself is not exercised against a live database in this suite β only the routing logic that decides whether to call it. Testing it live requires a real Postgres/Supabase connection string, which should never be hardcoded into test files or committed to the repo.
π Deployment
Option A β Glama (free directory listing + browser inspector)
Submit this repo's GitHub URL at glama.ai/mcp β Glama indexes your tools directly from the source, no build or manifest required. Visitors get an in-browser inspector to try fetch_markdown, read_log, search_web, and query_database without installing anything locally.
Optional: add glama.json (already included) to claim/attribute the listing to your GitHub account.
Option B β Glama hosted deployment (Glama runs it for you, 24/7)
Connect the Glama GitHub App to this repo and it builds the included Dockerfile into a running instance behind Glama's gateway (managed TLS, auth, logging). Check glama.ai/mcp/hosting for current plan details before committing to this path.
Option C β Smithery
β οΈ As of early 2026, Smithery no longer accepts new free hosted deployments via GitHub β that now requires a paid plan. The free path on Smithery is registering this server as an external server (i.e. you host it yourself β e.g. via Glama's hosted option above β and just point Smithery's listing at that URL). smithery.yaml is still included in this repo in case you go that route; see smithery.ai for current details, since their hosting model is actively changing.
π Environment Variables
Variable | Required | Used by |
| β Optional | Not read automatically β |
query_database is intentionally stateless with respect to credentials β nothing is read from environment variables inside the tool itself, so no database credentials are ever stored server-side by default.
πΊοΈ Roadmap
Add a real integration test against a disposable Postgres/Supabase instance (CI-only, credentials never committed)
Replace the substring-based SQL keyword check with a proper SQL parser (e.g.
sqlparse) to eliminate false positivesAdd caching for
search_webandfetch_markdownAdd an authentication layer for hosted Smithery deployments
π€ Contributing
Contributions, issues, and feature requests are welcome β feel free to open a PR or issue.
π License
This project is licensed under the MIT License.
This server cannot be installed
Maintenance
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables web search through DuckDuckGo and webpage content fetching with intelligent text extraction. Features built-in rate limiting and LLM-optimized result formatting for seamless integration with language models.2MIT
- Alicense-qualityDmaintenanceEnables AI models to search the web using DuckDuckGo, scrape webpage content in markdown format, and browse/read local files for code analysis and debugging.191MIT
- AlicenseAqualityDmaintenanceProvides web access capabilities for LLMs including search, fetching, content extraction, PDF reading, image viewing, and screenshots.346MIT
- Flicense-qualityCmaintenanceEnables AI agents to search the web via DuckDuckGo and fetch relevant webpage content using an LLM, without requiring an API key.
Related MCP Connectors
LLM-ready web search + instant answers + URL-to-clean-text fetch for agents and RAG.
Give your agent live data from Twitter, Reddit, the web and GitHub. No API keys, no scraping stack.
Read a URL as clean markdown, screenshot a website, url to PDF. Web access for agents, no signup.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/notayannn/devtools-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server