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.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
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.
Web search and page-reading for AI agents. One-click OAuth connect, or a Caesar API key.
Web data tools for AI agents: pages as markdown, search, maps, commerce, jobs, AI answers.
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
- AlicenseNot gradedqualityDmaintenanceEnables 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
- AlicenseAqualityCmaintenanceProvides filesystem, web search, SQLite, and system tools for AI assistants like Claude, enabling secure access to local resources and the web.6MIT
- AlicenseAqualityCmaintenanceExposes local file I/O, a restricted shell whitelist, and SQLite helpers for safe integration with AI clients like Cursor and Claude Desktop.7MIT
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