🔀 repo-mcp-server: 默认分支改为 notion/shuangyan(Notion人格体专属分支)

This commit is contained in:
bingshuo 2026-05-14 01:37:24 +08:00
parent b6d94445ec
commit 953b79173b

View File

@ -29,6 +29,7 @@ const GITEA_TOKEN = process.env.GITEA_TOKEN;
const GITEA_URL = process.env.GITEA_URL || 'https://guanghulab.com';
const REPO_OWNER = process.env.REPO_OWNER || 'bingshuo';
const REPO_NAME = process.env.REPO_NAME || 'guanghulab';
const DEFAULT_BRANCH = process.env.REPO_DEFAULT_BRANCH || 'notion/shuangyan'; // Notion 人格体专属分支
// ─── 常量时间比较(防时序攻击) ───
function safeCompare(a, b) {
@ -92,9 +93,9 @@ function registerTools(server) {
server.tool(
'repo_read',
'读取仓库文件内容',
{ path: z.string().describe('文件路径,如 brain/progress.json'), branch: z.string().optional().describe('分支,默认 main') },
{ path: z.string().describe('文件路径,如 brain/progress.json'), branch: z.string().optional().describe('分支,默认 notion/shuangyan') },
async ({ path, branch }) => {
const data = await repoFetch(`/contents/${encodeURIComponent(path)}?ref=${branch || 'main'}`);
const data = await repoFetch(`/contents/${encodeURIComponent(path)}?ref=${branch || DEFAULT_BRANCH}`);
if (data.error) return { content: [{ type: 'text', text: `❌ 读取失败: ${data.message}` }] };
const content = Buffer.from(data.content, 'base64').toString('utf-8');
return { content: [{ type: 'text', text: content }] };
@ -109,10 +110,10 @@ function registerTools(server) {
path: z.string().describe('文件路径'),
content: z.string().describe('文件内容'),
message: z.string().describe('提交信息'),
branch: z.string().optional().describe('目标分支,默认 main')
branch: z.string().optional().describe('目标分支,默认 notion/shuangyan')
},
async ({ path, content, message, branch }) => {
const ref = branch || 'main';
const ref = branch || DEFAULT_BRANCH;
let sha = null;
const existing = await repoFetch(`/contents/${encodeURIComponent(path)}?ref=${ref}`);
if (!existing.error) sha = existing.sha;
@ -136,10 +137,10 @@ function registerTools(server) {
{
path: z.string().describe('文件路径'),
message: z.string().describe('提交信息'),
branch: z.string().optional().describe('分支,默认 main')
branch: z.string().optional().describe('分支,默认 notion/shuangyan')
},
async ({ path, message, branch }) => {
const ref = branch || 'main';
const ref = branch || DEFAULT_BRANCH;
const existing = await repoFetch(`/contents/${encodeURIComponent(path)}?ref=${ref}`);
if (existing.error) return { content: [{ type: 'text', text: `❌ 文件不存在: ${path}` }] };
@ -156,11 +157,11 @@ function registerTools(server) {
server.tool(
'repo_list',
'列出仓库目录内容',
{ path: z.string().optional().describe('目录路径,默认根目录'), branch: z.string().optional().describe('分支,默认 main') },
{ path: z.string().optional().describe('目录路径,默认根目录'), branch: z.string().optional().describe('分支,默认 notion/shuangyan') },
async ({ path, branch }) => {
const dir = path || '';
const urlPath = dir ? `/contents/${encodeURIComponent(dir)}` : '/contents';
const data = await repoFetch(`${urlPath}?ref=${branch || 'main'}`);
const data = await repoFetch(`${urlPath}?ref=${branch || DEFAULT_BRANCH}`);
if (data.error) return { content: [{ type: 'text', text: `❌ 列出失败: ${data.message}` }] };
if (!Array.isArray(data)) {
return { content: [{ type: 'text', text: `📄 ${dir || '/'} 是一个文件,请用 repo_read 读取` }] };
@ -236,12 +237,12 @@ function registerTools(server) {
title: z.string().describe('PR 标题'),
body: z.string().optional().describe('PR 描述'),
head: z.string().describe('源分支'),
base: z.string().optional().describe('目标分支,默认 main')
base: z.string().optional().describe('目标分支,默认 notion/shuangyan')
},
async ({ title, body, head, base }) => {
const result = await repoFetch('/pulls', {
method: 'POST',
body: JSON.stringify({ title, body: body || '', head, base: base || 'main' })
body: JSON.stringify({ title, body: body || '', head, base: base || DEFAULT_BRANCH })
});
if (result.error) return { content: [{ type: 'text', text: `❌ 创建 PR 失败: ${result.message}` }] };
return {
@ -325,12 +326,12 @@ function registerTools(server) {
'查看最近提交历史',
{
limit: z.number().optional().describe('数量,默认 10'),
branch: z.string().optional().describe('分支,默认 main')
branch: z.string().optional().describe('分支,默认 notion/shuangyan')
},
async ({ limit, branch }) => {
const data = await repoFetch(`/commits?sha=${branch || 'main'}&limit=${limit || 10}`);
const data = await repoFetch(`/commits?sha=${branch || DEFAULT_BRANCH}&limit=${limit || 10}`);
if (data.error) return { content: [{ type: 'text', text: `❌ 获取提交历史失败: ${data.message}` }] };
let output = `📜 最近提交 (${branch || 'main'}):\n\n`;
let output = `📜 最近提交 (${branch || DEFAULT_BRANCH}):\n\n`;
for (const c of data) {
const date = c.commit?.committer?.date?.slice(0, 10) || '';
const msg = (c.commit?.message || '').split('\n')[0];
@ -346,13 +347,13 @@ function registerTools(server) {
'递归列出目录结构(探索仓库骨架)',
{
path: z.string().optional().describe('起始路径,默认 brain'),
branch: z.string().optional().describe('分支,默认 main'),
branch: z.string().optional().describe('分支,默认 notion/shuangyan'),
depth: z.number().optional().describe('递归深度,默认 2最大 4')
},
async ({ path, branch, depth }) => {
const startPath = path || 'brain';
const maxDepth = Math.min(depth || 2, 4);
const ref = branch || 'main';
const ref = branch || DEFAULT_BRANCH;
async function walk(dirPath, currentDepth) {
if (currentDepth > maxDepth) return '';
@ -425,4 +426,4 @@ app.listen(PORT, () => {
console.log(`健康: http://localhost:${PORT}/health`);
console.log(`MCP: POST http://localhost:${PORT}/mcp`);
console.log(`认证: ${MCP_SECRET ? '✅ Bearer Token' : '⚠️ 本地模式(仅127.0.0.1)'}`);
});
});