Demo HTTP MCP Server
This server exposes four MCP tools for weather, time, request access, and tool-call tracking.
Get the current weather for a location, with an optional temperature unit.
Get the current time.
Access a request for a specified username and return a message.
Retrieve the list of tools that have been called.
Provides OAuth2 authentication for the MCP endpoint, requiring valid Auth0 Bearer tokens with specific tool scopes, and supports dynamic client registration via RFC 7591.
Manages environment variables for backend configuration through .envrc and .env files.
Provides linting for the frontend codebase as part of the development workflow.
Serves as the backend framework for the MCP server, handling HTTP routes and mounting the MCP app with authentication middleware.
Renders formatted responses in the chat interface using the marked library for markdown processing.
Powers the chat interface agent that can call MCP tools to search for vulnerabilities in the National Vulnerability Database (NVD).
Handles configuration settings and data validation throughout the backend application.
Used for testing the Python backend codebase as part of the development workflow.
Provides the frontend chat interface for querying vulnerabilities, built with React and TypeScript using Vite.
Provides linting for the Python backend codebase as part of the development workflow.
Persists chat history and message data locally through SQLite database integration for the chat interface.
Used for Python dependency management and configuration in pyproject.toml files.
Used for the frontend implementation with typed interfaces for the chat application and API client.
Builds and serves the React frontend in development with proxy configuration to the backend, and handles production builds.
Click on "Deploy 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., "@Demo HTTP MCP Server what's the weather in London right now?"
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.
test-http-mcp
Demo Model Context Protocol (MCP) server implemented in Python using the
http-mcp package. It can run over HTTP (Starlette/Uvicorn, protected with
Auth0) or over stdio, exposing two web tools, web_search and web_fetch, to
any MCP-capable client. Each tool runs a Claude sub-agent built with
pydantic-ai that checks every web result for
prompt injection before reading it.
Project structure
test-http-mcp/
├── backend/ # Python MCP server
│ ├── app/ # Application source code
│ │ ├── app.py # Auth0-protected HTTP app (auth_mcp)
│ │ ├── main.py # Entry points (HTTP / stdio)
│ │ ├── config.py # Settings via pydantic-settings
│ │ ├── agents.py # Claude sub-agents (pydantic-ai) behind the web tools
│ │ ├── auth0/ # Auth0 integration
│ │ │ ├── __init__.py # JWT token validator
│ │ │ └── client_store.py # Dynamic client registration (RFC 7591, not mounted)
│ │ └── tools/ # MCP tools (web_search, web_fetch)
│ ├── tests/ # pytest suite, incl. end-to-end MCP client tests
│ ├── pyproject.toml # Python deps & scripts
│ ├── uv.lock # Locked dependencies
│ ├── ruff.toml # Linter config
│ ├── mypy.ini # Type-checker config
│ └── .envrc # direnv auto-activation
├── flake.nix # Nix dev shell
├── AGENTS.md
├── LICENSE
└── README.mdProtocol
The server speaks only MCP protocol revision 2026-07-28 (http-mcp >= 0.17).
There is no initialize handshake, so clients must use an MCP SDK that supports
that revision, for example the Python mcp SDK >= 2.x or FastMCP 4.
Authentication (Auth0, HTTP only)
The HTTP endpoint (/mcp/) is protected with Auth0 OAuth2 authentication.
Tools require scopes (tool:web_search, tool:web_fetch) to be present in
the access token; define both as permissions on the Auth0 API. stdio mode has no
authentication and no tool scopes.
Required environment variables
Variable | Description |
| Auth0 tenant domain (e.g. |
| Auth0 API identifier. Must be the MCP resource URI ( |
| Auth0 application client ID for the MCP app (used by |
| Management API client ID (used by |
| Management API client secret (used by |
| Set to |
Place these in backend/.env (git-ignored).
Claude sub-agents (HTTP and stdio)
Both tools call Claude through the Anthropic API, so the server needs Anthropic
credentials. Set ANTHROPIC_API_KEY in backend/.env or the environment, or
sign in once with ant auth login: without a key, the Anthropic SDK uses that
profile (or ANTHROPIC_AUTH_TOKEN). The server starts without credentials; a
tool call then fails with "the server has no Anthropic credentials configured".
Variable | Description |
| Anthropic API key (optional, see above) |
| Claude model for both sub-agents (default: |
|
|
Requests opt into Anthropic's server-side refusal fallback (fallbacks: "default"):
a request a safety classifier declines is re-run on Anthropic's recommended
fallback model instead of failing.
HTTP routes
Path | Purpose | Auth |
| MCP server (Streamable HTTP) | Auth0 Bearer token required |
| Protected resource metadata (RFC 9728), names Auth0 as the authorization server | Unauthenticated |
Clients discover Auth0's endpoints from the tenant itself, so client registration depends on the tenant: enable Dynamic Client Registration in Auth0, or configure the client with a pre-registered client ID.
Requirements
Python 3.13
uv(recommended) orpipNode.js (optional): only for
npx-based MCP clients and servers
Alternatively, Nix supplies all of the above — see Nix dev shell.
Nix dev shell
flake.nix pins the whole toolchain (Python 3.13, uv, Node.js 24, git),
so nothing needs to be installed system-wide:
nix developWith direnv the shell loads automatically on cd, and
also syncs backend/.venv:
direnv allowLibrary dependencies stay owned by backend/uv.lock, so pinned tool versions
(ruff, mypy, pytest) come from uv, not from Nix. Inside the shell uv is
pinned to the Nix interpreter (UV_PYTHON, UV_PYTHON_DOWNLOADS=never) so it
never downloads a second Python.
To bump the pinned nixpkgs revision:
nix flake updateInstall
Using uv:
cd backend
uv syncUsing pip:
cd backend
python3.13 -m venv .venv
source .venv/bin/activate
pip install .Run
HTTP (needs the Auth0 variables above):
cd backend
uv run run-app # → MCP endpoint on http://localhost:8000/mcp/
uv run run-app-local # same, with auto-reloadstdio (no Auth0 configuration needed):
cd backend
uv run run-stdioTest with an MCP client
With the Python mcp SDK (installed in the dev group):
import asyncio
import httpx2
from mcp import Client, StdioServerParameters
from mcp.client.streamable_http import streamable_http_client
async def main() -> None:
# stdio: the client launches the server as a subprocess
stdio = StdioServerParameters(command="uv", args=["run", "--project", "backend", "run-stdio"])
async with Client(stdio) as client:
print(await client.list_tools())
# HTTP: pass an Auth0 access token for this API (audience = the MCP resource URI)
http_client = httpx2.AsyncClient(headers={"Authorization": "Bearer <access-token>"})
async with Client(streamable_http_client("http://localhost:8000/mcp/", http_client=http_client)) as client:
print(await client.call_tool("web_search", {"query": "What is the Model Context Protocol?"}))
asyncio.run(main())Example .cursor/mcp.json for HTTP mode:
{
"mcpServers": {
"test-http-mcp": {
"type": "http",
"url": "http://localhost:8000/mcp/"
}
}
}Usage with Gemini:
{
"mcpServers": {
"test": {
"httpUrl": "http://localhost:8000/mcp/",
"timeout": 5000
}
}
}Example .cursor/mcp.json entry to connect via stdio:
{
"mcpServers": {
"test_studio": {
"command": "uv",
"args": ["run", "--project", "backend", "run-stdio"]
}
}
}What this server exposes
Two tools (see backend/app/tools/ and backend/app/agents.py), no prompts:
web_search(query): a Claude sub-agent searches DuckDuckGo (pydantic-ai'sduckduckgo_search_tool) and answers from the results.web_fetch(url, question?): a Claude sub-agent reads the page (pydantic-ai'sweb_fetch_tool) and answers the question, or summarizes the page. It can follow links on the same site only (the URL's host and itswww.twin, redirects included); private and cloud-metadata addresses are refused.
Both return {answer, sources, prompt_injection_detections}. Each sub-agent has
pydantic-ai-harness's PromptInjectionDefender with block_high_risk=True: every
search result and fetched page is classified (StackOne defender, pattern
detection) before the model reads it, high- and critical-risk results are
replaced with a short notice, and each flagged result is listed in
prompt_injection_detections. Treat answer as untrusted web content all the
same: the defender catches known patterns, not every injection.
Anthropic's server-side web search and fetch tools are not used on purpose: they run on Anthropic's side, so the defender would never see their results.
Project scripts
Three console entry points are defined in backend/pyproject.toml:
run-app→app.main:run_http(HTTP onlocalhost:8000)run-app-local→app.app:main(HTTP with auto-reload)run-stdio→app.main:run_stdio
Development
Common tasks (run from the backend/ directory):
uv run ruff check . # lint
uv run mypy . # type check
uv run pytest # tests
uv run mdformat . # format markdowntests/test_mcp_client_compat.py drives the server with the real mcp SDK
client over HTTP (plain and Auth0-protected) and over stdio (run-stdio), so it
catches protocol drift between http-mcp and MCP clients.
tests/test_web_agents.py runs the real prompt-injection defender against
injected search results and pages. No test calls Claude or the web: models are
replaced with pydantic-ai's TestModel/FunctionModel, and an autouse fixture
fails any test that would reach DuckDuckGo or download a page.
Implementation notes
The HTTP app is an Auth0-protected MCP app created by
auth_mcp; the MCP endpoint at/mcp/requires a valid Auth0 Bearer token with the appropriate tool scopes.Auth0ClientStore(dynamic client registration proxied to a pre-created Auth0 application) is kept but not mounted: http-mcp >= 0.19 accepts only HTTPS authorization servers and endpoints unless loopback HTTP is explicitly enabled withAuthorizationTransportPolicy.ALLOW_LOOPBACK_HTTP(0.19.0rc2+, development only), and MCP clients on SDK 2.x require the metadataissuerto match the advertised server, which a localhost proxy for Auth0 cannot satisfy.Only loopback browser origins are accepted on
/mcp/(http-mcp's DNS rebinding defence); clients that send noOriginheader are unaffected.
License
MIT — see LICENSE.
Available Tools
4 toolsget_called_toolsGet Called ToolsAIdempotent
Get the list of called tools.
Inputs: no named parameters. Returns: called_tools
get_timeGet TimeAIdempotent
Get the current time.
Inputs: no named parameters. Returns: time
get_weatherGet WeatherBIdempotent
Get the current weather in a given location.
Inputs: location (required), unit. Returns: weather
tool_that_access_requestTool That Access RequestCIdempotent
Access the request.
Inputs: username (required). Returns: message
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 4 tools
Each tool has a clearly distinct purpose: get_called_tools retrieves internal server usage data, get_time provides current time, get_weather fetches location-based weather, and tool_that_access_request handles request metadata. There is no overlap in functionality, making tool selection unambiguous.
Three tools follow a consistent 'get_*' verb_noun pattern, but tool_that_access_request deviates with a noun_verb structure and uses 'that' as a connector. This mixed convention reduces predictability, though the names remain readable.
With 4 tools, the count is reasonable for a demo HTTP server, covering basic utilities like time, weather, and request handling. It is slightly thin for broader HTTP operations but appropriate for a limited scope.
The server covers basic utilities but lacks core HTTP operations like making requests (GET, POST) or handling responses, which are expected for an HTTP server. The tools are standalone utilities rather than a cohesive HTTP interface, leaving notable gaps in functionality.
Maintenance
Related MCP Connectors
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA minimal Model Context Protocol server demo that exposes tools through HTTP API, including greeting, weather lookup, and HTTP request capabilities. Demonstrates MCP server implementation with stdio communication and HTTP gateway functionality.6 npmISC
- FlicenseBqualityDmaintenanceA demonstration server showcasing MCP capabilities with basic tools including addition calculations and weather API integration for fetching city weather data.2-
- FlicenseNot gradedqualityDmaintenanceA basic MCP server for testing with echo, datetime, and calculator tools.71 npm-
- AlicenseAqualityDmaintenanceA minimal MCP server example demonstrating Tools, Resources, and Prompts. It enables calculations, time queries, note management, and code review prompts via stdio transport.319 npmMIT