| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- 'use strict';
- // Check the portable MCP contract without starting a server or printing credentials.
- const assert = require('node:assert/strict');
- const fs = require('node:fs');
- const path = require('node:path');
- const ROOT = path.resolve(__dirname, '..');
- function readJson(filePath) {
- return JSON.parse(fs.readFileSync(filePath, 'utf8').replace(/^\uFEFF/, ''));
- }
- function isAbsoluteLike(value) {
- const text = String(value || '').trim();
- return path.isAbsolute(text) || /^[A-Za-z]:[\\/]/.test(text) || /^\\\\/.test(text);
- }
- function checkConfig(filePath, { packageConfig = false } = {}) {
- assert(fs.existsSync(filePath), `缺少 MCP 配置:${filePath}`);
- const raw = fs.readFileSync(filePath, 'utf8');
- assert(!/(?:r:|sk-(?!ant-))[A-Za-z0-9._~+/=-]{6,}/i.test(raw), `MCP 配置疑似包含凭据:${filePath}`);
- const config = readJson(filePath);
- const entry = config?.mcpServers?.['qiwei-assistant'];
- assert(entry && typeof entry === 'object', `${filePath} 未注册 qiwei-assistant`);
- assert(Array.isArray(entry.args), `${filePath} args 必须是数组`);
- assert(typeof entry.command === 'string' && entry.command.trim(), `${filePath} 缺少 command`);
- assert(typeof entry.cwd === 'string' && entry.cwd.trim(), `${filePath} 缺少 cwd`);
- assert(!isAbsoluteLike(entry.cwd), `${filePath} cwd 不能依赖绝对路径`);
- for (const arg of entry.args) assert(!isAbsoluteLike(arg), `${filePath} args 不能依赖绝对路径`);
- for (const [key, value] of Object.entries(entry.env || {})) {
- assert(typeof value === 'string', `${filePath} env.${key} 必须是字符串`);
- assert(!isAbsoluteLike(value), `${filePath} env.${key} 不能依赖绝对路径`);
- }
- if (packageConfig) {
- assert(entry.args.includes('mcp'), `${filePath} 未配置 mcp 子命令`);
- assert(/^\.([\\/])qiwei-workbench(?:\.exe)?$/i.test(entry.command), `${filePath} 未指向包内工作台`);
- assert(entry.cwd === '.', `${filePath} 交付包 cwd 必须为 .`);
- assert(entry.env?.QIWEI_PACKAGE_ROOT === '.', `${filePath} 缺少包根环境标记`);
- } else {
- assert(entry.command === 'node', `${filePath} 开发配置应使用 PATH 中的 node`);
- assert(entry.args.includes('./mcp/src/server.js'), `${filePath} 开发配置未指向源码入口`);
- }
- return {
- status: 'ok',
- file: path.relative(ROOT, filePath).replace(/\\/g, '/'),
- server: 'qiwei-assistant',
- command: entry.command,
- portable: true,
- };
- }
- function main() {
- const packageDir = process.argv[2] ? path.resolve(process.argv[2]) : '';
- const results = [checkConfig(path.join(ROOT, '.mcp.json'))];
- if (packageDir) results.push(checkConfig(path.join(packageDir, '.mcp.json'), { packageConfig: true }));
- process.stdout.write(`${JSON.stringify({ status: 'ok', configs: results }, null, 2)}\n`);
- }
- try {
- main();
- } catch (error) {
- process.stderr.write(`${error.message}\n`);
- process.exit(1);
- }
|