mcpField
E
Elekto MCP for SQL Server

Elekto MCP for SQL Server

本地服务
github.com数据库02 周前更新

关于 Elekto MCP for SQL Server

Elekto MCP for SQL Server 是面向 SQL Server 2017 及更高版本的只读 MCP 服务,为开发者和 AI 客户端提供数据库结构、定义、依赖关系及查询结果。工具覆盖从权限检查和数据概览到表数据筛选,并支持限制单次查询返回行数。

主要功能

  1. 01浏览数据库、架构和表视图
  2. 02读取表、视图及程序定义
  3. 03检查对象依赖与表使用情况
  4. 04分析列数据概况和索引健康度
  5. 05比较数据库架构
  6. 06筛选、分组和分页查询数据

适用场景

  1. 01让 AI 客户端了解数据库结构
  2. 02查找对象定义和关联依赖
  3. 03分析数据分布或索引问题
  4. 04在配置的数据库间比较架构

MCP 相关

该 MCP 服务通过 stdio 向客户端提供 SQL Server 元数据检查和数据查询工具。服务设计为只读,并可设置单次查询的最大返回行数。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库
安装包
nugetElekto.Mcp.Sql2.3.4

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Elekto.Mcp.Sql

.NET NuGet NuGet Downloads License: GPL v3 CI elekto-com-br/elekto-mcp-sql MCP server

用于 SQL Server 2017 及更高版本(已在 2019 和 2022 上测试)的只读 MCP 服务,可用于检查和查询数据库。 它通过 MCP 协议(stdio)提供架构元数据、对象定义和数据查询,使 GitHub Copilot(以及 Claude 等其他 MCP 客户端)能够了解数据库结构, 而无需在代码库中存储凭据。

⚠️ 隐私与数据安全警告

MCP 服务充当本地数据与 AI 语言模型之间的桥梁。当你将此服务与 AI 助手(例如 GitHub Copilot、Claude 或其他工具)搭配使用时, 会发生以下情况:

  1. AI Agent 调用此服务上的工具,以读取 SQL Server 数据库中的数据。
  2. 结果——可能包括表架构、存储过程定义或实际行数据——会发送回 AI Agent,并传输至大模型提供商的基础设施进行分析。
  3. 这意味着你的数据会离开你的计算机,并发送给第三方服务 (Microsoft、Anthropic、OpenAI 等),且受其各自的服务条款和隐私政策约束。

在将此服务连接到任何数据库之前,请仔细考虑:

  • 可以读取哪些数据?其中是否包含个人身份信息(PII)、财务记录、商业机密或其他敏感信息?
  • 大模型提供商是谁?其数据保留和隐私政策是什么?
  • 根据适用的法律法规,你是否有权与该第三方共享这些数据?

建议:

  • 除非已明确评估并接受相关风险,否则切勿连接包含敏感数据的数据库。
  • 使用权限范围最小的数据库账户(只读,并尽可能限制为特定架构)。
  • 使用 max_query_rows 限制单次调用可返回的数据量。
  • 开发和探索时,优先使用已匿名化的数据或合成数据。
  • AI Agent 在寻找任务执行方法时可能极具创造性。尽管此服务 旨在保持只读并验证所有输入,但向 AI Agent 开放数据库访问始终存在 意外后果的风险。

无论采取何种预防措施,使用此工具所产生的任何后果均由你全权负责。 本软件按现状提供, 不附带任何形式的保证。

可用工具

工具描述
list_databases配置中注册的数据库
get_database_overview数据库的高级摘要(计数、大小、连接元数据),以及登录用户是否能看到全部内容
check_permissions已连接的登录用户可以和不可以查看的内容、完成授权所需的 GRANT,以及该用户是否可以写入
get_schema_summary按架构汇总的指标(对象、行数、大小)
list_schemas数据库中的架构(不包括系统架构)
list_tables用户表及其架构、日期、估算行数和估算大小;可按架构和名称模式筛选
list_views用户视图,可按架构和名称模式筛选
find_columns列名与模式匹配的所有表和视图
list_procedures用户存储过程(含基本复杂度指标)
list_functions用户定义的函数(含基本复杂度指标)
get_table_schema列及其明确的类型声明、所有扩展属性、主键、外键、检查约束、唯一约束和索引(含键顺序和声明的键宽度)
get_view_definition视图的 DDL 定义及列信息,包含相同的列详细信息
get_procedure_definitionCREATE PROCEDURE 文本
get_function_definitionCREATE FUNCTION 文本
get_dependency_graph对象依赖边(外键 + SQL 依赖)
get_table_usage表在外键和 SQL 模块中的引用
get_data_profile列概况(空值比例、不同值数量、最小值/最大值、热门值)
get_index_health重复/未使用索引诊断 + 缺失索引建议
compare_schemas比较两个已配置数据库之间的表/列结构
generate_dependency_dot带节点元数据(node_kind)的 Graphviz DOT 依赖关系图
query_table从表或视图中 SELECT,支持筛选、分组、安全聚合、排序、抽样和分页

