Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Swag

БесплатноНе проверен

Enables agents to browse a catalog of OpenAPI specs, search for operations, and retrieve full operation contracts to build API requests without calling the targ

GitHubEmbed

Описание

Enables agents to browse a catalog of OpenAPI specs, search for operations, and retrieve full operation contracts to build API requests without calling the target APIs.

README

MCP server (Python, FastMCP).

Run

The only runtime mode is an HTTP server: FastAPI + MCP on /mcp and GET /health. Locally it runs via Docker; in production the same image runs (uv run uvicorn swag.app.asgi:app).

Local (Docker)

docker compose up --build

Compose mounts ./swag into the container and runs uvicorn with --reload, so code changes are picked up without rebuilding the image.

Check:

curl http://localhost:8765/health
# {"status":"ok","service":"swag"}
# MCP endpoint: http://localhost:8765/mcp/

docker-compose.yml maps host port 8765 → container port 8000, so on the host the server is reachable at http://localhost:8765. The MCP endpoint is mounted at /mcp/ (note the trailing slash — without it Starlette returns a 307 redirect to /mcp/).

Connecting a client

The server speaks MCP Streamable HTTP (FastMCP, stateless_http, JSON responses). Use a Streamable HTTP client config, not an SSE one — the distinction matters because some clients pick the transport from the config key.

Cursor

Cursor's url key uses Streamable HTTP:

{
  "mcpServers": {
    "swag": {
      "url": "http://localhost:8765/mcp/"
    }
  }
}

qwen-code / gemini-cli

In these clients the config key selects the transport: httpUrl = Streamable HTTP, while url = SSE. This server is Streamable HTTP, so you must use httpUrl:

{
  "mcpServers": {
    "swag": {
      "httpUrl": "http://localhost:8765/mcp/"
    }
  }
}

Using url here makes the client open an SSE stream (GET /mcp/) without a session id; the server replies 400 Bad Request: Missing session ID, and the client then falls back to OAuth discovery and fails (Failed to discover OAuth configuration from MCP server).

If qwen-code itself runs in a container, localhost points at its own container, not the host. Use the host address (host.docker.internal or the host IP) or put both containers on a shared Docker network.

Troubleshooting

GET /mcp/ 400 Bad Request followed by an OAuth-discovery attempt almost always means the client is configured for SSE (url) instead of Streamable HTTP (httpUrl). Verify the server itself is fine with a direct initialize call:

curl -i -X POST http://localhost:8765/mcp/ \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'

A JSON initialize result confirms the server works and the problem is the client config.

Tools

Tool Description
list_services Returns id, name, description for each registered API (no OpenAPI bodies or spec URLs)
search_spec Searches a selected service spec and returns compact ranked operation hits (method, path, summary, score)
get_operation Returns one operation's full contract for a chosen method+path: parameters, request body, and responses, with local $ref schemas resolved inline

On MCP initialize, the server sends instructions telling the agent to call list_services first, pick a service_id from name/description, then search_spec with the user's action/entity query and any clear method/path/tag hints, and finally get_operation on the chosen hit to fetch the details needed to build a request.

search_spec does not return the full OpenAPI document. It builds an in-memory search index from the selected spec (JSON or YAML) and returns top operation candidates; get_operation then returns the self-contained contract of a single operation. The server never calls the target API itself.

Configuration

Variable Default Description
SWAG_HOST 0.0.0.0 HTTP bind host
SWAG_PORT 8000 HTTP port
SWAG_MCP_MOUNT_PATH /mcp MCP Streamable HTTP mount path
SWAG_CATALOG_PATH data/catalog.json Path to the services catalog JSON
SWAG_SPEC_FETCH_TIMEOUT 15.0 HTTP timeout (seconds) for fetching a spec document

Layout

The code is organized into vertical feature packages: each package is self-contained (its own models / service / tool).

swag/
  config.py             # settings
  exceptions.py         # SwagError hierarchy
  mcp_instructions.py   # server instructions for agents
  catalog/              # services registry (list_services): models, source, service, tool
  spec/                 # raw OpenAPI/Swagger document: models, fetch, decode, validate, parsing, service
  search/               # search index + ranking (search_spec): models, text, extractors,
                        #   index, keyword, fuzzy, boosters, engine, tool
  operation/            # full contract of a single operation (get_operation): models, detail, ref_resolver, tool
  app/                  # composition root: gateway (orchestrator), tools, server (FastMCP), asgi (FastAPI)
data/
  catalog.json          # production catalog (URLs only)

Development

Install dev dependencies and pre-commit hooks (runs ruff + mypy from pyproject.toml before each commit):

uv sync --group dev
task pre-commit-install
# or: uv run pre-commit install
Task Description
task test Run pytest
task up docker compose up --build
task down docker compose down
task ruff Ruff check (no auto-fix)
task ruff-fix Ruff check with --fix
task mypy Mypy type check
task check Ruff + mypy
task pre-commit-install Install git hooks

Run all hooks manually:

uv run pre-commit run --all-files

Requires go-task: brew install go-task (or see project docs).

Tests

uv run pytest
# or: task test

from github.com/MaxRadzey/swag-mcp

Установка Swag

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/MaxRadzey/swag-mcp

FAQ

Swag MCP бесплатный?

Да, Swag MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Swag?

Нет, Swag работает без API-ключей и переменных окружения.

Swag — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Swag в Claude Desktop, Claude Code или Cursor?

Открой Swag на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Swag with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development