feat(§03): 实现 MCP Server 核心 - Storage/Service/Tool/MCP Protocol Layers
**Storage Layer:** - Database 类(aiosqlite + WAL + 并发保护) - WikiPage 数据模型 - fix_dirty_states 恢复机制 - FTS5 全文搜索支持 - 完整的 SQLite 表结构 **Service Layer:** - CacheService(LRU 缓存 + TTL + 大小限制) - QueryService(查询服务) - ParserService(Markdown 解析) - IndexerService(索引服务) - GraphService(链接图服务) **Tool Layer (8 个 MCP Tools):** - wiki_query - FTS5 全文搜索 + 标签过滤 - memory_bridge - 按工具来源浏览 - wiki_status - 索引状态 - wiki_lint - 健康审计 - cross_linker - 缺失链接发现 - tag_taxonomy - 标签一致性 - wiki_synthesize - 跨概念综合分析 - daily_update - 日常维护 + hot.md 生成 **MCP Protocol Layer:** - MCP 协议解析和封装 - 工具注册和路由 - 错误处理和日志 - stdio 模式支持 **配置和部署:** - requirements.txt - config.example.yaml - ecosystem.config.cjs (PM2) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
"""
|
||||
Tool Layer - daily_update 工具
|
||||
|
||||
日常维护(检查源新鲜度、更新 index、重新生成 hot.md)。
|
||||
|
||||
参考设计文档:第 2.2 节
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import Dict, Any
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from ..services import QueryService, IndexerService
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DailyUpdateTool:
|
||||
"""daily_update 工具实现"""
|
||||
|
||||
def __init__(self, query_service: QueryService, indexer_service: IndexerService):
|
||||
self.query_service = query_service
|
||||
self.indexer_service = indexer_service
|
||||
|
||||
async def handle(self) -> Dict[str, Any]:
|
||||
"""
|
||||
日常维护
|
||||
|
||||
Returns:
|
||||
{
|
||||
"updated": 5,
|
||||
"new": 2,
|
||||
"hot_md_generated": true,
|
||||
"index_status": {...}
|
||||
}
|
||||
"""
|
||||
# 1. 增量更新索引
|
||||
index_status = await self.indexer_service.incremental_update()
|
||||
|
||||
# 2. 获取最近更新的页面
|
||||
recent_pages = await self.query_service.db.get_recent_pages(days=7, limit=20)
|
||||
|
||||
# 3. 获取新增标签
|
||||
new_tags = await self.query_service.db.get_new_tags(days=7)
|
||||
|
||||
# 4. 查找孤立页面
|
||||
from ..services import GraphService
|
||||
graph_service = GraphService(self.query_service.db)
|
||||
orphans = await graph_service.find_orphans()
|
||||
|
||||
# 5. 生成 hot.md
|
||||
hot_md_generated = await self._generate_hot_md(recent_pages, new_tags, orphans)
|
||||
|
||||
return {
|
||||
"updated": len(recent_pages),
|
||||
"new": len(new_tags),
|
||||
"hot_md_generated": hot_md_generated,
|
||||
"index_status": index_status
|
||||
}
|
||||
|
||||
async def _generate_hot_md(self, recent_pages, new_tags, orphans) -> bool:
|
||||
"""生成热点文件"""
|
||||
try:
|
||||
# 确定 hot.md 保存路径
|
||||
vault_path = Path(self.query_service.db.path).parent.parent / "wiki-vault"
|
||||
hot_path = vault_path / "hot.md"
|
||||
|
||||
# 格式化内容
|
||||
content = f"""# Wiki Hot - {datetime.now().strftime('%Y-%m-%d')}
|
||||
|
||||
## 最近更新(7 天内)
|
||||
|
||||
"""
|
||||
for page in recent_pages[:10]:
|
||||
content += f"- [[{page.path}|{page.title}]] - {page.updated_at}\n"
|
||||
|
||||
content += "\n## 新增标签(7 天内)\n\n"
|
||||
for tag, updated_at in new_tags[:10]:
|
||||
content += f"- `{tag}` - {updated_at}\n"
|
||||
|
||||
content += "\n## 待链接页面(孤立页面)\n\n"
|
||||
for orphan in sorted(list(orphans))[:10]:
|
||||
content += f"- [[{orphan}]]\n"
|
||||
|
||||
# 写入文件
|
||||
with open(hot_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
|
||||
logger.info(f"Generated hot.md: {hot_path}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to generate hot.md: {e}")
|
||||
return False
|
||||
|
||||
def get_schema(self) -> dict:
|
||||
"""返回 MCP Tool schema"""
|
||||
return {
|
||||
"name": "daily_update",
|
||||
"description": "日常维护(检查源新鲜度、更新 index、重新生成 hot.md)",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user