🚀 Florentine.ai MCP 服務器 - 與你的 MongoDB 和 MySQL 數據對話
Florentine.ai 模型上下文協議(MCP)服務器允許你將針對 MongoDB 和 MySQL 數據的自然語言查詢直接集成到自定義 AI 代理或 AI 桌面應用程序中。
AI 代理將問題轉發給 MCP 服務器,服務器將其轉換為數據庫查詢,然後將查詢結果返回給代理進行進一步處理。
此外,它還具備一些額外功能,例如:
- 多租戶使用的安全數據分離
- 自動模式探索
- 支持語義向量搜索/檢索增強生成(RAG),可自動創建嵌入
- 高級查找支持
- 鍵排除
注意:如果你正在尋找我們的 API,可以點擊此處。
🚀 快速開始
Florentine.ai MCP 服務器能讓你輕鬆實現對 MongoDB 和 MySQL 數據的自然語言查詢。以下是使用該服務器的基本步驟和相關信息。
✨ 主要特性
- 支持將自然語言查詢集成到自定義 AI 代理或 AI 桌面應用中。
- 具備多租戶使用的安全數據分離功能。
- 可自動進行模式探索。
- 支持語義向量搜索和 RAG,能自動創建嵌入。
- 提供高級查找支持和鍵排除功能。
📦 安裝指南
MCP 服務器的詳細文檔可點擊此處查看。
你可以使用 npx 輕鬆運行服務器。以下是針對 Claude 桌面應用(claude_desktop_config.json)的示例:
{
"mcpServers": {
"florentine": {
"command": "npx",
"args": ["-y", "@florentine-ai/mcp", "--mode", "static"],
"env": {
"FLORENTINE_TOKEN": "<FLORENTINE_API_KEY>"
}
}
}
}
💻 使用示例
基礎用法
Florentine.ai MCP 服務器提供了兩個實用工具,以下是它們的使用示例:
- florentine_list_collections:列出所有當前可查詢的活動集合/表,包括描述、鍵和值的類型。
- florentine_ask:接收一個問題,並根據
returnTypes 設置返回查詢、查詢結果或答案。
高級用法
在不同的集成模式下,你可以更靈活地使用 florentine_ask 工具,具體請參考後續的集成模式部分。
📚 詳細文檔
前提條件
- Node.js >= v18.0.0
- 一個 Florentine.ai 賬戶(可點擊此處創建免費賬戶)
- 一個已連接的數據庫,並且在你的 Florentine.ai 賬戶中至少有一個已分析並激活的集合/表
- 一個 Florentine.ai API 密鑰(你可以在賬戶儀表盤中找到)
可用工具
- florentine_list_collections:列出所有當前可查詢的活動集合/表,包括描述、鍵和值的類型。
- florentine_ask:接收一個問題,並根據
returnTypes 設置返回查詢、查詢結果或答案。
參數說明
| 變量 |
是否必需 |
允許的值 |
描述 |
--mode |
是 |
static, dynamic |
static(適用於現有的外部 MCP 客戶端,如 Claude 桌面應用)或 dynamic(適用於自定義 MCP 客戶端)。請參考集成模式部分。 |
--debug |
否 |
true |
啟用將日誌記錄到外部文件。如果設置了該參數,則還需要設置 --logpath。 |
--logpath |
否 |
絕對日誌文件路徑 |
調試日誌的文件路徑。如果設置了該參數,則還需要設置 --debug。 |
身份驗證
Florentine.ai MCP 服務器使用 API 密鑰對請求進行身份驗證。你可以在賬戶儀表盤中查看和管理你的 API 密鑰。該密鑰必須作為環境變量添加到 MCP 服務器的配置設置中:
"env": {
"FLORENTINE_TOKEN": "<FLORENTINE_API_KEY>"
}
連接你的大語言模型(LLM)賬戶
Florentine.ai 採用自帶密鑰模式,因此你需要在 MCP 請求中提供你的 LLM API 密鑰(OpenAI、Google、Anthropic、Deepseek)。
你有兩種添加 LLM API 密鑰的方式:
選項 1:將 LLM 密鑰保存到你的賬戶中(推薦)
連接到 LLM 提供商的最簡單方法是將你的 LLM API 密鑰保存到Florentine.ai 儀表盤中。
- 添加你的 API 密鑰
- 選擇你的 LLM 提供商(OpenAI、Deepseek、Google 或 Anthropic)
- 點擊保存

