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 MCP 2025-11-25 schema.

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 binnen configure() 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> — breidt MCP uit, serialiseert direct als zijn map.
  • MapModel<K, V> — een eenvoudig map-achtig model zonder de MCP basis.

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')],
    );
  }
  // ...
},

Zie Ook