Files
claude_dev dfd8421dc6 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>
2026-06-26 11:32:43 +08:00

113 lines
3.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Tool Layer - memory_bridge 工具
按 AI 工具来源浏览和对比 wiki 知识。
参考设计文档:第 2.2 节
"""
import logging
from typing import Dict, Any, Optional
from datetime import datetime
from ..services import QueryService
logger = logging.getLogger(__name__)
class MemoryBridgeTool:
"""memory_bridge 工具实现"""
def __init__(self, query_service: QueryService):
self.query_service = query_service
async def handle(self, tool_name: str = "claude", date_range: str = "") -> Dict[str, Any]:
"""
按 AI 工具来源浏览和对比 wiki 知识
Args:
tool_name: AI 工具名称(claude/web_reader/gitea/other
date_range: 日期范围(如 "2024-01-01:2024-12-31" 或空字符串表示不限)
Returns:
{
"entries": [
{
"path": "practices/moziplus-orchestration.md",
"title": "moziplus 编排实践",
"summary": "...",
"updated_at": "2024-06-15T10:30:00",
"relevance_score": 0.85
}
],
"total": 12,
"tool_name": "claude",
"date_range": "2024-01-01:2024-12-31"
}
"""
# 按工具来源搜索
pages = await self.query_service.search_by_source_tool(tool_name, limit=100)
# 按日期范围过滤
if date_range:
try:
start_str, end_str = date_range.split(":")
start_date = datetime.fromisoformat(start_str)
end_date = datetime.fromisoformat(end_str)
filtered = []
for page in pages:
updated = datetime.fromisoformat(page.updated_at)
if start_date <= updated <= end_date:
filtered.append(page)
pages = filtered
except Exception as e:
logger.warning(f"Invalid date_range format '{date_range}': {e}")
# 格式化结果
entries = []
for page in pages:
# 计算相关性分数(基于摘要长度和更新时间)
recency_days = (datetime.now() - datetime.fromisoformat(page.updated_at)).days
relevance_score = max(0.1, 1.0 - recency_days / 365) # 简单衰减
entries.append({
"path": page.path,
"title": page.title,
"summary": page.summary,
"updated_at": page.updated_at,
"relevance_score": round(relevance_score, 2)
})
# 按相关性排序
entries.sort(key=lambda x: x["relevance_score"], reverse=True)
return {
"entries": entries[:50], # 最多返回 50 条
"total": len(entries),
"tool_name": tool_name,
"date_range": date_range
}
def get_schema(self) -> dict:
"""返回 MCP Tool schema"""
return {
"name": "memory_bridge",
"description": "按 AI 工具来源浏览和对比 wiki 知识",
"inputSchema": {
"type": "object",
"properties": {
"tool_name": {
"type": "string",
"default": "claude",
"description": "AI 工具名称(claude/web_reader/gitea/other",
"enum": ["claude", "web_reader", "gitea", "other"]
},
"date_range": {
"type": "string",
"default": "",
"description": "日期范围,格式:YYYY-MM-DD:YYYY-MM-DD"
}
}
}
}