This is page 1 of 2. Use http://codebase.md/mgsrevolver/seo-inspector-mcp?page={x} to view the full context.
# Directory Structure
```
├── .cursor
│ └── mcp.json
├── .gitignore
├── console-spy-mcp.js
├── cs-mcp-server.js
├── mcp-tools.js
├── node_modules
│ ├── .bin
│ │ ├── mime
│ │ └── supergateway
│ ├── .package-lock.json
│ ├── @modelcontextprotocol
│ │ └── sdk
│ │ ├── dist
│ │ │ ├── cjs
│ │ │ │ ├── cli.d.ts
│ │ │ │ ├── cli.d.ts.map
│ │ │ │ ├── cli.js
│ │ │ │ ├── cli.js.map
│ │ │ │ ├── client
│ │ │ │ │ ├── auth.d.ts
│ │ │ │ │ ├── auth.d.ts.map
│ │ │ │ │ ├── auth.js
│ │ │ │ │ ├── auth.js.map
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── index.d.ts.map
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── index.js.map
│ │ │ │ │ ├── sse.d.ts
│ │ │ │ │ ├── sse.d.ts.map
│ │ │ │ │ ├── sse.js
│ │ │ │ │ ├── sse.js.map
│ │ │ │ │ ├── stdio.d.ts
│ │ │ │ │ ├── stdio.d.ts.map
│ │ │ │ │ ├── stdio.js
│ │ │ │ │ ├── stdio.js.map
│ │ │ │ │ ├── websocket.d.ts
│ │ │ │ │ ├── websocket.d.ts.map
│ │ │ │ │ ├── websocket.js
│ │ │ │ │ └── websocket.js.map
│ │ │ │ ├── inMemory.d.ts
│ │ │ │ ├── inMemory.d.ts.map
│ │ │ │ ├── inMemory.js
│ │ │ │ ├── inMemory.js.map
│ │ │ │ ├── package.json
│ │ │ │ ├── server
│ │ │ │ │ ├── auth
│ │ │ │ │ │ ├── clients.d.ts
│ │ │ │ │ │ ├── clients.d.ts.map
│ │ │ │ │ │ ├── clients.js
│ │ │ │ │ │ ├── clients.js.map
│ │ │ │ │ │ ├── errors.d.ts
│ │ │ │ │ │ ├── errors.d.ts.map
│ │ │ │ │ │ ├── errors.js
│ │ │ │ │ │ ├── errors.js.map
│ │ │ │ │ │ ├── handlers
│ │ │ │ │ │ │ ├── authorize.d.ts
│ │ │ │ │ │ │ ├── authorize.d.ts.map
│ │ │ │ │ │ │ ├── authorize.js
│ │ │ │ │ │ │ ├── authorize.js.map
│ │ │ │ │ │ │ ├── metadata.d.ts
│ │ │ │ │ │ │ ├── metadata.d.ts.map
│ │ │ │ │ │ │ ├── metadata.js
│ │ │ │ │ │ │ ├── metadata.js.map
│ │ │ │ │ │ │ ├── register.d.ts
│ │ │ │ │ │ │ ├── register.d.ts.map
│ │ │ │ │ │ │ ├── register.js
│ │ │ │ │ │ │ ├── register.js.map
│ │ │ │ │ │ │ ├── revoke.d.ts
│ │ │ │ │ │ │ ├── revoke.d.ts.map
│ │ │ │ │ │ │ ├── revoke.js
│ │ │ │ │ │ │ ├── revoke.js.map
│ │ │ │ │ │ │ ├── token.d.ts
│ │ │ │ │ │ │ ├── token.d.ts.map
│ │ │ │ │ │ │ ├── token.js
│ │ │ │ │ │ │ └── token.js.map
│ │ │ │ │ │ ├── middleware
│ │ │ │ │ │ │ ├── allowedMethods.d.ts
│ │ │ │ │ │ │ ├── allowedMethods.d.ts.map
│ │ │ │ │ │ │ ├── allowedMethods.js
│ │ │ │ │ │ │ ├── allowedMethods.js.map
│ │ │ │ │ │ │ ├── bearerAuth.d.ts
│ │ │ │ │ │ │ ├── bearerAuth.d.ts.map
│ │ │ │ │ │ │ ├── bearerAuth.js
│ │ │ │ │ │ │ ├── bearerAuth.js.map
│ │ │ │ │ │ │ ├── clientAuth.d.ts
│ │ │ │ │ │ │ ├── clientAuth.d.ts.map
│ │ │ │ │ │ │ ├── clientAuth.js
│ │ │ │ │ │ │ └── clientAuth.js.map
│ │ │ │ │ │ ├── provider.d.ts
│ │ │ │ │ │ ├── provider.d.ts.map
│ │ │ │ │ │ ├── provider.js
│ │ │ │ │ │ ├── provider.js.map
│ │ │ │ │ │ ├── router.d.ts
│ │ │ │ │ │ ├── router.d.ts.map
│ │ │ │ │ │ ├── router.js
│ │ │ │ │ │ ├── router.js.map
│ │ │ │ │ │ ├── types.d.ts
│ │ │ │ │ │ ├── types.d.ts.map
│ │ │ │ │ │ ├── types.js
│ │ │ │ │ │ └── types.js.map
│ │ │ │ │ ├── completable.d.ts
│ │ │ │ │ ├── completable.d.ts.map
│ │ │ │ │ ├── completable.js
│ │ │ │ │ ├── completable.js.map
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── index.d.ts.map
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── index.js.map
│ │ │ │ │ ├── mcp.d.ts
│ │ │ │ │ ├── mcp.d.ts.map
│ │ │ │ │ ├── mcp.js
│ │ │ │ │ ├── mcp.js.map
│ │ │ │ │ ├── sse.d.ts
│ │ │ │ │ ├── sse.d.ts.map
│ │ │ │ │ ├── sse.js
│ │ │ │ │ ├── sse.js.map
│ │ │ │ │ ├── stdio.d.ts
│ │ │ │ │ ├── stdio.d.ts.map
│ │ │ │ │ ├── stdio.js
│ │ │ │ │ └── stdio.js.map
│ │ │ │ ├── shared
│ │ │ │ │ ├── auth.d.ts
│ │ │ │ │ ├── auth.d.ts.map
│ │ │ │ │ ├── auth.js
│ │ │ │ │ ├── auth.js.map
│ │ │ │ │ ├── protocol.d.ts
│ │ │ │ │ ├── protocol.d.ts.map
│ │ │ │ │ ├── protocol.js
│ │ │ │ │ ├── protocol.js.map
│ │ │ │ │ ├── stdio.d.ts
│ │ │ │ │ ├── stdio.d.ts.map
│ │ │ │ │ ├── stdio.js
│ │ │ │ │ ├── stdio.js.map
│ │ │ │ │ ├── transport.d.ts
│ │ │ │ │ ├── transport.d.ts.map
│ │ │ │ │ ├── transport.js
│ │ │ │ │ ├── transport.js.map
│ │ │ │ │ ├── uriTemplate.d.ts
│ │ │ │ │ ├── uriTemplate.d.ts.map
│ │ │ │ │ ├── uriTemplate.js
│ │ │ │ │ └── uriTemplate.js.map
│ │ │ │ ├── types.d.ts
│ │ │ │ ├── types.d.ts.map
│ │ │ │ ├── types.js
│ │ │ │ └── types.js.map
│ │ │ └── esm
│ │ │ ├── cli.d.ts
│ │ │ ├── cli.d.ts.map
│ │ │ ├── cli.js
│ │ │ ├── cli.js.map
│ │ │ ├── client
│ │ │ │ ├── auth.d.ts
│ │ │ │ ├── auth.d.ts.map
│ │ │ │ ├── auth.js
│ │ │ │ ├── auth.js.map
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── sse.d.ts
│ │ │ │ ├── sse.d.ts.map
│ │ │ │ ├── sse.js
│ │ │ │ ├── sse.js.map
│ │ │ │ ├── stdio.d.ts
│ │ │ │ ├── stdio.d.ts.map
│ │ │ │ ├── stdio.js
│ │ │ │ ├── stdio.js.map
│ │ │ │ ├── websocket.d.ts
│ │ │ │ ├── websocket.d.ts.map
│ │ │ │ ├── websocket.js
│ │ │ │ └── websocket.js.map
│ │ │ ├── inMemory.d.ts
│ │ │ ├── inMemory.d.ts.map
│ │ │ ├── inMemory.js
│ │ │ ├── inMemory.js.map
│ │ │ ├── package.json
│ │ │ ├── server
│ │ │ │ ├── auth
│ │ │ │ │ ├── clients.d.ts
│ │ │ │ │ ├── clients.d.ts.map
│ │ │ │ │ ├── clients.js
│ │ │ │ │ ├── clients.js.map
│ │ │ │ │ ├── errors.d.ts
│ │ │ │ │ ├── errors.d.ts.map
│ │ │ │ │ ├── errors.js
│ │ │ │ │ ├── errors.js.map
│ │ │ │ │ ├── handlers
│ │ │ │ │ │ ├── authorize.d.ts
│ │ │ │ │ │ ├── authorize.d.ts.map
│ │ │ │ │ │ ├── authorize.js
│ │ │ │ │ │ ├── authorize.js.map
│ │ │ │ │ │ ├── metadata.d.ts
│ │ │ │ │ │ ├── metadata.d.ts.map
│ │ │ │ │ │ ├── metadata.js
│ │ │ │ │ │ ├── metadata.js.map
│ │ │ │ │ │ ├── register.d.ts
│ │ │ │ │ │ ├── register.d.ts.map
│ │ │ │ │ │ ├── register.js
│ │ │ │ │ │ ├── register.js.map
│ │ │ │ │ │ ├── revoke.d.ts
│ │ │ │ │ │ ├── revoke.d.ts.map
│ │ │ │ │ │ ├── revoke.js
│ │ │ │ │ │ ├── revoke.js.map
│ │ │ │ │ │ ├── token.d.ts
│ │ │ │ │ │ ├── token.d.ts.map
│ │ │ │ │ │ ├── token.js
│ │ │ │ │ │ └── token.js.map
│ │ │ │ │ ├── middleware
│ │ │ │ │ │ ├── allowedMethods.d.ts
│ │ │ │ │ │ ├── allowedMethods.d.ts.map
│ │ │ │ │ │ ├── allowedMethods.js
│ │ │ │ │ │ ├── allowedMethods.js.map
│ │ │ │ │ │ ├── bearerAuth.d.ts
│ │ │ │ │ │ ├── bearerAuth.d.ts.map
│ │ │ │ │ │ ├── bearerAuth.js
│ │ │ │ │ │ ├── bearerAuth.js.map
│ │ │ │ │ │ ├── clientAuth.d.ts
│ │ │ │ │ │ ├── clientAuth.d.ts.map
│ │ │ │ │ │ ├── clientAuth.js
│ │ │ │ │ │ └── clientAuth.js.map
│ │ │ │ │ ├── provider.d.ts
│ │ │ │ │ ├── provider.d.ts.map
│ │ │ │ │ ├── provider.js
│ │ │ │ │ ├── provider.js.map
│ │ │ │ │ ├── router.d.ts
│ │ │ │ │ ├── router.d.ts.map
│ │ │ │ │ ├── router.js
│ │ │ │ │ ├── router.js.map
│ │ │ │ │ ├── types.d.ts
│ │ │ │ │ ├── types.d.ts.map
│ │ │ │ │ ├── types.js
│ │ │ │ │ └── types.js.map
│ │ │ │ ├── completable.d.ts
│ │ │ │ ├── completable.d.ts.map
│ │ │ │ ├── completable.js
│ │ │ │ ├── completable.js.map
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── mcp.d.ts
│ │ │ │ ├── mcp.d.ts.map
│ │ │ │ ├── mcp.js
│ │ │ │ ├── mcp.js.map
│ │ │ │ ├── sse.d.ts
│ │ │ │ ├── sse.d.ts.map
│ │ │ │ ├── sse.js
│ │ │ │ ├── sse.js.map
│ │ │ │ ├── stdio.d.ts
│ │ │ │ ├── stdio.d.ts.map
│ │ │ │ ├── stdio.js
│ │ │ │ └── stdio.js.map
│ │ │ ├── shared
│ │ │ │ ├── auth.d.ts
│ │ │ │ ├── auth.d.ts.map
│ │ │ │ ├── auth.js
│ │ │ │ ├── auth.js.map
│ │ │ │ ├── protocol.d.ts
│ │ │ │ ├── protocol.d.ts.map
│ │ │ │ ├── protocol.js
│ │ │ │ ├── protocol.js.map
│ │ │ │ ├── stdio.d.ts
│ │ │ │ ├── stdio.d.ts.map
│ │ │ │ ├── stdio.js
│ │ │ │ ├── stdio.js.map
│ │ │ │ ├── transport.d.ts
│ │ │ │ ├── transport.d.ts.map
│ │ │ │ ├── transport.js
│ │ │ │ ├── transport.js.map
│ │ │ │ ├── uriTemplate.d.ts
│ │ │ │ ├── uriTemplate.d.ts.map
│ │ │ │ ├── uriTemplate.js
│ │ │ │ └── uriTemplate.js.map
│ │ │ ├── types.d.ts
│ │ │ ├── types.d.ts.map
│ │ │ ├── types.js
│ │ │ └── types.js.map
│ │ ├── LICENSE
│ │ ├── node_modules
│ │ │ ├── accepts
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ ├── body-parser
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── lib
│ │ │ │ │ ├── read.js
│ │ │ │ │ └── types
│ │ │ │ │ ├── json.js
│ │ │ │ │ ├── raw.js
│ │ │ │ │ ├── text.js
│ │ │ │ │ └── urlencoded.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── node_modules
│ │ │ │ │ ├── debug
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ ├── README.md
│ │ │ │ │ │ └── src
│ │ │ │ │ │ ├── browser.js
│ │ │ │ │ │ ├── common.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── node.js
│ │ │ │ │ ├── iconv-lite
│ │ │ │ │ │ ├── Changelog.md
│ │ │ │ │ │ ├── encodings
│ │ │ │ │ │ │ ├── dbcs-codec.js
│ │ │ │ │ │ │ ├── dbcs-data.js
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ ├── internal.js
│ │ │ │ │ │ │ ├── sbcs-codec.js
│ │ │ │ │ │ │ ├── sbcs-data-generated.js
│ │ │ │ │ │ │ ├── sbcs-data.js
│ │ │ │ │ │ │ ├── tables
│ │ │ │ │ │ │ │ ├── big5-added.json
│ │ │ │ │ │ │ │ ├── cp936.json
│ │ │ │ │ │ │ │ ├── cp949.json
│ │ │ │ │ │ │ │ ├── cp950.json
│ │ │ │ │ │ │ │ ├── eucjp.json
│ │ │ │ │ │ │ │ ├── gb18030-ranges.json
│ │ │ │ │ │ │ │ ├── gbk-added.json
│ │ │ │ │ │ │ │ └── shiftjis.json
│ │ │ │ │ │ │ ├── utf16.js
│ │ │ │ │ │ │ ├── utf32.js
│ │ │ │ │ │ │ └── utf7.js
│ │ │ │ │ │ ├── lib
│ │ │ │ │ │ │ ├── bom-handling.js
│ │ │ │ │ │ │ ├── extend-node.js
│ │ │ │ │ │ │ ├── index.d.ts
│ │ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ │ └── streams.js
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ └── README.md
│ │ │ │ │ ├── ms
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── license.md
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ └── readme.md
│ │ │ │ │ └── qs
│ │ │ │ │ ├── .editorconfig
│ │ │ │ │ ├── .eslintrc
│ │ │ │ │ ├── .github
│ │ │ │ │ │ └── FUNDING.yml
│ │ │ │ │ ├── .nycrc
│ │ │ │ │ ├── CHANGELOG.md
│ │ │ │ │ ├── dist
│ │ │ │ │ │ └── qs.js
│ │ │ │ │ ├── lib
│ │ │ │ │ │ ├── formats.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── parse.js
│ │ │ │ │ │ ├── stringify.js
│ │ │ │ │ │ └── utils.js
│ │ │ │ │ ├── LICENSE.md
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── README.md
│ │ │ │ │ └── test
│ │ │ │ │ ├── empty-keys-cases.js
│ │ │ │ │ ├── parse.js
│ │ │ │ │ ├── stringify.js
│ │ │ │ │ └── utils.js
│ │ │ │ ├── package.json
│ │ │ │ ├── README.md
│ │ │ │ └── SECURITY.md
│ │ │ ├── content-disposition
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ ├── cookie-signature
│ │ │ │ ├── History.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── Readme.md
│ │ │ ├── debug
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ ├── README.md
│ │ │ │ └── src
│ │ │ │ ├── browser.js
│ │ │ │ ├── common.js
│ │ │ │ ├── index.js
│ │ │ │ └── node.js
│ │ │ ├── express
│ │ │ │ ├── History.md
│ │ │ │ ├── index.js
│ │ │ │ ├── lib
│ │ │ │ │ ├── application.js
│ │ │ │ │ ├── express.js
│ │ │ │ │ ├── request.js
│ │ │ │ │ ├── response.js
│ │ │ │ │ ├── utils.js
│ │ │ │ │ └── view.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── Readme.md
│ │ │ ├── finalhandler
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── node_modules
│ │ │ │ │ ├── debug
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ ├── README.md
│ │ │ │ │ │ └── src
│ │ │ │ │ │ ├── browser.js
│ │ │ │ │ │ ├── common.js
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── node.js
│ │ │ │ │ └── ms
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── license.md
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── readme.md
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ ├── fresh
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ ├── media-typer
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ ├── merge-descriptors
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── license
│ │ │ │ ├── package.json
│ │ │ │ └── readme.md
│ │ │ ├── mime-db
│ │ │ │ ├── db.json
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ ├── mime-types
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── mimeScore.js
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ ├── ms
│ │ │ │ ├── index.js
│ │ │ │ ├── license.md
│ │ │ │ ├── package.json
│ │ │ │ └── readme.md
│ │ │ ├── negotiator
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── lib
│ │ │ │ │ ├── charset.js
│ │ │ │ │ ├── encoding.js
│ │ │ │ │ ├── language.js
│ │ │ │ │ └── mediaType.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ ├── raw-body
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ ├── README.md
│ │ │ │ └── SECURITY.md
│ │ │ ├── send
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── node_modules
│ │ │ │ │ ├── fresh
│ │ │ │ │ │ ├── HISTORY.md
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ └── README.md
│ │ │ │ │ ├── mime-db
│ │ │ │ │ │ ├── db.json
│ │ │ │ │ │ ├── HISTORY.md
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ └── README.md
│ │ │ │ │ ├── mime-types
│ │ │ │ │ │ ├── HISTORY.md
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── LICENSE
│ │ │ │ │ │ ├── package.json
│ │ │ │ │ │ └── README.md
│ │ │ │ │ └── ms
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── license.md
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── readme.md
│ │ │ │ ├── package.json
│ │ │ │ ├── README.md
│ │ │ │ └── SECURITY.md
│ │ │ ├── serve-static
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ └── type-is
│ │ │ ├── HISTORY.md
│ │ │ ├── index.js
│ │ │ ├── LICENSE
│ │ │ ├── package.json
│ │ │ └── README.md
│ │ ├── package.json
│ │ └── README.md
│ ├── accepts
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── ansi-regex
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── license
│ │ ├── package.json
│ │ └── readme.md
│ ├── ansi-styles
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── license
│ │ ├── package.json
│ │ └── readme.md
│ ├── array-flatten
│ │ ├── array-flatten.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── body-parser
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── lib
│ │ │ ├── read.js
│ │ │ └── types
│ │ │ ├── json.js
│ │ │ ├── raw.js
│ │ │ ├── text.js
│ │ │ └── urlencoded.js
│ │ ├── LICENSE
│ │ ├── node_modules
│ │ │ └── iconv-lite
│ │ │ ├── Changelog.md
│ │ │ ├── encodings
│ │ │ │ ├── dbcs-codec.js
│ │ │ │ ├── dbcs-data.js
│ │ │ │ ├── index.js
│ │ │ │ ├── internal.js
│ │ │ │ ├── sbcs-codec.js
│ │ │ │ ├── sbcs-data-generated.js
│ │ │ │ ├── sbcs-data.js
│ │ │ │ ├── tables
│ │ │ │ │ ├── big5-added.json
│ │ │ │ │ ├── cp936.json
│ │ │ │ │ ├── cp949.json
│ │ │ │ │ ├── cp950.json
│ │ │ │ │ ├── eucjp.json
│ │ │ │ │ ├── gb18030-ranges.json
│ │ │ │ │ ├── gbk-added.json
│ │ │ │ │ └── shiftjis.json
│ │ │ │ ├── utf16.js
│ │ │ │ └── utf7.js
│ │ │ ├── lib
│ │ │ │ ├── bom-handling.js
│ │ │ │ ├── extend-node.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ └── streams.js
│ │ │ ├── LICENSE
│ │ │ ├── package.json
│ │ │ └── README.md
│ │ ├── package.json
│ │ ├── README.md
│ │ └── SECURITY.md
│ ├── boolbase
│ │ ├── index.js
│ │ ├── package.json
│ │ └── README.md
│ ├── bytes
│ │ ├── History.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── Readme.md
│ ├── call-bind-apply-helpers
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── actualApply.d.ts
│ │ ├── actualApply.js
│ │ ├── applyBind.d.ts
│ │ ├── applyBind.js
│ │ ├── CHANGELOG.md
│ │ ├── functionApply.d.ts
│ │ ├── functionApply.js
│ │ ├── functionCall.d.ts
│ │ ├── functionCall.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── reflectApply.d.ts
│ │ ├── reflectApply.js
│ │ ├── test
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── call-bound
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── test
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── cheerio
│ │ ├── dist
│ │ │ ├── browser
│ │ │ │ ├── api
│ │ │ │ │ ├── attributes.d.ts
│ │ │ │ │ ├── attributes.d.ts.map
│ │ │ │ │ ├── attributes.js
│ │ │ │ │ ├── attributes.js.map
│ │ │ │ │ ├── css.d.ts
│ │ │ │ │ ├── css.d.ts.map
│ │ │ │ │ ├── css.js
│ │ │ │ │ ├── css.js.map
│ │ │ │ │ ├── extract.d.ts
│ │ │ │ │ ├── extract.d.ts.map
│ │ │ │ │ ├── extract.js
│ │ │ │ │ ├── extract.js.map
│ │ │ │ │ ├── forms.d.ts
│ │ │ │ │ ├── forms.d.ts.map
│ │ │ │ │ ├── forms.js
│ │ │ │ │ ├── forms.js.map
│ │ │ │ │ ├── manipulation.d.ts
│ │ │ │ │ ├── manipulation.d.ts.map
│ │ │ │ │ ├── manipulation.js
│ │ │ │ │ ├── manipulation.js.map
│ │ │ │ │ ├── traversing.d.ts
│ │ │ │ │ ├── traversing.d.ts.map
│ │ │ │ │ ├── traversing.js
│ │ │ │ │ └── traversing.js.map
│ │ │ │ ├── cheerio.d.ts
│ │ │ │ ├── cheerio.d.ts.map
│ │ │ │ ├── cheerio.js
│ │ │ │ ├── cheerio.js.map
│ │ │ │ ├── index-browser.d.mts.map
│ │ │ │ ├── index-browser.mjs.map
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── load-parse.d.ts
│ │ │ │ ├── load-parse.d.ts.map
│ │ │ │ ├── load-parse.js
│ │ │ │ ├── load-parse.js.map
│ │ │ │ ├── load.d.ts
│ │ │ │ ├── load.d.ts.map
│ │ │ │ ├── load.js
│ │ │ │ ├── load.js.map
│ │ │ │ ├── options.d.ts
│ │ │ │ ├── options.d.ts.map
│ │ │ │ ├── options.js
│ │ │ │ ├── options.js.map
│ │ │ │ ├── package.json
│ │ │ │ ├── parse.d.ts
│ │ │ │ ├── parse.d.ts.map
│ │ │ │ ├── parse.js
│ │ │ │ ├── parse.js.map
│ │ │ │ ├── parsers
│ │ │ │ │ ├── parse5-adapter.d.ts
│ │ │ │ │ ├── parse5-adapter.d.ts.map
│ │ │ │ │ ├── parse5-adapter.js
│ │ │ │ │ └── parse5-adapter.js.map
│ │ │ │ ├── slim.d.ts
│ │ │ │ ├── slim.d.ts.map
│ │ │ │ ├── slim.js
│ │ │ │ ├── slim.js.map
│ │ │ │ ├── static.d.ts
│ │ │ │ ├── static.d.ts.map
│ │ │ │ ├── static.js
│ │ │ │ ├── static.js.map
│ │ │ │ ├── types.d.ts
│ │ │ │ ├── types.d.ts.map
│ │ │ │ ├── types.js
│ │ │ │ ├── types.js.map
│ │ │ │ ├── utils.d.ts
│ │ │ │ ├── utils.d.ts.map
│ │ │ │ ├── utils.js
│ │ │ │ └── utils.js.map
│ │ │ ├── commonjs
│ │ │ │ ├── api
│ │ │ │ │ ├── attributes.d.ts
│ │ │ │ │ ├── attributes.d.ts.map
│ │ │ │ │ ├── attributes.js
│ │ │ │ │ ├── attributes.js.map
│ │ │ │ │ ├── css.d.ts
│ │ │ │ │ ├── css.d.ts.map
│ │ │ │ │ ├── css.js
│ │ │ │ │ ├── css.js.map
│ │ │ │ │ ├── extract.d.ts
│ │ │ │ │ ├── extract.d.ts.map
│ │ │ │ │ ├── extract.js
│ │ │ │ │ ├── extract.js.map
│ │ │ │ │ ├── forms.d.ts
│ │ │ │ │ ├── forms.d.ts.map
│ │ │ │ │ ├── forms.js
│ │ │ │ │ ├── forms.js.map
│ │ │ │ │ ├── manipulation.d.ts
│ │ │ │ │ ├── manipulation.d.ts.map
│ │ │ │ │ ├── manipulation.js
│ │ │ │ │ ├── manipulation.js.map
│ │ │ │ │ ├── traversing.d.ts
│ │ │ │ │ ├── traversing.d.ts.map
│ │ │ │ │ ├── traversing.js
│ │ │ │ │ └── traversing.js.map
│ │ │ │ ├── cheerio.d.ts
│ │ │ │ ├── cheerio.d.ts.map
│ │ │ │ ├── cheerio.js
│ │ │ │ ├── cheerio.js.map
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── load-parse.d.ts
│ │ │ │ ├── load-parse.d.ts.map
│ │ │ │ ├── load-parse.js
│ │ │ │ ├── load-parse.js.map
│ │ │ │ ├── load.d.ts
│ │ │ │ ├── load.d.ts.map
│ │ │ │ ├── load.js
│ │ │ │ ├── load.js.map
│ │ │ │ ├── options.d.ts
│ │ │ │ ├── options.d.ts.map
│ │ │ │ ├── options.js
│ │ │ │ ├── options.js.map
│ │ │ │ ├── package.json
│ │ │ │ ├── parse.d.ts
│ │ │ │ ├── parse.d.ts.map
│ │ │ │ ├── parse.js
│ │ │ │ ├── parse.js.map
│ │ │ │ ├── parsers
│ │ │ │ │ ├── parse5-adapter.d.ts
│ │ │ │ │ ├── parse5-adapter.d.ts.map
│ │ │ │ │ ├── parse5-adapter.js
│ │ │ │ │ └── parse5-adapter.js.map
│ │ │ │ ├── slim.d.ts
│ │ │ │ ├── slim.d.ts.map
│ │ │ │ ├── slim.js
│ │ │ │ ├── slim.js.map
│ │ │ │ ├── static.d.ts
│ │ │ │ ├── static.d.ts.map
│ │ │ │ ├── static.js
│ │ │ │ ├── static.js.map
│ │ │ │ ├── types.d.ts
│ │ │ │ ├── types.d.ts.map
│ │ │ │ ├── types.js
│ │ │ │ ├── types.js.map
│ │ │ │ ├── utils.d.ts
│ │ │ │ ├── utils.d.ts.map
│ │ │ │ ├── utils.js
│ │ │ │ └── utils.js.map
│ │ │ └── esm
│ │ │ ├── api
│ │ │ │ ├── attributes.d.ts
│ │ │ │ ├── attributes.d.ts.map
│ │ │ │ ├── attributes.js
│ │ │ │ ├── attributes.js.map
│ │ │ │ ├── css.d.ts
│ │ │ │ ├── css.d.ts.map
│ │ │ │ ├── css.js
│ │ │ │ ├── css.js.map
│ │ │ │ ├── extract.d.ts
│ │ │ │ ├── extract.d.ts.map
│ │ │ │ ├── extract.js
│ │ │ │ ├── extract.js.map
│ │ │ │ ├── forms.d.ts
│ │ │ │ ├── forms.d.ts.map
│ │ │ │ ├── forms.js
│ │ │ │ ├── forms.js.map
│ │ │ │ ├── manipulation.d.ts
│ │ │ │ ├── manipulation.d.ts.map
│ │ │ │ ├── manipulation.js
│ │ │ │ ├── manipulation.js.map
│ │ │ │ ├── traversing.d.ts
│ │ │ │ ├── traversing.d.ts.map
│ │ │ │ ├── traversing.js
│ │ │ │ └── traversing.js.map
│ │ │ ├── cheerio.d.ts
│ │ │ ├── cheerio.d.ts.map
│ │ │ ├── cheerio.js
│ │ │ ├── cheerio.js.map
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── index.js
│ │ │ ├── index.js.map
│ │ │ ├── load-parse.d.ts
│ │ │ ├── load-parse.d.ts.map
│ │ │ ├── load-parse.js
│ │ │ ├── load-parse.js.map
│ │ │ ├── load.d.ts
│ │ │ ├── load.d.ts.map
│ │ │ ├── load.js
│ │ │ ├── load.js.map
│ │ │ ├── options.d.ts
│ │ │ ├── options.d.ts.map
│ │ │ ├── options.js
│ │ │ ├── options.js.map
│ │ │ ├── package.json
│ │ │ ├── parse.d.ts
│ │ │ ├── parse.d.ts.map
│ │ │ ├── parse.js
│ │ │ ├── parse.js.map
│ │ │ ├── parsers
│ │ │ │ ├── parse5-adapter.d.ts
│ │ │ │ ├── parse5-adapter.d.ts.map
│ │ │ │ ├── parse5-adapter.js
│ │ │ │ └── parse5-adapter.js.map
│ │ │ ├── slim.d.ts
│ │ │ ├── slim.d.ts.map
│ │ │ ├── slim.js
│ │ │ ├── slim.js.map
│ │ │ ├── static.d.ts
│ │ │ ├── static.d.ts.map
│ │ │ ├── static.js
│ │ │ ├── static.js.map
│ │ │ ├── types.d.ts
│ │ │ ├── types.d.ts.map
│ │ │ ├── types.js
│ │ │ ├── types.js.map
│ │ │ ├── utils.d.ts
│ │ │ ├── utils.d.ts.map
│ │ │ ├── utils.js
│ │ │ └── utils.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── Readme.md
│ │ └── src
│ │ ├── __fixtures__
│ │ │ └── fixtures.ts
│ │ ├── __tests__
│ │ │ ├── deprecated.spec.ts
│ │ │ └── xml.spec.ts
│ │ ├── api
│ │ │ ├── attributes.spec.ts
│ │ │ ├── attributes.ts
│ │ │ ├── css.spec.ts
│ │ │ ├── css.ts
│ │ │ ├── extract.spec.ts
│ │ │ ├── extract.ts
│ │ │ ├── forms.spec.ts
│ │ │ ├── forms.ts
│ │ │ ├── manipulation.spec.ts
│ │ │ ├── manipulation.ts
│ │ │ ├── traversing.spec.ts
│ │ │ └── traversing.ts
│ │ ├── cheerio.spec.ts
│ │ ├── cheerio.ts
│ │ ├── index-browser.mts
│ │ ├── index.spec.ts
│ │ ├── index.ts
│ │ ├── load-parse.ts
│ │ ├── load.spec.ts
│ │ ├── load.ts
│ │ ├── options.ts
│ │ ├── parse.spec.ts
│ │ ├── parse.ts
│ │ ├── parsers
│ │ │ └── parse5-adapter.ts
│ │ ├── slim.ts
│ │ ├── static.spec.ts
│ │ ├── static.ts
│ │ ├── types.ts
│ │ ├── utils.spec.ts
│ │ └── utils.ts
│ ├── cheerio-select
│ │ ├── lib
│ │ │ ├── esm
│ │ │ │ ├── helpers.d.ts
│ │ │ │ ├── helpers.d.ts.map
│ │ │ │ ├── helpers.js
│ │ │ │ ├── helpers.js.map
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── package.json
│ │ │ │ ├── positionals.d.ts
│ │ │ │ ├── positionals.d.ts.map
│ │ │ │ ├── positionals.js
│ │ │ │ └── positionals.js.map
│ │ │ ├── helpers.d.ts
│ │ │ ├── helpers.d.ts.map
│ │ │ ├── helpers.js
│ │ │ ├── helpers.js.map
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── index.js
│ │ │ ├── index.js.map
│ │ │ ├── positionals.d.ts
│ │ │ ├── positionals.d.ts.map
│ │ │ ├── positionals.js
│ │ │ └── positionals.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── cliui
│ │ ├── build
│ │ │ ├── index.cjs
│ │ │ ├── index.d.cts
│ │ │ └── lib
│ │ │ ├── index.js
│ │ │ └── string-utils.js
│ │ ├── CHANGELOG.md
│ │ ├── index.mjs
│ │ ├── LICENSE.txt
│ │ ├── package.json
│ │ └── README.md
│ ├── color-convert
│ │ ├── CHANGELOG.md
│ │ ├── conversions.js
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── route.js
│ ├── color-name
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── content-disposition
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── content-type
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── cookie
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── SECURITY.md
│ ├── cookie-signature
│ │ ├── .npmignore
│ │ ├── History.md
│ │ ├── index.js
│ │ ├── package.json
│ │ └── Readme.md
│ ├── cors
│ │ ├── CONTRIBUTING.md
│ │ ├── HISTORY.md
│ │ ├── lib
│ │ │ └── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── css-select
│ │ ├── lib
│ │ │ ├── attributes.d.ts
│ │ │ ├── attributes.d.ts.map
│ │ │ ├── attributes.js
│ │ │ ├── attributes.js.map
│ │ │ ├── compile.d.ts
│ │ │ ├── compile.d.ts.map
│ │ │ ├── compile.js
│ │ │ ├── compile.js.map
│ │ │ ├── esm
│ │ │ │ ├── attributes.d.ts
│ │ │ │ ├── attributes.d.ts.map
│ │ │ │ ├── attributes.js
│ │ │ │ ├── attributes.js.map
│ │ │ │ ├── compile.d.ts
│ │ │ │ ├── compile.d.ts.map
│ │ │ │ ├── compile.js
│ │ │ │ ├── compile.js.map
│ │ │ │ ├── general.d.ts
│ │ │ │ ├── general.d.ts.map
│ │ │ │ ├── general.js
│ │ │ │ ├── general.js.map
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── package.json
│ │ │ │ ├── pseudo-selectors
│ │ │ │ │ ├── aliases.d.ts
│ │ │ │ │ ├── aliases.d.ts.map
│ │ │ │ │ ├── aliases.js
│ │ │ │ │ ├── aliases.js.map
│ │ │ │ │ ├── filters.d.ts
│ │ │ │ │ ├── filters.d.ts.map
│ │ │ │ │ ├── filters.js
│ │ │ │ │ ├── filters.js.map
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── index.d.ts.map
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── index.js.map
│ │ │ │ │ ├── pseudos.d.ts
│ │ │ │ │ ├── pseudos.d.ts.map
│ │ │ │ │ ├── pseudos.js
│ │ │ │ │ ├── pseudos.js.map
│ │ │ │ │ ├── subselects.d.ts
│ │ │ │ │ ├── subselects.d.ts.map
│ │ │ │ │ ├── subselects.js
│ │ │ │ │ └── subselects.js.map
│ │ │ │ ├── sort.d.ts
│ │ │ │ ├── sort.d.ts.map
│ │ │ │ ├── sort.js
│ │ │ │ ├── sort.js.map
│ │ │ │ ├── types.d.ts
│ │ │ │ ├── types.d.ts.map
│ │ │ │ ├── types.js
│ │ │ │ └── types.js.map
│ │ │ ├── general.d.ts
│ │ │ ├── general.d.ts.map
│ │ │ ├── general.js
│ │ │ ├── general.js.map
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── index.js
│ │ │ ├── index.js.map
│ │ │ ├── pseudo-selectors
│ │ │ │ ├── aliases.d.ts
│ │ │ │ ├── aliases.d.ts.map
│ │ │ │ ├── aliases.js
│ │ │ │ ├── aliases.js.map
│ │ │ │ ├── filters.d.ts
│ │ │ │ ├── filters.d.ts.map
│ │ │ │ ├── filters.js
│ │ │ │ ├── filters.js.map
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── pseudos.d.ts
│ │ │ │ ├── pseudos.d.ts.map
│ │ │ │ ├── pseudos.js
│ │ │ │ ├── pseudos.js.map
│ │ │ │ ├── subselects.d.ts
│ │ │ │ ├── subselects.d.ts.map
│ │ │ │ ├── subselects.js
│ │ │ │ └── subselects.js.map
│ │ │ ├── sort.d.ts
│ │ │ ├── sort.d.ts.map
│ │ │ ├── sort.js
│ │ │ ├── sort.js.map
│ │ │ ├── types.d.ts
│ │ │ ├── types.d.ts.map
│ │ │ ├── types.js
│ │ │ └── types.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── css-what
│ │ ├── lib
│ │ │ ├── commonjs
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── parse.d.ts
│ │ │ │ ├── parse.d.ts.map
│ │ │ │ ├── parse.js
│ │ │ │ ├── stringify.d.ts
│ │ │ │ ├── stringify.d.ts.map
│ │ │ │ ├── stringify.js
│ │ │ │ ├── types.d.ts
│ │ │ │ ├── types.d.ts.map
│ │ │ │ └── types.js
│ │ │ └── es
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── index.js
│ │ │ ├── parse.d.ts
│ │ │ ├── parse.d.ts.map
│ │ │ ├── parse.js
│ │ │ ├── stringify.d.ts
│ │ │ ├── stringify.d.ts.map
│ │ │ ├── stringify.js
│ │ │ ├── types.d.ts
│ │ │ ├── types.d.ts.map
│ │ │ └── types.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── readme.md
│ ├── debug
│ │ ├── .coveralls.yml
│ │ ├── .eslintrc
│ │ ├── .npmignore
│ │ ├── .travis.yml
│ │ ├── CHANGELOG.md
│ │ ├── component.json
│ │ ├── karma.conf.js
│ │ ├── LICENSE
│ │ ├── Makefile
│ │ ├── node.js
│ │ ├── package.json
│ │ ├── README.md
│ │ └── src
│ │ ├── browser.js
│ │ ├── debug.js
│ │ ├── index.js
│ │ ├── inspector-log.js
│ │ └── node.js
│ ├── depd
│ │ ├── History.md
│ │ ├── index.js
│ │ ├── lib
│ │ │ └── browser
│ │ │ └── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── Readme.md
│ ├── destroy
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── dom-serializer
│ │ ├── lib
│ │ │ ├── esm
│ │ │ │ ├── foreignNames.d.ts
│ │ │ │ ├── foreignNames.d.ts.map
│ │ │ │ ├── foreignNames.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ └── package.json
│ │ │ ├── foreignNames.d.ts
│ │ │ ├── foreignNames.d.ts.map
│ │ │ ├── foreignNames.js
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ └── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── domelementtype
│ │ ├── lib
│ │ │ ├── esm
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ └── package.json
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ └── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── readme.md
│ ├── domhandler
│ │ ├── lib
│ │ │ ├── esm
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── node.d.ts
│ │ │ │ ├── node.d.ts.map
│ │ │ │ ├── node.js
│ │ │ │ └── package.json
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── index.js
│ │ │ ├── node.d.ts
│ │ │ ├── node.d.ts.map
│ │ │ └── node.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── readme.md
│ ├── domutils
│ │ ├── lib
│ │ │ ├── esm
│ │ │ │ ├── feeds.d.ts
│ │ │ │ ├── feeds.d.ts.map
│ │ │ │ ├── feeds.js
│ │ │ │ ├── feeds.js.map
│ │ │ │ ├── helpers.d.ts
│ │ │ │ ├── helpers.d.ts.map
│ │ │ │ ├── helpers.js
│ │ │ │ ├── helpers.js.map
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── legacy.d.ts
│ │ │ │ ├── legacy.d.ts.map
│ │ │ │ ├── legacy.js
│ │ │ │ ├── legacy.js.map
│ │ │ │ ├── manipulation.d.ts
│ │ │ │ ├── manipulation.d.ts.map
│ │ │ │ ├── manipulation.js
│ │ │ │ ├── manipulation.js.map
│ │ │ │ ├── package.json
│ │ │ │ ├── querying.d.ts
│ │ │ │ ├── querying.d.ts.map
│ │ │ │ ├── querying.js
│ │ │ │ ├── querying.js.map
│ │ │ │ ├── stringify.d.ts
│ │ │ │ ├── stringify.d.ts.map
│ │ │ │ ├── stringify.js
│ │ │ │ ├── stringify.js.map
│ │ │ │ ├── traversal.d.ts
│ │ │ │ ├── traversal.d.ts.map
│ │ │ │ ├── traversal.js
│ │ │ │ └── traversal.js.map
│ │ │ ├── feeds.d.ts
│ │ │ ├── feeds.d.ts.map
│ │ │ ├── feeds.js
│ │ │ ├── feeds.js.map
│ │ │ ├── helpers.d.ts
│ │ │ ├── helpers.d.ts.map
│ │ │ ├── helpers.js
│ │ │ ├── helpers.js.map
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── index.js
│ │ │ ├── index.js.map
│ │ │ ├── legacy.d.ts
│ │ │ ├── legacy.d.ts.map
│ │ │ ├── legacy.js
│ │ │ ├── legacy.js.map
│ │ │ ├── manipulation.d.ts
│ │ │ ├── manipulation.d.ts.map
│ │ │ ├── manipulation.js
│ │ │ ├── manipulation.js.map
│ │ │ ├── querying.d.ts
│ │ │ ├── querying.d.ts.map
│ │ │ ├── querying.js
│ │ │ ├── querying.js.map
│ │ │ ├── stringify.d.ts
│ │ │ ├── stringify.d.ts.map
│ │ │ ├── stringify.js
│ │ │ ├── stringify.js.map
│ │ │ ├── traversal.d.ts
│ │ │ ├── traversal.d.ts.map
│ │ │ ├── traversal.js
│ │ │ └── traversal.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── readme.md
│ ├── dunder-proto
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── get.d.ts
│ │ ├── get.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── set.d.ts
│ │ ├── set.js
│ │ ├── test
│ │ │ ├── get.js
│ │ │ ├── index.js
│ │ │ └── set.js
│ │ └── tsconfig.json
│ ├── ee-first
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── emoji-regex
│ │ ├── es2015
│ │ │ ├── index.js
│ │ │ └── text.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE-MIT.txt
│ │ ├── package.json
│ │ ├── README.md
│ │ └── text.js
│ ├── encodeurl
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── encoding-sniffer
│ │ ├── dist
│ │ │ ├── commonjs
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── package.json
│ │ │ │ ├── sniffer.d.ts
│ │ │ │ ├── sniffer.d.ts.map
│ │ │ │ ├── sniffer.js
│ │ │ │ └── sniffer.js.map
│ │ │ └── esm
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── index.js
│ │ │ ├── index.js.map
│ │ │ ├── package.json
│ │ │ ├── sniffer.d.ts
│ │ │ ├── sniffer.d.ts.map
│ │ │ ├── sniffer.js
│ │ │ └── sniffer.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── entities
│ │ ├── lib
│ │ │ ├── decode_codepoint.d.ts
│ │ │ ├── decode_codepoint.d.ts.map
│ │ │ ├── decode_codepoint.js
│ │ │ ├── decode_codepoint.js.map
│ │ │ ├── decode.d.ts
│ │ │ ├── decode.d.ts.map
│ │ │ ├── decode.js
│ │ │ ├── decode.js.map
│ │ │ ├── encode.d.ts
│ │ │ ├── encode.d.ts.map
│ │ │ ├── encode.js
│ │ │ ├── encode.js.map
│ │ │ ├── escape.d.ts
│ │ │ ├── escape.d.ts.map
│ │ │ ├── escape.js
│ │ │ ├── escape.js.map
│ │ │ ├── esm
│ │ │ │ ├── decode_codepoint.d.ts
│ │ │ │ ├── decode_codepoint.d.ts.map
│ │ │ │ ├── decode_codepoint.js
│ │ │ │ ├── decode_codepoint.js.map
│ │ │ │ ├── decode.d.ts
│ │ │ │ ├── decode.d.ts.map
│ │ │ │ ├── decode.js
│ │ │ │ ├── decode.js.map
│ │ │ │ ├── encode.d.ts
│ │ │ │ ├── encode.d.ts.map
│ │ │ │ ├── encode.js
│ │ │ │ ├── encode.js.map
│ │ │ │ ├── escape.d.ts
│ │ │ │ ├── escape.d.ts.map
│ │ │ │ ├── escape.js
│ │ │ │ ├── escape.js.map
│ │ │ │ ├── generated
│ │ │ │ │ ├── decode-data-html.d.ts
│ │ │ │ │ ├── decode-data-html.d.ts.map
│ │ │ │ │ ├── decode-data-html.js
│ │ │ │ │ ├── decode-data-html.js.map
│ │ │ │ │ ├── decode-data-xml.d.ts
│ │ │ │ │ ├── decode-data-xml.d.ts.map
│ │ │ │ │ ├── decode-data-xml.js
│ │ │ │ │ ├── decode-data-xml.js.map
│ │ │ │ │ ├── encode-html.d.ts
│ │ │ │ │ ├── encode-html.d.ts.map
│ │ │ │ │ ├── encode-html.js
│ │ │ │ │ └── encode-html.js.map
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ └── package.json
│ │ │ ├── generated
│ │ │ │ ├── decode-data-html.d.ts
│ │ │ │ ├── decode-data-html.d.ts.map
│ │ │ │ ├── decode-data-html.js
│ │ │ │ ├── decode-data-html.js.map
│ │ │ │ ├── decode-data-xml.d.ts
│ │ │ │ ├── decode-data-xml.d.ts.map
│ │ │ │ ├── decode-data-xml.js
│ │ │ │ ├── decode-data-xml.js.map
│ │ │ │ ├── encode-html.d.ts
│ │ │ │ ├── encode-html.d.ts.map
│ │ │ │ ├── encode-html.js
│ │ │ │ └── encode-html.js.map
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── index.js
│ │ │ └── index.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── readme.md
│ ├── es-define-property
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── test
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── es-errors
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── CHANGELOG.md
│ │ ├── eval.d.ts
│ │ ├── eval.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── range.d.ts
│ │ ├── range.js
│ │ ├── README.md
│ │ ├── ref.d.ts
│ │ ├── ref.js
│ │ ├── syntax.d.ts
│ │ ├── syntax.js
│ │ ├── test
│ │ │ └── index.js
│ │ ├── tsconfig.json
│ │ ├── type.d.ts
│ │ ├── type.js
│ │ ├── uri.d.ts
│ │ └── uri.js
│ ├── es-object-atoms
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── CHANGELOG.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── isObject.d.ts
│ │ ├── isObject.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── RequireObjectCoercible.d.ts
│ │ ├── RequireObjectCoercible.js
│ │ ├── test
│ │ │ └── index.js
│ │ ├── ToObject.d.ts
│ │ ├── ToObject.js
│ │ └── tsconfig.json
│ ├── escalade
│ │ ├── dist
│ │ │ ├── index.js
│ │ │ └── index.mjs
│ │ ├── index.d.mts
│ │ ├── index.d.ts
│ │ ├── license
│ │ ├── package.json
│ │ ├── readme.md
│ │ └── sync
│ │ ├── index.d.mts
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ └── index.mjs
│ ├── escape-html
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── Readme.md
│ ├── etag
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── eventsource
│ │ ├── dist
│ │ │ ├── index.cjs
│ │ │ ├── index.cjs.map
│ │ │ ├── index.d.cts
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ └── index.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── src
│ │ ├── errors.ts
│ │ ├── EventSource.ts
│ │ ├── index.ts
│ │ └── types.ts
│ ├── eventsource-parser
│ │ ├── dist
│ │ │ ├── index.cjs
│ │ │ ├── index.cjs.map
│ │ │ ├── index.d.cts
│ │ │ ├── index.d.ts
│ │ │ ├── index.esm.js
│ │ │ ├── index.esm.js.map
│ │ │ ├── index.js
│ │ │ ├── index.js.map
│ │ │ ├── stats.html
│ │ │ ├── stream.cjs
│ │ │ ├── stream.cjs.map
│ │ │ ├── stream.d.cts
│ │ │ ├── stream.d.ts
│ │ │ ├── stream.esm.js
│ │ │ ├── stream.esm.js.map
│ │ │ ├── stream.js
│ │ │ └── stream.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── errors.ts
│ │ │ ├── index.ts
│ │ │ ├── parse.ts
│ │ │ ├── stream.ts
│ │ │ └── types.ts
│ │ └── stream.js
│ ├── express
│ │ ├── History.md
│ │ ├── index.js
│ │ ├── lib
│ │ │ ├── application.js
│ │ │ ├── express.js
│ │ │ ├── middleware
│ │ │ │ ├── init.js
│ │ │ │ └── query.js
│ │ │ ├── request.js
│ │ │ ├── response.js
│ │ │ ├── router
│ │ │ │ ├── index.js
│ │ │ │ ├── layer.js
│ │ │ │ └── route.js
│ │ │ ├── utils.js
│ │ │ └── view.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── Readme.md
│ ├── express-rate-limit
│ │ ├── dist
│ │ │ ├── index.cjs
│ │ │ ├── index.d.cts
│ │ │ ├── index.d.mts
│ │ │ ├── index.d.ts
│ │ │ └── index.mjs
│ │ ├── license.md
│ │ ├── package.json
│ │ ├── readme.md
│ │ └── tsconfig.json
│ ├── finalhandler
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── SECURITY.md
│ ├── forwarded
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── fresh
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── function-bind
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ ├── FUNDING.yml
│ │ │ └── SECURITY.md
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── implementation.js
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── test
│ │ ├── .eslintrc
│ │ └── index.js
│ ├── get-caller-file
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.js.map
│ │ ├── LICENSE.md
│ │ ├── package.json
│ │ └── README.md
│ ├── get-intrinsic
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── test
│ │ └── GetIntrinsic.js
│ ├── get-proto
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── Object.getPrototypeOf.d.ts
│ │ ├── Object.getPrototypeOf.js
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── Reflect.getPrototypeOf.d.ts
│ │ ├── Reflect.getPrototypeOf.js
│ │ ├── test
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── gopd
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── CHANGELOG.md
│ │ ├── gOPD.d.ts
│ │ ├── gOPD.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── test
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── has-symbols
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── shams.d.ts
│ │ ├── shams.js
│ │ ├── test
│ │ │ ├── index.js
│ │ │ ├── shams
│ │ │ │ ├── core-js.js
│ │ │ │ └── get-own-property-symbols.js
│ │ │ └── tests.js
│ │ └── tsconfig.json
│ ├── hasown
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── tsconfig.json
│ ├── htmlparser2
│ │ ├── lib
│ │ │ ├── esm
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── package.json
│ │ │ │ ├── Parser.d.ts
│ │ │ │ ├── Parser.d.ts.map
│ │ │ │ ├── Parser.js
│ │ │ │ ├── Parser.js.map
│ │ │ │ ├── Tokenizer.d.ts
│ │ │ │ ├── Tokenizer.d.ts.map
│ │ │ │ ├── Tokenizer.js
│ │ │ │ ├── Tokenizer.js.map
│ │ │ │ ├── WritableStream.d.ts
│ │ │ │ ├── WritableStream.d.ts.map
│ │ │ │ ├── WritableStream.js
│ │ │ │ └── WritableStream.js.map
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── index.js
│ │ │ ├── index.js.map
│ │ │ ├── Parser.d.ts
│ │ │ ├── Parser.d.ts.map
│ │ │ ├── Parser.js
│ │ │ ├── Parser.js.map
│ │ │ ├── Tokenizer.d.ts
│ │ │ ├── Tokenizer.d.ts.map
│ │ │ ├── Tokenizer.js
│ │ │ ├── Tokenizer.js.map
│ │ │ ├── WritableStream.d.ts
│ │ │ ├── WritableStream.d.ts.map
│ │ │ ├── WritableStream.js
│ │ │ └── WritableStream.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── http-errors
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── iconv-lite
│ │ ├── .github
│ │ │ └── dependabot.yml
│ │ ├── .idea
│ │ │ ├── codeStyles
│ │ │ │ ├── codeStyleConfig.xml
│ │ │ │ └── Project.xml
│ │ │ ├── iconv-lite.iml
│ │ │ ├── inspectionProfiles
│ │ │ │ └── Project_Default.xml
│ │ │ ├── modules.xml
│ │ │ └── vcs.xml
│ │ ├── Changelog.md
│ │ ├── encodings
│ │ │ ├── dbcs-codec.js
│ │ │ ├── dbcs-data.js
│ │ │ ├── index.js
│ │ │ ├── internal.js
│ │ │ ├── sbcs-codec.js
│ │ │ ├── sbcs-data-generated.js
│ │ │ ├── sbcs-data.js
│ │ │ ├── tables
│ │ │ │ ├── big5-added.json
│ │ │ │ ├── cp936.json
│ │ │ │ ├── cp949.json
│ │ │ │ ├── cp950.json
│ │ │ │ ├── eucjp.json
│ │ │ │ ├── gb18030-ranges.json
│ │ │ │ ├── gbk-added.json
│ │ │ │ └── shiftjis.json
│ │ │ ├── utf16.js
│ │ │ ├── utf32.js
│ │ │ └── utf7.js
│ │ ├── lib
│ │ │ ├── bom-handling.js
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ └── streams.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── inherits
│ │ ├── inherits_browser.js
│ │ ├── inherits.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── ipaddr.js
│ │ ├── ipaddr.min.js
│ │ ├── lib
│ │ │ ├── ipaddr.js
│ │ │ └── ipaddr.js.d.ts
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── is-fullwidth-code-point
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── license
│ │ ├── package.json
│ │ └── readme.md
│ ├── is-promise
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── index.mjs
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── readme.md
│ ├── math-intrinsics
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── abs.d.ts
│ │ ├── abs.js
│ │ ├── CHANGELOG.md
│ │ ├── constants
│ │ │ ├── maxArrayLength.d.ts
│ │ │ ├── maxArrayLength.js
│ │ │ ├── maxSafeInteger.d.ts
│ │ │ ├── maxSafeInteger.js
│ │ │ ├── maxValue.d.ts
│ │ │ └── maxValue.js
│ │ ├── floor.d.ts
│ │ ├── floor.js
│ │ ├── isFinite.d.ts
│ │ ├── isFinite.js
│ │ ├── isInteger.d.ts
│ │ ├── isInteger.js
│ │ ├── isNaN.d.ts
│ │ ├── isNaN.js
│ │ ├── isNegativeZero.d.ts
│ │ ├── isNegativeZero.js
│ │ ├── LICENSE
│ │ ├── max.d.ts
│ │ ├── max.js
│ │ ├── min.d.ts
│ │ ├── min.js
│ │ ├── mod.d.ts
│ │ ├── mod.js
│ │ ├── package.json
│ │ ├── pow.d.ts
│ │ ├── pow.js
│ │ ├── README.md
│ │ ├── round.d.ts
│ │ ├── round.js
│ │ ├── sign.d.ts
│ │ ├── sign.js
│ │ ├── test
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── media-typer
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── merge-descriptors
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── methods
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── mime
│ │ ├── .npmignore
│ │ ├── CHANGELOG.md
│ │ ├── cli.js
│ │ ├── LICENSE
│ │ ├── mime.js
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── build.js
│ │ │ └── test.js
│ │ └── types.json
│ ├── mime-db
│ │ ├── db.json
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── mime-types
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── ms
│ │ ├── index.js
│ │ ├── license.md
│ │ ├── package.json
│ │ └── readme.md
│ ├── negotiator
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── lib
│ │ │ ├── charset.js
│ │ │ ├── encoding.js
│ │ │ ├── language.js
│ │ │ └── mediaType.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── nth-check
│ │ ├── lib
│ │ │ ├── compile.d.ts
│ │ │ ├── compile.d.ts.map
│ │ │ ├── compile.js
│ │ │ ├── compile.js.map
│ │ │ ├── esm
│ │ │ │ ├── compile.d.ts
│ │ │ │ ├── compile.d.ts.map
│ │ │ │ ├── compile.js
│ │ │ │ ├── compile.js.map
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.d.ts.map
│ │ │ │ ├── index.js
│ │ │ │ ├── index.js.map
│ │ │ │ ├── package.json
│ │ │ │ ├── parse.d.ts
│ │ │ │ ├── parse.d.ts.map
│ │ │ │ ├── parse.js
│ │ │ │ └── parse.js.map
│ │ │ ├── index.d.ts
│ │ │ ├── index.d.ts.map
│ │ │ ├── index.js
│ │ │ ├── index.js.map
│ │ │ ├── parse.d.ts
│ │ │ ├── parse.d.ts.map
│ │ │ ├── parse.js
│ │ │ └── parse.js.map
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── object-assign
│ │ ├── index.js
│ │ ├── license
│ │ ├── package.json
│ │ └── readme.md
│ ├── object-inspect
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── example
│ │ │ ├── all.js
│ │ │ ├── circular.js
│ │ │ ├── fn.js
│ │ │ └── inspect.js
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package-support.json
│ │ ├── package.json
│ │ ├── readme.markdown
│ │ ├── test
│ │ │ ├── bigint.js
│ │ │ ├── browser
│ │ │ │ └── dom.js
│ │ │ ├── circular.js
│ │ │ ├── deep.js
│ │ │ ├── element.js
│ │ │ ├── err.js
│ │ │ ├── fakes.js
│ │ │ ├── fn.js
│ │ │ ├── global.js
│ │ │ ├── has.js
│ │ │ ├── holes.js
│ │ │ ├── indent-option.js
│ │ │ ├── inspect.js
│ │ │ ├── lowbyte.js
│ │ │ ├── number.js
│ │ │ ├── quoteStyle.js
│ │ │ ├── toStringTag.js
│ │ │ ├── undef.js
│ │ │ └── values.js
│ │ ├── test-core-js.js
│ │ └── util.inspect.js
│ ├── on-finished
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── once
│ │ ├── LICENSE
│ │ ├── once.js
│ │ ├── package.json
│ │ └── README.md
│ ├── parse5
│ │ ├── dist
│ │ │ ├── cjs
│ │ │ │ ├── common
│ │ │ │ │ ├── doctype.d.ts
│ │ │ │ │ ├── doctype.js
│ │ │ │ │ ├── error-codes.d.ts
│ │ │ │ │ ├── error-codes.js
│ │ │ │ │ ├── foreign-content.d.ts
│ │ │ │ │ ├── foreign-content.js
│ │ │ │ │ ├── html.d.ts
│ │ │ │ │ ├── html.js
│ │ │ │ │ ├── token.d.ts
│ │ │ │ │ ├── token.js
│ │ │ │ │ ├── unicode.d.ts
│ │ │ │ │ └── unicode.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── package.json
│ │ │ │ ├── parser
│ │ │ │ │ ├── formatting-element-list.d.ts
│ │ │ │ │ ├── formatting-element-list.js
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── open-element-stack.d.ts
│ │ │ │ │ └── open-element-stack.js
│ │ │ │ ├── serializer
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ └── index.js
│ │ │ │ ├── tokenizer
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── preprocessor.d.ts
│ │ │ │ │ └── preprocessor.js
│ │ │ │ └── tree-adapters
│ │ │ │ ├── default.d.ts
│ │ │ │ ├── default.js
│ │ │ │ ├── interface.d.ts
│ │ │ │ └── interface.js
│ │ │ ├── common
│ │ │ │ ├── doctype.d.ts
│ │ │ │ ├── doctype.js
│ │ │ │ ├── error-codes.d.ts
│ │ │ │ ├── error-codes.js
│ │ │ │ ├── foreign-content.d.ts
│ │ │ │ ├── foreign-content.js
│ │ │ │ ├── html.d.ts
│ │ │ │ ├── html.js
│ │ │ │ ├── token.d.ts
│ │ │ │ ├── token.js
│ │ │ │ ├── unicode.d.ts
│ │ │ │ └── unicode.js
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ ├── parser
│ │ │ │ ├── formatting-element-list.d.ts
│ │ │ │ ├── formatting-element-list.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── open-element-stack.d.ts
│ │ │ │ └── open-element-stack.js
│ │ │ ├── serializer
│ │ │ │ ├── index.d.ts
│ │ │ │ └── index.js
│ │ │ ├── tokenizer
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── preprocessor.d.ts
│ │ │ │ └── preprocessor.js
│ │ │ └── tree-adapters
│ │ │ ├── default.d.ts
│ │ │ ├── default.js
│ │ │ ├── interface.d.ts
│ │ │ └── interface.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── parse5-htmlparser2-tree-adapter
│ │ ├── dist
│ │ │ ├── cjs
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ └── package.json
│ │ │ ├── index.d.ts
│ │ │ └── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── parse5-parser-stream
│ │ ├── dist
│ │ │ ├── cjs
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ └── package.json
│ │ │ ├── index.d.ts
│ │ │ └── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── parseurl
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── path-to-regexp
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── Readme.md
│ ├── pkce-challenge
│ │ ├── dist
│ │ │ ├── index.browser.d.ts
│ │ │ ├── index.browser.js
│ │ │ ├── index.node.d.ts
│ │ │ └── index.node.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── proxy-addr
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── qs
│ │ ├── .editorconfig
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── dist
│ │ │ └── qs.js
│ │ ├── lib
│ │ │ ├── formats.js
│ │ │ ├── index.js
│ │ │ ├── parse.js
│ │ │ ├── stringify.js
│ │ │ └── utils.js
│ │ ├── LICENSE.md
│ │ ├── package.json
│ │ ├── README.md
│ │ └── test
│ │ ├── empty-keys-cases.js
│ │ ├── parse.js
│ │ ├── stringify.js
│ │ └── utils.js
│ ├── range-parser
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── raw-body
│ │ ├── HISTORY.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── node_modules
│ │ │ └── iconv-lite
│ │ │ ├── Changelog.md
│ │ │ ├── encodings
│ │ │ │ ├── dbcs-codec.js
│ │ │ │ ├── dbcs-data.js
│ │ │ │ ├── index.js
│ │ │ │ ├── internal.js
│ │ │ │ ├── sbcs-codec.js
│ │ │ │ ├── sbcs-data-generated.js
│ │ │ │ ├── sbcs-data.js
│ │ │ │ ├── tables
│ │ │ │ │ ├── big5-added.json
│ │ │ │ │ ├── cp936.json
│ │ │ │ │ ├── cp949.json
│ │ │ │ │ ├── cp950.json
│ │ │ │ │ ├── eucjp.json
│ │ │ │ │ ├── gb18030-ranges.json
│ │ │ │ │ ├── gbk-added.json
│ │ │ │ │ └── shiftjis.json
│ │ │ │ ├── utf16.js
│ │ │ │ └── utf7.js
│ │ │ ├── lib
│ │ │ │ ├── bom-handling.js
│ │ │ │ ├── extend-node.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ └── streams.js
│ │ │ ├── LICENSE
│ │ │ ├── package.json
│ │ │ └── README.md
│ │ ├── package.json
│ │ ├── README.md
│ │ └── SECURITY.md
│ ├── require-directory
│ │ ├── .jshintrc
│ │ ├── .npmignore
│ │ ├── .travis.yml
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.markdown
│ ├── router
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── lib
│ │ │ ├── layer.js
│ │ │ └── route.js
│ │ ├── LICENSE
│ │ ├── node_modules
│ │ │ └── path-to-regexp
│ │ │ ├── dist
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ └── index.js.map
│ │ │ ├── LICENSE
│ │ │ ├── package.json
│ │ │ └── Readme.md
│ │ ├── package.json
│ │ ├── README.md
│ │ └── SECURITY.md
│ ├── safe-buffer
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── safer-buffer
│ │ ├── dangerous.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── Porting-Buffer.md
│ │ ├── Readme.md
│ │ ├── safer.js
│ │ └── tests.js
│ ├── send
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── node_modules
│ │ │ ├── encodeurl
│ │ │ │ ├── HISTORY.md
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ └── ms
│ │ │ ├── index.js
│ │ │ ├── license.md
│ │ │ ├── package.json
│ │ │ └── readme.md
│ │ ├── package.json
│ │ ├── README.md
│ │ └── SECURITY.md
│ ├── serve-static
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── setprototypeof
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── test
│ │ └── index.js
│ ├── side-channel
│ │ ├── .editorconfig
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── test
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── side-channel-list
│ │ ├── .editorconfig
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── list.d.ts
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── test
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── side-channel-map
│ │ ├── .editorconfig
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── test
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── side-channel-weakmap
│ │ ├── .editorconfig
│ │ ├── .eslintrc
│ │ ├── .github
│ │ │ └── FUNDING.yml
│ │ ├── .nycrc
│ │ ├── CHANGELOG.md
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── test
│ │ │ └── index.js
│ │ └── tsconfig.json
│ ├── statuses
│ │ ├── codes.json
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── string-width
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── license
│ │ ├── package.json
│ │ └── readme.md
│ ├── strip-ansi
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── license
│ │ ├── package.json
│ │ └── readme.md
│ ├── supergateway
│ │ ├── dist
│ │ │ └── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── src
│ │ │ └── index.ts
│ │ ├── supergateway.png
│ │ └── tsconfig.json
│ ├── toidentifier
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── type-is
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── undici
│ │ ├── docs
│ │ │ └── docs
│ │ │ ├── api
│ │ │ │ ├── Agent.md
│ │ │ │ ├── api-lifecycle.md
│ │ │ │ ├── BalancedPool.md
│ │ │ │ ├── CacheStorage.md
│ │ │ │ ├── Client.md
│ │ │ │ ├── Connector.md
│ │ │ │ ├── ContentType.md
│ │ │ │ ├── Cookies.md
│ │ │ │ ├── Debug.md
│ │ │ │ ├── DiagnosticsChannel.md
│ │ │ │ ├── Dispatcher.md
│ │ │ │ ├── DispatchInterceptor.md
│ │ │ │ ├── EnvHttpProxyAgent.md
│ │ │ │ ├── Errors.md
│ │ │ │ ├── EventSource.md
│ │ │ │ ├── Fetch.md
│ │ │ │ ├── MockAgent.md
│ │ │ │ ├── MockClient.md
│ │ │ │ ├── MockErrors.md
│ │ │ │ ├── MockPool.md
│ │ │ │ ├── Pool.md
│ │ │ │ ├── PoolStats.md
│ │ │ │ ├── ProxyAgent.md
│ │ │ │ ├── RedirectHandler.md
│ │ │ │ ├── RetryAgent.md
│ │ │ │ ├── RetryHandler.md
│ │ │ │ ├── Util.md
│ │ │ │ └── WebSocket.md
│ │ │ └── best-practices
│ │ │ ├── client-certificate.md
│ │ │ ├── mocking-request.md
│ │ │ ├── proxy.md
│ │ │ └── writing-tests.md
│ │ ├── index-fetch.js
│ │ ├── index.d.ts
│ │ ├── index.js
│ │ ├── lib
│ │ │ ├── api
│ │ │ │ ├── abort-signal.js
│ │ │ │ ├── api-connect.js
│ │ │ │ ├── api-pipeline.js
│ │ │ │ ├── api-request.js
│ │ │ │ ├── api-stream.js
│ │ │ │ ├── api-upgrade.js
│ │ │ │ ├── index.js
│ │ │ │ ├── readable.js
│ │ │ │ └── util.js
│ │ │ ├── core
│ │ │ │ ├── connect.js
│ │ │ │ ├── constants.js
│ │ │ │ ├── diagnostics.js
│ │ │ │ ├── errors.js
│ │ │ │ ├── request.js
│ │ │ │ ├── symbols.js
│ │ │ │ ├── tree.js
│ │ │ │ └── util.js
│ │ │ ├── dispatcher
│ │ │ │ ├── agent.js
│ │ │ │ ├── balanced-pool.js
│ │ │ │ ├── client-h1.js
│ │ │ │ ├── client-h2.js
│ │ │ │ ├── client.js
│ │ │ │ ├── dispatcher-base.js
│ │ │ │ ├── dispatcher.js
│ │ │ │ ├── env-http-proxy-agent.js
│ │ │ │ ├── fixed-queue.js
│ │ │ │ ├── pool-base.js
│ │ │ │ ├── pool-stats.js
│ │ │ │ ├── pool.js
│ │ │ │ ├── proxy-agent.js
│ │ │ │ └── retry-agent.js
│ │ │ ├── global.js
│ │ │ ├── handler
│ │ │ │ ├── decorator-handler.js
│ │ │ │ ├── redirect-handler.js
│ │ │ │ └── retry-handler.js
│ │ │ ├── interceptor
│ │ │ │ ├── dns.js
│ │ │ │ ├── dump.js
│ │ │ │ ├── redirect-interceptor.js
│ │ │ │ ├── redirect.js
│ │ │ │ ├── response-error.js
│ │ │ │ └── retry.js
│ │ │ ├── llhttp
│ │ │ │ ├── .gitkeep
│ │ │ │ ├── constants.js
│ │ │ │ ├── llhttp_simd-wasm.js
│ │ │ │ ├── llhttp-wasm.js
│ │ │ │ └── utils.js
│ │ │ ├── mock
│ │ │ │ ├── mock-agent.js
│ │ │ │ ├── mock-client.js
│ │ │ │ ├── mock-errors.js
│ │ │ │ ├── mock-interceptor.js
│ │ │ │ ├── mock-pool.js
│ │ │ │ ├── mock-symbols.js
│ │ │ │ ├── mock-utils.js
│ │ │ │ ├── pending-interceptors-formatter.js
│ │ │ │ └── pluralizer.js
│ │ │ ├── util
│ │ │ │ └── timers.js
│ │ │ └── web
│ │ │ ├── cache
│ │ │ │ ├── cache.js
│ │ │ │ ├── cachestorage.js
│ │ │ │ ├── symbols.js
│ │ │ │ └── util.js
│ │ │ ├── cookies
│ │ │ │ ├── constants.js
│ │ │ │ ├── index.js
│ │ │ │ ├── parse.js
│ │ │ │ └── util.js
│ │ │ ├── eventsource
│ │ │ │ ├── eventsource-stream.js
│ │ │ │ ├── eventsource.js
│ │ │ │ └── util.js
│ │ │ ├── fetch
│ │ │ │ ├── body.js
│ │ │ │ ├── constants.js
│ │ │ │ ├── data-url.js
│ │ │ │ ├── dispatcher-weakref.js
│ │ │ │ ├── file.js
│ │ │ │ ├── formdata-parser.js
│ │ │ │ ├── formdata.js
│ │ │ │ ├── global.js
│ │ │ │ ├── headers.js
│ │ │ │ ├── index.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── request.js
│ │ │ │ ├── response.js
│ │ │ │ ├── symbols.js
│ │ │ │ ├── util.js
│ │ │ │ └── webidl.js
│ │ │ ├── fileapi
│ │ │ │ ├── encoding.js
│ │ │ │ ├── filereader.js
│ │ │ │ ├── progressevent.js
│ │ │ │ ├── symbols.js
│ │ │ │ └── util.js
│ │ │ └── websocket
│ │ │ ├── connection.js
│ │ │ ├── constants.js
│ │ │ ├── events.js
│ │ │ ├── frame.js
│ │ │ ├── permessage-deflate.js
│ │ │ ├── receiver.js
│ │ │ ├── sender.js
│ │ │ ├── symbols.js
│ │ │ ├── util.js
│ │ │ └── websocket.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── scripts
│ │ │ └── strip-comments.js
│ │ └── types
│ │ ├── agent.d.ts
│ │ ├── api.d.ts
│ │ ├── balanced-pool.d.ts
│ │ ├── cache.d.ts
│ │ ├── client.d.ts
│ │ ├── connector.d.ts
│ │ ├── content-type.d.ts
│ │ ├── cookies.d.ts
│ │ ├── diagnostics-channel.d.ts
│ │ ├── dispatcher.d.ts
│ │ ├── env-http-proxy-agent.d.ts
│ │ ├── errors.d.ts
│ │ ├── eventsource.d.ts
│ │ ├── fetch.d.ts
│ │ ├── file.d.ts
│ │ ├── filereader.d.ts
│ │ ├── formdata.d.ts
│ │ ├── global-dispatcher.d.ts
│ │ ├── global-origin.d.ts
│ │ ├── handlers.d.ts
│ │ ├── header.d.ts
│ │ ├── index.d.ts
│ │ ├── interceptors.d.ts
│ │ ├── mock-agent.d.ts
│ │ ├── mock-client.d.ts
│ │ ├── mock-errors.d.ts
│ │ ├── mock-interceptor.d.ts
│ │ ├── mock-pool.d.ts
│ │ ├── patch.d.ts
│ │ ├── pool-stats.d.ts
│ │ ├── pool.d.ts
│ │ ├── proxy-agent.d.ts
│ │ ├── readable.d.ts
│ │ ├── README.md
│ │ ├── retry-agent.d.ts
│ │ ├── retry-handler.d.ts
│ │ ├── util.d.ts
│ │ ├── webidl.d.ts
│ │ └── websocket.d.ts
│ ├── unpipe
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── utils-merge
│ │ ├── .npmignore
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── vary
│ │ ├── HISTORY.md
│ │ ├── index.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── whatwg-encoding
│ │ ├── lib
│ │ │ ├── labels-to-names.json
│ │ │ ├── supported-names.json
│ │ │ └── whatwg-encoding.js
│ │ ├── LICENSE.txt
│ │ ├── package.json
│ │ └── README.md
│ ├── whatwg-mimetype
│ │ ├── lib
│ │ │ ├── mime-type-parameters.js
│ │ │ ├── mime-type.js
│ │ │ ├── parser.js
│ │ │ ├── serializer.js
│ │ │ └── utils.js
│ │ ├── LICENSE.txt
│ │ ├── package.json
│ │ └── README.md
│ ├── wrap-ansi
│ │ ├── index.js
│ │ ├── license
│ │ ├── package.json
│ │ └── readme.md
│ ├── wrappy
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── README.md
│ │ └── wrappy.js
│ ├── y18n
│ │ ├── build
│ │ │ ├── index.cjs
│ │ │ └── lib
│ │ │ ├── cjs.js
│ │ │ ├── index.js
│ │ │ └── platform-shims
│ │ │ └── node.js
│ │ ├── CHANGELOG.md
│ │ ├── index.mjs
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ ├── yargs
│ │ ├── browser.d.ts
│ │ ├── browser.mjs
│ │ ├── build
│ │ │ ├── index.cjs
│ │ │ └── lib
│ │ │ ├── argsert.js
│ │ │ ├── command.js
│ │ │ ├── completion-templates.js
│ │ │ ├── completion.js
│ │ │ ├── middleware.js
│ │ │ ├── parse-command.js
│ │ │ ├── typings
│ │ │ │ ├── common-types.js
│ │ │ │ └── yargs-parser-types.js
│ │ │ ├── usage.js
│ │ │ ├── utils
│ │ │ │ ├── apply-extends.js
│ │ │ │ ├── is-promise.js
│ │ │ │ ├── levenshtein.js
│ │ │ │ ├── maybe-async-result.js
│ │ │ │ ├── obj-filter.js
│ │ │ │ ├── process-argv.js
│ │ │ │ ├── set-blocking.js
│ │ │ │ └── which-module.js
│ │ │ ├── validation.js
│ │ │ ├── yargs-factory.js
│ │ │ └── yerror.js
│ │ ├── helpers
│ │ │ ├── helpers.mjs
│ │ │ ├── index.js
│ │ │ └── package.json
│ │ ├── index.cjs
│ │ ├── index.mjs
│ │ ├── lib
│ │ │ └── platform-shims
│ │ │ ├── browser.mjs
│ │ │ └── esm.mjs
│ │ ├── LICENSE
│ │ ├── locales
│ │ │ ├── be.json
│ │ │ ├── cs.json
│ │ │ ├── de.json
│ │ │ ├── en.json
│ │ │ ├── es.json
│ │ │ ├── fi.json
│ │ │ ├── fr.json
│ │ │ ├── hi.json
│ │ │ ├── hu.json
│ │ │ ├── id.json
│ │ │ ├── it.json
│ │ │ ├── ja.json
│ │ │ ├── ko.json
│ │ │ ├── nb.json
│ │ │ ├── nl.json
│ │ │ ├── nn.json
│ │ │ ├── pirate.json
│ │ │ ├── pl.json
│ │ │ ├── pt_BR.json
│ │ │ ├── pt.json
│ │ │ ├── ru.json
│ │ │ ├── th.json
│ │ │ ├── tr.json
│ │ │ ├── uk_UA.json
│ │ │ ├── uz.json
│ │ │ ├── zh_CN.json
│ │ │ └── zh_TW.json
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── yargs
│ │ └── yargs.mjs
│ ├── yargs-parser
│ │ ├── browser.js
│ │ ├── build
│ │ │ ├── index.cjs
│ │ │ └── lib
│ │ │ ├── index.js
│ │ │ ├── string-utils.js
│ │ │ ├── tokenize-arg-string.js
│ │ │ ├── yargs-parser-types.js
│ │ │ └── yargs-parser.js
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE.txt
│ │ ├── package.json
│ │ └── README.md
│ ├── zod
│ │ ├── index.d.ts
│ │ ├── lib
│ │ │ ├── __tests__
│ │ │ │ ├── Mocker.d.ts
│ │ │ │ └── Mocker.js
│ │ │ ├── benchmarks
│ │ │ │ ├── datetime.d.ts
│ │ │ │ ├── datetime.js
│ │ │ │ ├── discriminatedUnion.d.ts
│ │ │ │ ├── discriminatedUnion.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── ipv4.d.ts
│ │ │ │ ├── ipv4.js
│ │ │ │ ├── object.d.ts
│ │ │ │ ├── object.js
│ │ │ │ ├── primitives.d.ts
│ │ │ │ ├── primitives.js
│ │ │ │ ├── realworld.d.ts
│ │ │ │ ├── realworld.js
│ │ │ │ ├── string.d.ts
│ │ │ │ ├── string.js
│ │ │ │ ├── union.d.ts
│ │ │ │ └── union.js
│ │ │ ├── errors.d.ts
│ │ │ ├── errors.js
│ │ │ ├── external.d.ts
│ │ │ ├── external.js
│ │ │ ├── helpers
│ │ │ │ ├── enumUtil.d.ts
│ │ │ │ ├── enumUtil.js
│ │ │ │ ├── errorUtil.d.ts
│ │ │ │ ├── errorUtil.js
│ │ │ │ ├── parseUtil.d.ts
│ │ │ │ ├── parseUtil.js
│ │ │ │ ├── partialUtil.d.ts
│ │ │ │ ├── partialUtil.js
│ │ │ │ ├── typeAliases.d.ts
│ │ │ │ ├── typeAliases.js
│ │ │ │ ├── util.d.ts
│ │ │ │ └── util.js
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ ├── index.mjs
│ │ │ ├── index.umd.js
│ │ │ ├── locales
│ │ │ │ ├── en.d.ts
│ │ │ │ └── en.js
│ │ │ ├── standard-schema.d.ts
│ │ │ ├── standard-schema.js
│ │ │ ├── types.d.ts
│ │ │ ├── types.js
│ │ │ ├── ZodError.d.ts
│ │ │ └── ZodError.js
│ │ ├── LICENSE
│ │ ├── package.json
│ │ └── README.md
│ └── zod-to-json-schema
│ ├── .github
│ │ ├── CR_logotype-full-color.png
│ │ └── FUNDING.yml
│ ├── .prettierrc.json
│ ├── changelog.md
│ ├── contributing.md
│ ├── createIndex.ts
│ ├── dist
│ │ ├── cjs
│ │ │ ├── errorMessages.js
│ │ │ ├── index.js
│ │ │ ├── Options.js
│ │ │ ├── package.json
│ │ │ ├── parseDef.js
│ │ │ ├── parsers
│ │ │ │ ├── any.js
│ │ │ │ ├── array.js
│ │ │ │ ├── bigint.js
│ │ │ │ ├── boolean.js
│ │ │ │ ├── branded.js
│ │ │ │ ├── catch.js
│ │ │ │ ├── date.js
│ │ │ │ ├── default.js
│ │ │ │ ├── effects.js
│ │ │ │ ├── enum.js
│ │ │ │ ├── intersection.js
│ │ │ │ ├── literal.js
│ │ │ │ ├── map.js
│ │ │ │ ├── nativeEnum.js
│ │ │ │ ├── never.js
│ │ │ │ ├── null.js
│ │ │ │ ├── nullable.js
│ │ │ │ ├── number.js
│ │ │ │ ├── object.js
│ │ │ │ ├── optional.js
│ │ │ │ ├── pipeline.js
│ │ │ │ ├── promise.js
│ │ │ │ ├── readonly.js
│ │ │ │ ├── record.js
│ │ │ │ ├── set.js
│ │ │ │ ├── string.js
│ │ │ │ ├── tuple.js
│ │ │ │ ├── undefined.js
│ │ │ │ ├── union.js
│ │ │ │ └── unknown.js
│ │ │ ├── parseTypes.js
│ │ │ ├── Refs.js
│ │ │ ├── selectParser.js
│ │ │ └── zodToJsonSchema.js
│ │ ├── esm
│ │ │ ├── errorMessages.js
│ │ │ ├── index.js
│ │ │ ├── Options.js
│ │ │ ├── package.json
│ │ │ ├── parseDef.js
│ │ │ ├── parsers
│ │ │ │ ├── any.js
│ │ │ │ ├── array.js
│ │ │ │ ├── bigint.js
│ │ │ │ ├── boolean.js
│ │ │ │ ├── branded.js
│ │ │ │ ├── catch.js
│ │ │ │ ├── date.js
│ │ │ │ ├── default.js
│ │ │ │ ├── effects.js
│ │ │ │ ├── enum.js
│ │ │ │ ├── intersection.js
│ │ │ │ ├── literal.js
│ │ │ │ ├── map.js
│ │ │ │ ├── nativeEnum.js
│ │ │ │ ├── never.js
│ │ │ │ ├── null.js
│ │ │ │ ├── nullable.js
│ │ │ │ ├── number.js
│ │ │ │ ├── object.js
│ │ │ │ ├── optional.js
│ │ │ │ ├── pipeline.js
│ │ │ │ ├── promise.js
│ │ │ │ ├── readonly.js
│ │ │ │ ├── record.js
│ │ │ │ ├── set.js
│ │ │ │ ├── string.js
│ │ │ │ ├── tuple.js
│ │ │ │ ├── undefined.js
│ │ │ │ ├── union.js
│ │ │ │ └── unknown.js
│ │ │ ├── parseTypes.js
│ │ │ ├── Refs.js
│ │ │ ├── selectParser.js
│ │ │ └── zodToJsonSchema.js
│ │ └── types
│ │ ├── errorMessages.d.ts
│ │ ├── index.d.ts
│ │ ├── Options.d.ts
│ │ ├── parseDef.d.ts
│ │ ├── parsers
│ │ │ ├── any.d.ts
│ │ │ ├── array.d.ts
│ │ │ ├── bigint.d.ts
│ │ │ ├── boolean.d.ts
│ │ │ ├── branded.d.ts
│ │ │ ├── catch.d.ts
│ │ │ ├── date.d.ts
│ │ │ ├── default.d.ts
│ │ │ ├── effects.d.ts
│ │ │ ├── enum.d.ts
│ │ │ ├── intersection.d.ts
│ │ │ ├── literal.d.ts
│ │ │ ├── map.d.ts
│ │ │ ├── nativeEnum.d.ts
│ │ │ ├── never.d.ts
│ │ │ ├── null.d.ts
│ │ │ ├── nullable.d.ts
│ │ │ ├── number.d.ts
│ │ │ ├── object.d.ts
│ │ │ ├── optional.d.ts
│ │ │ ├── pipeline.d.ts
│ │ │ ├── promise.d.ts
│ │ │ ├── readonly.d.ts
│ │ │ ├── record.d.ts
│ │ │ ├── set.d.ts
│ │ │ ├── string.d.ts
│ │ │ ├── tuple.d.ts
│ │ │ ├── undefined.d.ts
│ │ │ ├── union.d.ts
│ │ │ └── unknown.d.ts
│ │ ├── parseTypes.d.ts
│ │ ├── Refs.d.ts
│ │ ├── selectParser.d.ts
│ │ └── zodToJsonSchema.d.ts
│ ├── dist-test
│ │ ├── cjs
│ │ │ ├── index.js
│ │ │ ├── node_modules
│ │ │ │ ├── .package-lock.json
│ │ │ │ └── zod
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── lib
│ │ │ │ │ ├── __tests__
│ │ │ │ │ │ ├── Mocker.d.ts
│ │ │ │ │ │ └── Mocker.js
│ │ │ │ │ ├── benchmarks
│ │ │ │ │ │ ├── datetime.d.ts
│ │ │ │ │ │ ├── datetime.js
│ │ │ │ │ │ ├── discriminatedUnion.d.ts
│ │ │ │ │ │ ├── discriminatedUnion.js
│ │ │ │ │ │ ├── index.d.ts
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── ipv4.d.ts
│ │ │ │ │ │ ├── ipv4.js
│ │ │ │ │ │ ├── object.d.ts
│ │ │ │ │ │ ├── object.js
│ │ │ │ │ │ ├── primitives.d.ts
│ │ │ │ │ │ ├── primitives.js
│ │ │ │ │ │ ├── realworld.d.ts
│ │ │ │ │ │ ├── realworld.js
│ │ │ │ │ │ ├── string.d.ts
│ │ │ │ │ │ ├── string.js
│ │ │ │ │ │ ├── union.d.ts
│ │ │ │ │ │ └── union.js
│ │ │ │ │ ├── errors.d.ts
│ │ │ │ │ ├── errors.js
│ │ │ │ │ ├── external.d.ts
│ │ │ │ │ ├── external.js
│ │ │ │ │ ├── helpers
│ │ │ │ │ │ ├── enumUtil.d.ts
│ │ │ │ │ │ ├── enumUtil.js
│ │ │ │ │ │ ├── errorUtil.d.ts
│ │ │ │ │ │ ├── errorUtil.js
│ │ │ │ │ │ ├── parseUtil.d.ts
│ │ │ │ │ │ ├── parseUtil.js
│ │ │ │ │ │ ├── partialUtil.d.ts
│ │ │ │ │ │ ├── partialUtil.js
│ │ │ │ │ │ ├── typeAliases.d.ts
│ │ │ │ │ │ ├── typeAliases.js
│ │ │ │ │ │ ├── util.d.ts
│ │ │ │ │ │ └── util.js
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── index.mjs
│ │ │ │ │ ├── index.umd.js
│ │ │ │ │ ├── locales
│ │ │ │ │ │ ├── en.d.ts
│ │ │ │ │ │ └── en.js
│ │ │ │ │ ├── standard-schema.d.ts
│ │ │ │ │ ├── standard-schema.js
│ │ │ │ │ ├── types.d.ts
│ │ │ │ │ ├── types.js
│ │ │ │ │ ├── ZodError.d.ts
│ │ │ │ │ └── ZodError.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ ├── package-lock.json
│ │ │ └── package.json
│ │ ├── esm
│ │ │ ├── index.js
│ │ │ ├── node_modules
│ │ │ │ ├── .package-lock.json
│ │ │ │ └── zod
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── lib
│ │ │ │ │ ├── __tests__
│ │ │ │ │ │ ├── Mocker.d.ts
│ │ │ │ │ │ └── Mocker.js
│ │ │ │ │ ├── benchmarks
│ │ │ │ │ │ ├── datetime.d.ts
│ │ │ │ │ │ ├── datetime.js
│ │ │ │ │ │ ├── discriminatedUnion.d.ts
│ │ │ │ │ │ ├── discriminatedUnion.js
│ │ │ │ │ │ ├── index.d.ts
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ ├── ipv4.d.ts
│ │ │ │ │ │ ├── ipv4.js
│ │ │ │ │ │ ├── object.d.ts
│ │ │ │ │ │ ├── object.js
│ │ │ │ │ │ ├── primitives.d.ts
│ │ │ │ │ │ ├── primitives.js
│ │ │ │ │ │ ├── realworld.d.ts
│ │ │ │ │ │ ├── realworld.js
│ │ │ │ │ │ ├── string.d.ts
│ │ │ │ │ │ ├── string.js
│ │ │ │ │ │ ├── union.d.ts
│ │ │ │ │ │ └── union.js
│ │ │ │ │ ├── errors.d.ts
│ │ │ │ │ ├── errors.js
│ │ │ │ │ ├── external.d.ts
│ │ │ │ │ ├── external.js
│ │ │ │ │ ├── helpers
│ │ │ │ │ │ ├── enumUtil.d.ts
│ │ │ │ │ │ ├── enumUtil.js
│ │ │ │ │ │ ├── errorUtil.d.ts
│ │ │ │ │ │ ├── errorUtil.js
│ │ │ │ │ │ ├── parseUtil.d.ts
│ │ │ │ │ │ ├── parseUtil.js
│ │ │ │ │ │ ├── partialUtil.d.ts
│ │ │ │ │ │ ├── partialUtil.js
│ │ │ │ │ │ ├── typeAliases.d.ts
│ │ │ │ │ │ ├── typeAliases.js
│ │ │ │ │ │ ├── util.d.ts
│ │ │ │ │ │ └── util.js
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── index.mjs
│ │ │ │ │ ├── index.umd.js
│ │ │ │ │ ├── locales
│ │ │ │ │ │ ├── en.d.ts
│ │ │ │ │ │ └── en.js
│ │ │ │ │ ├── standard-schema.d.ts
│ │ │ │ │ ├── standard-schema.js
│ │ │ │ │ ├── types.d.ts
│ │ │ │ │ ├── types.js
│ │ │ │ │ ├── ZodError.d.ts
│ │ │ │ │ └── ZodError.js
│ │ │ │ ├── LICENSE
│ │ │ │ ├── package.json
│ │ │ │ └── README.md
│ │ │ ├── package-lock.json
│ │ │ └── package.json
│ │ ├── package.json
│ │ └── types
│ │ ├── index.ts
│ │ ├── node_modules
│ │ │ ├── .package-lock.json
│ │ │ └── zod
│ │ │ ├── index.d.ts
│ │ │ ├── lib
│ │ │ │ ├── __tests__
│ │ │ │ │ ├── Mocker.d.ts
│ │ │ │ │ └── Mocker.js
│ │ │ │ ├── benchmarks
│ │ │ │ │ ├── datetime.d.ts
│ │ │ │ │ ├── datetime.js
│ │ │ │ │ ├── discriminatedUnion.d.ts
│ │ │ │ │ ├── discriminatedUnion.js
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── ipv4.d.ts
│ │ │ │ │ ├── ipv4.js
│ │ │ │ │ ├── object.d.ts
│ │ │ │ │ ├── object.js
│ │ │ │ │ ├── primitives.d.ts
│ │ │ │ │ ├── primitives.js
│ │ │ │ │ ├── realworld.d.ts
│ │ │ │ │ ├── realworld.js
│ │ │ │ │ ├── string.d.ts
│ │ │ │ │ ├── string.js
│ │ │ │ │ ├── union.d.ts
│ │ │ │ │ └── union.js
│ │ │ │ ├── errors.d.ts
│ │ │ │ ├── errors.js
│ │ │ │ ├── external.d.ts
│ │ │ │ ├── external.js
│ │ │ │ ├── helpers
│ │ │ │ │ ├── enumUtil.d.ts
│ │ │ │ │ ├── enumUtil.js
│ │ │ │ │ ├── errorUtil.d.ts
│ │ │ │ │ ├── errorUtil.js
│ │ │ │ │ ├── parseUtil.d.ts
│ │ │ │ │ ├── parseUtil.js
│ │ │ │ │ ├── partialUtil.d.ts
│ │ │ │ │ ├── partialUtil.js
│ │ │ │ │ ├── typeAliases.d.ts
│ │ │ │ │ ├── typeAliases.js
│ │ │ │ │ ├── util.d.ts
│ │ │ │ │ └── util.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── index.mjs
│ │ │ │ ├── index.umd.js
│ │ │ │ ├── locales
│ │ │ │ │ ├── en.d.ts
│ │ │ │ │ └── en.js
│ │ │ │ ├── standard-schema.d.ts
│ │ │ │ ├── standard-schema.js
│ │ │ │ ├── types.d.ts
│ │ │ │ ├── types.js
│ │ │ │ ├── ZodError.d.ts
│ │ │ │ └── ZodError.js
│ │ │ ├── LICENSE
│ │ │ ├── package.json
│ │ │ └── README.md
│ │ ├── package-lock.json
│ │ └── package.json
│ ├── LICENSE
│ ├── package.json
│ ├── postcjs.ts
│ ├── postesm.ts
│ ├── README.md
│ └── SECURITY.md
├── package-lock.json
├── package.json
├── README.md
├── run-mcp.sh
├── seo-mcp-server.js
├── seo-requirements.js
└── src
├── analyzers
│ ├── html-analyzer.js
│ └── keyword-analyzer.js
├── formatters
│ └── text-formatter.js
├── server.js
└── utils
└── file-utils.js
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
# Dependencies
/node_modules
/.pnp
.pnp.js
# Testing
/coverage
# Production
/build
/dist
# Misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
logs
*.log
# Editor directories and files
.idea
.vscode
*.swp
*.swo
.DS_Store
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
// README.md - Instructions for setup and use
# SEO Inspector & Schema Validator MCP
A Model Context Protocol (MCP) server for Cursor that analyzes web pages for SEO issues and validates structured data schemas.
## Features
- Analyze HTML files in a codebase for SEO issues
- Validate JSON-LD structured data
- Get recommendations to improve SEO
- No browser extension required - works directly with your codebase
## Installation
1. Clone this repository:
```
git clone https://github.com/yourusername/seo-inspector-mcp.git
cd seo-inspector-mcp
```
2. Install dependencies:
```
npm install
```
3. Configure Cursor to use this MCP server:
- Go to Settings > Features > MCP in Cursor
- Add a new MCP server with:
- Name: SEO Inspector
- Type: sse
- URL: http://localhost:8767/sse
## Usage
1. Start the MCP server:
```
./run-mcp.sh
```
2. In Cursor, you can now use the SEO Inspector tools:
- `seo.analyze-codebase` - Analyze HTML files in a directory
- `seo.analyze-html` - Analyze a specific HTML string
## Prioritized SEO Components
The tool checks for these key SEO elements (in order of importance):
### Critical
- Page Title
- Meta Description
- H1 Heading
- Canonical URL
### Important
- Heading Structure (H2-H6)
- Image Alt Text
- Structured Data (JSON-LD)
- Robots Directives
### Recommended
- Open Graph Tags
- Twitter Cards
- Internal Linking
- URL Structure
- Mobile Friendliness
## Schema Validation
The tool validates the following schema types:
- Organization
- LocalBusiness
- Product
- Article
- WebPage
- FAQPage
- Event
- Recipe
- Review
## License
MIT
```
--------------------------------------------------------------------------------
/.cursor/mcp.json:
--------------------------------------------------------------------------------
```json
{
"mcpServers": {
"seo-inspector": {
"url": "http://localhost:8768/sse"
}
}
}
```
--------------------------------------------------------------------------------
/run-mcp.sh:
--------------------------------------------------------------------------------
```bash
#!/bin/bash
# Script to start the MCP server
npx supergateway --port 8768 --stdio "node ./src/server.js"
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "seo-inspector-mcp",
"version": "1.0.0",
"description": "SEO Inspector and Schema Validator MCP for Cursor",
"main": "src/server.js",
"type": "module",
"scripts": {
"start": "node src/server.js",
"start-mcp": "npx supergateway --port 8768 --stdio \"node src/server.js\"",
"seo-analysis": "npx supergateway --port 8768 --stdio \"node src/server.js\""
},
"dependencies": {
"cheerio": "^1.0.0-rc.12",
"cors": "^2.8.5",
"express": "^4.18.2",
"puppeteer": "^19.7.2",
"supergateway": "*"
}
}
```
--------------------------------------------------------------------------------
/src/utils/file-utils.js:
--------------------------------------------------------------------------------
```javascript
// src/utils/file-utils.js
import fs from 'fs/promises';
import path from 'path';
export async function findHtmlFiles(directory) {
const htmlFiles = [];
// Check if directory exists first
try {
await fs.access(directory);
} catch (error) {
console.error(`Directory does not exist: ${directory}`);
return htmlFiles; // Return empty array instead of crashing
}
async function traverse(dir) {
try {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.name === 'node_modules' || entry.name === '.git') {
continue;
}
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
await traverse(fullPath);
} else if (
entry.name.endsWith('.html') ||
entry.name.endsWith('.htm')
) {
htmlFiles.push(fullPath);
}
}
} catch (error) {
console.error(`Error traversing ${dir}:`, error);
// Continue execution instead of crashing
}
}
await traverse(directory);
return htmlFiles;
}
```
--------------------------------------------------------------------------------
/mcp-tools.js:
--------------------------------------------------------------------------------
```javascript
// mcp-tools.js - The interface for Cursor MCP
const MCP_TOOLS = {
namespace: 'seo',
displayName: 'SEO Inspector',
description: 'Analyze web pages for SEO issues and validate structured data',
tools: [
{
name: 'analyze-codebase',
description: 'Scan HTML files in a directory for SEO issues',
parameters: {
type: 'object',
properties: {
directoryPath: {
type: 'string',
description:
'Path to the directory containing HTML files to analyze',
},
},
required: ['directoryPath'],
},
handler: async ({ directoryPath }) => {
// This will be implemented in the MCP framework
// The actual implementation is in the /analyze-codebase endpoint
},
},
{
name: 'analyze-html',
description: 'Analyze a specific HTML string for SEO issues',
parameters: {
type: 'object',
properties: {
html: {
type: 'string',
description: 'HTML content to analyze',
},
url: {
type: 'string',
description: 'Optional URL for context',
},
},
required: ['html'],
},
handler: async ({ html, url }) => {
// This will be implemented in the MCP framework
// The actual implementation is in the /analyze-html endpoint
},
},
],
};
module.exports = MCP_TOOLS;
```
--------------------------------------------------------------------------------
/src/formatters/text-formatter.js:
--------------------------------------------------------------------------------
```javascript
// src/formatters/text-formatter.js
export function formatAnalysisResult(result) {
return `SEO ANALYSIS FOR: ${result.pageIdentifier}
PAGE INFO:
- Title: ${result.title || 'Missing'} (${
result.title ? result.title.length : 0
} chars)
- Meta Description: ${result.metaDescription || 'Missing'} (${
result.metaDescription ? result.metaDescription.length : 0
} chars)
- Heading Structure: H1: ${result.headingStructure.h1}, H2: ${
result.headingStructure.h2
}, H3: ${result.headingStructure.h3}
- Schema Count: ${result.schemaCount}
${
result.isReactApp ? '- React App: Yes (client-side rendering detected)' : ''
}
POTENTIAL TARGET KEYWORDS:
${
result.keywordAnalysis.phrases.length > 0
? `- Primary phrase: ${result.keywordAnalysis.phrases[0].phrase}
- Other phrases: ${result.keywordAnalysis.phrases
.slice(1)
.map((p) => p.phrase)
.join(', ')}`
: '- No clear target keywords detected'
}
ISSUES (sorted by impact):
${result.issues
.map(
(issue) =>
`- [${issue.severity.toUpperCase()}] [Impact: ${issue.impact}] ${
issue.message
}`
)
.join('\n')}
RECOMMENDATIONS (sorted by impact):
${result.recommendations
.map(
(rec) => `- [Impact: ${rec.impact}] ${rec.text}
Why: ${rec.reason}
How: ${rec.implementation}`
)
.join('\n\n')}
${
result.isReactApp
? '\nNOTE: This is a static HTML analysis. For JavaScript-heavy sites like React apps, the rendered content may differ from the static HTML.'
: ''
}`;
}
export function formatDirectoryAnalysisResults(results, directoryPath) {
// Implementation...
}
```
--------------------------------------------------------------------------------
/console-spy-mcp.js:
--------------------------------------------------------------------------------
```javascript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import http from 'http';
// Define the Console Spy tool
const CONSOLE_SPY_TOOL = {
name: 'getConsoleLogs',
description: 'Get console logs from the browser',
inputSchema: {
type: 'object',
properties: {},
required: [],
},
};
// Create the server
const server = new Server(
{
name: 'console-spy-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
// Handle tool listing requests
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [CONSOLE_SPY_TOOL],
}));
// Handle tool call requests
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === 'getConsoleLogs') {
try {
// Fetch logs from original MCP server
const logs = await fetchConsoleLogs();
return {
content: [
{
type: 'text',
text: logs.content,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `Error fetching console logs: ${error.message}`,
},
],
isError: true,
};
}
}
return {
content: [
{
type: 'text',
text: `Unknown tool: ${request.params.name}`,
},
],
isError: true,
};
});
// Function to fetch console logs
async function fetchConsoleLogs() {
return new Promise((resolve, reject) => {
http
.get('http://localhost:3333/mcp', (mcpRes) => {
let responseData = '';
mcpRes.on('data', (chunk) => {
responseData += chunk;
});
mcpRes.on('end', () => {
try {
const logs = JSON.parse(responseData);
resolve(logs);
} catch (error) {
reject(new Error('Failed to parse logs: ' + error.message));
}
});
})
.on('error', (error) => {
reject(new Error('Failed to fetch logs: ' + error.message));
});
});
}
// Start the server
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('Console Spy MCP Server running on stdio');
}
runServer().catch((error) => {
console.error('Fatal error running server:', error);
process.exit(1);
});
```
--------------------------------------------------------------------------------
/seo-requirements.js:
--------------------------------------------------------------------------------
```javascript
// seo-requirements.js - Prioritized list of SEO components to check
const SEO_REQUIREMENTS = {
critical: [
{
id: 'title',
name: 'Page Title',
description:
'Each page should have a unique, descriptive title between 30-60 characters',
impact: 'Critical for search engine rankings and click-through rates',
},
{
id: 'meta-description',
name: 'Meta Description',
description:
'Compelling summary of page content between 50-160 characters',
impact: 'Affects click-through rates from search results',
},
{
id: 'h1',
name: 'H1 Heading',
description:
'Each page should have exactly one H1 heading that describes the content',
impact: 'Important for search engines to understand page content',
},
{
id: 'canonical',
name: 'Canonical URL',
description: 'Specify the preferred URL for duplicate or similar content',
impact:
'Prevents duplicate content issues and consolidates ranking signals',
},
],
important: [
{
id: 'heading-structure',
name: 'Heading Structure',
description: 'Proper use of H2-H6 headings to create content hierarchy',
impact:
'Helps search engines understand content structure and importance',
},
{
id: 'img-alt',
name: 'Image Alt Text',
description: 'Descriptive alternative text for all non-decorative images',
impact: 'Improves accessibility and helps images rank in image search',
},
{
id: 'schema',
name: 'Structured Data',
description: 'JSON-LD schema markup for relevant entity types',
impact: 'Enables rich snippets and enhanced search features',
},
{
id: 'meta-robots',
name: 'Robots Directives',
description:
'Appropriate use of index/noindex and follow/nofollow directives',
impact: 'Controls how search engines crawl and index pages',
},
],
recommended: [
{
id: 'open-graph',
name: 'Open Graph Tags',
description: 'OG tags for title, description, image, and type',
impact: 'Controls how content appears when shared on social media',
},
{
id: 'twitter-cards',
name: 'Twitter Cards',
description: 'Twitter-specific metadata for shared content',
impact: 'Enhances appearance of links shared on Twitter',
},
{
id: 'internal-links',
name: 'Internal Linking',
description: 'Descriptive anchor text for internal links',
impact:
'Distributes page authority and helps search engines understand content relationships',
},
{
id: 'url-structure',
name: 'URL Structure',
description: 'Clean, descriptive URLs with keywords when relevant',
impact: 'Affects user experience and keyword relevance',
},
{
id: 'mobile-friendly',
name: 'Mobile Friendliness',
description: 'Responsive design and appropriate viewport settings',
impact: 'Critical for mobile search rankings',
},
],
};
module.exports = SEO_REQUIREMENTS;
```
--------------------------------------------------------------------------------
/src/analyzers/keyword-analyzer.js:
--------------------------------------------------------------------------------
```javascript
// src/analyzers/keyword-analyzer.js
import * as cheerio from 'cheerio';
// Simple stemming function (very basic, but works for common cases)
function simpleStem(word) {
word = word.toLowerCase();
// Handle common endings
if (word.endsWith('ing')) return word.slice(0, -3);
if (word.endsWith('ly')) return word.slice(0, -2);
if (word.endsWith('es')) return word.slice(0, -2);
if (word.endsWith('s')) return word.slice(0, -1);
if (word.endsWith('ed')) return word.slice(0, -2);
if (word.endsWith('er')) return word.slice(0, -2);
if (word.endsWith('ment')) return word.slice(0, -4);
if (word.endsWith('tion')) return word.slice(0, -4);
return word;
}
export function detectTargetKeywords(html, title, metaDescription) {
const $ = cheerio.load(html);
const bodyText = $('body').text().toLowerCase();
// Remove common words and keep only potential keywords
const commonWords = [
'a',
'an',
'the',
'and',
'or',
'but',
'in',
'on',
'at',
'to',
'for',
'with',
'by',
'about',
'as',
'of',
'from',
'is',
'are',
'was',
'were',
'be',
'been',
'being',
'have',
'has',
'had',
'do',
'does',
'did',
'will',
'would',
'should',
'could',
'can',
'may',
'might',
'must',
'shall',
'this',
'that',
'these',
'those',
'it',
'they',
'them',
'their',
'we',
'us',
'our',
'you',
'your',
'he',
'him',
'his',
'she',
'her',
'hers',
'i',
'me',
'my',
'mine',
'who',
'whom',
'whose',
'which',
'what',
'when',
'where',
'why',
'how',
'all',
'any',
'both',
'each',
'few',
'more',
'most',
'some',
'such',
'no',
'nor',
'not',
'only',
'own',
'same',
'so',
'than',
'too',
'very',
];
// Extract words from title, meta description, and headings
const titleWords = title ? title.toLowerCase().split(/\s+/) : [];
const metaWords = metaDescription
? metaDescription.toLowerCase().split(/\s+/)
: [];
const h1Words = [];
$('h1').each((i, el) => {
h1Words.push(...$(el).text().toLowerCase().split(/\s+/));
});
// Add h2 words collection
const h2Words = [];
$('h2').each((i, el) => {
h2Words.push(...$(el).text().toLowerCase().split(/\s+/));
});
// Combine all important words
const importantWords = [...titleWords, ...metaWords, ...h1Words, ...h2Words];
// Count word frequency in body text
const wordCounts = {};
const stemmedWordMap = {}; // Maps stemmed words to original forms
const words = bodyText.split(/\s+/);
const totalWords = words.length;
words.forEach((word) => {
// Clean the word (remove punctuation, etc.)
const cleanWord = word.replace(/[^\w\s]/g, '').trim();
if (cleanWord && cleanWord.length > 3 && !commonWords.includes(cleanWord)) {
// Get the stem of the word
const stemmed = simpleStem(cleanWord);
// Count the stemmed word
wordCounts[stemmed] = (wordCounts[stemmed] || 0) + 1;
// Keep track of the original form (use the most frequent one)
if (
!stemmedWordMap[stemmed] ||
words.filter((w) => w === cleanWord).length >
words.filter((w) => w === stemmedWordMap[stemmed]).length
) {
stemmedWordMap[stemmed] = cleanWord;
}
}
});
// Count 2-word phrases (potential keywords)
const phraseCounts = {};
const originalPhraseMap = {}; // Maps normalized phrases to original forms
for (let i = 0; i < words.length - 1; i++) {
const word1 = words[i].replace(/[^\w\s]/g, '').trim();
const word2 = words[i + 1].replace(/[^\w\s]/g, '').trim();
if (
word1 &&
word2 &&
word1.length > 2 &&
word2.length > 2 &&
!commonWords.includes(word1) &&
!commonWords.includes(word2)
) {
const phrase = `${word1} ${word2}`;
const normalizedPhrase = `${simpleStem(word1)} ${simpleStem(word2)}`;
phraseCounts[normalizedPhrase] =
(phraseCounts[normalizedPhrase] || 0) + 1;
// Keep track of the original form
if (!originalPhraseMap[normalizedPhrase]) {
originalPhraseMap[normalizedPhrase] = phrase;
}
}
}
// Prioritize words that appear in title, meta description, and h1
const scoredWords = Object.keys(wordCounts).map((stemmed) => {
let score = wordCounts[stemmed];
const originalWord = stemmedWordMap[stemmed];
// Boost score if word appears in important elements
const stemmedImportantWords = importantWords.map((w) => simpleStem(w));
if (stemmedImportantWords.includes(stemmed)) {
score += 10;
}
if (titleWords.map((w) => simpleStem(w)).includes(stemmed)) score += 10;
if (metaWords.map((w) => simpleStem(w)).includes(stemmed)) score += 5;
if (h1Words.map((w) => simpleStem(w)).includes(stemmed)) score += 8;
if (h2Words.map((w) => simpleStem(w)).includes(stemmed)) score += 6;
// Calculate density (for analysis only, not for recommendations)
const density = ((wordCounts[stemmed] / totalWords) * 100).toFixed(2);
return {
word: originalWord,
score,
density,
inTitle: titleWords.map((w) => simpleStem(w)).includes(stemmed),
inMetaDescription: metaWords.map((w) => simpleStem(w)).includes(stemmed),
inH1: h1Words.map((w) => simpleStem(w)).includes(stemmed),
inH2: h2Words.map((w) => simpleStem(w)).includes(stemmed),
};
});
// Prioritize phrases that appear in title, meta description, and h1
const scoredPhrases = Object.keys(phraseCounts).map((normalizedPhrase) => {
let score = phraseCounts[normalizedPhrase] * 1.5; // Phrases are more valuable than single words
const originalPhrase = originalPhraseMap[normalizedPhrase];
const phraseWords = normalizedPhrase.split(' ');
// Boost score if phrase appears in important elements
const inTitle =
title && phraseWords.every((pw) => title.toLowerCase().includes(pw));
const inMetaDescription =
metaDescription &&
phraseWords.every((pw) => metaDescription.toLowerCase().includes(pw));
if (inTitle) score += 15;
if (inMetaDescription) score += 10;
let inH1 = false;
$('h1').each((i, el) => {
const h1Text = $(el).text().toLowerCase();
if (phraseWords.every((pw) => h1Text.includes(pw))) {
inH1 = true;
}
});
let inH2 = false;
$('h2').each((i, el) => {
const h2Text = $(el).text().toLowerCase();
if (phraseWords.every((pw) => h2Text.includes(pw))) {
inH2 = true;
}
});
if (inH1) score += 12;
if (inH2) score += 8;
// Calculate density (for analysis only, not for recommendations)
const density = (
(phraseCounts[normalizedPhrase] / (totalWords - 1)) *
100
).toFixed(2);
return {
phrase: originalPhrase,
score,
density,
inTitle,
inMetaDescription,
inH1,
inH2,
};
});
// Sort by score and take top results
const topWords = scoredWords.sort((a, b) => b.score - a.score).slice(0, 5);
const topPhrases = scoredPhrases
.sort((a, b) => b.score - a.score)
.slice(0, 5);
// Add placement analysis for the top phrase
const placementAnalysis =
topPhrases.length > 0
? {
primaryPhrase: topPhrases[0].phrase,
inTitle: topPhrases[0].inTitle,
inMetaDescription: topPhrases[0].inMetaDescription,
inH1: topPhrases[0].inH1,
inH2: topPhrases[0].inH2,
missingFrom: [],
}
: null;
if (!placementAnalysis.inTitle) placementAnalysis.missingFrom.push('title');
if (!placementAnalysis.inMetaDescription)
placementAnalysis.missingFrom.push('meta description');
if (!placementAnalysis.inH1) placementAnalysis.missingFrom.push('H1 heading');
if (!placementAnalysis.inH2)
placementAnalysis.missingFrom.push('H2 headings');
return {
singleWords: topWords,
phrases: topPhrases,
placementAnalysis,
keywordSummary: {
primaryPhrase: topPhrases.length > 0 ? topPhrases[0].phrase : null,
secondaryPhrases: topPhrases.slice(1, 3).map((p) => p.phrase),
topSingleWords: topWords.slice(0, 3).map((w) => w.word),
},
};
}
```
--------------------------------------------------------------------------------
/cs-mcp-server.js:
--------------------------------------------------------------------------------
```javascript
console.log('Starting MCP server initialization...');
try {
console.log('Loading express...');
const express = require('express');
console.log('Express loaded successfully');
console.log('Loading cors...');
const cors = require('cors');
console.log('CORS loaded successfully');
console.log('Creating express app...');
const app = express();
console.log('Express app created');
const port = 3333;
// In-memory storage for logs with improved structure
const sessions = {};
const MAX_LOGS_PER_SESSION = 500; // Increased from 100
console.log('Setting up middleware...');
app.use(
cors({
origin: '*', // Allow all origins
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
credentials: true,
preflightContinue: false,
optionsSuccessStatus: 204,
})
);
console.log('CORS middleware added');
app.use(express.json({ limit: '1mb' }));
console.log('JSON middleware added');
// Add a simple root route with strict CSP
app.get('/', (req, res) => {
console.log('Root endpoint hit');
// Set strict Content-Security-Policy header
res.setHeader(
'Content-Security-Policy',
"default-src 'self'; style-src 'unsafe-inline'; script-src 'unsafe-inline'"
);
res.send(`
<html>
<head>
<title>Console to Cursor MCP</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 { color: #333; }
p { line-height: 1.6; }
code {
background: #f4f4f4;
padding: 2px 5px;
border-radius: 3px;
font-family: monospace;
}
button {
background: #4CAF50;
border: none;
color: white;
padding: 10px 15px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 4px;
}
.manual-logging {
margin-top: 30px;
padding: 15px;
background: #f9f9f9;
border: 1px solid #ddd;
border-radius: 5px;
}
</style>
</head>
<body>
<h1>Console to Cursor MCP</h1>
<p>This server is running correctly. Available endpoints:</p>
<ul>
<li><code>/console-logs</code> - POST endpoint for receiving logs from browser extension</li>
<li><code>/mcp</code> - GET endpoint for Cursor to retrieve logs</li>
<li><code>/test</code> - GET endpoint for testing server connectivity</li>
<li><code>/view-logs</code> - GET endpoint for viewing logs in browser</li>
</ul>
<h2>Test Console Logging</h2>
<p>Click the button below to test console logging:</p>
<button id="test-log">Test Console Log</button>
<div class="manual-logging">
<h2>Manual Logging</h2>
<p>If automatic console capture isn't working, you can use these manual logging functions:</p>
<ul>
<li><code>window.mcpLog("Your message here")</code> - Send a log message</li>
<li><code>window.mcpWarn("Your warning here")</code> - Send a warning message</li>
<li><code>window.mcpError("Your error here")</code> - Send an error message</li>
</ul>
<p>Example: Open your browser console and type <code>mcpLog("Hello from manual logging")</code></p>
</div>
<script>
document.getElementById('test-log').addEventListener('click', function() {
console.log('Test log from button click', new Date().toISOString());
console.warn('Test warning from button click');
console.error('Test error from button click');
alert('Test logs sent! Check the /view-logs endpoint to see them.');
});
</script>
</body>
</html>
`);
});
console.log('Setting up /console-logs endpoint...');
// Endpoint to receive logs from browser extension
app.post('/console-logs', (req, res) => {
console.log('Received request to /console-logs');
try {
const { logs, sessionId, url } = req.body;
if (!logs || !sessionId || !url) {
console.log('Missing required fields in request');
return res
.status(400)
.json({ success: false, error: 'Missing required fields' });
}
// Log the content for debugging
logs.forEach((log) => {
console.log(`Received ${log.type} log from ${url}:`, log.content);
});
if (!sessions[sessionId]) {
sessions[sessionId] = {
logs: [],
url: url,
firstSeen: new Date(),
lastSeen: new Date(),
};
} else {
sessions[sessionId].lastSeen = new Date();
}
// Add new logs
sessions[sessionId].logs.push(...logs);
// Trim if too many
if (sessions[sessionId].logs.length > MAX_LOGS_PER_SESSION) {
sessions[sessionId].logs = sessions[sessionId].logs.slice(
-MAX_LOGS_PER_SESSION
);
}
res.json({ success: true, logCount: sessions[sessionId].logs.length });
} catch (error) {
console.error('Error processing /console-logs request:', error);
res.status(500).json({ success: false, error: 'Server error' });
}
});
console.log('Setting up /mcp endpoint...');
// MCP endpoint for Cursor
app.get('/mcp', (req, res) => {
try {
// Get all sessions sorted by last activity
const allSessions = Object.values(sessions).sort(
(a, b) => new Date(b.lastSeen) - new Date(a.lastSeen)
);
if (allSessions.length === 0) {
return res.json({
content:
'No console logs captured. Toggle the Console to Cursor extension on your localhost tab.',
});
}
// Use the most recently active session
const activeSession = allSessions[0];
// Format logs for Cursor
const formattedLogs = activeSession.logs
.map(
(log) =>
`[${log.timestamp}] ${log.type.toUpperCase()}: ${JSON.stringify(
log.content
)}`
)
.join('\n');
// Make sure we're returning the exact format Cursor expects
res.json({
content: `Console logs from ${activeSession.url} (${activeSession.logs.length} logs):\n\n${formattedLogs}`,
});
} catch (error) {
console.error('Error processing /mcp request:', error);
res.status(200).json({
// Still return 200 with error message
content: 'Error retrieving logs: ' + error.message,
});
}
});
// New endpoint to view logs in browser
app.get('/view-logs', (req, res) => {
try {
// Get all sessions sorted by last activity
const allSessions = Object.values(sessions).sort(
(a, b) => new Date(b.lastSeen) - new Date(a.lastSeen)
);
if (allSessions.length === 0) {
return res.send(`
<html>
<head>
<title>MCP Logs</title>
<style>
body { font-family: sans-serif; padding: 20px; }
h1 { color: #333; }
.refresh { margin-bottom: 20px; }
</style>
</head>
<body>
<h1>MCP Logs</h1>
<div class="refresh">
<button onclick="location.reload()">Refresh</button>
</div>
<p>No logs captured yet. Make sure the console capture script is running.</p>
<p><a href="/">Back to home</a></p>
</body>
</html>
`);
}
// Generate HTML for logs
let html = `
<html>
<head>
<title>MCP Logs</title>
<style>
body { font-family: sans-serif; padding: 20px; }
h1, h2 { color: #333; }
.refresh { margin-bottom: 20px; }
.log-entry { margin-bottom: 5px; font-family: monospace; white-space: pre-wrap; }
.log { color: black; }
.warn { color: orange; }
.error { color: red; }
.info { color: blue; }
.debug { color: gray; }
.timestamp { color: #666; font-size: 0.8em; }
.session { margin-bottom: 30px; border: 1px solid #ddd; padding: 15px; border-radius: 5px; }
.controls { margin-bottom: 20px; }
.controls button { margin-right: 10px; }
.log-content { max-height: 500px; overflow: auto; }
.filter { margin-bottom: 15px; }
.filter label { margin-right: 10px; }
.nav { margin-bottom: 20px; }
.nav a { margin-right: 15px; }
</style>
</head>
<body>
<h1>MCP Logs</h1>
<div class="nav">
<a href="/">Home</a>
<a href="/test">Test Server</a>
</div>
<div class="refresh">
<button onclick="location.reload()">Refresh</button>
<span>(Auto-refreshes every 5 seconds)</span>
<button onclick="window.location.href='/clear-logs'" style="margin-left: 20px; background-color: #f44336;">Clear All Logs</button>
</div>
<div class="filter">
<label><input type="checkbox" class="filter-type" value="log" checked> Logs</label>
<label><input type="checkbox" class="filter-type" value="warn" checked> Warnings</label>
<label><input type="checkbox" class="filter-type" value="error" checked> Errors</label>
<label><input type="checkbox" class="filter-type" value="info" checked> Info</label>
<label><input type="checkbox" class="filter-type" value="debug" checked> Debug</label>
</div>
`;
// Add each session
allSessions.forEach((session, index) => {
const firstSeen = new Date(session.firstSeen).toLocaleString();
const lastSeen = new Date(session.lastSeen).toLocaleString();
html += `
<div class="session">
<h2>Session ${index + 1}: ${session.url}</h2>
<p>First seen: ${firstSeen} | Last seen: ${lastSeen} | Total logs: ${
session.logs.length
}</p>
<div class="log-content">
`;
// Add logs
if (session.logs.length === 0) {
html += `<p>No logs in this session.</p>`;
} else {
session.logs.forEach((log) => {
const timestamp = new Date(log.timestamp).toLocaleTimeString();
let content;
try {
content = JSON.stringify(log.content, null, 2);
} catch (e) {
content = String(log.content);
}
html += `
<div class="log-entry ${log.type}" data-type="${log.type}">
<span class="timestamp">[${timestamp}]</span>
<span class="${log.type}">${log.type.toUpperCase()}:</span>
${content}
</div>
`;
});
}
html += `
</div>
</div>`;
});
html += `
<script>
// Auto-refresh every 5 seconds
setTimeout(() => {
location.reload();
}, 5000);
// Set up filtering
document.querySelectorAll('.filter-type').forEach(checkbox => {
checkbox.addEventListener('change', function() {
const type = this.value;
const checked = this.checked;
document.querySelectorAll(\`.log-entry[data-type="\${type}"]\`).forEach(entry => {
entry.style.display = checked ? 'block' : 'none';
});
});
});
</script>
</body>
</html>
`;
res.send(html);
} catch (error) {
console.error('Error generating logs view:', error);
res.status(500).send('Error generating logs view: ' + error.message);
}
});
app.listen(port, () => {
console.log(`MCP server is running on port ${port}`);
});
} catch (error) {
console.error('Error initializing MCP server:', error);
}
```
--------------------------------------------------------------------------------
/seo-mcp-server.js:
--------------------------------------------------------------------------------
```javascript
#!/usr/bin/env node
import * as cheerio from 'cheerio';
import fs from 'fs/promises';
import path from 'path';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
// Define the SEO tool
const SEO_ANALYZER_TOOL = {
name: 'analyzeSEO',
description:
'Analyzes HTML files for SEO issues and provides recommendations.',
inputSchema: {
type: 'object',
properties: {
html: {
type: 'string',
description: 'HTML content to analyze (optional)',
},
directoryPath: {
type: 'string',
description: 'Path to directory to analyze (optional)',
},
},
},
};
// Create the server
const server = new Server(
{
name: 'seo-inspector-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
// Handle tool listing requests
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [SEO_ANALYZER_TOOL],
}));
// Handle tool call requests
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === 'analyzeSEO') {
try {
// Handle HTML content analysis
if (request.params.arguments.html) {
const html = request.params.arguments.html;
const analysis = analyzeHtml(html, 'Provided HTML');
return {
content: [
{
type: 'text',
text: formatAnalysisResult(analysis),
},
],
};
}
// Handle directory analysis
else if (request.params.arguments.directoryPath) {
const directoryPath = request.params.arguments.directoryPath;
console.error(`Analyzing directory: ${directoryPath}`);
try {
// Check if directory exists
try {
await fs.access(directoryPath);
} catch (error) {
return {
content: [
{
type: 'text',
text: `Directory "${directoryPath}" does not exist or is not accessible. Please provide a valid directory path.`,
},
],
};
}
// Find HTML files
const htmlFiles = await findHtmlFiles(directoryPath);
if (htmlFiles.length === 0) {
// Look for index.html in common locations
const commonLocations = [
path.join(directoryPath, 'public', 'index.html'),
path.join(directoryPath, 'build', 'index.html'),
path.join(directoryPath, 'dist', 'index.html'),
path.join(directoryPath, 'index.html'),
];
for (const location of commonLocations) {
try {
await fs.access(location);
htmlFiles.push(location);
console.error(`Found index.html at ${location}`);
} catch (error) {
// File doesn't exist, continue checking
}
}
if (htmlFiles.length === 0) {
return {
content: [
{
type: 'text',
text: `No HTML files found in ${directoryPath} or common subdirectories (public, build, dist).
If this is a React project, please specify the path to the public or build directory, or provide the path to a specific HTML file.`,
},
],
};
}
}
// Analyze each HTML file
const results = [];
for (const file of htmlFiles) {
try {
const content = await fs.readFile(file, 'utf8');
const relativePath = path.relative(directoryPath, file);
const analysis = analyzeHtml(content, relativePath);
results.push(analysis);
} catch (error) {
console.error(`Error analyzing ${file}:`, error);
}
}
// Format and return results
return {
content: [
{
type: 'text',
text: formatDirectoryAnalysisResults(results, directoryPath),
},
],
};
} catch (error) {
console.error('Error analyzing directory:', error);
return {
content: [
{
type: 'text',
text: `Error analyzing directory: ${error.message}`,
},
],
isError: true,
};
}
} else {
return {
content: [
{
type: 'text',
text: 'Please provide either HTML content or a directory path to analyze.',
},
],
};
}
} catch (error) {
console.error('Error in analyzeSEO tool:', error);
return {
content: [
{
type: 'text',
text: `Error analyzing SEO: ${error.message}`,
},
],
isError: true,
};
}
}
});
// Find HTML files in a directory
async function findHtmlFiles(directory) {
const htmlFiles = [];
async function traverse(dir) {
try {
const entries = await fs.readdir(dir, { withFileTypes: true });
for (const entry of entries) {
if (entry.name === 'node_modules' || entry.name === '.git') {
continue;
}
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
await traverse(fullPath);
} else if (
entry.name.endsWith('.html') ||
entry.name.endsWith('.htm')
) {
htmlFiles.push(fullPath);
}
}
} catch (error) {
console.error(`Error traversing ${dir}:`, error);
}
}
await traverse(directory);
return htmlFiles;
}
// Analyze HTML content
function analyzeHtml(html, pageIdentifier) {
const $ = cheerio.load(html);
const issues = [];
const recommendations = [];
// Basic SEO checks
const title = $('title').text();
const metaDescription = $('meta[name="description"]').attr('content');
const h1Count = $('h1').length;
const h2Count = $('h2').length;
const h3Count = $('h3').length;
// Check for React-specific elements
const hasReactRoot =
$('#root').length > 0 ||
$('#app').length > 0 ||
$('[data-reactroot]').length > 0;
// Check title
if (!title) {
issues.push({ severity: 'high', message: 'Missing page title' });
recommendations.push('Add a descriptive page title');
} else if (title.length > 60) {
issues.push({
severity: 'medium',
message: `Title length (${title.length} chars) exceeds recommended maximum of 60 characters`,
});
recommendations.push('Shorten title to under 60 characters');
}
// Check meta description
if (!metaDescription) {
issues.push({ severity: 'high', message: 'Missing meta description' });
recommendations.push('Add a descriptive meta description');
} else if (metaDescription.length < 50 || metaDescription.length > 160) {
issues.push({
severity: 'medium',
message: `Meta description length (${metaDescription.length} chars) outside recommended range (50-160)`,
});
recommendations.push(
'Adjust meta description to be between 50-160 characters'
);
}
// Check headings
if (h1Count === 0) {
issues.push({ severity: 'high', message: 'No H1 heading found' });
recommendations.push('Add an H1 heading to your page');
} else if (h1Count > 1) {
issues.push({
severity: 'medium',
message: `Multiple H1 headings found (${h1Count})`,
});
recommendations.push('Use only one H1 heading per page');
}
// Check images
$('img').each((i, img) => {
const alt = $(img).attr('alt');
if (!alt && !$(img).attr('role')) {
issues.push({
severity: 'medium',
message: `Image missing alt text: ${
$(img).attr('src') || 'unknown image'
}`,
});
}
});
const imagesWithoutAlt = $('img:not([alt])').length;
if (imagesWithoutAlt > 0) {
recommendations.push('Add alt text to all images');
}
// Check for schema markup
const schemas = [];
$('script[type="application/ld+json"]').each((i, script) => {
try {
const schema = JSON.parse($(script).html());
schemas.push(schema);
} catch (e) {
issues.push({ severity: 'high', message: 'Invalid JSON-LD schema' });
}
});
if (schemas.length === 0) {
issues.push({
severity: 'medium',
message: 'No structured data (schema.org) found',
});
recommendations.push('Add structured data using JSON-LD');
}
// Check for canonical URL
if ($('link[rel="canonical"]').length === 0) {
issues.push({ severity: 'medium', message: 'Missing canonical URL tag' });
recommendations.push('Add a canonical URL tag');
}
// Check for viewport meta tag
if ($('meta[name="viewport"]').length === 0) {
issues.push({ severity: 'medium', message: 'Missing viewport meta tag' });
recommendations.push('Add a viewport meta tag for better mobile rendering');
}
// Check for social media tags
const hasOgTags = $('meta[property^="og:"]').length > 0;
const hasTwitterTags = $('meta[name^="twitter:"]').length > 0;
if (!hasOgTags) {
issues.push({ severity: 'low', message: 'Missing Open Graph meta tags' });
recommendations.push(
'Add Open Graph meta tags for better social media sharing'
);
}
if (!hasTwitterTags) {
issues.push({ severity: 'low', message: 'Missing Twitter Card meta tags' });
recommendations.push(
'Add Twitter Card meta tags for better Twitter sharing'
);
}
// React-specific recommendations
if (hasReactRoot) {
issues.push({
severity: 'info',
message:
'This appears to be a React application with client-side rendering',
});
recommendations.push(
'Consider using server-side rendering (Next.js) or static site generation (Gatsby) for better SEO'
);
recommendations.push(
'Note: This analysis is limited to the static HTML. The rendered content may differ.'
);
}
return {
pageIdentifier,
title,
metaDescription,
headingStructure: {
h1: h1Count,
h2: h2Count,
h3: h3Count,
},
schemaCount: schemas.length,
issues,
recommendations,
isReactApp: hasReactRoot,
};
}
// Format a single analysis result
function formatAnalysisResult(result) {
return `SEO ANALYSIS FOR: ${result.pageIdentifier}
PAGE INFO:
- Title: ${result.title || 'Missing'} (${
result.title ? result.title.length : 0
} chars)
- Meta Description: ${result.metaDescription || 'Missing'} (${
result.metaDescription ? result.metaDescription.length : 0
} chars)
- Heading Structure: H1: ${result.headingStructure.h1}, H2: ${
result.headingStructure.h2
}, H3: ${result.headingStructure.h3}
- Schema Count: ${result.schemaCount}
${result.isReactApp ? '- React App: Yes (client-side rendering detected)' : ''}
ISSUES:
${result.issues
.map((issue) => `- [${issue.severity.toUpperCase()}] ${issue.message}`)
.join('\n')}
RECOMMENDATIONS:
${result.recommendations.map((rec) => `- ${rec}`).join('\n')}
${
result.isReactApp
? '\nNOTE: This is a static HTML analysis. For JavaScript-heavy sites like React apps, the rendered content may differ from the static HTML.'
: ''
}`;
}
// Format directory analysis results
function formatDirectoryAnalysisResults(results, directoryPath) {
let output = `SEO ANALYSIS FOR DIRECTORY: ${directoryPath}\n\n`;
output += `Analyzed ${results.length} HTML files\n\n`;
// Count issues by severity
const issueCounts = {
high: 0,
medium: 0,
low: 0,
info: 0,
};
results.forEach((result) => {
result.issues.forEach((issue) => {
if (issue.severity in issueCounts) {
issueCounts[issue.severity]++;
}
});
});
output += `ISSUE SUMMARY:\n`;
output += `- High: ${issueCounts.high}\n`;
output += `- Medium: ${issueCounts.medium}\n`;
output += `- Low: ${issueCounts.low}\n`;
output += `- Info: ${issueCounts.info}\n\n`;
// Check if any React apps were detected
const reactApps = results.filter((r) => r.isReactApp);
if (reactApps.length > 0) {
output += `REACT APPLICATIONS DETECTED: ${reactApps.length} files\n`;
output += `Note: For React applications, this analysis is limited to the static HTML. The rendered content may differ.\n`;
output += `Consider using server-side rendering (Next.js) or static site generation (Gatsby) for better SEO.\n\n`;
}
// Individual file results
results.forEach((result, index) => {
output += `FILE ${index + 1}: ${result.pageIdentifier}\n`;
output += `- Title: ${result.title || 'Missing'} (${
result.title ? result.title.length : 0
} chars)\n`;
output += `- Meta Description: ${result.metaDescription || 'Missing'} (${
result.metaDescription ? result.metaDescription.length : 0
} chars)\n`;
output += `- Heading Structure: H1: ${result.headingStructure.h1}, H2: ${result.headingStructure.h2}, H3: ${result.headingStructure.h3}\n`;
output += `- Schema Count: ${result.schemaCount}\n`;
output += `- Issues: ${result.issues.length}\n\n`;
});
// Common recommendations
const allRecommendations = new Set();
results.forEach((result) => {
result.recommendations.forEach((rec) => {
allRecommendations.add(rec);
});
});
output += `COMMON RECOMMENDATIONS:\n`;
Array.from(allRecommendations).forEach((rec) => {
output += `- ${rec}\n`;
});
return output;
}
// Start the server
async function runServer() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('SEO Inspector MCP Server running on stdio');
}
runServer().catch((error) => {
console.error('Fatal error running server:', error);
process.exit(1);
});
```