mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
82 lines
2.6 KiB
JavaScript
82 lines
2.6 KiB
JavaScript
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const { test } = require('node:test');
|
|
|
|
const {
|
|
LOCAL_MCP_SERVER_CONFIG_SCHEMA,
|
|
normalizeLocalMcpServerConfig,
|
|
readLocalMcpServerConfig,
|
|
} = require('@qinglong/local-mcp-server/config');
|
|
|
|
function candidate(root) {
|
|
return {
|
|
schema: LOCAL_MCP_SERVER_CONFIG_SCHEMA,
|
|
profile: 'edge',
|
|
projectId: 'default',
|
|
deploymentRoot: root,
|
|
databasePath: path.join(root, 'data', 'qinglong3.sqlite'),
|
|
artifactRoot: path.join(root, 'artifacts'),
|
|
ownerPepperKeyringDirectory: path.join(root, 'owner-peppers'),
|
|
credentialFilePath: path.join(root, 'operator', 'credential.json'),
|
|
busyTimeoutMs: 500,
|
|
};
|
|
}
|
|
|
|
test('accepts an exact private MCP config with deployment-root descendants', (t) => {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-mcp-config-'));
|
|
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
fs.chmodSync(root, 0o700);
|
|
const filePath = path.join(root, 'mcp.json');
|
|
fs.writeFileSync(filePath, `${JSON.stringify(candidate(root))}\n`, {
|
|
mode: 0o600,
|
|
});
|
|
|
|
assert.deepEqual(readLocalMcpServerConfig(filePath), candidate(root));
|
|
});
|
|
|
|
test('rejects public config files, extra keys and authority paths outside deployment root', () => {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-mcp-config-bad-'));
|
|
try {
|
|
fs.chmodSync(root, 0o700);
|
|
const filePath = path.join(root, 'mcp.json');
|
|
fs.writeFileSync(filePath, `${JSON.stringify(candidate(root))}\n`, {
|
|
mode: 0o644,
|
|
});
|
|
assert.throws(() => readLocalMcpServerConfig(filePath), {
|
|
code: 'LOCAL_MCP_SERVER_CONFIG_INVALID',
|
|
});
|
|
assert.throws(
|
|
() => normalizeLocalMcpServerConfig({ ...candidate(root), extra: true }),
|
|
{ code: 'LOCAL_MCP_SERVER_CONFIG_INVALID' },
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
normalizeLocalMcpServerConfig({
|
|
...candidate(root),
|
|
schema: 'qinglong/local-mcp-server@v1',
|
|
}),
|
|
{ code: 'LOCAL_MCP_SERVER_CONFIG_INVALID' },
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
normalizeLocalMcpServerConfig({
|
|
...candidate(root),
|
|
credentialFilePath: path.join(os.tmpdir(), 'credential.json'),
|
|
}),
|
|
{ code: 'LOCAL_MCP_SERVER_CONFIG_INVALID' },
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
normalizeLocalMcpServerConfig({
|
|
...candidate(root),
|
|
artifactRoot: path.join(root, 'data', 'qinglong3.sqlite'),
|
|
}),
|
|
{ code: 'LOCAL_MCP_SERVER_CONFIG_INVALID' },
|
|
);
|
|
} finally {
|
|
fs.rmSync(root, { recursive: true, force: true });
|
|
}
|
|
});
|