数据服务器+MCP服务器部署MCP供Workbuddy调用

发布时间:2026/11/5 11:58:12

数据服务器+MCP服务器部署MCP供Workbuddy调用 需求分析公司希望用Workbuddy连接即有的数据供用户通过对话模式得到报表等数据。即有资源分析Workbuddy购买了企业版安全性有一定保障且能得到官方的支持。源头系统的数据服务器不对外全部部署在内网环境且数据需要严格控制不能让AI工具随意获取数据。现有服务器有空余资源可以在不新购服务器的情况下部署MCP服务。内部人力众所周知ALL IN 1系统架构架构图数据服务器新增用户、密码赋予查询某个表的权限MCP服务器服务器配置白名单加入MCP服务的对外端口选择自己的技术栈部署MCP服务这里举例用python来进行MCP服务部署python安装mcp包以及其他依赖包pycharm同时安装AI工具通过AI进行初步的代码生成历经超过30次的调试MCP服务调通最终的示例代码如下#codingutf-8importasyncioimportloggingimportoracledbfromtypingimportAny,Dict,Listfrommcp.serverimportServerfrommcp.typesimportTool,TextContentfromstarlette.applicationsimportStarlettefromstarlette.routingimportRoutefromstarlette.requestsimportRequestfromstarlette.responsesimportResponsefrommcp.server.sseimportSseServerTransportimportuvicornimportos# 配置日志logging.basicConfig(levellogging.INFO)loggerlogging.getLogger(MCP-Oracle-Server)# 环境变量读取注意这里配置环境变量更安全hostos.environ.get(host,localhost)portint(os.environ.get(port,))oracleuseros.environ.get(oracleuser,)oraclepasswordos.environ.get(oraclepassword,)service_nameos.environ.get(service_name,)# 启动前校验避免带空配置运行ifnotall([oracleuser,oraclepassword,service_name]):logger.warning(⚠️ Missing required environment variables (oracleuser, oraclepassword, service_name). Server may fail to connect.)# 数据库配置DB_CONFIG{host:host,port:port,service_name:service_name,user:oracleuser,password:oraclepassword}# 初始化 MCP ServerappServer(oracle-data-connector)# 白名单ALLOWED_TABLES{实例.表名:[X,XX,XXX,XXXX]}# 全局连接池poolNonedefinit_oracle_client():初始化 Oracle Thick 模式try:# 使用客户端路径client_dirr有效路径oracledb.init_oracle_client(lib_dirclient_dir)logger.info(f✅ Oracle Thick mode initialized successfully using client:{client_dir})exceptExceptionase:logger.error(f❌ Failed to initialize Oracle Thick mode:{e})raisedefinit_connection_pool():初始化 Oracle 连接池提升查询性能globalpoolifpoolisNone:try:dsnf{DB_CONFIG[host]}:{DB_CONFIG[port]}/{DB_CONFIG[service_name]}pooloracledb.create_pool(userDB_CONFIG[user],passwordDB_CONFIG[password],dsndsn,min1,max4,increment1,getmodeoracledb.POOL_GETMODE_WAIT)logger.info(✅ Oracle Connection Pool initialized successfully.)exceptExceptionase:logger.error(f❌ Failed to initialize Oracle Connection Pool:{e})raisedefget_db_connection():从连接池获取连接ifpoolisNone:init_connection_pool()returnpool.acquire()app.list_tools()asyncdeflist_tools()-List[Tool]:return[Tool(namelist_allowed_tables,description列出当前 MCP 服务允许查询的所有表名,inputSchema{type:object,properties:{},required:[]}),Tool(namequery_oracle_table,description查询指定 Oracle 表的数据。仅支持预定义白名单中的表和列。,inputSchema{type:object,properties:{table_name:{type:string,description:要查询的表名必须在大写白名单中},columns:{type:array,items:{type:string},description:要查询的列名列表。如果为空或包含*则返回所有允许列。},limit:{type:integer,description:限制返回行数默认 10最大 100,default:10},filter_column:{type:string,description:可选用于过滤的列名},filter_value:{type:string,description:可选过滤值}},required:[table_name]})]app.call_tool()asyncdefcall_tool(name:str,arguments:Dict[str,Any])-List[TextContent]:try:ifnamelist_allowed_tables:tableslist(ALLOWED_TABLES.keys())return[TextContent(typetext,textfAllowed tables:{, .join(tables)})]elifnamequery_oracle_table:table_namearguments.get(table_name,).upper()requested_columnsarguments.get(columns,[])limitmin(arguments.get(limit,10),100)filter_colarguments.get(filter_column)filter_valarguments.get(filter_value)iftable_namenotinALLOWED_TABLES:return[TextContent(typetext,textfError: Table {table_name} is not allowed.)]allowed_colsALLOWED_TABLES[table_name]ifnotrequested_columnsor*inrequested_columns:select_colsallowed_colselse:invalid_cols[colforcolinrequested_columnsifcol.upper()notinallowed_cols]ifinvalid_cols:return[TextContent(typetext,textfError: Columns{invalid_cols}are not allowed.)]select_cols[col.upper()forcolinrequested_columns]col_str, .join(select_cols)# 修复使用字典传参更安全可靠params{}base_sqlfSELECT{col_str}FROM{table_name}iffilter_colandfilter_valisnotNone:iffilter_col.upper()notinallowed_cols:return[TextContent(typetext,textfError: Filter column {filter_col} is not allowed.)]base_sqlf WHERE{filter_col.upper()} :bind_valparams[:bind_val]filter_val# Oracle 11g 兼容写法sqlfSELECT * FROM ({base_sql}) WHERE ROWNUM {limit}connget_db_connection()cursorconn.cursor()try:cursor.execute(sql,params)columns[desc[0]fordescincursor.description]rowscursor.fetchall()result_textfQuery Result for{table_name}:\nresult_text| | .join(columns) |\nresult_text||.join([---for_incolumns])|\nforrowinrows:formatted_row[str(item)ifitemisnotNoneelseNULLforiteminrow]result_text| | .join(formatted_row) |\nreturn[TextContent(typetext,textresult_text)]finally:# 无论是否报错必须关闭游标并将连接归还连接池cursor.close()conn.close()else:return[TextContent(typetext,textfUnknown tool:{name})]exceptExceptionase:logger.error(fError executing tool{name}:{e})return[TextContent(typetext,textfError:{str(e)})]defmain():# 1. 强制启用 Thick 模式并指定路径init_oracle_client()# 2. 初始化连接池try:init_connection_pool()exceptException:logger.error(❌ Database connection pool failed to initialize. MCP Server will not start.)returnsseSseServerTransport(/messages/)asyncdefhandle_sse(request:Request):asyncwithsse.connect_sse(request.scope,request.receive,request._send)as(read_stream,write_stream):awaitapp.run(read_stream,write_stream,app.create_initialization_options())asyncdefhandle_messages(request:Request):awaitsse.handle_post_message(request.scope,request.receive,request._send)returnResponse(status_code200)starlette_appStarlette(debugTrue,routes[Route(/sse,endpointhandle_sse),Route(/messages/,endpointhandle_messages,methods[POST]),Route(/messages,endpointhandle_messages,methods[POST]),],)logger.info( Starting Oracle MCP Server on port 白名单端口号...)uvicorn.run(starlette_app,host0.0.0.0,port白名单端口号)if__name____main__:main()Workbuddy端操作路径截图MCP配置代码{mcpServers:{Oracle-Connector:{transport:sse,url:http://地址:端口/sse,disabled:false}}}结论通过上述案例可以将系统的数据放在内网通过物理网络数据库单独账号控制权限同时MCP服务器单独部署也进一步杜绝了网络安全问题以及AI查数据不可控的情况。
延伸阅读

