MCP Server Gids
Deze gids legt uit hoe u een Model Context Protocol (MCP) endpoint kunt blootstellen vanuit uw Finch applicatie. MCP is een JSON-RPC–gebaseerd protocol (versie 2025-11-25) ontworpen voor AI-agents en taalmodellen om serverzijdige mogelijkheden te ontdekken en aan te roepen — tools, resources en prompts.
Finch integreert met het mcp_models pakket om het volgende te bieden:
McpServerController— een abstracte Finch controller die alle MCP JSON-RPC routering automatisch afhandelt.McpBuilder— een declaratieve builder voor het registreren van tools, resources, prompts en aangepaste method handlers.mcp_models— een zero-dependency Dart bibliotheek met volledige dekking van het MCP2025-11-25schema.
Hoe Het Werkt
Wanneer een client (een AI-agent, IDE-plugin, etc.) een MCP-verzoek stuurt, stuurt het een standaard JSON-RPC payload via HTTP naar uw Finch endpoint. McpServerController decodeert de payload, routeert het naar de juiste ingebouwde handler of naar een handler die u bij McpBuilder heeft geregistreerd, en streamt het antwoord terug als Server-Sent Events (SSE).
Client ──POST /mcp/books──► McpServerController.index()
│
▼
_dispatch(method, id, payload)
│
┌──────────────┼──────────────────┐
▼ ▼ ▼
tools/call resources/read prompts/get
│ │ │
▼ ▼ ▼
McpBuilder McpBuilder McpBuilder
.toolHandler() .resourceHandler() .promptHandler()
Mogelijkheden Registreren met McpBuilder
Tools
Een tool is een aanroepbare functie die een AI-agent kan aanroepen. Registreer er één met mcp.tool():
mcp.tool(
name: 'add',
description: 'Telt twee gehele getallen op en geeft de som terug.',
inputSchema: ToolSchema(
type: 'object',
properties: {
'a': Schema(type: 'integer', description: 'Eerste operand', title: 'A'),
'b': Schema(type: 'integer', description: 'Tweede operand', title: 'B'),
},
required: ['a', 'b'],
),
outputSchema: ToolSchema(
type: 'object',
properties: {
'result': Schema(type: 'integer', description: 'De som', title: 'Result'),
},
required: ['result'],
),
handler: (CallToolRequest req) async {
final args = req.params.arguments ?? {};
final sum = (args['a'] as int) + (args['b'] as int);
return CallToolResult(
content: [TextContent(text: '$sum', mimeType: 'text/plain')],
structuredContent: {'result': sum},
);
},
);
| Parameter | Type | Beschrijving |
|---|---|---|
name |
String |
Unieke tool-identificator |
description |
String |
Leesbare beschrijving voor AI-agents |
inputSchema |
ToolSchema |
JSON Schema die de verwachte argumenten beschrijft |
outputSchema |
ToolSchema? |
JSON Schema die de gestructureerde uitvoer beschrijft (optioneel) |
handler |
Future<CallToolResult> Function(CallToolRequest) |
Asynchrone handler aangeroepen bij tools/call |
Resources
Een resource exposeert een URI-adresseerbare gegevensbron (een bestand, databaserecord, API-antwoord, etc.):
mcp.resource(
name: 'config',
uri: 'file:///config.json',
description: 'Applicatie configuratiebestand.',
handler: (ReadResourceRequest req) async {
final content = await File('config.json').readAsString();
return ReadResourceResult(
contents: [
TextResourceContents(
uri: req.params.uri,
text: content,
mimeType: 'application/json',
),
],
);
},
);
| Parameter | Type | Beschrijving |
|---|---|---|
name |
String |
Unieke resourcenaam |
uri |
String |
De URI die deze resource identificeert |
description |
String? |
Optionele beschrijving |
handler |
Future<ReadResourceResult> Function(ReadResourceRequest) |
Handler aangeroepen bij resources/read |
U kunt ook
rq.url('path')gebruiken binnenconfigure()om dynamisch absolute URI's te bouwen.
Resource Templates
Voor geparametriseerde URI's (bijv. file:///books/{id}), gebruik mcp.resourceTemplate():
mcp.resourceTemplate(
name: 'book',
uriTemplate: 'db:///books/{id}',
description: 'Haalt een enkel boek op via ID.',
);
Prompts
Een prompt is een herbruikbaar berichtsjabloon dat een AI-agent kan ophalen:
mcp.prompt(
name: 'greet',
description: 'Geeft een begroetingsbericht terug.',
handler: (GetPromptRequest req) async {
final name = req.params.arguments?['name'] ?? 'World';
return GetPromptResult(
messages: [
PromptMessage(
role: Role.assistant,
content: TextContent(text: 'Hallo, $name!'),
),
],
);
},
);
| Parameter | Type | Beschrijving |
|---|---|---|
name |
String |
Unieke prompt-identificator |
description |
String? |
Optionele beschrijving |
handler |
Future<GetPromptResult> Function(GetPromptRequest) |
Handler aangeroepen bij prompts/get |
Aangepaste Method Handlers
Overschrijf of breid elke JSON-RPC methode uit — inclusief ingebouwde — met mcp.method():
mcp.method(
'notifications/initialized',
(Map<String, Object?> payload) async {
// Aangepaste logica bij client-initialisatiemelding.
return JSONRPCNotification(method: 'notifications/initialized');
},
);
Aangepaste handlers geregistreerd via mcp.method() hebben prioriteit boven de ingebouwde dispatcher.
De Route Registreren
Voeg de MCP controller toe aan uw Finch routeboom met Methods.ALL zodat zowel GET als POST verzoeken worden geaccepteerd:
import 'package:finch/finch_route.dart';
import 'controllers/my_mcp_controller.dart';
List<FinchRoute> getRoutes() {
return [
FinchRoute(
key: 'mcp.my_server',
path: 'mcp/my-server',
methods: Methods.ALL,
index: MyMcpController().index,
),
];
}
Met Authenticatie
Beveilig uw MCP endpoint door een AuthController te verstrekken:
import 'controllers/mcp_auth_controller.dart';
FinchRoute(
key: 'mcp.my_server',
path: 'mcp/my-server',
methods: Methods.ALL,
index: MyMcpController().index,
auth: McpAuthController(),
),
Een typische AuthController voor MCP controleert een Bearer API-sleutel:
import 'package:finch/finch_route.dart';
class McpAuthController extends AuthController<String> {
final List<String> _allowedKeys = ['your-secret-api-key'];
@override
Future<bool> auth() async => (await checkLogin()).success;
@override
Future<bool> authApi() async {
final auth = rq.authorization;
if (auth.type == AuthType.bearer) {
return _allowedKeys.contains(auth.token);
}
return false;
}
@override
Future<String> loginForm() async => rq.renderJson(
data: {'error': 'Unauthorized'},
status: 401,
);
}
mcp_models Pakket
mcp_models biedt gewone Dart-klassen voor elk type in het MCP 2025-11-25 schema. Er is geen codegeneratie — elke klasse wordt geleverd met:
- Een
toMap()methode voor serialisatie. - Een benoemde factory
TypeName.toMCP(Map)voor deserialisatie.
Sleuteltypes
| Categorie | Types |
|---|---|
| JSON-RPC | JSONRPCRequest, JSONRPCResultResponse, JSONRPCErrorResponse, JSONRPCNotification |
| Levenscyclus | InitializeRequest, InitializeResult, InitializeResultResponse |
| Tools | Tool, ToolSchema, Schema, CallToolRequest, CallToolResult, CallToolResultResponse, ListToolsResult, ListToolsResultResponse |
| Resources | Resource, ResourceTemplate, ReadResourceRequest, ReadResourceResult, TextResourceContents, BlobResourceContents, ListResourcesResult, ListResourceTemplatesResult |
| Prompts | Prompt, PromptMessage, GetPromptRequest, GetPromptResult, ListPromptsResult |
| Inhoud | TextContent, ImageContent, AudioContent, EmbeddedResource |
| Mogelijkheden | ServerCapabilities, ClientCapabilities, Implementation |
| Fouten | Error (JSON-RPC foutobject) |
| Overig | Result, EmptyResult, Role, LoggingLevel |
Serialisatie Voorbeeld
import 'package:mcp_models/mcp_models.dart';
// Bouw een initialize verzoek.
final request = InitializeRequest(
id: '1',
params: InitializeRequestParams(
protocolVersion: '2025-11-25',
capabilities: ClientCapabilities({}),
clientInfo: Implementation(name: 'my_client', version: '1.0.0'),
),
);
// Serialiseer naar een Map (klaar voor JSON-codering).
final json = request.toMap();
// Deserialiseer terug.
final restored = InitializeRequest.toMCP(json);
ToolSchema en Schema
ToolSchema en Schema beschrijven beide JSON Schema-objecten die worden gebruikt voor tool input/output validatie:
ToolSchema(
type: 'object',
properties: {
'name': Schema(
type: 'string',
description: 'De naam van het item.',
defaultValue: '',
title: 'Name',
),
'count': Schema(
type: 'integer',
description: 'Hoeveel items.',
defaultValue: 1,
title: 'Count',
),
},
required: ['name'],
)
MapMC en MapModel Basisklassen
Voor types waarvan de geserialiseerde vorm de onderliggende map zelf is (in plaats van een wrapper object), biedt mcp_models twee basisklassen:
MapMC<K, V>— breidtMCPuit, serialiseert direct als zijn map.MapModel<K, V>— een eenvoudig map-achtig model zonder deMCPbasis.
ServerCapabilities en ClientCapabilities zijn gebouwd op MapMC.
Foutafhandeling
Gooi elke Exception binnen een tool handler — McpServerController wikkelt niet-afgehandelde uitzonderingen in een JSONRPCErrorResponse met code -32600 en streamt een 400 SSE-antwoord naar de client. Voor gestructureerde foutvoortplanting, retourneer een CallToolResult met isError: true:
handler: (req) async {
final id = req.params.arguments?['id'];
if (id == null) {
return CallToolResult(
isError: true,
content: [TextContent(text: 'Verplicht argument ontbreekt: id')],
);
}
// ...
},