swag
Allows querying and retrieving details from OpenAPI/Swagger specifications, enabling agents to discover services, search operations, and get full operation contracts.
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., "@swagFind a 'create pet' operation in Petstore API"
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.
swag
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 --buildCompose 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/).
Related MCP server: OpenAPI MCP Server
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,
localhostpoints at its own container, not the host. Use the host address (host.docker.internalor 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 |
| Returns |
| Searches a selected service spec and returns compact ranked operation hits ( |
| Returns one operation's full contract for a chosen |
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 |
|
| HTTP bind host |
|
| HTTP port |
|
| MCP Streamable HTTP mount path |
|
| Path to the services catalog JSON |
|
| 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 installTask | Description |
| Run pytest |
|
|
|
|
| Ruff check (no auto-fix) |
| Ruff check with |
| Mypy type check |
| Ruff + mypy |
| Install git hooks |
Run all hooks manually:
uv run pre-commit run --all-filesRequires go-task: brew install go-task (or see project docs).
Tests
uv run pytest
# or: task testThis server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- 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/MaxRadzey/swag-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server