从 1.x 升级

2.0.0 版本更改了工具的返回内容以及参数声明方式。无需重新配置——连接文件、.mcp.json 和 CLI 参数均未更改——但任何解析输出的程序都会受到影响:

更改处理方式
query_table 返回对象而非数组从 rows 读取行;检查 truncated
失败时返回 ok: false 内容,而不是引发工具错误将负载视为数据之前,先检查 ok === false
列结果新增了 type_declaration、max_length_chars、is_persisted 和 extended_properties优先使用 type_declaration,而不是以字节为单位的 max_length
列上的 description 现在是 extended_properties.MS_Description 的别名无需处理;仍可正常使用
工具的可选参数不再允许为空通过 MCP 使用时无需处理。直接调用的 C# 客户端传入 ""(或 0),而不是 null
新增:find_columns;list_tables 和 list_views 接受 name_pattern无需处理;这两项均为增量新增

其他所有内容——其他每个工具、其他每个字段——均未更改。

2.1.0 中的变更

结构没有变化:数组仍是数组,对象仍保留所有原有字段。现在,部分值会显示“未知”,而不是猜测事实,解析这些值时请留意:

变更原因
新增:check_permissions按工具说明登录用户缺少什么权限,以及可修复问题的 GRANT
get_database_overview、get_table_usage、get_index_health 和 generate_dependency_dot 新增了 visibility 块这样,当登录用户只能部分查看结果时,会明确说明这一点
list_procedures / list_functions 的行新增了 definition_visible;当其值为 false 时,line_count 和 join_count 为 null以前,隐藏的定义会显示为 0 行正文
当登录用户无法读取 sys.sql_expression_dependencies 时,referenced_object_count 为 null,且 get_table_usage 的 sql_module_usage 也为 null以前,两者都会导致整个调用因错误 229 而失败
当登录用户缺少服务器权限时,get_index_health 会返回重复项,并将 DMV 部分设为 null以前调用会直接失败,连无需权限的部分也无法获取
对于登录用户不可见的名称,get_*_definition 会返回 ok: false,而不是 [][] 无法区分“名称不存在”和“对你不可见”
SQL 错误会带上错误编号,提示也会区分权限、名称不存在和语法问题以前这三种情况共用一个通用提示

2.2.0 中的变更

工具结果的结构没有变化。改变的是服务的启动方式和打包方式:

变更原因
服务可以在没有任何连接的情况下启动,并在服务说明中注明这一点;每个工具都会以 ok: false 作答,告知需要创建的文件、查找位置和示例启动时退出的服务只会显示为“失败”;如果为所有项目注册服务,它会在每个项目中都失败
无法读取的配置(无效 JSON、未设置的 %{VARIABLE}、缺失或为空的 --connections 文件)会以同样的方式报告,而不会导致进程结束现在,调用工具的一方可以收到错误信息
尚未加载任何配置时,每次调用都会重新查找配置服务启动后创建的连接文件无需重启即可使用
此软件包已列入 nuget.org 的 MCP 服务,并包含 .mcp/server.json这样就能在那里找到它,并在其 MCP 服务选项卡中使用现成的配置

配置缺失或无法读取时,进程不再以代码 1 退出。依赖该退出代码的内容应改为读取工具的答复。README 还新增了 Claude Code 和 Codex 的设置说明。

2.3.0 中的变更

工具结果的结构没有变化;改变的是工具对自身的说明,而 Agent 正是根据这些说明选择工具:

变更原因
每个工具都声明了标题以及 MCP 注解 readOnlyHint、idempotentHint、destructiveHint: false 和 openWorldHint: false客户端可以将工具标示为安全,Agent 无需从文字说明中推断
每项说明都会介绍工具的功能、适用场景,以及应改用哪个工具这样,Agent 首次就能从 21 个工具中选对
服务在连接时始终发送说明,介绍各工具如何配合使用以前只有在未配置连接时才会发送说明

