Skip to main content
Glama
zhangwanli09

internal-swagger-mcp

by zhangwanli09
README.md
# internal-swagger-mcp

Let AI agents query your internal Swagger platform's API docs via MCP.

> This server talks to the internal Swagger management platform's private share endpoint (`/flow/swagger/share?uid=...`), not a public OpenAPI URL.

## Tools

| Tool | Purpose |
|------|---------|
| `swagger_list_sources` | List all configured services and their cache status |
| `swagger_search_api` | Search APIs by keyword (filterable by method / service) |
| `swagger_get_api_detail` | View an API's full parameters and mock example |
| `swagger_refresh_cache` | Force-refresh the doc cache (default TTL is 30 minutes) |

## Connecting MCP clients

Requires Node.js ≥ 18. Swagger sources are always supplied by the client — this server holds no configuration. Pass them in stdio mode via the `SWAGGER_SOURCES` env var or [`--sources-file`](#sources-file), and in HTTP mode via the `X-Swagger-Sources` header per request. **Use project scope** for every client's MCP config so each repo pins its own sources and the config can be committed to git. In the snippets below, `<SOURCE>` looks like `http://your-server/...#/swaggerManage?uid=xxx`; if `swagger_list_sources` works inside the client, the integration is up.

Start in HTTP mode (for deploying on a shared internal host):

```bash
npx -y internal-swagger-mcp --http   # defaults to port 3000; override with --port or PORT
```

### Claude Code

[Official docs](https://code.claude.com/docs/en/mcp) — using `--scope project` writes to the project root's `.mcp.json`.

Local (stdio):

```bash
claude mcp add swagger --scope project --env SWAGGER_SOURCES='["<SOURCE>"]' -- npx -y internal-swagger-mcp
```

Remote (HTTP):

```bash
claude mcp add --transport http swagger --scope project http://<internal-IP>:3000/mcp --header 'X-Swagger-Sources: ["<SOURCE>"]'
```

### opencode

[Official docs](https://opencode.ai/docs/mcp-servers) — place this in `opencode.json` at the project root.

Local (stdio):

```json
{
  "mcp": {
    "swagger": {
      "type": "local",
      "command": ["npx", "-y", "internal-swagger-mcp"],
      "environment": {
        "SWAGGER_SOURCES": "[\"<SOURCE>\"]"
      }
    }
  }
}
```

Remote (HTTP):

```json
{
  "mcp": {
    "swagger": {
      "type": "remote",
      "url": "http://<internal-IP>:3000/mcp",
      "headers": {
        "X-Swagger-Sources": "[\"<SOURCE>\"]"
      }
    }
  }
}
```

### Cursor

[Official docs](https://cursor.com/docs/context/mcp) — place this in `.cursor/mcp.json` at the project root.

Local (stdio):

```json
{
  "mcpServers": {
    "swagger": {
      "command": "npx",
      "args": ["-y", "internal-swagger-mcp"],
      "env": {
        "SWAGGER_SOURCES": "[\"<SOURCE>\"]"
      }
    }
  }
}
```

Remote (HTTP):

```json
{
  "mcpServers": {
    "swagger": {
      "url": "http://<internal-IP>:3000/mcp",
      "headers": {
        "X-Swagger-Sources": "[\"<SOURCE>\"]"
      }
    }
  }
}
```

### Sources file

When the source list belongs to the project, pass `--sources-file <path>` instead of pasting the same JSON-as-string into every client's `env`. Use a path relative to the project root (e.g. `./swagger-sources.json`) — it resolves from `process.cwd()`, which is the project root under project-scoped configs in Claude Code, Cursor, opencode, etc. — so the MCP config can be committed and shared as-is.

`swagger-sources.json` (each entry is a `<SOURCE>` URL as defined above):

```json
[
  "<SOURCE_1>",
  "<SOURCE_2>"
]
```

Each client config then becomes a thin wrapper around the same command:

Claude Code:

```bash
claude mcp add swagger --scope project -- npx -y internal-swagger-mcp --sources-file ./swagger-sources.json
```

opencode (`opencode.json`):

```json
{
  "mcp": {
    "swagger": {
      "type": "local",
      "command": ["npx", "-y", "internal-swagger-mcp", "--sources-file", "./swagger-sources.json"]
    }
  }
}
```

Cursor (`.cursor/mcp.json`) — and other clients using the `mcpServers` shape:

```json
{
  "mcpServers": {
    "swagger": {
      "command": "npx",
      "args": ["-y", "internal-swagger-mcp", "--sources-file", "./swagger-sources.json"]
    }
  }
}
```

The file is read once at startup; the source list is fixed for the server's lifetime (clients relaunch on config change anyway). When both `--sources-file` and `SWAGGER_SOURCES` are provided, the file wins. The flag is rejected in `--http` mode because HTTP sources are inherently per-request.

## HTTP deployment security

The server binds to `0.0.0.0` by default for easy intranet sharing, and prints a warning if started bare. In production, set at least one of the following:

| Environment variable | Effect |
|------|--------|
| `MCP_BIND_HOST` | Bind address; set to `127.0.0.1` to restrict access to the local host (default `0.0.0.0`) |
| `MCP_BEARER_TOKEN` | Require an `Authorization: Bearer <token>` header on every request |
| `MCP_ALLOWED_ORIGINS` | Comma-separated Origin allowlist (DNS-rebinding protection) |

> When `MCP_ALLOWED_ORIGINS` is set, requests without an `Origin` header are rejected — except for requests carrying a valid `MCP_BEARER_TOKEN`, so server-to-server calls still work.

TDQS

A4.5/5.0

Scored across 4 tools

Disambiguation5/5

Each tool serves a distinct function: listing sources, searching APIs, fetching details, and refreshing cache. There is no overlap between these operations.

Naming Consistency5/5

All tool names follow the consistent pattern 'swagger_<verb>_<noun>' with lowercase and underscores. The naming is uniform and predictable.

Tool Count5/5

Four tools are well-scoped for a Swagger documentation MCP server, covering the essential operations without unnecessary bloat.

Completeness5/5

The tool surface covers the full workflow: discover sources, search endpoints, get detailed specs, and refresh cached docs. No obvious gaps exist for the stated purpose.

Maintenance

ActivityInactive
ResponsivenessNo issues