adbpg-mcp-server 1.0.8__py3-none-any.whl → 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- adbpg_mcp_server/__init__.py +0 -0
- adbpg_mcp_server/__main__.py +45 -0
- adbpg_mcp_server/adbpg.py +113 -0
- adbpg_mcp_server/adbpg_basic_operation.py +160 -0
- adbpg_mcp_server/adbpg_config.py +155 -0
- adbpg_mcp_server/adbpg_graphrag.py +197 -0
- adbpg_mcp_server/adbpg_memory.py +201 -0
- adbpg_mcp_server/server_http.py +206 -0
- adbpg_mcp_server/server_stdio.py +216 -0
- adbpg_mcp_server-2.0.0.dist-info/METADATA +278 -0
- adbpg_mcp_server-2.0.0.dist-info/RECORD +14 -0
- {adbpg_mcp_server-1.0.8.dist-info → adbpg_mcp_server-2.0.0.dist-info}/WHEEL +2 -1
- adbpg_mcp_server-2.0.0.dist-info/entry_points.txt +2 -0
- adbpg_mcp_server-2.0.0.dist-info/top_level.txt +1 -0
- adbpg_mcp_server-1.0.8.dist-info/METADATA +0 -10
- adbpg_mcp_server-1.0.8.dist-info/RECORD +0 -6
- adbpg_mcp_server-1.0.8.dist-info/entry_points.txt +0 -2
- adbpg_mcp_server-1.0.8.dist-info/licenses/LICENSE +0 -201
- adbpg_mcp_server.py +0 -1175
@@ -0,0 +1,201 @@
|
|
1
|
+
import json
|
2
|
+
import logging
|
3
|
+
from mcp.types import Tool, TextContent
|
4
|
+
from .adbpg import DatabaseManager
|
5
|
+
|
6
|
+
logger = logging.getLogger(__name__)
|
7
|
+
|
8
|
+
def get_memory_tools() -> list[Tool]:
|
9
|
+
return [
|
10
|
+
Tool(
|
11
|
+
name = "adbpg_llm_memory_add",
|
12
|
+
description = "Execute llm_memory add operation",
|
13
|
+
# 参数:messages json, user_id text, run_id text, agent_id text, metadata json
|
14
|
+
# 增加新的记忆
|
15
|
+
inputSchema={
|
16
|
+
"type": "object",
|
17
|
+
"properties": {
|
18
|
+
"messages": {
|
19
|
+
"type": "array",
|
20
|
+
"items": {
|
21
|
+
"type": "object",
|
22
|
+
"properties": {
|
23
|
+
"role": {"type": "string"},
|
24
|
+
"content": {"type": "string"}
|
25
|
+
},
|
26
|
+
"required": ["role", "content"]
|
27
|
+
},
|
28
|
+
"description": "List of messages objects (e.g., conversation history)"
|
29
|
+
},
|
30
|
+
"user_id": {
|
31
|
+
"type": "string",
|
32
|
+
"description": "the user_id"
|
33
|
+
},
|
34
|
+
"run_id": {
|
35
|
+
"type": "string",
|
36
|
+
"description": "the run_id"
|
37
|
+
},
|
38
|
+
"agent_id": {
|
39
|
+
"type": "string",
|
40
|
+
"description": "the agent_id"
|
41
|
+
},
|
42
|
+
"metadata": {
|
43
|
+
"type": "object",
|
44
|
+
"description": "the metatdata json"
|
45
|
+
},
|
46
|
+
"memory_type": {
|
47
|
+
"type": "string",
|
48
|
+
"description": "the memory_type text"
|
49
|
+
},
|
50
|
+
"prompt": {
|
51
|
+
"type": "string",
|
52
|
+
"description": "the prompt"
|
53
|
+
}
|
54
|
+
},
|
55
|
+
"required": ["messages"]
|
56
|
+
}
|
57
|
+
),
|
58
|
+
Tool(
|
59
|
+
name = "adbpg_llm_memory_get_all",
|
60
|
+
description = "Execute llm_memory get_all operation",
|
61
|
+
# 参数:user_id text, run_id text, agent_id text
|
62
|
+
# 获取某个用户或者某个agent的所有记忆
|
63
|
+
inputSchema={
|
64
|
+
"type": "object",
|
65
|
+
"properties": {
|
66
|
+
"user_id": {
|
67
|
+
"type": "string",
|
68
|
+
"description": "The user_id"
|
69
|
+
},
|
70
|
+
"run_id": {
|
71
|
+
"type": "string",
|
72
|
+
"description": "The run_id"
|
73
|
+
},
|
74
|
+
"agent_id": {
|
75
|
+
"type": "string",
|
76
|
+
"description": "The agent_id"
|
77
|
+
}
|
78
|
+
},
|
79
|
+
"required": []
|
80
|
+
}
|
81
|
+
),
|
82
|
+
Tool(
|
83
|
+
name = "adbpg_llm_memory_search",
|
84
|
+
description = "Execute llm_memory search operation",
|
85
|
+
# 参数:query text, user_id text, run_id text, agent_id text, filter json
|
86
|
+
# 获取与给定 query 相关的记忆
|
87
|
+
inputSchema={
|
88
|
+
"type": "object",
|
89
|
+
"properties": {
|
90
|
+
"query": {
|
91
|
+
"type": "string",
|
92
|
+
"description": "llm_memory relevant query"
|
93
|
+
},
|
94
|
+
"user_id": {
|
95
|
+
"type": "string",
|
96
|
+
"description": "The search of user_id"
|
97
|
+
},
|
98
|
+
"run_id": {
|
99
|
+
"type": "string",
|
100
|
+
"description": "The search of run_id"
|
101
|
+
},
|
102
|
+
"agent_id": {
|
103
|
+
"type": "string",
|
104
|
+
"description": "The search of agent_id"
|
105
|
+
},
|
106
|
+
"filter": {
|
107
|
+
"type": "object",
|
108
|
+
"description": "The search of filter"
|
109
|
+
}
|
110
|
+
},
|
111
|
+
"required": ["query"]
|
112
|
+
}
|
113
|
+
),
|
114
|
+
Tool(
|
115
|
+
name = "adbpg_llm_memory_delete_all",
|
116
|
+
description = "Execute llm_memory delete_all operation",
|
117
|
+
# 参数:user_id text, run_id text, agent_id text
|
118
|
+
# 删除某个用户或者agent的所有记忆
|
119
|
+
inputSchema={
|
120
|
+
"type": "object",
|
121
|
+
"properties": {
|
122
|
+
"user_id": {
|
123
|
+
"type": "string",
|
124
|
+
"description": "The user_id"
|
125
|
+
},
|
126
|
+
"run_id": {
|
127
|
+
"type": "string",
|
128
|
+
"description": "The run_id"
|
129
|
+
},
|
130
|
+
"agent_id": {
|
131
|
+
"type": "string",
|
132
|
+
"description": "The agent_id"
|
133
|
+
}
|
134
|
+
},
|
135
|
+
"required": []
|
136
|
+
}
|
137
|
+
)
|
138
|
+
]
|
139
|
+
|
140
|
+
def _execute_memory_tool(sql: str, params: list, db: DatabaseManager) -> list[TextContent]:
|
141
|
+
try:
|
142
|
+
conn = db.get_llm_memory_connection()
|
143
|
+
with conn.cursor() as cursor:
|
144
|
+
cursor.execute(sql, params)
|
145
|
+
if cursor.description:
|
146
|
+
json_result = cursor.fetchone()[0]
|
147
|
+
return [TextContent(type="text", text=json_result)]
|
148
|
+
else:
|
149
|
+
return [TextContent(type="text", text="LLM memory tool executed successfully.")]
|
150
|
+
except Exception as e:
|
151
|
+
return [TextContent(type="text", text=f"Error executing LLM memory tool: {str(e)}")]
|
152
|
+
|
153
|
+
|
154
|
+
async def call_memory_tool(name: str, arguments: dict, db: DatabaseManager) -> list[TextContent]:
|
155
|
+
"""调用 LLM Memory 工具"""
|
156
|
+
user_id = arguments.get("user_id")
|
157
|
+
run_id = arguments.get("run_id")
|
158
|
+
agent_id = arguments.get("agent_id")
|
159
|
+
|
160
|
+
if name == "adbpg_llm_memory_add":
|
161
|
+
messages = arguments.get("messages")
|
162
|
+
if not messages:
|
163
|
+
raise ValueError("messages is required")
|
164
|
+
if not any([user_id, run_id, agent_id]):
|
165
|
+
raise ValueError("At least one of user_id, run_id, or agent_id must be provided.")
|
166
|
+
sql = "SELECT adbpg_llm_memory.add(%s::json, %s::text, %s::text, %s::text, %s::json, %s::text, %s::text)"
|
167
|
+
params = [
|
168
|
+
json.dumps(messages, ensure_ascii=False),
|
169
|
+
user_id, run_id, agent_id,
|
170
|
+
json.dumps(arguments.get("metadata"),ensure_ascii=False) if arguments.get("metadata") else None,
|
171
|
+
arguments.get("memory_type"),
|
172
|
+
arguments.get("prompt")
|
173
|
+
]
|
174
|
+
|
175
|
+
elif name == "adbpg_llm_memory_search":
|
176
|
+
query = arguments.get("query")
|
177
|
+
if not query:
|
178
|
+
raise ValueError("query is required")
|
179
|
+
if not any([user_id, run_id, agent_id]):
|
180
|
+
raise ValueError("At least one of user_id, run_id, or agent_id must be provided.")
|
181
|
+
sql = "SELECT adbpg_llm_memory.search(%s::text, %s::text, %s::text, %s::text, %s::json)"
|
182
|
+
params = [
|
183
|
+
query, user_id, run_id, agent_id,
|
184
|
+
json.dumps(arguments.get("filter"), ensure_ascii=False) if arguments.get("filter") else None
|
185
|
+
]
|
186
|
+
|
187
|
+
elif name == "adbpg_llm_memory_get_all":
|
188
|
+
if not any([user_id, run_id, agent_id]):
|
189
|
+
raise ValueError("At least one of user_id, run_id, or agent_id must be provided.")
|
190
|
+
sql = "SELECT adbpg_llm_memory.get_all(%s::text, %s::text, %s::text)"
|
191
|
+
params = [user_id, run_id, agent_id]
|
192
|
+
|
193
|
+
elif name == "adbpg_llm_memory_delete_all":
|
194
|
+
if not any([user_id, run_id, agent_id]):
|
195
|
+
raise ValueError("At least one of user_id, run_id, or agent_id must be provided.")
|
196
|
+
sql = "SELECT adbpg_llm_memory.delete_all(%s::text, %s::text, %s::text)"
|
197
|
+
params = [user_id, run_id, agent_id]
|
198
|
+
else:
|
199
|
+
raise ValueError(f"Unknown memory tool: {name}")
|
200
|
+
|
201
|
+
return _execute_memory_tool(sql, params, db)
|
@@ -0,0 +1,206 @@
|
|
1
|
+
import requests
|
2
|
+
import logging
|
3
|
+
import json
|
4
|
+
import click
|
5
|
+
import contextlib
|
6
|
+
import uvicorn
|
7
|
+
import sys
|
8
|
+
import mcp.types as types
|
9
|
+
from pydantic import AnyUrl
|
10
|
+
from collections.abc import AsyncIterator
|
11
|
+
from mcp.server.lowlevel import Server
|
12
|
+
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
|
13
|
+
from mcp.types import Resource, Tool, TextContent, ResourceTemplate
|
14
|
+
from starlette.applications import Starlette
|
15
|
+
from starlette.routing import Mount
|
16
|
+
from .adbpg import DatabaseManager
|
17
|
+
from . import adbpg_basic_operation, adbpg_graphrag, adbpg_memory
|
18
|
+
from .adbpg_config import settings
|
19
|
+
|
20
|
+
|
21
|
+
db_manager: DatabaseManager | None = None
|
22
|
+
graphrag_is_available = False
|
23
|
+
llm_memory_is_available = False
|
24
|
+
|
25
|
+
logging.basicConfig(
|
26
|
+
level=logging.DEBUG,
|
27
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
28
|
+
)
|
29
|
+
logger = logging.getLogger("ADBPG MCP Server")
|
30
|
+
|
31
|
+
def initialize_services():
|
32
|
+
"""初始化数据库、GraphRAG 和 LLM Memory"""
|
33
|
+
global db_manager, graphrag_is_available, llm_memory_is_available
|
34
|
+
|
35
|
+
if not settings.db_env_ready:
|
36
|
+
logger.error("Cannot start server: Database environment is not configured.")
|
37
|
+
sys.exit(1)
|
38
|
+
|
39
|
+
db_manager = DatabaseManager(settings)
|
40
|
+
|
41
|
+
# 测试主连接
|
42
|
+
try:
|
43
|
+
db_manager.get_basic_connection()
|
44
|
+
logger.info("Successfully connected to database.")
|
45
|
+
except Exception as e:
|
46
|
+
logger.error(f"Failed to connect to database: {e}")
|
47
|
+
sys.exit(1)
|
48
|
+
|
49
|
+
# 初始化 GraphRAG
|
50
|
+
if settings.graphrag_env_ready:
|
51
|
+
try:
|
52
|
+
db_manager.get_graphrag_connection()
|
53
|
+
graphrag_is_available = True
|
54
|
+
logger.info("GraphRAG initialized successfully.")
|
55
|
+
except Exception as e:
|
56
|
+
logger.error(f"Failed to initialize GraphRAG: {e}")
|
57
|
+
graphrag_is_available = False
|
58
|
+
|
59
|
+
# 初始化 LLM Memory
|
60
|
+
if settings.memory_env_ready:
|
61
|
+
try:
|
62
|
+
db_manager.get_llm_memory_connection()
|
63
|
+
llm_memory_is_available = True
|
64
|
+
logger.info("LLM Memory initialized successfully.")
|
65
|
+
except Exception as e:
|
66
|
+
logger.error(f"Failed to initialize LLM Memory: {e}")
|
67
|
+
llm_memory_is_available = False
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
def run_http_server(host, port):
|
72
|
+
|
73
|
+
# 创建MCP服务端
|
74
|
+
app = Server("adbpg-mcp-server")
|
75
|
+
initialize_services()
|
76
|
+
@app.list_resources()
|
77
|
+
async def list_resources() -> list[Resource]:
|
78
|
+
"""列出可用的基本资源"""
|
79
|
+
return await adbpg_basic_operation.list_resources()
|
80
|
+
|
81
|
+
@app.list_resource_templates()
|
82
|
+
async def list_resource_templates() -> list[ResourceTemplate]:
|
83
|
+
"""
|
84
|
+
定义动态资源模板
|
85
|
+
|
86
|
+
返回:
|
87
|
+
list[ResourceTemplate]: 资源模板列表
|
88
|
+
包含以下模板:
|
89
|
+
- 列出schema中的表
|
90
|
+
- 获取表DDL
|
91
|
+
- 获取表统计信息
|
92
|
+
"""
|
93
|
+
return await adbpg_basic_operation.list_resource_templates()
|
94
|
+
|
95
|
+
@app.read_resource()
|
96
|
+
async def read_resource(uri: AnyUrl) -> str:
|
97
|
+
"""
|
98
|
+
读取资源内容
|
99
|
+
|
100
|
+
参数:
|
101
|
+
uri (AnyUrl): 资源URI
|
102
|
+
|
103
|
+
返回:
|
104
|
+
str: 资源内容
|
105
|
+
|
106
|
+
支持的URI格式:
|
107
|
+
- adbpg:///schemas: 列出所有schema
|
108
|
+
- adbpg:///{schema}/tables: 列出指定schema中的表
|
109
|
+
- adbpg:///{schema}/{table}/ddl: 获取表的DDL
|
110
|
+
- adbpg:///{schema}/{table}/statistics: 获取表的统计信息
|
111
|
+
"""
|
112
|
+
if not db_manager:
|
113
|
+
raise Exception("Database connection not established")
|
114
|
+
return await adbpg_basic_operation.read_resource(uri, db_manager)
|
115
|
+
|
116
|
+
# 工具调用
|
117
|
+
@app.call_tool()
|
118
|
+
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
|
119
|
+
"""
|
120
|
+
执行工具操作
|
121
|
+
|
122
|
+
参数:
|
123
|
+
name (str): 工具名称
|
124
|
+
arguments (dict): 工具参数
|
125
|
+
|
126
|
+
返回:
|
127
|
+
list[TextContent]: 执行结果
|
128
|
+
"""
|
129
|
+
if not db_manager:
|
130
|
+
raise Exception("Database manager not initialized")
|
131
|
+
|
132
|
+
try:
|
133
|
+
# 分发到 Basic Operation
|
134
|
+
if name in [t.name for t in adbpg_basic_operation.get_basic_tools()]:
|
135
|
+
query, params, needs_json_agg = await adbpg_basic_operation.call_basic_tool(name, arguments, db_manager)
|
136
|
+
conn = db_manager.get_basic_connection()
|
137
|
+
with conn.cursor() as cursor:
|
138
|
+
cursor.execute(query, params)
|
139
|
+
if needs_json_agg:
|
140
|
+
json_result = cursor.fetchone()[0]
|
141
|
+
return [TextContent(type="text", text=json.dumps(json_result, ensure_ascii=False, indent=2))]
|
142
|
+
else:
|
143
|
+
return [TextContent(type="text", text="Tool executed successfully.")]
|
144
|
+
|
145
|
+
# 分发到 GraphRAG
|
146
|
+
elif name in [t.name for t in adbpg_graphrag.get_graphrag_tools()]:
|
147
|
+
if not graphrag_is_available:
|
148
|
+
raise ValueError("GraphRAG tool is not available due to configuration or initialization errors.")
|
149
|
+
return await adbpg_graphrag.call_graphrag_tool(name, arguments, db_manager)
|
150
|
+
|
151
|
+
# 分发到 LLM Memory
|
152
|
+
elif name in [t.name for t in adbpg_memory.get_memory_tools()]:
|
153
|
+
if not llm_memory_is_available:
|
154
|
+
raise ValueError("LLM Memory tool is not available due to configuration or initialization errors.")
|
155
|
+
return await adbpg_memory.call_memory_tool(name, arguments, db_manager)
|
156
|
+
|
157
|
+
else:
|
158
|
+
raise ValueError(f"Unknown tool: {name}")
|
159
|
+
|
160
|
+
except Exception as e:
|
161
|
+
logger.error(f"Error calling tool '{name}': {e}", exc_info=True)
|
162
|
+
return [TextContent(type="text", text=f"Error executing tool '{name}': {str(e)}")]
|
163
|
+
|
164
|
+
# 工具列表
|
165
|
+
@app.list_tools()
|
166
|
+
async def list_tools() -> list[Tool]:
|
167
|
+
"""
|
168
|
+
列出可用的工具
|
169
|
+
"""
|
170
|
+
tools = adbpg_basic_operation.get_basic_tools()
|
171
|
+
|
172
|
+
if graphrag_is_available:
|
173
|
+
tools.extend(adbpg_graphrag.get_graphrag_tools())
|
174
|
+
if llm_memory_is_available:
|
175
|
+
tools.extend(adbpg_memory.get_memory_tools())
|
176
|
+
return tools
|
177
|
+
|
178
|
+
#----------管理请求会话--------------
|
179
|
+
session_manager = StreamableHTTPSessionManager(
|
180
|
+
app=app,
|
181
|
+
event_store=None, #无状态,不保存历史事件
|
182
|
+
stateless=True
|
183
|
+
)
|
184
|
+
async def handle_streamable_http(scope, receive, send):
|
185
|
+
await session_manager.handle_request(scope, receive, send)
|
186
|
+
|
187
|
+
@contextlib.asynccontextmanager
|
188
|
+
async def lifespan(app):
|
189
|
+
async with session_manager.run():
|
190
|
+
logger.info("ADBPG MCP Server Started! ")
|
191
|
+
try:
|
192
|
+
yield
|
193
|
+
finally:
|
194
|
+
logger.info("ADBPG MCP Server shutting down…")
|
195
|
+
|
196
|
+
# 将MCP服务挂载到/mcp路径上,用户访问整个路径时,就会进入刚才创建的MCP HTTP会话管理器
|
197
|
+
starlette_app = Starlette(
|
198
|
+
debug=False,
|
199
|
+
routes=[Mount("/mcp", app=handle_streamable_http)],
|
200
|
+
lifespan=lifespan,
|
201
|
+
)
|
202
|
+
|
203
|
+
# 利用uvicorn启动ASGI服务器并监听指定端口
|
204
|
+
uvicorn.run(starlette_app, host=host, port=port)
|
205
|
+
|
206
|
+
return 0
|
@@ -0,0 +1,216 @@
|
|
1
|
+
import asyncio
|
2
|
+
import logging
|
3
|
+
import os
|
4
|
+
import sys
|
5
|
+
import json
|
6
|
+
import psycopg
|
7
|
+
import re
|
8
|
+
import ast
|
9
|
+
from psycopg import OperationalError as Error
|
10
|
+
from psycopg import Connection
|
11
|
+
from mcp.server import Server
|
12
|
+
from mcp.types import Resource, Tool, TextContent, ResourceTemplate
|
13
|
+
from pydantic import AnyUrl
|
14
|
+
from dotenv import load_dotenv
|
15
|
+
from mcp.server.stdio import stdio_server
|
16
|
+
|
17
|
+
# 配置日志,输出到标准错误
|
18
|
+
logging.basicConfig(
|
19
|
+
level=logging.DEBUG,
|
20
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
21
|
+
stream=sys.stderr
|
22
|
+
)
|
23
|
+
logger = logging.getLogger("adbpg-mcp-server")
|
24
|
+
|
25
|
+
SERVER_VERSION = "0.2.0"
|
26
|
+
|
27
|
+
from .adbpg_config import settings
|
28
|
+
from .adbpg import DatabaseManager
|
29
|
+
from . import adbpg_basic_operation, adbpg_graphrag, adbpg_memory
|
30
|
+
|
31
|
+
|
32
|
+
# 初始化服务器
|
33
|
+
try:
|
34
|
+
app = Server("adbpg-mcp-server")
|
35
|
+
logger.info("MCP server initialized")
|
36
|
+
except Exception as e:
|
37
|
+
logger.error(f"Error initializing MCP server: {e}")
|
38
|
+
sys.exit(1)
|
39
|
+
db_manager: DatabaseManager | None = None
|
40
|
+
graphrag_is_available = False
|
41
|
+
llm_memory_is_available = False
|
42
|
+
|
43
|
+
@app.list_resources()
|
44
|
+
async def list_resources() -> list[Resource]:
|
45
|
+
"""列出可用的基本资源"""
|
46
|
+
return await adbpg_basic_operation.list_resources()
|
47
|
+
|
48
|
+
@app.list_resource_templates()
|
49
|
+
async def list_resource_templates() -> list[ResourceTemplate]:
|
50
|
+
"""
|
51
|
+
定义动态资源模板
|
52
|
+
|
53
|
+
返回:
|
54
|
+
list[ResourceTemplate]: 资源模板列表
|
55
|
+
包含以下模板:
|
56
|
+
- 列出schema中的表
|
57
|
+
- 获取表DDL
|
58
|
+
- 获取表统计信息
|
59
|
+
"""
|
60
|
+
return await adbpg_basic_operation.list_resource_templates()
|
61
|
+
|
62
|
+
|
63
|
+
@app.read_resource()
|
64
|
+
async def read_resource(uri: AnyUrl) -> str:
|
65
|
+
"""
|
66
|
+
读取资源内容
|
67
|
+
|
68
|
+
参数:
|
69
|
+
uri (AnyUrl): 资源URI
|
70
|
+
|
71
|
+
返回:
|
72
|
+
str: 资源内容
|
73
|
+
|
74
|
+
支持的URI格式:
|
75
|
+
- adbpg:///schemas: 列出所有schema
|
76
|
+
- adbpg:///{schema}/tables: 列出指定schema中的表
|
77
|
+
- adbpg:///{schema}/{table}/ddl: 获取表的DDL
|
78
|
+
- adbpg:///{schema}/{table}/statistics: 获取表的统计信息
|
79
|
+
"""
|
80
|
+
if not db_manager:
|
81
|
+
raise Exception("Database connection not established")
|
82
|
+
return await adbpg_basic_operation.read_resource(uri, db_manager)
|
83
|
+
|
84
|
+
@app.list_tools()
|
85
|
+
async def list_tools() -> list[Tool]:
|
86
|
+
"""
|
87
|
+
列出可用的工具
|
88
|
+
"""
|
89
|
+
tools = adbpg_basic_operation.get_basic_tools()
|
90
|
+
#tools.extend(adbpg_graphrag.get_graphrag_tools())
|
91
|
+
#tools.extend(adbpg_memory.get_memory_tools())
|
92
|
+
|
93
|
+
if graphrag_is_available:
|
94
|
+
tools.extend(adbpg_graphrag.get_graphrag_tools())
|
95
|
+
if llm_memory_is_available:
|
96
|
+
tools.extend(adbpg_memory.get_memory_tools())
|
97
|
+
return tools
|
98
|
+
@app.call_tool()
|
99
|
+
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
|
100
|
+
"""
|
101
|
+
执行工具操作
|
102
|
+
|
103
|
+
参数:
|
104
|
+
name (str): 工具名称
|
105
|
+
arguments (dict): 工具参数
|
106
|
+
|
107
|
+
返回:
|
108
|
+
list[TextContent]: 执行结果
|
109
|
+
"""
|
110
|
+
if not db_manager:
|
111
|
+
raise Exception("Database manager not initialized")
|
112
|
+
|
113
|
+
try:
|
114
|
+
# 分发到 Basic Operation
|
115
|
+
if name in [t.name for t in adbpg_basic_operation.get_basic_tools()]:
|
116
|
+
query, params, needs_json_agg = await adbpg_basic_operation.call_basic_tool(name, arguments, db_manager)
|
117
|
+
conn = db_manager.get_basic_connection()
|
118
|
+
with conn.cursor() as cursor:
|
119
|
+
cursor.execute(query, params)
|
120
|
+
if needs_json_agg:
|
121
|
+
json_result = cursor.fetchone()[0]
|
122
|
+
return [TextContent(type="text", text=json.dumps(json_result, ensure_ascii=False, indent=2))]
|
123
|
+
else:
|
124
|
+
return [TextContent(type="text", text="Tool executed successfully.")]
|
125
|
+
|
126
|
+
# 分发到 GraphRAG
|
127
|
+
elif name in [t.name for t in adbpg_graphrag.get_graphrag_tools()]:
|
128
|
+
if not graphrag_is_available:
|
129
|
+
raise ValueError("GraphRAG tool is not available due to configuration or initialization errors.")
|
130
|
+
return await adbpg_graphrag.call_graphrag_tool(name, arguments, db_manager)
|
131
|
+
|
132
|
+
# 分发到 LLM Memory
|
133
|
+
elif name in [t.name for t in adbpg_memory.get_memory_tools()]:
|
134
|
+
if not llm_memory_is_available:
|
135
|
+
raise ValueError("LLM Memory tool is not available due to configuration or initialization errors.")
|
136
|
+
return await adbpg_memory.call_memory_tool(name, arguments, db_manager)
|
137
|
+
|
138
|
+
else:
|
139
|
+
raise ValueError(f"Unknown tool: {name}")
|
140
|
+
|
141
|
+
except Exception as e:
|
142
|
+
logger.error(f"Error calling tool '{name}': {e}", exc_info=True)
|
143
|
+
return [TextContent(type="text", text=f"Error executing tool '{name}': {str(e)}")]
|
144
|
+
|
145
|
+
# --- 服务器生命周期 ---
|
146
|
+
def initialize_services():
|
147
|
+
"""初始化数据库、GraphRAG 和 LLM Memory"""
|
148
|
+
global db_manager, graphrag_is_available, llm_memory_is_available
|
149
|
+
|
150
|
+
if not settings.db_env_ready:
|
151
|
+
logger.error("Cannot start server: Database environment is not configured.")
|
152
|
+
sys.exit(1)
|
153
|
+
|
154
|
+
db_manager = DatabaseManager(settings)
|
155
|
+
|
156
|
+
# 测试主连接
|
157
|
+
try:
|
158
|
+
db_manager.get_basic_connection()
|
159
|
+
logger.info("Successfully connected to database.")
|
160
|
+
except Exception as e:
|
161
|
+
logger.error(f"Failed to connect to database: {e}")
|
162
|
+
sys.exit(1)
|
163
|
+
|
164
|
+
# 初始化 GraphRAG
|
165
|
+
if settings.graphrag_env_ready:
|
166
|
+
try:
|
167
|
+
db_manager.get_graphrag_connection()
|
168
|
+
graphrag_is_available = True
|
169
|
+
logger.info("GraphRAG initialized successfully.")
|
170
|
+
except Exception as e:
|
171
|
+
logger.error(f"Failed to initialize GraphRAG: {e}")
|
172
|
+
graphrag_is_available = False
|
173
|
+
|
174
|
+
# 初始化 LLM Memory
|
175
|
+
if settings.memory_env_ready:
|
176
|
+
try:
|
177
|
+
db_manager.get_llm_memory_connection()
|
178
|
+
llm_memory_is_available = True
|
179
|
+
logger.info("LLM Memory initialized successfully.")
|
180
|
+
except Exception as e:
|
181
|
+
logger.error(f"Failed to initialize LLM Memory: {e}")
|
182
|
+
llm_memory_is_available = False
|
183
|
+
|
184
|
+
async def main():
|
185
|
+
"""服务器主入口点"""
|
186
|
+
try:
|
187
|
+
initialize_services()
|
188
|
+
logger.info("Starting ADBPG MCP server...")
|
189
|
+
|
190
|
+
# 使用 stdio 传输
|
191
|
+
async with stdio_server() as (read_stream, write_stream):
|
192
|
+
try:
|
193
|
+
logger.info("Running MCP server with stdio transport...")
|
194
|
+
await app.run(
|
195
|
+
read_stream=read_stream,
|
196
|
+
write_stream=write_stream,
|
197
|
+
initialization_options=app.create_initialization_options()
|
198
|
+
)
|
199
|
+
except Exception as e:
|
200
|
+
logger.error(f"Error running server: {str(e)}")
|
201
|
+
raise
|
202
|
+
except Exception as e:
|
203
|
+
logger.error(f"Server initialization error: {str(e)}")
|
204
|
+
raise
|
205
|
+
|
206
|
+
finally:
|
207
|
+
if db_manager:
|
208
|
+
db_manager.close_all()
|
209
|
+
|
210
|
+
def run_stdio_server():
|
211
|
+
"""同步运行入口点"""
|
212
|
+
try:
|
213
|
+
asyncio.run(main())
|
214
|
+
except Exception as e:
|
215
|
+
logger.error(f"Fatal error: {e}")
|
216
|
+
sys.exit(1)
|