npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@codon/mcp-swagger

v0.1.7

Published

MCP Server for searching Swagger/OpenAPI documentation (Knife4j compatible)

Readme

@codon/mcp-swagger

MCP Server for Swagger/OpenAPI documentation — search, browse, and generate typed code (TypeScript / Dart) from your backend API specs.

Compatible with Knife4j, Swagger 2.0, and OpenAPI 3.0.

Features

| Tool | Description | |------|-------------| | search_api | Search endpoints by keyword or semantic similarity (embedding) | | get_api_detail | Get full details of a specific endpoint (params, request body, response schema) | | list_api_tags | List all tags/groups with endpoint counts | | list_tag_apis | List all endpoints under a specific tag | | open_api_doc | Open the Knife4j doc page in the browser | | generate_types | Generate TypeScript interfaces or Dart classes from API schemas | | check_updates | Detect backend spec changes via conditional GET (ETag / Last-Modified / sha256) and auto-reload with a diff of added/removed endpoints | | reload_spec | Force a full reload of the OpenAPI spec |

Automatic freshness checks

Every tool call (except reload_spec, check_updates, call_api) transparently issues an HTTP conditional GET against each cached spec URL:

  • 304 Not Modified → cache hit, ~5ms overhead on an internal LAN, tool proceeds immediately
  • 200 OK with same sha256 → still unchanged, tool proceeds
  • 200 OK with new content → spec is auto-reloaded, embedding index rebuilt, tool then runs against fresh data

This means the agent is always querying the latest backend spec without you ever having to call reload_spec. Network errors are swallowed — the cached spec is used so transient upstream issues never break tool calls.

For remote/slow backends you can throttle these checks with SWAGGER_FRESHNESS_THROTTLE_MS (see below).

Type Generation

generate_types resolves all $ref references recursively and produces ready-to-use code:

  • TypeScriptexport interface / export type with JSDoc comments
  • Dart — Full classes with final fields, const constructor, fromJson(), toJson(), null-safety

Specify a single endpoint (path + method) or batch-generate for an entire tag.

Setup

Environment Variables

| Variable | Required | Description | |----------|----------|-------------| | SWAGGER_BASE_URL | Yes | Backend URL, e.g. http://10.15.10.9:18888 | | OPENAI_API_KEY | No | Enables semantic (embedding) search | | OPENAI_BASE_URL | No | Custom embedding API base (default: https://api.openai.com/v1) | | EMBEDDING_MODEL | No | Embedding model name (default: text-embedding-3-small) | | SWAGGER_REFRESH_INTERVAL | No | Background auto-refresh interval in minutes (default: 0 = disabled). Complementary to the per-call freshness check | | SWAGGER_LOAD_RETRIES | No | Max retry attempts on startup (default: 3) | | SWAGGER_FRESHNESS_THROTTLE_MS | No | Minimum interval between per-call freshness checks (default: 0 = check on every tool call). Set to a positive value (e.g. 30000) for remote backends where ETag round-trips are expensive |

Cursor MCP Config

From npm:

{
  "mcpServers": {
    "swagger": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@codon/mcp-swagger"],
      "env": {
        "SWAGGER_BASE_URL": "http://10.15.10.9:18888"
      }
    }
  }
}

Local development:

{
  "mcpServers": {
    "swagger": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/mcp-swagger/dist/index.js"],
      "env": {
        "SWAGGER_BASE_URL": "http://10.15.10.9:18888"
      }
    }
  }
}

Usage

In Cursor chat, just describe what you need in natural language:

搜一下用户相关的接口
生成 POST /api/user/list 的 TypeScript 类型
生成「订单管理」分组下所有接口的 Dart 类,写到 lib/models/order.dart

The AI will automatically call the appropriate MCP tools.

Example Output

TypeScript

export interface ResultPageUserVO {
  /** 状态码 */
  code?: number
  /** 消息 */
  message?: string
  data?: PageUserVO
}

export interface PageUserVO {
  records?: UserVO[]
  total?: number
}

export type ListUserResponse = ResultPageUserVO

Dart

class UserVO {
  /// 用户ID
  final int? id;
  /// 用户名
  final String? name;
  /// 角色列表
  final List<RoleVO>? roles;

  const UserVO({this.id, this.name, this.roles});

  factory UserVO.fromJson(Map<String, dynamic> json) {
    return UserVO(
      id: json['id'] as int?,
      name: json['name'] as String?,
      roles: (json['roles'] as List<dynamic>?)
          ?.map((e) => RoleVO.fromJson(e as Map<String, dynamic>))
          .toList(),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'roles': roles?.map((e) => e.toJson()).toList(),
    };
  }
}

Development

pnpm install
pnpm build        # Compile TypeScript
pnpm dev          # Run with tsx (hot reload)

License

MIT