選項 2:在 MCP 服務器配置環境變量中提供 LLM 密鑰
如果你不想將密鑰存儲在 Florentine.ai 賬戶中,或者想使用多個 LLM 密鑰,可以在 MCP 服務器配置中傳遞密鑰:
"env": {
"LLM_SERVICE": "<YOUR_LLM_SERVICE>",
"LLM_KEY": "<YOUR_LLM_API_KEY>"
}
| 參數 |
描述 |
允許的值 |
LLM_SERVICE |
指定要使用的 LLM 提供商。 |
openai、google、anthropic 或 deepseek |
LLM_KEY |
你為所提供的 LLM 服務使用的 API 密鑰。 |
有效的 API 密鑰字符串 |
注意:如果你在 MCP 服務器配置的環境變量中提供了 LLM_KEY,它將覆蓋你賬戶中存儲的任何密鑰。
集成模式
你需要在 MCP 服務器配置的 args 數組中設置操作模式為 static 或 dynamic:
"args": [
"-y",
"@florentine-ai/mcp",
"--mode",
"static"
]
靜態模式
如果你要將 Florentine.ai 集成到現有的外部 MCP 客戶端(如 Claude 桌面應用或 Dive AI 等支持 MCP 的桌面應用),則應使用靜態模式。
在 static 模式下,你將所有參數(如返回類型、必需輸入等)作為環境變量設置在配置 JSON 中。這意味著這些參數將保持靜態,直到你更改設置配置,並且每次向 Florentine.ai 發送請求時都會包含這些參數。以下是一個示例:
{
"mcpServers": {
"florentine": {
"command": "npx",
"args": ["-y", "@florentine-ai/mcp", "--mode", "static"],
"env": {
"FLORENTINE_TOKEN": "<FLORENTINE_API_KEY>",
"SESSION_ID": "6f7d62f9-8ceb-456b-b7ef-6bd869c3b13a",
"LLM_SERVICE": "openai",
"LLM_KEY": "<YOUR_OPENAI_KEY>",
"RETURN_TYPES": "[\"result\"]",
"REQUIRED_INPUTS": "[{\"keyPath\":\"accountId\",\"value\":\"507f1f77bcf86cd799439011\"}]"
}
}
}
}
環境變量
| 變量 |
是否必需 |
類型 |
描述 |
FLORENTINE_TOKEN |
是 |
字符串 |
你的 Florentine.ai API 密鑰,可從儀表盤複製。 |
SESSION_ID |
否 |
字符串 |
客戶端的會話 ID,用於服務器端聊天曆史記錄。請參考會話部分。 |
LLM_SERVICE |
否 |
字符串 |
指定要使用的 LLM 提供商。僅當你未將 LLM 密鑰保存到 Florentine.ai 賬戶中時才需要。請參考連接你的 LLM 賬戶部分。 |
LLM_KEY |
否 |
字符串 |
你為所提供的 LLM 服務使用的 API 密鑰。僅當你未將 LLM 密鑰保存到 Florentine.ai 賬戶中時才需要。請參考連接你的 LLM 賬戶部分。 |
RETURN_TYPES |
否 |
字符串化的 JSON |
florentine_ask 工具調用的返回類型。請參考返回類型部分。 |
REQUIRED_INPUTS |
否 |
字符串化的 JSON |
必需輸入。請參考多租戶使用的安全數據分離部分。 |
動態模式
如果你要將 Florentine.ai 集成到自己的自定義 MCP 客戶端中,則應使用動態模式。
在動態模式下,你可以將所有參數(如返回類型、必需輸入等)直接傳遞給 florentine_ask 工具。這意味著你可以為轉發給 Florentine.ai 的每個請求動態注入單個參數(例如用戶 ID)。
為了能夠動態傳遞值,你需要在自定義客戶端/代理中覆蓋 florentine_ask 工具方法。以下是一個使用標準 @modelcontextprotocol TypeScript SDK 的示例:
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { fetchUserSpecificData } from './userService.js';
const mcpClient = new Client({
name: 'florentine',
version: '1.0.0'
});
const mcpSetupConfig = new StdioClientTransport({
command: 'npx',
args: ['-y', '@florentine-ai/mcp', '--mode', 'dynamic'],
env: {
FLORENTINE_TOKEN: '<FLORENTINE_API_KEY>'
}
});
await mcpClient.connect(mcpSetupConfig);
const originalCallTool = mcpClient.callTool;
const enhanceAskParameters = async ({ question }: { question: string }) => {
return {
question,
...(await fetchUserSpecificData({ userId: '<USER_ID>' }))
};
};
mcpClient.callTool = async (params, resultSchema, options) => {
if (params.name === 'florentine_ask')
params.arguments = await enhanceAskParameters(
params.arguments as unknown as { question: string }
);
return await originalCallTool(params, resultSchema, options);
};
const result = await mcpClient.callTool({
name: 'florentine_ask',
arguments: {
question: 'Who won the last tabletennis match?'
}
});
示例詳解
讓我們詳細看看上述示例中發生了什麼。
首先,我們創建並連接 MCP 客戶端:
const mcpClient = new Client({
name: 'florentine',
version: '1.0.0'
});
const mcpSetupConfig = new StdioClientTransport({
command: 'npx',
args: ['-y', '@florentine-ai/mcp', '--mode', 'dynamic'],
env: {
FLORENTINE_TOKEN: '<FLORENTINE_API_KEY>'
}
});
await mcpClient.connect(mcpSetupConfig);
注意:你也可以在 dynamic 模式下使用環境變量。但是,如果你動態指定參數,這些參數將覆蓋現有環境變量中的參數值。
接下來,我們將原始的 callTool 函數保存到一個變量中:
const originalCallTool = mcpClient.callTool;
然後,我們創建一個 enhanceAskParameters 函數,該函數接受一個問題作為輸入,為用戶獲取額外的參數(例如 returnTypes、requiredInputs 等),並返回合併後的參數:
const enhanceAskParameters = async ({ question }: { question: string }) => {
return {
question,
...(await fetchUserSpecificData({ userId: '<USER_ID>' }))
};
};
然後,我們用一個實現覆蓋原始的 callTool 函數,該實現使用來自 enhanceAskParameters 的參數增強 florentine_ask 工具,並調用我們保存到變量 originalCallTool 中的原始 callTool 函數:
mcpClient.callTool = async (params, resultSchema, options) => {
if (params.name === 'florentine_ask')
params.arguments = await enhanceAskParameters(
params.arguments as unknown as { question: string }
);
return await originalCallTool(params, resultSchema, options);
};
最後,我們可以使用一個問題調用 florentine_ask 工具,並動態注入用戶特定的參數:
const result = await mcpClient.callTool({
name: 'florentine_ask',
arguments: {
question: 'Who won the last tabletennis match?'
}
});
重要提示:
請確保在不覆蓋 florentine_ask 實現的情況下永遠不要使用動態模式。
如果你不覆蓋它,你的客戶端/代理將直接使用 florentine_ask 工具的 MCP 服務器端實現以及所有額外參數。
因此,客戶端/代理將自行決定為 returnTypes、requiredInputs 等填充哪些值。
這將導致意外行為,並導致錯誤和錯誤結果。
florentine_ask 參數
| 變量 |
是否必需 |
類型 |
描述 |
sessionId |
否 |
字符串 |
客戶端的會話 ID,用於服務器端聊天曆史記錄。請參考會話部分。 |
returnTypes |
否 |
Array<String> |
florentine_ask 工具調用的返回類型。請參考返回類型部分。 |
requiredInputs |
否 |
Array<Object> |
必需輸入。請參考多租戶使用的安全數據分離部分。 |
返回類型
默認情況下,florentine_ask 工具返回你在 Florentine.ai 賬戶中配置的結果類型(默認:result)。你可以通過指定一個 returnTypes 數組,在每個請求中覆蓋此設置,該數組可以包含以下三個步驟的任意組合:
- 查詢生成:將問題轉換為數據庫查詢(MongoDB 聚合管道或 MySQL 查詢)。
- 查詢執行:使用你提供的連接字符串對數據庫執行查詢。
- 答案生成:將結構化結果轉換為自然語言答案。
提供返回類型
你有兩種方式包含 returnTypes 數組:
- 作為 MCP 設置配置中的
RETURN_TYPES 環境變量(在 static 和 dynamic 模式下均可用)
- 作為
florentine_ask 工具的 returnTypes 參數(僅在 dynamic 模式下可用)
作為環境變量,你需要將值作為字符串化的 JSON 數組提供:
"env": {
"RETURN_TYPES": "[\"query\",\"result\",\"answer\"]"
}
作為工具參數,你需要將值作為數組提供:
{
"returnTypes": ["query", "result", "answer"]
}
返回類型配置
你可以通過指定一個 returnTypes 數組,選擇返回哪些步驟的結果,該數組可以包含以下任意組合:
returnTypes 值 |
描述 |
響應中預期的鍵 |
"query" |
返回生成的數據庫查詢、使用的數據庫和集合/表、0 到 10 的置信度得分以及數據庫類型("mongodb" 或 "mysql")。 |
confidence, database, collection, query, databaseType |
"result" |
返回執行查詢後的原始查詢結果。 |
result |
"answer" |
根據執行查詢的結果返回自然語言響應。 |
answer |
多租戶使用的安全數據分離
你可以通過確保查詢根據提供的值過濾數據來啟用安全數據分離,我們將這些值稱為 必需輸入。
這些值由 Florentine.ai 轉換層在大語言模型生成查詢後添加到查詢中。因此,Florentine.ai 可以確保每個用戶只能檢索到他有權限訪問的數據。
鍵在你的賬戶中被定義為 必需輸入,請參考我們官方文檔中的相關部分瞭解如何操作。
提供必需輸入
你有兩種方式包含 requiredInputs 數組:
- 作為 MCP 設置配置中的
REQUIRED_INPUTS 環境變量(在 static 和 dynamic 模式下均可用)
- 作為
florentine_ask 工具的 requiredInputs 參數(僅在 dynamic 模式下可用)
作為環境變量,你需要將值作為字符串化的 JSON 數組提供:
"env": {
"REQUIRED_INPUTS": "[{\"keyPath\":\"userId\",\"value\":\"507f1f77bcf86cd799439011\"}]"
}
作為工具參數,你需要將值作為數組提供:
"requiredInputs": [
{
"keyPath": "userId",
"value": "507f1f77bcf86cd799439011"
}
]
如果你在多個集合/表中有相同 keyPath 但不同 value 的必需輸入,你還可以提供 database 和 collections 數組:
{
"requiredInputs": [
{
"keyPath": "name",
"value": "Sesame Street",
"database": "rentals",
"collections": ["houses"]
},
{
"keyPath": "name",
"value": { "$in": ["Ernie", "Bert"] },
"database": "rentals",
"collections": ["tenants"]
}
]
}
必需輸入配置
| 字段 |
是否必需 |
類型 |
描述 |
約束 |
keyPath |
是 |
字符串 |
要過濾的字段的路徑。 |
必須是有效的鍵路徑。 |
value |
是 |
任意 |
用於過濾的值(特定類型,請參考支持的值類型)。 |
必須與字段的類型匹配(字符串、ObjectId、布爾值、數字或日期)。 |
database |
否 |
字符串 |
包含要過濾的集合的數據庫。 |
如果提供了 collections,則必須提供該字段。 |
collections |
否 |
Array<String> |
要應用過濾的數據庫中的特定集合/表。 |
必須包含至少一個集合/表。 |
支持的值類型
根據鍵的值類型,你可以提供不同的 必需輸入 值:
| 類型 |
格式示例 |
支持的運算符 |
注意事項 |
字符串 或 字符串數組 |
"text" { $in: ["text1", "text2"] } |
$in |
區分大小寫。 |
ObjectId 或 ObjectId 數組 |
"507f191e810c19729de860ea" { $in: ["507f191e810c19729de860ea", "507f191e810c19729de860eb"] } |
$in |
以字符串形式提供。 |
布爾值 |
true/false |
— |
僅支持精確值。 |
數字 或 數字數組 |
42 { $gt: 10, $lte: 100 } { $in: [1, 2, 3] } { $in: [{$gte:1}, {$lt:10}] } |
$gt, $gte, $lt, $lte, $in |
支持小數。 |
日期 或 日期數組 |
"2024-01-01T00:00:00Z"(UTC) "2024-01-01T00:00:00-05:00"(時區偏移) |
$gt, $gte, $lt, $lte, $in |
ISO 8601 格式。 |
使用示例
注意:我們僅提供作為工具參數輸入的示例。對於環境變量實現,你只需將鍵名更改為 REQUIRED_INPUTS 並將 JSON 字符串化。
示例類型:字符串
用例:用戶只能查看他經常與之對戰的球員的統計數據。
解決方案:通過球員姓名將訪問權限限制為一組 4 名球員。
const res = await FlorentineAI.ask({
question: 'Which player had the most wins?',
requiredInputs: [
{
keyPath: 'name',
value: { $in: ['Megan', 'Frank', 'Jen', 'Bob'] }
}
]
});
示例類型:ObjectId
用例:用戶只能查看他自己產品的收入情況。
解決方案:通過賬戶 ID 將訪問權限限制為一個特定賬戶。
const res = await FlorentineAI.ask({
question: 'Whats the revenue of my products?',
requiredInputs: [
{
keyPath: 'accountId',
value: '507f1f77bcf86cd799439011'
}
]
});
示例類型:布爾值
用例:對客戶的所有分析應僅針對付費客戶進行。
解決方案:通過 isPaidAccount 將訪問權限限制為僅付費客戶。
const res = await FlorentineAI.ask({
question: 'How many customers registered in the last year?',
requiredInputs: [
{
keyPath: 'isPaidAccount',
value: true
}
]
});
示例類型:數字
用例:員工只能查看低於一定金額的付款信息。
解決方案:通過金額將訪問權限限制為低於 10000 的付款。
const res = await FlorentineAI.ask({
question: 'List all payments we received.',
requiredInputs: [
{
keyPath: 'amount',
value: { $lt: 10000 }
}
]
});
示例類型:日期
用例:財務數據分析應僅包括特定的一年的數據。
解決方案:通過 transactionDate 將訪問權限限制為 2024 年的所有交易。
const res = await FlorentineAI.ask({
question: 'What was our revenue, profit and margin per month?',
requiredInputs: [
{
keyPath: 'transactionDate',
value: {
$gte: '2023-01-01T00:00:00Z',
$lt: '2024-01-01T00:00:00Z'
}
}
]
});
會話
會話允許 Florentine.ai 啟用服務器端聊天曆史記錄。
由於包含 MCP 服務器的客戶端/代理通常會自行跟蹤聊天曆史記錄,因此添加會話並非絕對必要。
然而,這可能仍然有助於 Florentine.ai 更好地理解上下文,並可能提高結果質量。
提供會話
你有兩種方式包含 sessionId:
- 作為 MCP 設置配置中的
SESSION_ID 環境變量(在 static 和 dynamic 模式下均可用)
- 作為
florentine_ask 工具的 sessionId 參數(僅在 dynamic 模式下可用)
作為環境變量:
"env": {
"SESSION_ID": "<YOUR_SESSION_ID>"
}
作為工具參數:
{
"sessionId": "<YOUR_SESSION_ID>"
}
錯誤處理
MCP 服務器工具調用的所有錯誤都遵循以下一致的 JSON 結構:
{
"error": {
"name": "FlorentineApiError",
"statusCode": 500,
"message": "The provided Florentine API key is invalid. You can find the key in your account settings: https://florentine.ai/settings",
"errorCode": "INVALID_TOKEN",
"requestId": "abc123"
}
}
| 字段 |
類型 |
描述 |
name |
字符串 |
錯誤類名(例如 FlorentineApiError、FlorentineConnectionError) |
statusCode |
數字 |
HTTP 狀態碼(例如 400、500) |
message |
字符串 |
對出錯原因的解釋 |
errorCode |
字符串 |
錯誤標識符(例如 NO_TOKEN、INVALID_LLM_KEY) |
requestId |
字符串 |
此請求的唯一 ID(有助於支持和調試) |
自定義客戶端錯誤處理
錯誤對象以字符串化的 JSON 形式返回到 content 數組中:
{
"content": [
{
"type": "text",
"text": "{\"error\":{\"name\":\"FlorentineApiError\",\"statusCode\":401,\"message\":\"The provided Florentine API key is invalid. You can find the key in your account settings: https://florentine.ai/settings\",\"errorCode\":\"INVALID_TOKEN\",\"requestId\":\"uhv99g\"}}"
}
],
"isError": true
}
你可以解析 text 中的 JSON,並在自定義客戶端/代理中處理不同的錯誤。
常見錯誤
| 錯誤名稱 |
錯誤代碼 |
含義 |
FlorentineApiError |
MODE_MISSING |
你必須提供 static 或 dynamic 作為模式參數 |
FlorentineApiError |
MODE_INVALID |
模式無效(必須是 static 或 dynamic) |
FlorentineApiError |
INVALID_TOKEN |
Florentine API 密鑰無效 |
FlorentineApiError |
LLM_KEY_WITHOUT_SERVICE |
如果定義了 llmKey,則必須提供 llmService |
FlorentineApiError |
LLM_SERVICE_WITHOUT_KEY |
如果定義了 llmService,則必須提供 llmKey |
FlorentineApiError |
INVALID_LLM_SERVICE |
提供的 llmService 無效 |
FlorentineApiError |
NO_OWN_LLM_KEY |
你需要提供自己的 LLM 密鑰 |
FlorentineApiError |
NO_ACTIVE_COLLECTIONS |
賬戶中沒有激活的集合/表 |
FlorentineApiError |
MISSING_REQUIRED_INPUT |
缺少必需輸入 |
FlorentineApiError |
INVALID_REQUIRED_INPUT |
必需輸入無效 |
FlorentineApiError |
INVALID_REQUIRED_INPUT_FORMAT |
必需輸入格式無效 |
FlorentineApiError |
NO_QUESTION |
缺少問題 |
FlorentineApiError |
EXECUTION_FAILURE |
創建的查詢執行失敗 |
FlorentineApiError |
NO_CHAT_ID |
需要歷史聊天 ID 但缺少 |
FlorentineApiError |
TOO_MANY_TOKENS |
查詢提示超過了 LLM 模型的最大令牌數 |
FlorentineLLMError |
API_KEY_ISSUE |
LLM API 密鑰無效 |
FlorentineLLMError |
NO_RETURN |
Florentine.ai 未收到有效的 LLM 返回 |
FlorentineLLMError |
RATE_LIMIT_EXCEEDED |
LLM 請求大小過大 |
FlorentineConnectionError |
CONNECTION_REFUSED |
無法連接到數據庫以執行查詢 |
FlorentineCollectionError |
NO_EXECUTION |
創建的查詢無法執行 |
FlorentinePipelineError |
MODIFICATION_FAILED |
修改查詢管道失敗 |
FlorentineUsageError |
LIMIT_REACHED |
你計劃中包含的所有 API 請求已耗盡 |
FlorentineUnknownError |
UNKNOWN_ERROR |
所有發生的未知錯誤 |