2.3.1 中的变更

结构没有变化。generate_dependency_dot 现在会说明箭头的指向、除 DOT 文本外还会返回什么、如何渲染,以及何时更适合使用其他工具。该服务已在 MCP Registry 中以 “Elekto MCP for SQL Server” 的名称列出,每个版本也会发布在代码仓库的 GitHub Releases 中。

2.3.2 的变更

形状没有变化。未配置连接时,现在返回给 Agent 的指导会要求它在写入任何内容前先征得用户同意,并且绝不将密码写入连接文件或其他任何位置,而是使用 %{VARIABLE} 代替。指导还会指出项目可能已保存、但本服务不会查找的连接配置(application.properties 或 application.yml 中的 spring.datasource.url,或 .env 文件中的 sqlserver:// 或 mssql:// URL),供 Agent 展示给用户,而不是由服务解析。

2.3.3 的变更

形状没有变化。该工具随附了 System.Security.Cryptography.Pkcs 9.0.13,这是 Microsoft.Data.SqlClient 引入的依赖,且受到两项 .NET 拒绝服务安全公告影响:GHSA-846f-f764-76mx(CVE-2026-84008,高危)和 GHSA-2fmv-rv2c-59x7(CVE-2026-70162,中危)。现在随附的是已修复的 10.0.13。使用 dotnet tool update -g Elekto.Mcp.Sql 更新全局工具;未指定版本的 dnx 配置会自动获取 2.3.3。

这也是首个在 GitHub Release 中附带程序包并提供构建来源证明的版本;验证版本发布介绍了如何检查。

2.3.4 的变更

形状没有变化。该工具现在运行于 Microsoft.Data.SqlClient 7.1.1(此前为 7.0.2)和 Microsoft.Extensions.Hosting 10.0.12。前者修复了连接池、事务和命名管道方面的问题。它仍然随附 2.3.3 中已修复的 System.Security.Cryptography.Pkcs 10.0.13。现在,程序包仅通过 Trusted Publishing 发布到 nuget.org:发布工作流不再使用已存储的 API 密钥。

读取结果

在依赖返回结果之前,有三点关于结果结构的信息值得了解。

有意报告两次列类型

sys.columns.max_length 的文档说明其单位是字节。因此,nvarchar(250) 列会报告 500,若将其理解为字符数,就会差一倍——而且这种错误不易察觉,因为下游没有任何信息会与之矛盾。为忠实反映系统目录,仍会报告这个原始值,但绝不会单独报告:

{
  "column_name": "Tag1",
  "data_type": "nvarchar",
  "type_declaration": "nvarchar(250)",
  "max_length": 500,
  "max_length_chars": 250
}

请使用 type_declaration 或 max_length_chars。它们不会被误读。

列还包含 extended_properties——所有属性,而不仅仅是 MS_Description——因此可以查看应用程序自己的约定(显示格式、单位、掩码),计算列还会包含 is_persisted。

query_table 返回的是封装对象,而非裸数组

仅凭包含两行的裸数组,无法判断它是一个包含两行的表,还是其他内容。因此,结果会明确说明自身类型:

{
  "table": { "schema": "Feeder", "name": "GenericSecurity" },
  "row_count": 100,
  "truncated": true,
  "top_applied": 100,
  "skip": 0,
  "max_query_rows": 10000,
  "rows": [ ... ]
}

truncated 是通过测量得出的,而非推断得出:会多获取一行,然后将其丢弃。只有在 max_query_rows 覆盖了请求的行数时,才会出现 top_requested。

失败会作为内容返回

从 MCP 工具抛出的异常不会传递给调用方——宿主会将其替换为一条通用信息。因此,失败会以普通结果的形式返回,并带有 ok: false:

{
  "ok": false,
  "tool": "query_table",
  "error": "'columns' looks like JSON: [\"Source\", \"Name\"]",
  "hint": "'columns' is a plain comma-separated string, not a JSON array or object.",
  "example": { "columns": "Source, Name, ReferenceDate" }
}

这是经过权衡后做出的选择:宿主不再将调用标记为错误,但调用方可以读取出错原因并进行修正。成功结果保持不变,且绝不包含 ok 字段。

登录名无法看到的内容会被静默省略,不会报错

SQL Server 只向登录名显示其拥有某些权限的对象(元数据可见性),并会静默过滤掉其余对象。仅属于 db_datareader 的登录名可以看到所有表,却看不到任何无法执行的过程,也看不到视图的文本。每个目录查询都会返回正常、格式完整的简短结果——“此数据库有 6 个过程”,而实际上有 672 个。

由于无法从数据本身发现这一点,服务端会检查决定对象可见性的权限,并明确报告结果。get_database_overview 是首先应调用的工具,包含:

"visibility": {
  "complete": false,
  "notes": [
    "The login lacks VIEW DEFINITION on the database. SQL Server then leaves out, without any error, every procedure, function and view the login holds no permission on, so their listings and counts may be short.",
    "756 of the 756 visible views, procedures and functions have their definition hidden from this login."
  ],
  "hint": "Call check_permissions for what this login is missing and the GRANT statements that fix it."
}

随后,check_permissions 会针对每组工具报告 complete、partial 或 unavailable,并指出缺少的权限以及可授予该权限的 GRANT,语法与服务端版本一致。它还会报告 write_access:是否存在角色、数据库权限或架构级、对象级 GRANT,允许登录名更改内容。这样便能检查本应只读的账户,而不是想当然地认为它是只读的。

安装

作为 .NET 全局工具(推荐)

需要 .NET 10 Runtime 或 SDK。

dotnet tool install -g Elekto.Mcp.Sql

升级到较新版本:

dotnet tool update -g Elekto.Mcp.Sql

安装后,elekto-mcp-sql 命令即可在 PATH 中使用。 可直接在 .mcp.json 中使用,无需指定路径:

{
  "servers": {
    "sql": {
      "type": "stdio",
      "command": "elekto-mcp-sql"
    }
  }
}

**零配置:**如果项目的 appsettings.json、web.config 或 App.config 中已有 ConnectionStrings 节,服务会自动读取,无需进一步配置。

Claude Code 和 Codex 的配置方式,请参阅 Claude Code 设置和 Codex 设置。

无需安装(dnx)

.NET 10 SDK(仅运行时不够)自带 dnx,可从 NuGet 下载软件包并运行,无需使用 dotnet tool install:

{
  "servers": {
    "sql": {
      "type": "stdio",
      "command": "dnx",
      "args": ["Elekto.Mcp.Sql", "--yes"]
    }
  }
}

此软件包列在 nuget.org 上的 MCP 服务中,其 MCP Server 选项卡提供了可直接粘贴到 VS Code 或 Visual Studio 中的配置。

从本地发布版本运行(隔离网络/企业环境)
cd src
dotnet publish -c Release -o C:\Tools\Elekto.Mcp.Sql
{
  "servers": {
    "sql": {
      "type": "stdio",
      "command": "dotnet",
      "args": ["C:\\Tools\\Elekto.Mcp.Sql\\Elekto.Mcp.Sql.dll"]
    }
  }
}

配置

如果提供了 --connections <path>,则只使用该文件,不会查询其他来源。

否则会读取并合并以下所有来源,因此在一个来源中定义的数据库和在另一个来源中定义的数据库都可用。如果多个来源中出现同名数据库,则优先级较高的来源生效:

优先级来源
1(最高)工作目录(项目根目录)中的 .elekto.mcp.sql.local.json
2appsettings.Development.json 中的 ConnectionStrings
3appsettings.json 中的 ConnectionStrings
4App.config / web.config 中的 <connectionStrings>
5用户主目录(~)中的 .elekto.mcp.sql.local.json
6(最低)MCP_SQL_CONNECTIONS 环境变量(旧版兼容)

请注意,主目录中的文件优先级低于项目的 appsettings.json:它用于保存默认值,项目中使用的配置会覆盖这些默认值。

启动时,服务会将所有提供了配置的来源记录到 stderr,便于诊断当前生效的文件。

现有 .NET 项目无需额外配置

如果项目已有包含 ConnectionStrings 部分的 appsettings.json 或 web.config,服务会自动读取,无需额外文件。

请注意:自动发现虽然方便,但可能会使用权限过大的项目连接,不适合安全地供 AI Agent 使用。 如果现有连接字符串具有写入权限或可访问敏感数据,请考虑使用单独的连接文件, 其中配置只读凭据,并通过 --connections 显式指定该文件,或将其放在项目根目录中。

连接文件格式

该文件是一个 JSON 对象,将逻辑数据库名称映射到对应配置。

简单格式(直接使用连接字符串):

{
  "MyDatabase": "Server=SQLSRV01\\INST;Database=MyDatabase;Integrated Security=SSPI"
}

完整格式(包含选项):

{
  "MyDatabase": {
    "connection_string": "Server=SQLSRV01\\INST;Database=MyDatabase;Integrated Security=SSPI",
    "max_query_rows": 5000,
    "default_timeout_seconds": 30
  }
}

两种格式可以在同一文件中混用。请参阅 sample-connections.json 获取可直接使用的示例。

建议将本地文件放在项目根目录(会自动发现)或 ~ (供所有项目共用)。该文件可能包含凭据,因此请将 .elekto.mcp.sql.local.json 添加到项目的 .gitignore 中,本仓库也是如此。

每个数据库的选项
选项类型默认值说明
connection_string字符串必填SQL Server 连接字符串
max_query_rows整数10 000每次查询调用返回的最大行数
default_timeout_seconds整数30SQL 命令超时时间,单位为秒
连接字符串中的环境变量展开

在连接字符串中使用 %{VARIABLE_NAME},避免以明文形式存储凭据。 服务启动时会从进程环境中解析变量。

{
  "CRM": {
    "connection_string": "Server=SQLSRV01;Database=CRM;User Id=%{CRM_DB_USER};Password=%{CRM_DB_PASS}",
    "max_query_rows": 2000
  }
}

%{CRM_DB_USER} 和 %{CRM_DB_PASS} 会替换为相应 OS 环境变量的值。如果引用的变量不存在,则不会加载任何连接, 并且每个工具都会指出缺失的变量(请参阅未配置连接时)。

回退方式:MCP_SQL_CONNECTIONS 环境变量

如果未提供 --connections,服务会回退到读取 MCP_SQL_CONNECTIONS 环境变量,该变量必须直接包含 JSON 内容。 此方式仅为向后兼容;建议使用基于文件的方式。

未配置连接时

即使没有找到连接,或无法读取配置 (JSON 无效、%{VARIABLE} 未设置、--connections 指定的文件不存在),服务也会启动。 MCP 客户端只能将启动时退出的服务显示为“失败”,原因则隐藏在日志中;而能正常响应的服务可以说明缺少什么。因此,服务会:

  • 在服务说明中指出问题,客户端连接后会立即将其传递给模型;
  • 对每个工具调用都作出响应,说明 ok: false、出错原因、需要创建的文件、尝试查找的位置以及内容示例:
{
  "ok": false,
  "tool": "list_databases",
  "error": "No database connection is configured: none of the places this server reads holds a connection string.",
  "hint": "Ask the user for a SQL Server connection string, preferably of a login that can only read, and save it in the file named in 'setup.file', with the shape shown in 'example'. ...",
  "example": {
    "MyDatabase": "Server=SQLSRV01;Database=MyDatabase;Integrated Security=True;TrustServerCertificate=True",
    "Reporting": { "connection_string": "...User Id=%{REPORTING_USER};Password=%{REPORTING_PASS}...", "max_query_rows": 5000 }
  },
  "setup": {
    "file": "C:\\Projects\\Risk\\.elekto.mcp.sql.local.json",
    "file_for_every_project": "C:\\Users\\YourName\\.elekto.mcp.sql.local.json",
    "searched": [ "C:\\Projects\\Risk\\.elekto.mcp.sql.local.json", "ConnectionStrings in C:\\Projects\\Risk\\appsettings.Development.json", "..." ],
    "notes": [ "..." ],
    "documentation": "https://github.com/elekto-com-br/elekto-mcp-sql#configuration"
  }
}
  • 在尚未加载任何连接时,每次调用都会再次查找;因此,之后创建的连接文件 (由你创建,或是在你提供连接字符串后由 Agent 创建)会在下一次调用时生效, 无需重启。

连接加载后会一直保留,直到服务重启。因此,已读取文件发生更改后,需要重启服务 (在 Claude Code 中,执行 /mcp 并重新连接;在 Codex 中,重新启动 Codex)。

Claude Code 配置

安装工具(参见安装),并使用 claude mcp add 注册。 -- 后的所有内容都是 Claude Code 运行的命令:

dotnet tool install -g Elekto.Mcp.Sql
claude mcp add sql -- elekto-mcp-sql

Claude Code 会在项目目录中启动服务,因此零配置发现功能和在 Visual Studio 中一样有效:项目中的 .elekto.mcp.sql.local.json,或 appsettings.json / web.config 中的 ConnectionStrings,无需任何参数即可找到。

-s(--scope)用于选择保存注册信息的位置:

范围命令适用范围
local(默认)claude mcp add sql -- elekto-mcp-sql仅限你在此项目中使用(保存在 ~/.claude.json 中)
userclaude mcp add -s user sql -- elekto-mcp-sql你在所有项目中使用
projectclaude mcp add -s project sql -- elekto-mcp-sql此项目中的所有克隆者(写入 .mcp.json)

使用 -s user 注册后,即使没有数据库的项目也会启动该服务;在这些项目中,工具会说明如何添加连接,而不是直接报错(参见 未配置连接时)。

其他形式:

# An explicit connections file; no other source is read
claude mcp add sql -- elekto-mcp-sql --connections C:\Users\YourName\sql-connections.json

# Without installing the tool (needs the .NET 10 SDK, which brings dnx)
claude mcp add sql -- dnx Elekto.Mcp.Sql --yes

在 Windows 上,安装的命令是一个真正的可执行文件(%USERPROFILE%\.dotnet\tools\elekto-mcp-sql.exe),因此无需像通过 npx 启动的服务那样使用 cmd /c 包装器。

机密信息。 claude mcp add -e NAME=value 会将值以纯文本形式存储在 ~/.claude.json 中;使用 -s project 时则存储在 .mcp.json 中,而该文件通常会提交到版本库。对于密码,请在连接字符串中写入 %{NAME},并将 NAME 设为你用户帐户的环境变量:Claude Code 会将自身环境变量传递给服务。

使用 claude mcp list 检查注册信息(服务应显示为 Connected),也可以在 Claude Code 中使用 /mcp,它还会列出工具并重新连接服务。

手动编写的 Claude Code .mcp.json 使用键 mcpServers,而 Visual Studio 和 VS Code 使用 servers:

{
  "mcpServers": {
    "sql": {
      "type": "stdio",
      "command": "elekto-mcp-sql",
      "args": []
    }
  }
}

Codex 配置

Codex 是 OpenAI 的编码 Agent(CLI、IDE 扩展和应用),同样可以运行本地 MCP 服务。安装工具(参见安装),并使用 codex mcp add 注册。-- 后的所有内容都是 Codex 运行的命令:

dotnet tool install -g Elekto.Mcp.Sql
codex mcp add sql -- elekto-mcp-sql

这会将服务添加到 ~/.codex/config.toml(Windows 上为 %USERPROFILE%\.codex\config.toml),因此适用于所有项目:

[mcp_servers.sql]
command = "elekto-mcp-sql"

Codex 会在项目目录中启动服务,因此零配置发现功能在这里同样有效。在没有数据库的项目中,工具会说明如何添加连接(参见 未配置连接时)。

若要仅为一个项目注册服务,请改为在项目根目录的 .codex/config.toml 中放入相同的表。Codex 只会在标记为可信的项目中读取该文件。

codex mcp list 和 codex mcp get sql 会显示配置。与 claude mcp list 不同,它们不会启动服务,因此命令中的错误只有在 Codex 会话启动时才会显示。

不会传递环境变量

与 Claude Code 不同,Codex 启动 MCP 服务时只会提供一小部分自身的环境变量(例如 HOME 和 PATH),而不会传递你的全部环境变量。因此,除非在 env_vars 中列出并从你的环境中转发,否则连接字符串中的 %{VARIABLE} 将无法找到:

[mcp_servers.sql]
command = "elekto-mcp-sql"
env_vars = ["CRM_DB_USER", "CRM_DB_PASS"]

即使未设置该项,服务仍会启动,并且每个工具都会指出它无法找到的变量。

codex mcp add --env NAME=value 会直接设置一个值(写入 env 表),但会将其以纯文本形式存储在 config.toml 中。请仅将其用于非机密值。

其他形式

使用显式连接文件,不读取其他来源:

[mcp_servers.sql]
command = "elekto-mcp-sql"
args = ["--connections", 'C:\Users\YourName\sql-connections.json']

Windows 路径要放在单引号中,TOML 会按字面值处理。在双引号中,C:\Users 里的 \U 会被识别为转义序列,Codex 因而拒绝整个文件;使用双引号时,必须将每个反斜杠 加倍。codex mcp add 会自行写入单引号。

不安装工具(需要 .NET 10 SDK,其中包含 dnx):

[mcp_servers.sql]
command = "dnx"
args = ["Elekto.Mcp.Sql", "--yes"]
startup_timeout_sec = 30

首次启动时会下载程序包,所需时间可能超过 Codex 默认等待服务启动的时长;startup_timeout_sec 可以延长等待时间。已安装的工具启动时间不到一秒,无需此类设置。

如果 Codex 在 WSL 中运行,它会在 Linux 中启动服务,而 Linux 无法访问安装在 Windows 上的工具:也要在 WSL 中安装 .NET 和该工具。Linux 中的 Integrated Security 还需要配置 Kerberos;使用 SQL Server 登录名,并将密码放在 env_vars 中列出的 %{VARIABLE} 里,会更简单。

Visual Studio 2026 设置(.mcp.json)

在解决方案根目录(或用户配置文件中,以便全局使用)创建或编辑 .mcp.json。

推荐:本地连接文件(零配置)

将 .elekto.mcp.sql.local.json 文件放在项目根目录或 ~ 中;服务会自动找到它。.mcp.json 中无需任何参数:

{
  "servers": {
    "sql": {
      "type": "stdio",
      "command": "dotnet",
      "args": ["D:\\Tools\\Elekto.Mcp.Sql\\Elekto.Mcp.Sql.dll"]
    }
  }
}
替代方案:通过 --connections 指定路径

使用 --connections 将服务指向任意文件。如果文件位于项目目录树之外,或者需要在多个配置之间切换,此方式会很有用:

{
  "servers": {
    "sql": {
      "type": "stdio",
      "command": "dotnet",
      "args": [
        "D:\\Tools\\Elekto.Mcp.Sql\\Elekto.Mcp.Sql.dll",
        "--connections",
        "C:\\Users\\YourName\\sql-connections.json"
      ]
    }
  }
}

连接文件本身保留在仓库之外,因此凭据永远不会提交到源代码管理中。

替代方案:环境变量(旧版)

如果不想使用文件,仍可通过环境变量传入 JSON。请注意,在嵌套的 JSON 中,反斜杠需要双重转义(\\\\):

{
  "servers": {
    "sql": {
      "type": "stdio",
      "command": "dotnet",
      "args": ["D:\\Tools\\Elekto.Mcp.Sql\\Elekto.Mcp.Sql.dll"],
      "env": {
        "MCP_SQL_CONNECTIONS": "{\"MyDb\": {\"connection_string\": \"Server=SQLSRV01\\\\INST;Database=MyDb;Integrated Security=SSPI\"}}"
      }
    }
  }
}

保存 .mcp.json 后,Copilot 会自动重启服务。 工具默认处于禁用状态:请在 Copilot Chat 工具面板中启用它们。

构建和发布

cd Elekto.Mcp.Sql\src
dotnet publish -c Release -o C:\Tools\Elekto.Mcp.Sql

需要在计算机上安装 .NET 10。发布目录约为 7 MB(NuGet 依赖项)。 对于内部使用,推荐采用此方式,而非独立部署(约 81 MB)。

dotnet pack 还会打包 src/.mcp/server.json,该文件会告知 nuget.org 如何启动服务。仓库中的文件以 $version$ 作为版本占位符;打包时会将其替换为当前打包的版本,因此发布时无需更新该文件。

每个标签还会将服务发布到 MCP Registry,名称为 io.github.elekto-com-br/elekto-mcp-sql,但需等 nuget.org 编入新版本索引后才会发布。Registry 只有在 README 中包含 mcp-name: io.github.elekto-com-br/elekto-mcp-sql 这一行时,才会接受该程序包为我们的程序包;因此必须保留本文件顶部的注释;如果打包后的 README 中缺少该行,CI 会失败。

程序包版本锁定在 src/packages.lock.json 和 tests/packages.lock.json 中。更改 PackageReference 后,请运行 dotnet restore 并一并提交锁定文件:CI 和发布还原会以锁定模式运行,如果锁定文件与项目不匹配,就会失败。

验证发布

2.3.2 之后的版本会在其 GitHub Release 中附带程序包,并附有构建来源证明,将其与此仓库的发布工作流及发布标签关联起来。可使用 GitHub CLI 检查:

gh release download vX.Y.Z --repo elekto-com-br/elekto-mcp-sql --pattern '*.nupkg'
gh attestation verify Elekto.Mcp.Sql.X.Y.Z.nupkg --repo elekto-com-br/elekto-mcp-sql

nuget.org 提供的副本还带有 nuget.org 自己的仓库签名,因此它与经过来源证明的文件不同;dotnet nuget verify 可用于验证该签名。

运行测试

在仓库根目录中运行:

dotnet test

测试项目包含两类测试:

  • 单元测试(例如 ConnectionConfigTests)只需要 .NET SDK。
  • 集成测试(SchemaReaderTests)会连接到真实的 SQL Server。每次运行都会创建名为 ElektoMcpTest 的数据库,填入少量种子架构,并在结束时将其删除。

集成测试会按以下顺序查找 SQL Server,并使用找到的第一个:

  1. ELEKTO_MCP_SQL_CONN_TEST 环境变量。 如果已设置,其中必须包含测试可以使用的服务器连接字符串。字符串中指定的数据库(如果有)会被忽略。登录名需要有权创建和删除数据库。如果无法连接到此服务器,测试会立即失败,而不会尝试下一个选项,因为显式指定的选项不可用是值得关注的错误。
  2. LocalDB,仅限 Windows,且仅当 (localdb)\MSSQLLocalDB 实例有响应时使用。
  3. 通过 Testcontainers 启动的临时容器,使用 mcr.microsoft.com/mssql/server:2022-latest 镜像。这需要 Docker(无根 Docker 也可)。只有集成测试需要时才会启动容器,并在运行结束时将其移除。首次运行还会下载镜像,这需要一些时间。

如果以上选项都不可用,集成测试会失败,并列出尝试过的选项以及各自不可用的原因。测试输出会说明使用了哪个服务器。

部分集成测试会使用受限登录名运行,以检查 SQL Server 隐藏对象时工具会如何响应。测试夹具会创建这些登录名(ElektoMcpTest_*),并在结束时将其删除;这同样需要 ALTER ANY LOGIN 权限。若服务器不允许此操作,相应测试会跳过并说明原因。

示例:将测试指向现有服务器:

export ELEKTO_MCP_SQL_CONN_TEST="Server=localhost,1433;User Id=sa;Password=<password>;TrustServerCertificate=True"
dotnet test

不要将 ELEKTO_MCP_SQL_CONN_TEST 指向其中名为 ElektoMcpTest 的数据库对任何人都很重要的服务器:测试会删除并重新创建该数据库。

若要仅运行单元测试,无需 SQL Server:

dotnet test --filter "FullyQualifiedName!~SchemaReaderTests"

建议的权限

允许读取工具读取的所有内容,但不授予任何修改权限:

USE [YourDatabase];
CREATE USER [mcp_reader] FOR LOGIN [mcp_reader];  -- if the user does not exist yet
ALTER ROLE db_datareader ADD MEMBER [mcp_reader];  -- tables and views; also covers sys.sql_expression_dependencies
GRANT VIEW DEFINITION TO [mcp_reader];             -- procedures, functions, view text, complete dependencies

USE master;
GRANT VIEW SERVER STATE TO [mcp_reader];           -- get_index_health: unused and missing indexes

在 SQL Server 2022 及更高版本中,最后一项授权可以缩小到索引 DMV 实际需要的权限:

USE master;
GRANT VIEW SERVER PERFORMANCE STATE TO [mcp_reader];
权限缺少时的影响
db_datareader(数据库上的 SELECT 权限)登录名未获得授权的表和视图不会列出;对其执行 query_table 会失败。如果登录名不属于 db_datareader,还需要 GRANT SELECT ON sys.sql_expression_dependencies
数据库上的 VIEW DEFINITION不会列出存储过程和函数,视图和模块文本会被隐藏,依赖关系不完整
VIEW SERVER STATE(2022+:VIEW SERVER PERFORMANCE STATE)get_index_health 只返回重复索引

这些权限均不允许登录名修改数据或架构。对数据库运行 check_permissions,即可查看缺少哪些权限——它会输出适用于该登录名和服务器版本的语句。

限制与安全

  • 只读:仅允许对表和视图执行 SELECT。不支持 DML,也不支持执行存储过程或函数。
  • query_table 会根据经过验证的参数在内部构建 SQL。标识符(表、架构、列)在组合成 SQL 之前会通过正则表达式进行验证。
  • WHERE 子句接受自由文本(这是实现灵活性所必需的),但无法执行 DML,因为命令始终构建为 SELECT TOP n ... FROM [t] WHERE ...。
  • max_query_rows 限制每个数据库返回的最大行数(默认值为 10,000)。query_table 中的 top 参数始终会被限制在此值以内,并通过 top_requested 和 truncated 说明这一点,而不是悄然返回较少的结果。
  • 即便如此,也应避免在不可信环境中或使用敏感数据时暴露此服务。使用防火墙和访问策略,限制可通过 MCP 执行查询的人员。所有已配置的连接都应使用权限符合最低要求(只读)的数据库账户。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。