如果你发现这个包有用,请考虑通过PayPal支持持续开发。
通过 PayPal 支持makemind
mcp_server: 向大型语言模型(LLM)提供工具、资源和提示。充当AI服务器。mcp_client: 连接Flutter/Dart应用到MCP服务器。充当客户端接口。mcp_llm: 桥接LLM(Claude、OpenAI等)到MCP客户端/服务器。充当LLM大脑。flutter_mcp: 完整的Flutter插件,用于与平台特性集成的MCP。flutter_mcp_ui_core: Flutter MCP UI系统的核心模型、常量和实用工具。flutter_mcp_ui_runtime: 通过JSON规范构建动态、响应式UI的综合运行时。flutter_mcp_ui_generator: 使用模板和流畅API创建UI定义的JSON生成工具包。mcp_flow_runtime: 使用MCP Flow DSL进行硬件控制和IoT编排的声明性运行时。这是一个实现模型上下文协议(MCP)服务器的Dart插件。该插件允许Flutter应用程序以标准化的方式向大型语言模型(LLM)应用程序暴露数据、功能和交互模式。
此包实现了模型上下文协议(MCP)规范版本2024-11-05和2025-03-26。
协议版本对于确保MCP客户端和服务器之间的兼容性至关重要。此包的每个版本可能支持不同的协议版本,因此重要的是:
在你的pubspec.yaml中添加包:
dependencies:
mcp_server: ^1.0.3
或者通过命令行安装:
dart pub add mcp_server
import 'package:mcp_server/mcp_server.dart';
void main() {
// 创建一个具有简单布尔能力的服务器
final server = Server(
name: '示例服务器',
version: '1.0.0',
capabilities: ServerCapabilities.simple(
tools: true,
resources: true,
prompts: true,
),
);
// 添加一个简单的计算器工具
server.addTool(
name: '计算器',
description: '执行基本计算',
inputSchema: {
'type': 'object',
'properties': {
'operation': {
'type': 'string',
'enum': ['加', '减', '乘', '除'],
'description': '要执行的数学运算'
},
'a': {
'type': 'number',
'description': '第一个操作数'
},
'b': {
'type': 'number',
'description': '第二个操作数'
}
},
'required': ['operation', 'a', 'b']
},
handler: (arguments) async {
final operation = arguments['operation'] as String;
final a = (arguments['a'] is int) ? (arguments['a'] as int).toDouble() : arguments['a'] as double;
final b = (arguments['b'] is int) ? (arguments['b'] as int).toDouble() : arguments['b'] as double;
double result;
switch (operation) {
case '加':
result = a + b;
break;
case '减':
result = a - b;
break;
case '乘':
result = a * b;
break;
case '除':
if (b == 0) {
return CallToolResult(
content: [TextContent(text: '除以零错误')],
isError: true,
);
}
result = a / b;
break;
default:
return CallToolResult(
content: [TextContent(text: '未知操作:$operation')],
isError: true,
);
}
return CallToolResult(content: [TextContent(text: '结果:$result')]);
},
);
// 添加一个资源
server.addResource(
uri: 'time://当前',
name: '当前时间',
description: '获取当前日期和时间',
mimeType: 'text/plain',
handler: (uri, params) async {
final now = DateTime.now().toString();
return ReadResourceResult(
contents: [
ResourceContentInfo(
uri: uri,
text: now,
mimeType: 'text/plain',
),
],
);
},
);
// 添加一个模板提示
server.addPrompt(
name: '问候',
description: '生成自定义问候语',
arguments: [
PromptArgument(
name: '姓名',
description: '要问候的名字',
required: true,
),
PromptArgument(
name: '正式',
description: '是否使用正式问候风格',
required: false,
),
],
handler: (arguments) async {
final name = arguments['姓名'] as String;
final formal = arguments['正式'] as bool? ?? false;
final String systemPrompt = formal
? '您是一个正式助手。以尊重和正式的方式称呼用户。'
: '您是一个友好的助手。语气温暖而随意。';
final messages = [
Message(
role: MessageRole.system.toString().split('.').last,
content: TextContent(text: systemPrompt),
),
Message(
role: MessageRole.user.toString().split('.').last,
content: TextContent(text: '请问候$name'),
),
];
return GetPromptResult(
description: '对$name的${formal ? '正式' : '随意'}问候',
messages: messages,
);
},
);
// 连接到传输 - 旧方式(仍然支持)
final transportResult = McpServer.createStdioTransport();
final transport = transportResult.get();
server.connect(transport);
}
// 新的:简化统一API(推荐)
void simplifiedMain() async {
final serverResult = await McpServer.createAndStart(
config: McpServer.simpleConfig(
name: '示例服务器',
version: '1.0.0',
),
transportConfig: TransportConfig.stdio(),
);
await serverResult.fold(
(server) async {
// 如上所示添加工具、资源、提示
// 服务器已经启动
await Future.delayed(const Duration(hours: 24));
},
(error) => print('服务器失败:$error'),
);
}
MCP服务器现在支持统一的传输配置:
// STDIO传输
TransportConfig.stdio()
// SSE传输
TransportConfig.sse(
host: 'localhost',
port: 8080,
endpoint: '/sse',
authToken: '可选令牌',
)
// 可流式传输的HTTP传输 - SSE流模式(默认)
TransportConfig.streamableHttp(
host: 'localhost',
port: 8081,
endpoint: '/mcp',
isJsonResponseEnabled: false, // SSE流模式(默认)
)
// 可流式传输的HTTP传输 - JSON响应模式
TransportConfig.streamableHttp(
host: 'localhost',
port: 8081,
endpoint: '/mcp',
isJsonResponseEnabled: true, // JSON响应模式
)
MCP服务器支持两种方式来配置能力:
对于基本使用和测试,使用ServerCapabilities.simple():
final server = Server(
name: '简单服务器',
version: '1.0.0',
capabilities: ServerCapabilities.simple(
tools: true,
toolsListChanged: true,
resources: true,
resourcesListChanged: true,
prompts: true,
promptsListChanged: true,
sampling: true,
logging: true,
progress: true,
),
);
对于生产使用,具有详细的控制能力:
final server = Server(
name: '高级服务器',
version: '1.0.0',
capabilities: ServerCapabilities(
tools: ToolsCapability(
listChanged: true,
supportsProgress: true,
supportsCancellation: true,
),
resources: ResourcesCapability(
listChanged: true,
subscribe: true,
),
prompts: PromptsCapability(
listChanged: true,
),
sampling: SamplingCapability(),
logging: LoggingCapability(),
progress: ProgressCapability(
supportsProgress: true,
),
),
);
Server类是您与MCP协议的核心接口。它处理连接管理、协议合规性和消息路由:
final server = Server(
name: '我的应用',
version: '1.0.0',
capabilities: ServerCapabilities.simple(
tools: true,
resources: true,
prompts: true,
),
);
资源是您如何向LLM暴露数据。它们类似于REST API中的GET端点——它们提供数据但不应执行大量计算或产生副作用:
// 静态资源
server.addResource(
uri: 'config://应用',
name: '应用配置',
description: '应用配置数据',
mimeType: 'text/plain',
handler: (uri, params) async {
final configData = "app_name=我的应用\nversion=1.0.0\ndebug=false";
return ReadResourceResult(
contents: [
ResourceContentInfo(
uri: uri,
text: configData,
mimeType: 'text/plain',
),
],
);
},
);
// 带URI模板的资源
server.addResource(
uri: 'file://{path}',
name: '文件资源',
description: '访问系统上的文件',
mimeType: 'application/octet-stream',
uriTemplate: {
'type': 'object',
'properties': {
'path': {
'type': 'string',
'description': '文件路径'
}
}
},
handler: (uri, params) async {
// 提取路径并读取文件内容
final path = params['path'] ?? uri.substring('file://'.length);
final content = await File(path).readAsString();
return ReadResourceResult(
contents: [
ResourceContentInfo(
uri: uri,
text: content,
mimeType: 'text/plain',
),
],
);
},
);
工具让LLM通过您的服务器采取行动。与资源不同,工具预期执行计算并产生副作用:
server.addTool(
name: '当前日期时间',
description: '获取当前日期和时间',
inputSchema: {
'type': 'object',
'properties': {
'format': {
'type': 'string',
'description': '输出格式(完整、日期、时间)',
'default': '完整'
}
},
'required': []
},
handler: (args) async {
final format = args['format'] as String? ?? '完整';
final now = DateTime.now();
String result;
switch (format) {
case '日期':
result = '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}';
break;
case '时间':
result = '${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}';
break;
case '完整':
default:
result = now.toIso8601String();
break;
}
return CallToolResult(content: [TextContent(text: result)]);
},
);
提示是可重用的模板,帮助LLM有效地与您的服务器交互:
server.addPrompt(
name: '代码审查',
description: '为代码片段生成代码审查',
arguments: [
PromptArgument(
name: '代码',
description: '要审查的代码',
required: true,
),
PromptArgument(
name: '语言',
description: '代码的编程语言',
required: true,
),
],
handler: (args) async {
final code = args['代码'] as String;
final language = args['语言'] as String;
final systemPrompt = '''
您是一位经验丰富的代码审查员。根据以下指南审查提供的代码:
1. 识别潜在的错误或问题
2. 建议性能或可读性的优化
3. 强调代码中使用的良好实践
4. 提供建设性的改进反馈
在提供反馈时具体,并在建议更改时提供代码示例。
''';
final messages = [
Message(
role: MessageRole.system.toString().split('.').last,
content: TextContent(text: systemPrompt),
),
Message(
role: MessageRole.user.toString().split('.').last,
content: TextContent(text: '请审查这段$language代码:\n\n```$language\n$code\n```'),
),
];
return GetPromptResult(
description: '$language代码的代码审查',
messages: messages,
);
},
);
MCP服务器提供了一个强大的基于流的系统来监控客户端会话事件:
// 创建日志器
final logger = Logger('mcp_server.sessions');
// 监听客户端连接
server.onConnect.listen((session) {
logger.info('客户端已连接:${session.id}');
// 初始化会话资源
});
// 监听客户端断开连接
server.onDisconnect.listen((session) {
logger.info('客户端已断开:${session.id}');
// 清理会话资源
});
ClientSession对象包含有用的信息:
始终处理两个事件:监听连接和断开连接事件以维护会话完整性。
为您的流订阅添加错误处理:
server.onConnect.listen(
(session) {
// 正常事件处理
},
onError: (error) {
logger.severe('连接流中的错误:$error');
},
);
当不再需要时取消订阅:
final subscription = server.onConnect.listen((session) { /* ... */ });
// 后来,当完成时:
subscription.cancel();
使用会话事件进行状态管理:根据会话事件维护应用程序状态。
跟踪指标以进行监控:计数会话、持续时间和其他指标。
适用于命令行工具和直接集成:
final transportResult = McpServer.createStdioTransport();
final transport = transportResult.get();
server.connect(transport);
适用于基于HTTP的通信:
final sseConfig = SseServerConfig(
endpoint: '/sse',
messagesEndpoint: '/messages',
port: 8080,
);
final transportResult = McpServer.createSseTransport(sseConfig);
final transport = transportResult.get();
server.connect(transport);
可流式传输的HTTP传输支持两种响应模式:
用于实时响应流:
final serverResult = await McpServer.createAndStart(
config: McpServer.simpleConfig(
name: '我的服务器',
version: '1.0.0',
),
transportConfig: TransportConfig.streamableHttp(
host: 'localhost',
port: 8081,
endpoint: '/mcp',
isJsonResponseEnabled: false, // SSE流模式
),
);
用于单一JSON响应(更简单但无流):
final serverResult = await McpServer.createAndStart(
config: McpServer.simpleConfig(
name: '我的服务器',
version: '1.0.0',
),
transportConfig: TransportConfig.streamableHttp(
host: 'localhost',
port: 8081,
endpoint: '/mcp',
isJsonResponseEnabled: true, // JSON响应模式
),
);
重要注意事项:
application/json和text/event-stream,无论服务器模式如何