Skip to main content
Glama
JJVvV

SP Database MCP Server

by JJVvV
simple_server.py13.8 kB
"""简化版 SP Database MCP Server - 演示版本""" import asyncio import json import os from typing import Any, Dict, List, Optional from dotenv import load_dotenv from mcp.server import Server from mcp.server.lowlevel import NotificationOptions from mcp.server.models import InitializationOptions from mcp.server.stdio import stdio_server from mcp.types import ( Resource, Tool, TextContent, ) # 加载环境变量 load_dotenv() # 创建服务器实例 server = Server("sp-database-mcp") # 模拟的数据库表信息 MOCK_TABLES = { "activity_node": { "name": "activity_node", "comment": "活动节点表 - 用于记录流程活动中的关键节点", "columns": [ { "name": "id", "type": "bigint", "nullable": False, "comment": "主键ID", "is_primary_key": True }, { "name": "type", "type": "varchar(50)", "nullable": False, "comment": "节点分类 - 高阶分类,如 TASK(任务节点), APPROVAL(审批节点), TRIGGER(触发器节点)" }, { "name": "activity_type", "type": "varchar(100)", "nullable": False, "comment": "具体类型 - 低阶分类,如 FILL_FORM(表单填报), AUTO_SCRIPT(自动化脚本)" }, { "name": "activity_code", "type": "varchar(100)", "nullable": False, "comment": "活动编码 - 节点的唯一标识编码" }, { "name": "development_status", "type": "varchar(20)", "nullable": True, "comment": "开发状态 - 当前节点的开发进展(已发布/草稿等)" }, { "name": "latest", "type": "boolean", "nullable": False, "comment": "是否最新版本 - true 表示该记录是最新版本" }, { "name": "status", "type": "varchar(20)", "nullable": True, "comment": "状态 - 活动当前使用状态(启用/停用)" }, { "name": "business_object_name", "type": "varchar(200)", "nullable": True, "comment": "业务对象名称 - 与之绑定的业务对象展示名" }, { "name": "business_object_id", "type": "bigint", "nullable": True, "comment": "业务对象ID - 与业务对象绑定的主键 ID" }, { "name": "ref_dac_id", "type": "bigint", "nullable": True, "comment": "所属资产对象id - 资产l3节点id(来自 da_asset_object)" }, { "name": "app_belong", "type": "varchar(100)", "nullable": True, "comment": "所属应用 - 节点所属应用" }, { "name": "created_at", "type": "timestamp", "nullable": False, "comment": "创建时间" }, { "name": "updated_at", "type": "timestamp", "nullable": False, "comment": "更新时间" } ] }, "scene_activity": { "name": "scene_activity", "comment": "场景活动表 - 记录各种业务场景下的活动信息", "columns": [ { "name": "id", "type": "bigint", "nullable": False, "comment": "主键ID", "is_primary_key": True }, { "name": "scene_id", "type": "bigint", "nullable": False, "comment": "场景ID" }, { "name": "activity_name", "type": "varchar(200)", "nullable": False, "comment": "活动名称" }, { "name": "activity_desc", "type": "text", "nullable": True, "comment": "活动描述" }, { "name": "status", "type": "varchar(20)", "nullable": False, "comment": "活动状态" } ] }, "da_asset_object": { "name": "da_asset_object", "comment": "数据资产对象表 - 存储数据资产的基本信息", "columns": [ { "name": "id", "type": "bigint", "nullable": False, "comment": "主键ID", "is_primary_key": True }, { "name": "asset_name", "type": "varchar(200)", "nullable": False, "comment": "资产名称" }, { "name": "asset_type", "type": "varchar(50)", "nullable": False, "comment": "资产类型" }, { "name": "description", "type": "text", "nullable": True, "comment": "资产描述" } ] } } @server.list_resources() async def handle_list_resources() -> List[Resource]: """列出可用的资源""" resources = [] for table_name in MOCK_TABLES.keys(): resources.append( Resource( uri=f"table://{table_name}", name=f"表: {table_name}", description=f"数据库表 {table_name} 的结构信息", mimeType="application/json" ) ) return resources @server.read_resource() async def handle_read_resource(uri: str) -> str: """读取资源内容""" try: if uri.startswith("table://"): table_name = uri.replace("table://", "") if table_name in MOCK_TABLES: table_info = MOCK_TABLES[table_name] return json.dumps(table_info, indent=2, ensure_ascii=False) else: return f"表 {table_name} 不存在" else: return f"不支持的资源 URI: {uri}" except Exception as e: return f"读取资源时出错: {str(e)}" @server.list_tools() async def handle_list_tools() -> List[Tool]: """列出可用的工具""" tools = [ Tool( name="get_table_info", description="获取指定数据库表的结构信息,包括字段定义、类型、注释等", inputSchema={ "type": "object", "properties": { "table_name": { "type": "string", "description": "要查询的表名,如:activity_node, scene_activity, da_asset_object" } }, "required": ["table_name"] } ), Tool( name="search_tables", description="根据关键词搜索数据库表", inputSchema={ "type": "object", "properties": { "keyword": { "type": "string", "description": "搜索关键词" } }, "required": ["keyword"] } ), Tool( name="list_all_tables", description="列出所有数据库表", inputSchema={ "type": "object", "properties": {} } ), Tool( name="get_table_fields_summary", description="获取表字段的简要说明", inputSchema={ "type": "object", "properties": { "table_name": { "type": "string", "description": "表名" } }, "required": ["table_name"] } ) ] return tools @server.call_tool() async def handle_call_tool(name: str, arguments: Dict[str, Any]) -> List[TextContent]: """处理工具调用""" try: if name == "get_table_info": table_name = arguments.get("table_name") if not table_name: return [TextContent(type="text", text="错误:缺少表名参数")] if table_name in MOCK_TABLES: table_info = MOCK_TABLES[table_name] output = format_table_info(table_info) return [TextContent(type="text", text=output)] else: available_tables = ", ".join(MOCK_TABLES.keys()) return [TextContent(type="text", text=f"未找到表 '{table_name}'。可用的表有: {available_tables}")] elif name == "search_tables": keyword = arguments.get("keyword") if not keyword: return [TextContent(type="text", text="错误:缺少搜索关键词")] matching_tables = [] for table_name, table_info in MOCK_TABLES.items(): if (keyword.lower() in table_name.lower() or keyword.lower() in table_info.get("comment", "").lower()): matching_tables.append((table_name, table_info)) if matching_tables: output = f"找到 {len(matching_tables)} 个匹配的表:\n\n" for table_name, table_info in matching_tables: output += f"## {table_name}\n" if table_info.get("comment"): output += f"**说明**: {table_info['comment']}\n" output += f"**字段数**: {len(table_info['columns'])}\n\n" return [TextContent(type="text", text=output)] else: return [TextContent(type="text", text=f"未找到包含关键词 '{keyword}' 的表")] elif name == "list_all_tables": output = f"数据库中共有 {len(MOCK_TABLES)} 个表:\n\n" for table_name, table_info in MOCK_TABLES.items(): output += f"- **{table_name}**: {table_info.get('comment', '无描述')}\n" return [TextContent(type="text", text=output)] elif name == "get_table_fields_summary": table_name = arguments.get("table_name") if not table_name: return [TextContent(type="text", text="错误:缺少表名参数")] if table_name in MOCK_TABLES: table_info = MOCK_TABLES[table_name] output = f"# {table_name} 表字段简要说明\n\n" if table_info.get("comment"): output += f"**表说明**: {table_info['comment']}\n\n" output += "## 主要字段\n\n" for column in table_info["columns"]: output += f"- **{column['name']}** ({column['type']}): {column.get('comment', '无描述')}\n" return [TextContent(type="text", text=output)] else: available_tables = ", ".join(MOCK_TABLES.keys()) return [TextContent(type="text", text=f"未找到表 '{table_name}'。可用的表有: {available_tables}")] else: return [TextContent(type="text", text=f"未知工具: {name}")] except Exception as e: return [TextContent(type="text", text=f"工具调用出错: {str(e)}")] def format_table_info(table_info: Dict[str, Any]) -> str: """格式化表信息输出""" output = f"# {table_info['name']} 表结构信息\n\n" if table_info.get("comment"): output += f"**表说明**: {table_info['comment']}\n\n" output += "## 字段信息\n\n" output += "| 字段名 | 类型 | 可空 | 主键 | 说明 |\n" output += "|--------|------|------|------|------|\n" for column in table_info["columns"]: nullable = "是" if column.get("nullable", True) else "否" primary_key = "是" if column.get("is_primary_key", False) else "否" comment = column.get("comment", "-") output += f"| {column['name']} | {column['type']} | {nullable} | {primary_key} | {comment} |\n" return output async def main(): """主函数""" print("SP Database MCP Server 启动中...") print("可用的表:") for table_name, table_info in MOCK_TABLES.items(): print(f" - {table_name}: {table_info.get('comment', '无描述')}") # 启动服务器 async with stdio_server() as (read_stream, write_stream): await server.run( read_stream, write_stream, InitializationOptions( server_name="sp-database-mcp", server_version="0.1.0", capabilities=server.get_capabilities( notification_options=NotificationOptions(), experimental_capabilities=None, ), ), ) def cli_main(): """CLI 入口点""" asyncio.run(main()) if __name__ == "__main__": cli_main()

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JJVvV/sp-enterprise-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server