更多相关文章

2026/11/5 11:58:11

【单片机毕业设计推荐】基于 STM32 单片机的智能鱼缸环境监控与自动控制系统设计,基于 STM32 的水族箱多参数监测与自动化养护系统设计(012304)

文章目录20 个相关毕业设计备选题目项目研究背景摘要总体方案核心功能技术路线项目演示关于我们项目案例源码获取温馨提示:本人主页置顶文章(点我)有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)有 CSDN 平台官…

2026/10/24 22:35:40

Postman Mock Server实战:契约驱动开发与前后端高效协作

1. 项目概述:为什么我们需要一个“假”后端? 在前后端分离的开发模式下,一个经典的矛盾总是反复上演:前端页面已经画好了,交互逻辑也写得差不多了,但后端接口文档还躺在产品经理的脑子里,或者后…

2026/10/25 12:25:39

C++编程实战:从快递费计算项目掌握输入验证与模块化设计

1. 项目概述:从“Hello World”到解决实际问题很多朋友学C,卡在了一个尴尬的阶段:语法书看完了,cout、if-else、for循环都认识了,甚至能写个小程序算算斐波那契数列。但一遇到稍微具体点的需求,比如“根据快…

2026/11/5 11:39:15

PostgreSQL数据类型选择指南与性能优化实践

1. PostgreSQL数据类型概述PostgreSQL作为一款功能强大的开源关系型数据库,其数据类型系统之丰富远超大多数同类产品。我在实际项目中最常遇到的问题是:面对十几种数字类型、多种字符串类型以及各种特殊类型时,开发团队往往凭直觉选择&#x…

2026/11/5 11:34:12

Simulink S-function执行时序与状态管理原理详解

简介:本资源是面向MATLAB/Simulink初学者与控制系统建模学习者的S-Function入门实践包,聚焦自定义系统函数开发这一核心能力,解决标准库无法覆盖的特定数学运算与动态逻辑建模需求。压缩包共4个文件(2个M文件实现核心算法逻辑&…

2026/11/5 11:34:12

低空经济三维智能感知与实时调度技术解析

1. 低空经济三维空间智能感知与管控体系概述低空经济作为新兴经济形态,正在全球范围内快速发展。根据国际航空运输协会(IATA)预测,到2030年,全球城市空中交通市场规模将达到1.5万亿美元。在这一背景下,《低…

2026/11/5 11:34:12

链表数据结构与PTA解题技巧详解

1. 链表基础与数据结构课程实践 链表作为线性表的链式存储结构,是数据结构课程中承前启后的关键内容。在山东理工大学(SDUT)的数据结构与算法课程体系中,链表章节通常安排在顺序表之后、树结构之前,这种教学顺序设计体…

2026/11/5 11:34:12

Simulink S-Function核心机制与两个经典C示例解析

简介:本资源是面向MATLAB/Simulink初学者与控制系统建模学习者的S-Function入门实践包,聚焦自定义系统函数开发这一核心能力,解决标准库无法覆盖的特定数学运算与动态逻辑建模需求。压缩包共4个文件(2个M文件实现核心算法逻辑&…

2026/11/5 11:34:12

Mantle系统架构:云存储局部性与扩展性的突破

1. 项目概述:Mantle系统架构演进的技术突围在云存储技术高度成熟的今天,百度沧海存储团队完成的Mantle系统设计堪称一次教科书级别的技术突围。这个被SOSP25收录的存储系统创新案例,完美诠释了如何在看似饱和的技术领域实现突破——不是通过堆…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/4 12:38:23

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