Skip to main content
Glama

DevTools MCP

A small developer-utility MCP server, built to learn the Model Context Protocol end-to-end: server implementation, local testing, using an existing MCP, public deployment, and Smithery publishing.

1. Overview

DevTools MCP exposes four small developer tools over the Model Context Protocol: explaining an error message, validating/formatting JSON, generating a regex from a description, and summarizing text with an LLM (Groq). A minimal TypeScript/Vite dashboard lets you exercise the tools from a browser, connecting as a real MCP client.

Related MCP server: ai-assistant

2. Why MCP

MCP standardizes how an LLM host (Claude Desktop, an IDE, an agent) discovers and calls tools, instead of every project inventing its own bespoke tool-calling API. Building a real MCP server - not a REST API with an MCP label slapped on - was the primary learning goal of this project.

3. Architecture

MCP Client
    |
MCP Protocol
    |
DevTools MCP Server
    |-- explain_error    (local/deterministic)
    |-- format_json      (local/deterministic)
    |-- generate_regex   (local/deterministic)
    `-- summarize_text
            |
        Groq API
            |
        GPT-OSS 120B

The server (server/server.py) is an mcp.server.MCPServer (MCP Python SDK v2). It runs over stdio for local testing (MCP Inspector, Client(mcp)) and over Streamable HTTP (/mcp) for remote/browser access. The TypeScript frontend (frontend/) is a genuine MCP client: it uses @modelcontextprotocol/sdk's Client + StreamableHTTPClientTransport to talk to the server directly over Streamable HTTP (CORS-enabled on the server), not a hand-rolled REST bridge.

4. Tools

Tool

Inputs

What it does

explain_error

error_message, language_or_framework?

Matches the error against a library of common error patterns (Python/JS/general) and returns a likely cause + practical fix. Local/deterministic.

format_json

json_text

Validates JSON and returns a pretty-printed version, or a precise parse error (line/column). Local/deterministic.

generate_regex

description

Matches the description against a small library of common regex patterns (email, URL, IPv4, date, UUID, etc.) and returns the pattern plus an explanation. Local/deterministic.

summarize_text

text, max_length?

Calls Groq (openai/gpt-oss-120b) to produce a concise summary. Handles missing credentials, timeouts, and API errors gracefully.

5. Project structure

devtools-mcp/
├── server/
│   ├── server.py               # MCPServer + tool registration + ASGI app
│   ├── tools.py                # explain_error / format_json / generate_regex logic
│   ├── ai.py                   # Groq-backed summarize_text logic
│   └── tests/
│       └── test_server.py      # pytest suite using the SDK's in-memory Client
├── frontend/
│   ├── index.html
│   ├── src/
│   │   ├── main.ts             # real MCP client (StreamableHTTPClientTransport)
│   │   └── style.css
│   ├── package.json
│   ├── tsconfig.json
│   └── vite.config.ts
├── .env.example
├── .gitignore
├── requirements.txt
├── render.yaml                 # optional Render Blueprint
├── README.md
└── EXISTING_MCP_EXPERIENCE.md

6. Prerequisites

  • Python 3.10+

  • Node.js 18+ and npm (for the frontend, and to run the MCP Inspector via npx)

  • A Groq API key (only required for summarize_text)

  • (Optional, for deployment) A Render account and a Smithery account

7. Installation

git clone <this-repo>
cd devtools-mcp
python3 -m venv .venv
. .venv/bin/activate          # Windows: .venv\Scripts\activate
pip install -r requirements.txt

8. Environment variables

Copy .env.example to .env and fill in what you need:

GROQ_API_KEY=            # required for summarize_text
GROQ_MODEL=openai/gpt-oss-120b
MCP_ALLOWED_HOSTS=        # only needed when deployed behind a real hostname
MCP_ALLOWED_ORIGINS=      # comma-separated browser origins allowed via CORS

.env is git-ignored. Never commit real secrets.

9. Local setup

Stdio (default, for local MCP clients):

python -m server.server

Streamable HTTP (for the frontend, or any HTTP-based MCP client), local only:

uvicorn server.server:app --host 127.0.0.1 --port 8000

MCP_ALLOWED_HOSTS can stay unset locally - the SDK's built-in localhost-only DNS-rebinding protection covers 127.0.0.1/localhost automatically. Health check: curl http://127.0.0.1:8000/health.

10. MCP Inspector testing

# Against stdio:
uv run mcp dev server/server.py     # requires uv; or: npx @modelcontextprotocol/inspector
# Against a running Streamable HTTP server:
npx @modelcontextprotocol/inspector --cli http://127.0.0.1:8000/mcp --method tools/list

This was run against the local Streamable HTTP server during development and verified all four tools are discoverable with correct input/output schemas (see "Testing" below for the exact results).

11. Frontend setup

cd frontend
npm install
npm run dev          # http://localhost:5173

In the running dashboard, set the server URL field to your MCP server's /mcp endpoint (default http://localhost:8000/mcp), click Connect, pick a tool, fill in the form, and click Run. For local use, start the backend with MCP_ALLOWED_ORIGINS=http://localhost:5173 so CORS allows it.

Production build: npm run build (outputs to frontend/dist/).

12. Groq setup

  1. Create an API key at console.groq.com.

  2. Set GROQ_API_KEY (and optionally GROQ_MODEL, default openai/gpt-oss-120b) in your .env or your deployment platform's environment variables.

  3. No other LLM provider is used anywhere in this project.

13. Existing MCP experience

See EXISTING_MCP_EXPERIENCE.md for the required demonstration of using an existing MCP server (Context7) - what it is, how it was connected, the actual query run, and what was learned.

14. Deployment to Render

Render's native Python runtime is used (no Docker required).

Dashboard setup:

  1. Push this repo to GitHub.

  2. In Render: New → Web Service → connect the repo.

  3. Runtime: Python 3. Build command: pip install -r requirements.txt. Start command: uvicorn server.server:app --host 0.0.0.0 --port $PORT.

  4. Set environment variables: GROQ_API_KEY, GROQ_MODEL, MCP_ALLOWED_HOSTS=<your-service>.onrender.com,<your-service>.onrender.com:*, and MCP_ALLOWED_ORIGINS=<your-frontend-origin> (if you also deploy the frontend).

  5. Deploy. The MCP endpoint will be https://<your-service>.onrender.com/mcp.

A render.yaml Blueprint is included as a convenience for the same setup.

Manual verification step required: actually deploying requires a Render account and was not performed as part of this response - see the completion report for what remains a manual step.

15. Smithery publishing

The current Smithery CLI supports publishing an already-hosted remote MCP server URL directly (no Docker/container packaging needed for this path):

npm install -g smithery
smithery auth login
smithery mcp publish "https://<your-service>.onrender.com/mcp" -n "<your-org>/devtools-mcp"

After publishing, verify the four tools are exposed:

smithery mcp add "https://<your-service>.onrender.com/mcp" --id devtools-mcp
smithery tool list devtools-mcp

Manual step required: this needs a Smithery account and a live, publicly reachable Render deployment first; it was not performed as part of this response.

16. Public MCP usage

Once deployed, any Streamable HTTP MCP client can connect to:

https://<your-service>.onrender.com/mcp

Example with the SDK's Client:

from mcp import Client
from mcp.client.streamable_http import streamable_http_client

async with streamable_http_client("https://<your-service>.onrender.com/mcp") as (r, w, _):
    async with Client(r, w) as client:
        await client.initialize()
        print(await client.list_tools())

17. Testing

Actually run in this environment:

pytest server/tests/ -v

Result: 11 passed - tool discovery; valid, malformed, and empty format_json input; matched and unmatched explain_error patterns (including empty input); generate_regex for a known pattern (with a live regex match check) and an unmatched description; summarize_text with a missing GROQ_API_KEY and with empty input.

Also actually run (manual, outside pytest):

  • uvicorn server.server:app started successfully; /health returned {"status":"ok",...}.

  • A raw initialize JSON-RPC POST to /mcp returned 200.

  • The real MCP Inspector CLI (npx @modelcontextprotocol/inspector --cli) connected over Streamable HTTP, listed all four tools with correct schemas, and successfully called generate_regex, explain_error, and format_json (both valid and invalid JSON), and summarize_text (correctly reported the missing-API-key error, since no real Groq key was available in this environment).

  • Transport security verified: a request with a spoofed Host header correctly received 421 Misdirected Request.

  • CORS preflight verified: an OPTIONS /mcp request with Origin: http://localhost:5173 returned 200 with the correct access-control-* headers once MCP_ALLOWED_ORIGINS was set.

  • Frontend: npx tsc --noEmit passed with no errors; npm run build succeeded and produced frontend/dist/.

Not verified (requires external accounts/credentials not available in this environment): a real summarize_text call with a live Groq API key, the Render deployment itself, and Smithery publishing/listing.

18. Limitations

  • summarize_text was only tested end-to-end for its error paths; it has not been called with real Groq credentials.

  • Render deployment and Smithery publishing require manual steps with your own accounts (see sections 14-15) and have not been performed here.

  • explain_error and generate_regex use small, hand-written pattern libraries, not an LLM - they're deliberately simple/deterministic per the project's scope, so they won't recognize every possible error or pattern description.

  • The frontend has no authentication and is meant for local/demo use, per the project's explicit "no accounts/auth" scope.

19. Learning outcomes

  • What MCP is: a standardized protocol separating "providing context/ actions to an LLM" from "the LLM interaction itself," so a server built once (like this one) works with any compliant client.

  • Host / client / server: the host is the LLM application (Claude Desktop, or the app behind the browser dashboard); the client is the MCP-speaking component inside it (the SDK's Client, or our frontend's StreamableHTTPClientTransport-based client); the server is what we built - it never talks to a model directly.

  • Tools vs. resources vs. prompts: tools are model-controlled (the LLM decides to call format_json); resources are application-controlled data loads; prompts are user-invoked templates. This project only needed tools.

  • Tool discovery and invocation: a client calls tools/list to learn what's available (name, description, JSON-schema inputs/outputs, all derived automatically from Python type hints and docstrings), then tools/call to invoke one by name with arguments.

  • Why MCP vs. a plain REST API: a REST API needs a bespoke integration per client; an MCP server describes its own capabilities and schemas, so any MCP-aware host can use it without custom glue code - demonstrated directly by connecting the same server to both the MCP Inspector and our own hand-built frontend client with zero server-side changes.

  • Where the LLM fits: only inside summarize_text, which calls out to Groq. The rest of the server is plain deterministic code - a useful reminder that "MCP server" and "AI application" are not the same thing.

  • Deployment realities: Streamable HTTP servers default to localhost-only Host/Origin allowlisting for safety, and that has to be explicitly opened up (TransportSecuritySettings) once deployed behind a real hostname - confirmed hands-on by triggering and then fixing a 421.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables AI clients to use developer utilities like JSON formatting, JWT decoding, UUID generation, and more via MCP.
    12
    36 npm
    2
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables MCP-compatible applications to interact with local and cloud-hosted LLM models for model management, text generation, chat, embeddings, and web search/fetch.
    958 npm
    AGPL 3.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables MCP-compatible applications to manage and use local or cloud LLM models through comprehensive SDK tools, including model management, text generation, chat with tool support, embeddings, and web search/fetch.
    958 npm
    AGPL 3.0