火鸟数据库助手
一个为Firebird SQL数据库实现Anthropic模型上下文协议(MCP)的服务器,使克劳德和其他大型语言模型能够通过自然语言安全地访问、分析和操作Firebird数据库中的数据。
MCP 服务配置
复制以下 JSON 到 OPClaw 或其他 MCP 客户端的配置文件中即可使用
{
"mcpServers": {
"mcp-firebird": {
"args": [
"mcp-firebird",
"--host",
"localhost",
"--port",
"3050",
"--database",
"C:Databasesexample.fdb",
"--user",
"SYSDBA",
"--password",
"masterkey"
],
"command": "npx"
}
}
}
该服务需要配置环境变量:FIREBIRD_DATABASE、FIREBIRD_DATABASE_DIR、FIREBIRD_HOST、FIREBIRD_PASSWORD、FIREBIRD_PORT、FIREBIRD_ROLE、FIREBIRD_USER、LOG_LEVEL
可用工具 (4 个)
该服务在 MCP 协议中暴露的工具,AI 可按需调用
execute-query 2 个参数 需填 1 项
必填参数:sql
list-tables
该工具无需必填参数,直接调用即可
describe-table 1 个参数 需填 1 项
必填参数:tableName
get-field-descriptions 1 个参数 需填 1 项
必填参数:tableName
服务介绍
MCP Firebird
Anthropic 的 MCP 协议在 Firebird 数据库中的实现。
什么是 MCP Firebird 以及它的用途?
MCP Firebird 是一个服务器,它实现了 Anthropic 的 Model Context Protocol (MCP) 用于 Firebird SQL 数据库。它允许像 Claude 这样的大型语言模型(LLMs)以安全和受控的方式访问、分析和操作 Firebird 数据库中的数据。
下面你会找到用例和示例。
安装
# Global installation
npm install -g mcp-firebird
# Project installation
npm install mcp-firebird
配置
环境变量
你可以使用环境变量来配置服务器:
# Basic configuration
export FIREBIRD_HOST=localhost
export FIREBIRD_PORT=3050
export FIREBIRD_DATABASE=/path/to/database.fdb
export FIREBIRD_USER=SYSDBA
export FIREBIRD_PASSWORD=masterkey
export FIREBIRD_ROLE=undefined # Optional
# Directory configuration (alternative)
export FIREBIRD_DATABASE_DIR=/path/to/databases # Directory with databases
使用 npx 运行
你可以直接使用 npx 来运行服务器:
npx mcp-firebird --host localhost --port 3050 --database /path/to/database.fdb --user SYSDBA --password masterkey
与 Claude Desktop 配置
要将 Firebird MCP 服务器与 Claude Desktop 一起使用:
添加以下配置:
{
"mcpServers": {
"mcp-firebird": {
"command": "npx",
"args": [
"mcp-firebird",
"--host",
"localhost",
"--port",
"3050",
"--database",
"C:\\Databases\\example.fdb",
"--user",
"SYSDBA",
"--password",
"masterkey"
]
}
}
}
资源和功能
MCP Firebird 服务器提供:
- Databases: 所有可用数据库的列表
- Tables: 数据库中所有表的列表
- Views: 数据库中所有视图的列表
- Stored procedures: 访问数据库中的过程
- Table schemas: 每个表的详细结构
- Data: 访问表数据
可用工具
-
list-tables: 列出数据库中的所有表
{} // 不需要参数 -
describe-table: 描述表的结构
{ "tableName": "EMPLOYEES" } -
execute-query: 在数据库中执行 SQL 查询
{ "sql": "SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID = 10", "params": [] // 可选参数,用于预处理查询 } -
get-field-descriptions: 获取字段描述
{ "tableName": "EMPLOYEES" }
get-field-descriptions 工具对 AI 模型特别有用,因为它从 Firebird 的 RDB$DESCRIPTION 元数据中检索注释,为每个字段的目的提供了额外的语义上下文。
可用提示
-
query-data: 使用自然语言查询数据
查找 2023 年销售部门招聘的所有员工 -
analyze-table: 分析表的结构
分析 EMPLOYEES 表并解释其结构 -
optimize-query: 优化 SQL 查询
优化:SELECT * FROM EMPLOYEES WHERE LAST_NAME = 'Smith' -
generate-sql: 根据描述生成 SQL
生成一个查询以获取 10 个最畅销的产品
从不同语言中使用
TypeScript/JavaScript
// Example with TypeScript
import { McpClient, ChildProcessTransport } from '@modelcontextprotocol/sdk';
import { spawn } from 'child_process';
async function main() {
// Start the MCP server process
const serverProcess = spawn('npx', [
'mcp-firebird',
'--database', '/path/to/database.fdb',
'--user', 'SYSDBA',
'--password', 'masterkey'
]);
// Create a transport and an MCP client
const transport = new ChildProcessTransport(serverProcess);
const client = new McpClient(transport);
try {
// Get server information
const serverInfo = await client.getServerInfo();
console.log('MCP Server:', serverInfo);
// List available tables
const tablesResult = await client.executeTool('list-tables', {});
console.log('Available tables:', tablesResult);
// Execute an SQL query
const queryResult = await client.executeTool('execute-query', {
sql: 'SELECT FIRST 10 * FROM EMPLOYEES'
});
console.log('Query results:', queryResult);
// Use a prompt to generate SQL
const sqlGeneration = await client.executePrompt('generate-sql', {
description: 'Get all premium customers'
});
console.log('Generated SQL:', sqlGeneration);
} catch (error) {
console.error('Error:', error);
} finally {
// Close the server process
serverProcess.kill();
}
}
main().catch(console.error);
Python
# Example with Python
import json
import subprocess
from subprocess import PIPE
class McpFirebirdClient:
def __init__(self, database_path, user='SYSDBA', password='masterkey'):
# Start the MCP server process
self.process = subprocess.Popen(
['npx', 'mcp-firebird', '--database', database_path, '--user', user, '--password', password],
stdin=PIPE,
stdout=PIPE,
stderr=PIPE,
text=True,
bufsize=1
)
def send_request(self, method, params={}):
request = {
'id': 1,
'method': method,
'params': params
}
# Send the request to the server
self.process.stdin.write(json.dumps(request) + '\n')
self.process.stdin.flush()
# Read the response
response_line = self.process.stdout.readline()
while not response_line.strip() or response_line.startswith('['):
response_line = self.process.stdout.readline()
# Parse and return the JSON response
return json.loads(response_line)
def get_server_info(self):
return self.send_request('getServerInfo')
def list_tables(self):
return self.send_request('executeTool', {'name': 'list-tables', 'args': {}})
def execute_query(self, sql, params=[]):
return self.send_request('executeTool', {
'name': 'execute-query',
'args': {'sql': sql, 'params': params}
})
def generate_sql(self, description):
return self.send_request('executePrompt', {
'name': 'generate-sql',
'args': {'description': description}
})
def close(self):
self.process.terminate()
# Client usage
client = McpFirebirdClient('/path/to/database.fdb')
try:
# Get server information
server_info = client.get_server_info()
print(f"MCP Server: {server_info}")
# List tables
tables = client.list_tables()
print(f"Available tables: {tables}")
# Execute a query
results = client.execute_query("SELECT FIRST 10 * FROM EMPLOYEES")
print(f"Results: {results}")
# Generate SQL
sql = client.generate_sql("List the best-selling products")
print(f"Generated SQL: {sql}")
finally:
client.close()
Delphi 和 Lazurus
// Example with Delphi
program McpFirebirdClient;
{$APPTYPE CONSOLE}
uses
System.SysUtils, System.Classes, System.JSON, System.Net.HttpClient,
System.Diagnostics, System.IOUtils;
type
TMcpFirebirdClient = class
private
FProcess: TProcess; //For Delphi change to TProcessDelphi and add https://github.com/ferruhkoroglu/TProcessDelphi
FRequestId: Integer;
function SendRequest(const Method: string; const Params: TJSONObject = nil): TJSONObject;
function ReadResponse: string;
public
constructor Create(const DatabasePath, User, Password: string);
destructor Destroy; override;
function GetServerInfo: TJSONObject;
function ListTables: TJSONObject;
function ExecuteQuery(const SQL: string; Params: TArray<Variant> = nil): TJSONObject;
function GenerateSQL(const Description: string): TJSONObject;
end;
constructor TMcpFirebirdClient.Create(const DatabasePath, User, Password: string);
begin
inherited Create;
FRequestId := 1;
// Create and configure the process
FProcess := TProcess.Create(nil);
FProcess.Executable := 'npx';
FProcess.Parameters.Add('mcp-firebird');
FProcess.Parameters.Add('--database');
FProcess.Parameters.Add(DatabasePath);
FProcess.Parameters.Add('--user');
FProcess.Parameters.Add(User);
FProcess.Parameters.Add('--password');
FProcess.Parameters.Add(Password);
FProcess.Options := [poUsePipes, poStderrToOutPut];
FProcess.Execute;
// Wait for the server to start
Sleep(2000);
end;
destructor TMcpFirebirdClient.Destroy;
begin
FProcess.Free;
inherited;
end;
function TMcpFirebirdClient.SendRequest(const Method: string; const Params: TJSONObject = nil): TJSONObject;
var
Request: TJSONObject;
RequestStr, ResponseStr: string;
begin
// Create the JSON request
Request := TJSONObject.Create;
try
Request.AddPair('id', TJSONNumber.Create(FRequestId));
Inc(FRequestId);
Request.AddPair('method', Method);
if Assigned(Params) then
Request.AddPair('params', Params)
else
Request.AddPair('params', TJSONObject.Create);
RequestStr := Request.ToString + #10;
// Send the request to the process
FProcess.Input.Write(RequestStr[1], Length(RequestStr) * 2);
// Read the response
ResponseStr := ReadResponse;
Result := TJSONObject.ParseJSONValue(ResponseStr) as TJSONObject;
finally
Request.Free;
end;
end;
function TMcpFirebirdClient.ReadResponse: string;
var
Buffer: TBytes;
BytesRead: Integer;
ResponseStr: string;
begin
SetLength(Buffer, 4096);
ResponseStr := '';
repeat
BytesRead := FProcess.Output.Read(Buffer[0], Length(Buffer));
if BytesRead > 0 then
begin
SetLength(Buffer, BytesRead);
ResponseStr := ResponseStr + TEncoding.UTF8.GetString(Buffer);
end;
until BytesRead = 0;
Result := ResponseStr;
end;
function TMcpFirebirdClient.GetServerInfo: TJSONObject;
begin
Result := SendRequest('getServerInfo');
end;
function TMcpFirebirdClient.ListTables: TJSONObject;
var
Params: TJSONObject;
begin
Params := TJSONObject.Create;
try
Params.AddPair('name', 'list-tables');
Params.AddPair('args', TJSONObject.Create);
Result := SendRequest('executeTool', Params);
finally
Params.Free;
end;
end;
function TMcpFirebirdClient.ExecuteQuery(const SQL: string; Params: TArray<Variant> = nil): TJSONObject;
var
RequestParams, Args: TJSONObject;
ParamsArray: TJSONArray;
I: Integer;
begin
RequestParams := TJSONObject.Create;
Args := TJSONObject.Create;
ParamsArray := TJSONArray.Create;
try
// Configure the arguments
Args.AddPair('sql', SQL);
if Length(Params) > 0 then
begin
for I := 0 to Length(Params) - 1 do
begin
case VarType(Params[I]) of
varInteger: ParamsArray.Add(TJSONNumber.Create(Integer(Params[I])));
varDouble: ParamsArray.Add(TJSONNumber.Create(Double(Params[I])));
varBoolean: ParamsArray.Add(TJSONBool.Create(Boolean(Params[I])));
else ParamsArray.Add(String(Params[I]));
end;
end;
end;
Args.AddPair('params', ParamsArray);
RequestParams.AddPair('name', 'execute-query');
RequestParams.AddPair('args', Args);
Result := SendRequest('executeTool', RequestParams);
finally
RequestParams.Free;
end;
end;
function TMcpFirebirdClient.GenerateSQL(const Description: string): TJSONObject;
var
RequestParams, Args: TJSONObject;
begin
RequestParams := TJSONObject.Create;
Args := TJSONObject.Create;
try
Args.AddPair('description', Description);
RequestParams.AddPair('name', 'generate-sql');
RequestParams.AddPair('args', Args);
Result := SendRequest('executePrompt', RequestParams);
finally
RequestParams.Free;
end;
end;
var
Client: TMcpFirebirdClient;
ServerInfo, Tables, QueryResults, GeneratedSQL: TJSONObject;
begin
try
WriteLn('Starting MCP Firebird client...');
// Create the client
Client := TMcpFirebirdClient.Create('C:\Databases\example.fdb', 'SYSDBA', 'masterkey');
try
// Get server information
ServerInfo := Client.GetServerInfo;
WriteLn('Server information: ', ServerInfo.ToString);
// List tables
Tables := Client.ListTables;
WriteLn('Available tables: ', Tables.ToString);
// Execute a query
QueryResults := Client.ExecuteQuery('SELECT FIRST 10 * FROM EMPLOYEES');
WriteLn('Query results: ', QueryResults.ToString);
// Generate SQL
GeneratedSQL := Client.GenerateSQL('Get all premium customers');
WriteLn('Generated SQL: ', GeneratedSQL.ToString);
finally
Client.Free;
end;
except
on E: Exception do
WriteLn('Error: ', E.Message);
end;
WriteLn('Press ENTER to exit...');
ReadLn;
end.
Docker 配置
您可以在 Docker 容器中运行 MCP Firebird 服务器:
Dockerfile
FROM node:18-alpine
# Install necessary dependencies for Firebird
RUN apk add --no-cache firebird-client
# Create application directory
WORKDIR /app
# Copy project files
COPY package*.json ./
RUN npm install
# Copy source code
COPY . .
# Compile the TypeScript project
RUN npm run build
# Expose port if HTTP is used (optional)
# EXPOSE 3000
# Set default environment variables
ENV FIREBIRD_HOST=firebird-db
ENV FIREBIRD_PORT=3050
ENV FIREBIRD_USER=SYSDBA
ENV FIREBIRD_PASSWORD=masterkey
ENV FIREBIRD_DATABASE=/firebird/data/database.fdb
# Start command
CMD ["node", "dist/index.js"]
Docker Compose
version: '3.8'
services:
# Firebird database server
firebird-db:
image: jacobalberty/firebird:3.0
environment:
ISC_PASSWORD: masterkey
FIREBIRD_DATABASE: database.fdb
FIREBIRD_USER: SYSDBA
volumes:
- firebird-data:/firebird/data
ports:
- "3050:3050"
networks:
- mcp-network
# MCP Firebird server
mcp-firebird:
build:
context: .
dockerfile: Dockerfile
environment:
FIREBIRD_HOST: firebird-db
FIREBIRD_PORT: 3050
FIREBIRD_USER: SYSDBA
FIREBIRD_PASSWORD: masterkey
FIREBIRD_DATABASE: /firebird/data/database.fdb
depends_on:
- firebird-db
networks:
- mcp-network
# For use with Claude Desktop, expose STDIO
stdin_open: true
tty: true
networks:
mcp-network:
driver: bridge
volumes:
firebird-data:
使用 Docker 运行
# Build and run with Docker Compose
docker compose up -d
# Check logs
docker compose logs -f mcp-firebird
# Stop services
docker compose down
最近更新
版本 1.0.93(从 1.0.91 更新)
MCP Firebird 已经有了显著改进,包括:
-
增强的 TypeScript 接口:
- 新增接口以提高类型安全性(FirebirdDatabase, ConfigOptions, DatabaseInfo, TableInfo 等)
- 对所有参数和返回值进行更严格的类型检查
-
改进的错误处理:
- 自定义
FirebirdError类别以更好地分类错误 - 详细检测不同类型的错误(连接、语法、权限等)
- 更具信息性的错误消息以便于调试
- 自定义
-
新功能和工具:
get-methods工具用于 API 发现- 用于分析表和优化查询的新提示
describeTable函数用于详细描述表结构listTables函数用于简单列出表名
-
更好的文档:
- 所有函数的全面 JSDoc
- 改进后的 MCP 工具描述,包含特定于 Firebird 的信息
- 明确指定 Firebird 使用 FIRST/ROWS 而不是 LIMIT 进行分页
-
安全改进:
- 显式的 SQL 参数验证
- 增强的 SQL 注入防护
- 可配置的表和操作访问限制
-
代码质量:
- 移除不必要的文件(server.js, server.new.js, test-*.js 等)
- 更紧凑的 JSON 响应(移除不必要的空格)
- 统一的日志记录方法
使用案例
-
使用 AI 进行数据分析:
- 分析历史销售趋势
- 识别财务数据中的模式
- 检测交易记录中的异常
-
SQL 查询生成:
- 从自然语言描述中创建复杂查询
- 优化现有查询以提高性能
- 在不同的 SQL 方言之间转换查询
-
自动化文档:
- 生成关于数据库结构的文档
- 解释表和模式之间的关系
- 创建详细的数据字典
-
开发辅助:
- 提议索引来提高性能
- 提出模式规范化建议
- 帮助在系统间迁移数据
销售分析用例示例
与 Claude 的交互:
User: Connect to my Firebird database and analyze sales trends by region in the last quarter.
Claude: I'll connect to your Firebird database to analyze regional sales trends.
[Claude uses MCP Firebird to execute several SQL queries]
Based on data from the last quarter, I've identified the following trends:
1. The North region has experienced 12.5% growth compared to the previous quarter
2. The South region shows a 3.2% decrease in electronics products
3. The "Laptop Pro X" product is the best-selling across all regions
4. Sales in the East region show a cyclical pattern with peaks on weekends
Graphically, the distribution of sales by region is:
[Graph generated by Claude based on the data]
Would you like to delve deeper into any specific region or product category?
查询优化示例
User: I have this query that's running slowly, can you optimize it?
SELECT c.CUSTOMER_NAME, SUM(o.ORDER_TOTAL)
FROM CUSTOMERS c
JOIN ORDERS o ON c.CUSTOMER_ID = o.CUSTOMER_ID
WHERE o.ORDER_DATE > '2024-01-01'
GROUP BY c.CUSTOMER_NAME
ORDER BY SUM(o.ORDER_TOTAL) DESC
Claude: I'll analyze this query to optimize it.
[Claude uses MCP Firebird to analyze the schema and query]
I've identified several optimization opportunities:
1. The current query doesn't efficiently use indexes
2. The calculation of SUM(o.ORDER_TOTAL) is performed twice
Here's the optimized version:
```sql
SELECT c.CUSTOMER_NAME, total_sales
FROM CUSTOMERS c
JOIN (
SELECT CUSTOMER_ID, SUM(ORDER_TOTAL) as total_sales
FROM ORDERS
WHERE ORDER_DATE > '2024-01-01'
GROUP BY CUSTOMER_ID
) o ON c.CUSTOMER_ID = o.CUSTOMER_ID
ORDER BY total_sales DESC
此版本:
- 在连接之前减少数据集
- 仅计算一次总和
- 可能受益于 ORDERS(ORDER_DATE, CUSTOMER_ID, ORDER_TOTAL) 上的索引
当在您的数据库上运行这两个查询时,优化版本大约快 45%。
## Integration with AI Agents
### Claude in the Terminal
You can use the MCP Firebird server with Claude in the terminal:
```bash
# Start the MCP server in one terminal
npx mcp-firebird --database /path/to/database.fdb --user SYSDBA --password masterkey
# In another terminal, use anthropic CLI with MCP
anthropic messages create \
--model claude-3-opus-20240229 \
--max-tokens 4096 \
--mcp "npx mcp-firebird --database /path/to/database.fdb --user SYSDBA --password masterkey" \
--message "Analyze the structure of my Firebird database"
其他 AI 代理
MCP Firebird 服务器与任何实现 MCP 协议的代理兼容,只需提供启动服务器的命令即可:
npx mcp-firebird --database /path/to/database.fdb --user SYSDBA --password masterkey
安全性
该服务器实现了以下安全措施:
- 使用 Zod 进行输入验证
- SQL 查询清理
- 安全处理凭证
- 防止 SQL 注入
- 限制破坏性操作
调试和故障排除
要启用调试模式:
export LOG_LEVEL=debug
常见问题
-
数据库连接错误:
- 验证凭证和数据库路径
- 确保 Firebird 服务器正在运行
- 检查用户是否有足够的权限
-
Claude Desktop 中未显示服务器:
- 重启 Claude Desktop
- 验证
claude_desktop_config.json中的配置 - 确保数据库路径是绝对路径
-
STDIO 问题:
- 确保标准输出没有被重定向
- 不要使用
console.log进行调试(请使用console.error)
许可证
MIT