Demo HTTP MCP Server
test-http-mcp
Демонстрационный сервер протокола контекста модели (MCP), реализованный на Python с использованием пакета http-mcp. Он может работать через HTTP (Starlette/Uvicorn) или через stdio, предоставляя примеры инструментов (Tools) и подсказок (Prompts) любому MCP-совместимому клиенту. Проект включает в себя фронтенд на React, который предоставляет чат-интерфейс для поиска уязвимостей через NVD (Национальная база данных уязвимостей).

Структура проекта
test-http-mcp/
├── backend/ # Python backend (FastAPI + MCP server)
│ ├── app/ # Application source code
│ │ ├── app.py # FastAPI app, routes, MCP mount
│ │ ├── main.py # Entry points (HTTP / stdio)
│ │ ├── agen_memory.py # SQLite message persistence
│ │ ├── config.py # Settings via pydantic-settings
│ │ ├── auth0/ # Auth0 integration
│ │ │ ├── __init__.py # JWT token validator
│ │ │ └── client_store.py # Dynamic client registration (RFC 7591)
│ │ ├── tools/ # MCP tools (CPE/CVE search via NVD)
│ │ └── prompts/ # MCP prompt templates
│ ├── pyproject.toml # Python deps & scripts
│ ├── uv.lock # Locked dependencies
│ ├── ruff.toml # Linter config
│ ├── mypy.ini # Type-checker config
│ └── .envrc # direnv auto-activation
├── frontend/ # React + TypeScript frontend (Vite)
│ ├── src/
│ │ ├── components/ # ChatApp, ChatInput, MessageList, MessageBubble
│ │ ├── api.ts # API client (fetch history, stream messages)
│ │ ├── types.ts # Shared TypeScript types
│ │ ├── App.tsx # Root component
│ │ └── App.css # Styles
│ ├── vite.config.ts # Vite config with dev proxy
│ └── package.json # Node dependencies
├── AGENTS.md
├── LICENSE
└── README.mdАутентификация (Auth0)
MCP-эндпоинт (/mcp/) защищен с помощью аутентификации Auth0 OAuth2. Для инструментов требуются области видимости (scopes) (tool:search_cpe, tool:search_cve), которые должны присутствовать в токене доступа.
Необходимые переменные окружения
Переменная | Описание |
| Домен арендатора Auth0 (например, |
| Идентификатор API для проверки токена |
| Идентификатор клиента приложения Auth0 для MCP-приложения |
| Идентификатор клиента Management API (для динамической регистрации) |
| Секрет клиента Management API |
| Установите |
Разместите их в backend/.env (файл игнорируется git).
Структура монтирования приложения
Путь | Приложение | Аутентификация |
| Защищенный MCP-сервер | Требуется токен Auth0 Bearer |
| Динамическая регистрация клиента (RFC 7591) | Без аутентификации |
| Метаданные OAuth/ресурсов | Без аутентификации |
| Эндпоинты чат-интерфейса | Без аутентификации (см. примечание) |
| Статические файлы фронтенда | Без аутентификации |
Примечание: Эндпоинты чата намеренно не защищены для локальной разработки. Добавьте аутентификацию перед тем, как открывать доступ за пределами localhost.
Требования
Python 3.13
Node.js 18+ и npm
uv(рекомендуется) илиpip
Установка
Бэкенд (с использованием uv):
cd backend
uv run python -V # creates a venv and syncs deps from pyprojectБэкенд (с использованием pip):
cd backend
python3.13 -m venv .venv
source .venv/bin/activate
pip install .Фронтенд:
cd frontend
npm installЗапуск
Разработка (фронтенд + бэкенд отдельно)
Запуск бэкенда:
cd backend
uv run run-app
# → API on http://localhost:8000
# → MCP endpoint on http://localhost:8000/mcp/Запуск сервера разработки фронтенда (в отдельном терминале):
cd frontend
npm run dev
# → UI on http://localhost:5173 (proxies /api/* → backend)Продакшн (бэкенд обслуживает собранный фронтенд)
Сборка фронтенда и запуск бэкенда:
cd frontend && npm run build && cd ..
cd backend && uv run run-app
# → Everything on http://localhost:8000Запуск (режим stdio)
Использование с Cursor или другими MCP-клиентами
При включенном Auth0 клиенты должны получить токен доступа OAuth2. Сервер поддерживает динамическую регистрацию клиентов RFC 7591 по адресу /register, поэтому MCP-клиенты, реализующие спецификацию аутентификации, будут регистрироваться автоматически.
Пример .cursor/mcp.json для режима HTTP:
{
"mcpServers": {
"test-http-mcp": {
"type": "http",
"url": "http://localhost:8000/mcp/"
}
}
}Использование с Gemini:
{
"mcpServers": {
"test": {
"httpUrl": "http://localhost:8000/mcp/",
"timeout": 5000
}
}
}Пример записи .cursor/mcp.json для подключения через stdio:
{
"mcpServers": {
"test_studio": {
"command": "uv",
"args": ["run", "--project", "backend", "run-stdio"],
"env": { "AUTHORIZATION_TOKEN": "Bearer TEST_TOKEN" }
}
}
}Что предоставляет этот сервер
Инструменты (см.
backend/app/tools/):search_cpe(product, version, vendor)— поиск перечислений общих платформ (CPE) через NVDsearch_cve(cpe_name)— поиск общих уязвимостей и рисков (CVE) для заданного CPE
Подсказки (см.
backend/app/prompts/):sync_nvd_search(dependency, version)— простая подсказка для поиска уязвимостейasync_nvd_search(dependency, version)— расширенная подсказка с предварительно полученными данными CVE
Скрипты проекта
В backend/pyproject.toml определены две точки входа в консоль:
run-app→app.main:run_httprun-stdio→app.main:run_stdiorun-app-local→app.app:main(с автоматической перезагрузкой)
Разработка
Общие задачи (запускаются из директории backend/):
uv run ruff check . # lint
uv run mypy . # type check
uv run pytest # tests
uv run mdformat . # format markdownЗадачи фронтенда (запускаются из директории frontend/):
npm run dev # start dev server
npm run build # production build
npm run lint # lint with ESLint
npx tsc --noEmit # type checkПримечания по реализации
Корневое приложение ASGI — это защищенное Auth0 MCP-приложение, созданное с помощью
auth_mcp, которое монтирует подприложение FastAPI по адресу/api.MCP-эндпоинт
/mcp/требует действительный токен Auth0 Bearer с соответствующими областями видимости инструментов.Динамическая регистрация клиентов по адресу
/registerпроксирует запросы к предварительно созданному приложению Auth0, обновляя его разрешенные URL-адреса обратного вызова. URI перенаправления проверяются (требуется HTTPS; HTTP разрешен только для localhost).Чат-интерфейс использует
pydantic-aiс агентом Ollama, который может вызывать инструменты MCP для поиска уязвимостей.История чата сохраняется в локальной базе данных SQLite через
agen_memory.py.Фронтенд на React передает ответы в виде JSON, разделенного символами новой строки, и отображает Markdown с помощью библиотеки
marked.В продакшене бэкенд обслуживает собранный фронтенд из
frontend/dist/с резервной маршрутизацией SPA (защищено от обхода путей).В режиме разработки Vite проксирует запросы
/api/*на бэкенд на порт 8000.
Лицензия
MIT — см. LICENSE.
Available Tools
4 toolsget_called_toolsGet Called ToolsAIdempotent
Get the list of called tools.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| called_tools | Yes | The list of called tools |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description doesn't contradict annotations and adds some context by specifying 'list of called tools' (implying retrieval of historical tool usage data). However, annotations already provide rich behavioral information: readOnlyHint=false (potentially confusing for a 'get' operation), openWorldHint=true, idempotentHint=true, destructiveHint=false. The description doesn't add significant behavioral details beyond what annotations already cover, but it doesn't contradict them either.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, clear sentence with zero wasted words. It's front-loaded with the essential information and perfectly sized for a simple tool. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (0 parameters, rich annotations, output schema exists), the description is reasonably complete. The annotations cover safety and behavioral traits, and the output schema will document return values. The description could be more specific about what 'called tools' means in context, but for a simple retrieval tool, it's mostly adequate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0 parameters and 100% schema description coverage, the schema already fully documents the lack of inputs. The description doesn't need to explain parameters, and it correctly doesn't mention any. The baseline for 0 parameters is 4, as the description appropriately focuses on the tool's purpose rather than nonexistent parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Get the list of called tools' clearly states the verb ('Get') and resource ('list of called tools'), making the purpose understandable. However, it doesn't distinguish this tool from its siblings (get_time, get_weather, tool_that_access_request) - all are 'get' operations but for different data. The description is adequate but lacks sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. There's no mention of context, prerequisites, or comparison with sibling tools. The agent must infer usage from the tool name alone, which offers minimal guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_timeGet TimeAIdempotent
Get the current time.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| time | Yes | The current time |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide key behavioral hints (readOnlyHint=false, openWorldHint=true, idempotentHint=true, destructiveHint=false), so the description doesn't need to repeat these. The description adds minimal context about what 'current time' means, but doesn't elaborate on format, timezone, or other behavioral details beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description 'Get the current time' is a single, efficient sentence that front-loads the core purpose with zero wasted words. It's appropriately sized for a simple tool with no parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (0 parameters, annotations covering key behaviors, and an output schema that presumably handles return values), the description is reasonably complete. However, it could slightly improve by hinting at the output format (e.g., timestamp vs. string) since sibling tools suggest varied contexts.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0 parameters and 100% schema description coverage, the schema fully documents the lack of inputs. The description doesn't need to add parameter information, so it appropriately avoids redundancy. A baseline of 4 is justified since no parameters exist to explain.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Get the current time' clearly states the verb ('Get') and resource ('current time'), making the purpose immediately understandable. However, it doesn't distinguish this tool from potential sibling tools like 'get_called_tools' or 'get_weather', which prevents a perfect score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. There are sibling tools like 'get_weather' that might serve related time/weather queries, but the description doesn't mention any context, prerequisites, or exclusions for usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_weatherGet WeatherBIdempotent
Get the current weather in a given location.
| Name | Required | Description | Default |
|---|---|---|---|
| location | Yes | The location to get the weather for | |
| unit | No | The unit of temperature | celsius |
Output Schema
| Name | Required | Description |
|---|---|---|
| weather | Yes | The weather in the given location |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide key behavioral hints (readOnlyHint=false, openWorldHint=true, idempotentHint=true, destructiveHint=false), so the description doesn't need to repeat these. It adds minimal context by implying real-time data retrieval, but doesn't disclose additional traits like rate limits, error handling, or authentication needs, which would elevate the score.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that front-loads the core purpose without unnecessary details. Every word earns its place, making it highly concise and well-structured for quick understanding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (2 parameters, 100% schema coverage, annotations provided, and an output schema exists), the description is reasonably complete. It states what the tool does, though it could benefit from slight enhancements like mentioning the output includes current conditions, but the output schema likely covers return values, reducing the burden.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents the parameters (location and unit). The description mentions 'location' but adds no extra meaning beyond what the schema provides, such as format examples or usage nuances, meeting the baseline for high coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with a specific verb ('Get') and resource ('current weather'), and it specifies the scope ('in a given location'). However, it doesn't distinguish this tool from potential siblings like 'get_forecast' or 'get_historical_weather', which would require explicit differentiation for a score of 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It lacks any mention of prerequisites, exclusions, or comparisons with sibling tools (e.g., 'get_time' or 'get_called_tools'), leaving the agent without context for tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tool_that_access_requestTool That Access RequestCIdempotent
Access the request.
| Name | Required | Description | Default |
|---|---|---|---|
| username | Yes | The username of the user |
Output Schema
| Name | Required | Description |
|---|---|---|
| message | Yes | The message to the user |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide significant behavioral information: readOnlyHint=false (implies mutation), openWorldHint=true (handles unknown inputs), idempotentHint=true (safe to retry), and destructiveHint=false (non-destructive). The description adds no behavioral context beyond these annotations—it doesn't explain what 'access' entails operationally, potential side effects, or any constraints like rate limits. However, it doesn't contradict the annotations, so it meets the lower bar with annotations present.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise at just three words ('Access the request.'), with no wasted language or unnecessary elaboration. It is front-loaded and efficiently communicates the core idea, though this brevity contributes to its vagueness in other dimensions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (1 parameter, annotations provide behavioral hints, output schema exists), the description is minimally adequate but incomplete. It lacks context on what the tool actually does, usage scenarios, or output expectations. The presence of an output schema means return values needn't be explained, but the description should still clarify purpose and guidelines better to be fully helpful.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage, with the 'username' parameter fully documented in the schema. The description adds no parameter semantics beyond what the schema provides—it doesn't explain why the username is needed, how it relates to the request, or any contextual details about parameter usage. With high schema coverage, the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Access the request' is a tautology that essentially restates the tool name 'tool_that_access_request' without adding meaningful specificity. It doesn't clarify what type of request is being accessed, what resource is involved, or what 'access' means in this context (read, modify, submit?). While it includes a verb ('access') and resource ('request'), it remains vague about the actual purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. There are sibling tools like 'get_called_tools', 'get_time', and 'get_weather', but the description doesn't explain how this tool differs from them or in what context it should be selected. No prerequisites, exclusions, or comparative context are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v1.0.0- First observed
get_called_tools - First observed
get_time - First observed
get_weather - First observed
tool_that_access_request
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.9 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.38 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.38 npmMIT