npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

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

About

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

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

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

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

Open Software & Tools

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

© 2026 – Pkg Stats / Ryan Hefner

@cscec3b-mcp/dop-portal-mcp

v0.1.3

Published

DOP门户MCP

Readme

@cscec3b-mcp/dop-portal-mcp

DOP门户MCP

由 @cscec/create-dop-mcp 脚手架生成,基于 DOP MCP 模板(扫码登录与 token 管理由 @cscec/dop-mcp-tool 提供)。

目录结构

dop-portal-mcp/
├── package.json          # bin 指向 dist/index.cjs;发布自包含(dependencies 为空,esbuild 全内联)
├── scripts/
│   ├── lib.mjs           # 构建共用路径:buildTool()(tsc 编译共享库) + buildMcp()(esbuild 打包 + 复制 help-doc.md)
│   ├── build.mjs         # yarn build:产出自包含 dist/index.cjs
│   ├── inspect.mjs       # yarn dev:MCP Inspector 调试 + esbuild watch(改源码自动 rebuild,Inspector 里重连即生效)
│   ├── typecheck.mjs     # yarn typecheck:先编译共享库(.d.ts)再 tsc --noEmit
│   └── gen-json.mjs      # yarn gen-json [--env test|pre|prod]:生成 .mcp.npm.json(MCP 客户端配置,npx 拉发布包)
└── src/
    ├── index.ts          # 入口:第一行 import './base/env.js'(解析 --env/--dev-mode,必须最先);createServer() 里每行注册一个工具
    ├── help-doc.md       # help 工具返回的文档:公共鉴权 + 各场景 SOP,新增业务场景时追加子章节
    ├── base/             # 基建层(被业务依赖、自身不依赖业务 service)
    │   ├── env.ts        # --env test|pre|prod + --dev-mode(日志)参数解析(Inspector 不继承父进程 env,用参数显式传;--dev 是 Inspector 保留字)
    │   ├── config.ts     # currentEnv() + 业务网关配置 ENV_BIZ_CONFIG(按环境切 apiBase/appId/tenant)
    │   ├── logger.ts     # JSON 追加日志到 cwd/mcp-dop-portal.log,仅 DEV_MODE=1 落盘(与 MCP_ENV 解耦)
    │   ├── http.ts       # 共用 axios 实例;拦截器统一注入 Authorization: bearer <iamToken>(实时读盘、临期自动续期)
    │   └── request.ts    # dopGet/dopPost/dopGetRaw:解 {code,success,message,data} 信封
    ├── service/          # 按接口域封装 REST 调用(纯函数,不碰 MCP)
    │   └── common.ts     # getUserInfo(biz /api/auth/getUserInfo)
    └── tools/            # 每个工具一个文件,导出 registerXxx(server)
        ├── help.ts                 # 返回 help-doc.md(+共享库文档)
        ├── portalQrLoginStart.ts   # 启动扫码登录(非阻塞,返回 loginUrl)
        ├── portalQrLoginWait.ts    # 阻塞等待扫码完成(登录态加密落盘)
        └── getUserInfo.ts          # 查当前用户与组织(未登录返回 loggedIn:false + 扫码指引)

快速开始

# 仓库根目录装依赖(yarn 1 workspaces,packages/* 自动纳入)
yarn install

# 调试:起 MCP Inspector(浏览器 UI)+ esbuild watch;改源码后 Inspector 里手动重连即可
yarn workspace @cscec3b-mcp/dop-portal-mcp dev

# 构建/类型检查
yarn workspace @cscec3b-mcp/dop-portal-mcp build
yarn workspace @cscec3b-mcp/dop-portal-mcp typecheck

环境由 MCP_ENV 决定(test|pre|prod,默认 prod),只切换后端域名;yarn dev 默认 test 并带 DEV_MODE=1。日志开关独立:DEV_MODE=1 才落盘(见 base/logger.ts,空/0 静默)。裸 node dist/index.cjs 不带参数回落 prod 且不写日志。

如何新增一个工具

  1. service 层:src/service/<域>.ts 封装 REST 调用——用 dopGet/dopPost(解 {code,success,message,data} 信封)或 dopGetRaw(不包信封的接口)。不要显式传 token,http.ts 拦截器统一注入。
  2. tool 层:src/tools/<工具名>.ts,导出 registerXxx(server: McpServer),用 zod 声明 inputSchema/outputSchema。声明了 outputSchema 就必须返回 structuredContent(SDK 强制)。参考 src/tools/getUserInfo.ts 的写法(含「未登录不算工具错误」的降级模式)。
  3. 注册:src/index.ts 的 createServer() 里加一行 registerXxx(server);。
  4. 文档:src/help-doc.md 追加场景章节(工具用途/入参约束/分页约定/展示要求)——这是给使用 MCP 的 AI 看的操作指引,工具描述里写「使用前先调用本 MCP 的 help_tool 查看文档」引导 AI 先读它。

改完跑 yarn typecheck;yarn dev 的 watch 会自动 rebuild(含 help-doc.md 复制),Inspector 里重连即生效。

关键约定 / 坑

  • esbuild 必须打成 CJS:axios 有动态 require,ESM bundle 会炸;bundle 里 import.meta.url 不可用——运行时定位文件用 process.cwd()/__dirname(见 logger.ts、tools/help.ts)。
  • MCP Inspector 不继承父进程 env:server 支持 --env <env> 与 --dev-mode(日志开关,等价 DEV_MODE=1)参数(src/base/env.ts 最先加载解析),inspect.mjs 把环境与日志开关写进启动命令。server 自定义参数避开 Inspector 保留字(--dev/-e/--config 等会被 Inspector 吃掉不透传)。
  • 19 位 snowflake ID 一律字符串透传(zod 用 z.string()):超 JS Number 安全整数,转数字精度丢失,后端查不到。
  • 日志不含 token:请求日志只记 method/url/params/body,不记 headers;日志文件仅 DEV_MODE=1 时落盘(与 MCP_ENV 解耦,prod 也可显式开)。
  • 登录态:扫码一次全场景通用,token 临期由共享库自动续期;任何工具返回 HTTP 401/402 或 token 无效 → 重新扫码登录 → 重试。
  • token 分工:业务工具只用 iamToken(拦截器注入);门户 token 只在共享库登录域内部使用,不出库。
  • 发布自包含:依赖全在 devDependencies(esbuild 内联),dependencies 为空;files: ["dist"],help-doc.md 靠 build 脚本复制进 dist——改文档要重新 yarn build。
  • yarn 1 的 .yarnrc 必须放各 package 目录(不向上查找),registry 指 https://registry.npmmirror.com。

发布

yarn workspace @cscec3b-mcp/dop-portal-mcp pub          # 发 alpha/当前 tag
yarn workspace @cscec3b-mcp/dop-portal-mcp pub-alpha    # 版本号 prerelease(alpha) + 发布
yarn workspace @cscec3b-mcp/dop-portal-mcp pub-release  # 版本号 patch + 发布 latest

发布前改 package.json 的 name/bin 为实际包名;registry 走 publishConfig.registry。