AgentStack
MCP verified MIT Self-run

Mcp Server Dart

mcp-zfinix-mcp-server-dart · by Zfinix

A developer-friendly MCP (Model Context Protocol) framework for Dart with annotations and code generation. Build MCP servers as easily as annotating methods with @MCPTool, @MCPResource, or @MCPPrompt - similar to how json_serializable or freezed works.

No reviews yet
0 installs
10 views
0.0% view→install

Install

$ agentstack add mcp-zfinix-mcp-server-dart

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Mcp Server Dart? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

[](https://dart.dev) [](https://modelcontextprotocol.io/) [](https://opensource.org/licenses/MIT)

A developer-friendly MCP (Model Context Protocol) framework for Dart with annotations and code generation. Build MCP servers as easily as annotating methods with @MCPTool, @MCPResource, or @MCPPrompt - similar to how json_serializable or freezed works.

✨ Features

  • 🏷️ Annotation-based: Declare MCP tools, resources, and prompts with simple annotations
  • 🔧 Code generation: Automatic boilerplate generation using build_runner with extension-based registration
  • ✨ No @override required: Clean method declarations without inheritance boilerplate
  • 📡 Multiple transports: Support for stdio, HTTP, and Streamable HTTP with Server-Sent Events (SSE)
  • 🔍 Type-safe: Full Dart type safety with automatic parameter extraction
  • 📚 JSON Schema: Automatic input schema generation from method signatures
  • 🧪 Fully tested: Comprehensive test suite with JSON-RPC command validation
  • ⚡ Production ready: Current MCP 2025-11-25-aligned protocol implementation with Relic HTTP server
  • 🧠 Modern capabilities: Built-in support for MCP logging, completions, task-augmented tool calls, and richer initialize metadata
  • 🌐 Modern HTTP: Built on Relic framework with middleware support, CORS, logging, and health checks
  • 🔧 Monitoring: Built-in health check endpoints and connection monitoring
  • 📊 SSE Support: Server-Sent Events for real-time streaming on the modern MCP streamable HTTP transport

🚀 Quick Start

1. Add Dependencies

dependencies:
  mcp_server_dart: ^1.1.2
  relic: ^0.5.0  # Modern HTTP framework
  logging: ^1.3.0  # For server logging

dev_dependencies:
  build_runner: ^2.4.13

2. Create Your MCP Server

import 'package:mcp_server_dart/mcp_server_dart.dart';

part 'my_server.mcp.dart'; // Generated file

class MyMCPServer extends MCPServer {
  MyMCPServer() : super(name: 'my-server', version: '1.0.0') {
    // Register all generated handlers using the extension
    registerGeneratedHandlers();
  }

  @MCPTool('greet', description: 'Greet someone by name')
  Future greet(String name) async {
    return 'Hello, $name! 👋';
  }

  @MCPTool('calculate', description: 'Perform basic arithmetic')
  Future calculate(double a, double b, String operation) async {
    switch (operation) {
      case 'add': return a + b;
      case 'subtract': return a - b;
      case 'multiply': return a * b;
      case 'divide': return b != 0 ? a / b : throw ArgumentError('Division by zero');
      default: throw ArgumentError('Unknown operation: $operation');
    }
  }

  @MCPResource('status', description: 'Server status information')
  Future> getStatus() async {
    return {
      'server': name,
      'version': version,
      'uptime': DateTime.now().toIso8601String(),
      'status': 'healthy',
    };
  }

  @MCPPrompt('codeReview', description: 'Generate code review prompts')
  String codeReviewPrompt(String code, String language) {
    return '''Please review this $language code for:
- Best practices and conventions
- Potential bugs or issues
- Performance improvements
- Security considerations

Code:
```$language
$code
```''';
  }
}

3. Generate Code

dart run build_runner build

This generates my_server.mcp.dart with an extension that provides automatic registration methods.

4. Run Your Server

import 'dart:io';
import 'package:logging/logging.dart';

void main() async {
  Logger.root.level = Level.INFO;

  final server = MyMCPServer(); // Handlers auto-registered in constructor
  server.attachLogger(Logger.root); // Forward Dart LogRecord events to MCP logging

  // Optional: also mirror logs locally for humans
  Logger.root.onRecord.listen((record) {
    stderr.writeln('${record.level.name}: ${record.time}: ${record.message}');
  });

  // Choose your transport:
  await server.start();        // For CLI integration (stdio)
  // OR
  await server.serve(port: 8080);   // For HTTP server with health checks
}

Server Features:

  • 🌐 HTTP Server: Runs on specified port with Relic framework
  • 🔍 Health Check: Available at http://localhost:8080/health
  • 📊 Status Endpoint: Server metrics at http://localhost:8080/status
  • 📡 MCP Endpoint: Streamable HTTP at http://localhost:8080/mcp
  • 📝 Request Logging: All HTTP requests logged with timing
  • 🛡️ CORS Support: Cross-origin requests enabled by default
  • Graceful Shutdown: Handles SIGINT/SIGTERM signals properly
  • 🔄 SSE Streaming: Server-Sent Events for real-time communication

MCP logging bridge

If your server already uses package:logging, you can forward Dart LogRecord events directly to MCP notifications/message:

final server = MyMCPServer();
server.attachLogger(Logger.root);

Attaching a logger automatically enables MCP logging capability advertisement. You can still set enableLogging: true explicitly, but it is no longer required for the common attached-logger case.

The bridge:

  • respects the client's logging/setLevel threshold
  • maps Dart logging levels to MCP logging levels
  • includes message, time, sequence number, and optional error/stack trace

Auto-advertised capabilities

Some modern MCP capabilities can now be advertised automatically:

  • Logging: enabled automatically when a logger is attached with server.attachLogger(...)
  • Completions: enabled automatically when an @MCPCompletion(...) handler is registered
  • Tasks: enabled automatically when any tool uses annotations: {'taskSupport': ...}

You can still opt in explicitly with enableLogging: true, enableCompletions: true, or enableTasks: true, but they're no longer required for these common cases.

📖 Annotations Reference

@MCPTool

Marks a method as an MCP tool that LLMs can call:

@MCPTool('toolName', description: 'What this tool does')
Future myTool(ParameterType param) async {
  // Implementation
}

Features:

  • Automatic parameter extraction and type checking
  • JSON Schema generation from method signature
  • Support for optional parameters with defaults
  • Async and sync method support

@MCPResource

Marks a method as an MCP resource that provides data:

@MCPResource('resourceName', 
  description: 'What this resource contains',
  mimeType: 'application/json'  // Optional
)
Future> getResource() async {
  // Return resource data
}

@MCPPrompt

Marks a method as an MCP prompt template:

@MCPPrompt('promptName', description: 'What this prompt does')
String generatePrompt(String context, String task) {
  return 'Generated prompt based on $context and $task';
}

@MCPCompletion

Marks a method as a completion provider for a prompt or resource:

@MCPCompletion('classify')
Future completeClassify(
  MCPCompletionRequest request,
) async {
  final value = request.argument.value.toLowerCase();
  return MCPCompletionResult(
    completion: MCPCompletionData(
      values: ['bug', 'feature'].where((v) => v.startsWith(value)).toList(),
      hasMore: false,
    ),
  );
}

Use a plain name like classify for prompt completions. Use a full mcp://... URI to attach a completion provider to a resource. Completion capability advertisement is automatic when one or more completion providers are registered, though you can still set enableCompletions: true explicitly if you prefer.

@MCPParam

Provides additional metadata for parameters:

@MCPTool('example')
Future example(
  @MCPParam(description: 'The user name', example: 'John Doe') 
  String name,
  
  @MCPParam(required: false, description: 'Age in years')
  int age = 25,
) async {
  return 'Hello $name, age $age';
}

🌟 Complete Example

See the [Google Maps MCP example](example/lib/advanced/google_maps.dart) for a comprehensive demonstration:

class GoogleMapsMCP extends MCPServer {
  GoogleMapsMCP() : super(name: 'google-maps-mcp', version: '1.0.0') {
    registerGeneratedHandlers();
  }

  @MCPTool('searchPlace', description: 'Find places by name or address')
  Future> searchPlace(String query, int limit = 5) async {
    // Implementation with mock Google Maps API calls
  }

  @MCPTool('getDirections', description: 'Get directions between two points')
  Future> getDirections(
    String origin, 
    String destination, 
    String mode = 'driving'
  ) async {
    // Implementation
  }

  @MCPResource('currentLocation', description: 'Current user location')
  Future> getCurrentLocation() async {
    // Implementation
  }

  @MCPPrompt('locationSummary', description: 'Generate location summaries')
  String locationSummaryPrompt(String location, String summaryType = 'general') {
    // Generate contextual prompts
  }
}

🔧 Advanced Usage

Custom Parameter Validation

@MCPTool('validateEmail')
Future validateEmail(String email) async {
  if (!email.contains('@')) {
    throw ArgumentError('Invalid email format');
  }
  // Validation logic
}

Complex Input Schemas

@MCPTool('complexTool', inputSchema: {
  'type': 'object',
  'properties': {
    'config': {
      'type': 'object',
      'properties': {
        'timeout': {'type': 'integer', 'minimum': 1},
        'retries': {'type': 'integer', 'maximum': 10}
      }
    }
  }
})
Future complexTool(Map config) async {
  // Handle complex nested parameters
}

Multiple Transport Support

The server supports both stdio and HTTP transports. You can extend the basic example above to handle command-line arguments:

// Add argument handling to your main() function:
if (args.contains('--stdio')) {
  print('🔌 Starting MCP server on stdio...');
  await server.start();
} else {
  final port = args.contains('--port') 
      ? int.parse(args[args.indexOf('--port') + 1])
      : 8080;
  
  print('🌐 Starting HTTP server on port $port...');
  print('🔍 Health check: http://localhost:$port/health');
  print('📊 Status: http://localhost:$port/status');
  print('📡 MCP endpoint: http://localhost:$port/mcp');
  
  await server.serve(port: port);
}

Transport Options:

  • Stdio: Perfect for Claude Desktop integration and CLI tools
  • HTTP: Ideal for web applications, testing, and debugging with Relic framework
  • Streamable HTTP: Latest MCP 2025-11-25 transport expectations with Server-Sent Events support
  • Health Monitoring: Built-in endpoints for production monitoring

🌐 Streamable HTTP Transport (MCP 2025-11-25 aligned)

The MCP Dart framework now supports the latest Streamable HTTP transport specification:

Key Features

  • Single MCP Endpoint: POST/GET /mcp handles all MCP communication
  • Server-Sent Events: Real-time streaming for server-initiated messages
  • Session Management: Automatic session ID generation and validation
  • Protocol Headers: MCP-Protocol-Version: 2025-11-25 support
  • Security: Origin validation and localhost binding for development

Testing with MCP Inspector

# Start your server
dart run main.dart --example calculator --http --port 8080

# Test with Inspector CLI
npx @modelcontextprotocol/inspector --cli http://localhost:8080/mcp --transport streamable-http --method tools/list

# Test with Inspector UI
npx @modelcontextprotocol/inspector
# Then connect to: http://localhost:8080/mcp with "Streamable HTTP" transport

cURL Testing

# Initialize connection
curl -X POST http://localhost:8080/mcp \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'MCP-Protocol-Version: 2025-11-25' \
  --data '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{}}}'

# List tools
curl -X POST http://localhost:8080/mcp \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'MCP-Protocol-Version: 2025-11-25' \
  --data '{"jsonrpc":"2.0","id":"2","method":"tools/list"}'

# Open SSE stream
curl -H 'Accept: text/event-stream' http://localhost:8080/mcp

🌐 Relic Framework Integration

The MCP Dart framework uses Relic as its HTTP server foundation. Relic is a modern, type-safe web server framework inspired by Shelf but with significant improvements:

Why Relic?

  • 🔒 Type Safety: No more dynamic types - everything is strongly typed
  • ⚡ Performance: Uses Uint8List instead of List for better performance
  • 🛣️ Advanced Routing: Efficient trie-based routing with parameter extraction
  • 🔧 Modern Headers: Typed header parsing with validation
  • 🧪 Well Tested: Extended test coverage and production-ready

Server Features Powered by Relic

// Your MCP server automatically gets these features:
await server.serve(
  port: 8080,
  address: InternetAddress.anyIPv4,
  enableCors: true,  // CORS middleware
  keepAliveTimeout: Duration(seconds: 30),
);

Built-in Endpoints:

  • GET /health - Health check with server metrics
  • GET /status - Detailed server status and capabilities
  • POST/GET /mcp - MCP Streamable HTTP endpoint
  • GET /ws - WebSocket upgrade endpoint (coming soon)

Middleware Stack:

  • 🌐 CORS Middleware: Cross-origin request support
  • 📝 Logging Middleware: Request/response logging with timing
  • 🛡️ Error Handling: Graceful error handling and responses
  • 🛣️ Routing: Automatic route registration and parameter extraction

For more details about Relic's capabilities, see the official Relic documentation.

Binary Compilation for Production

Compile your MCP server to a native binary for optimal performance and easy deployment:

# Compile to standalone binary
dart compile exe my_server.dart -o mcp-server

# Cross-platform compilation
dart compile exe my_server.dart -o mcp-server-linux --target-os=linux
dart compile exe my_server.dart -o mcp-server-macos --target-os=macos
dart compile exe my_server.dart -o mcp-server.exe --target-os=windows

Benefits of binary deployment:

  • No Dart runtime required - Standalone executable
  • Faster startup - No VM overhead
  • Easy distribution - Single file deployment
  • Production ready - Optimized performance

Claude Desktop configuration with binary:

{
  "mcpServers": {
    "my-server": {
      "command": "/path/to/mcp-server"
    }
  }
}

🧪 Testing

The framework includes comprehensive testing capabilities with both unit and integration testing. Here are several approaches:

Testing the HTTP Server

With Relic integration, you can easily test your MCP server's HTTP endpoints:

import 'dart:convert';
import 'dart:io';
import 'package:test/test.dart';

void main() {
  group('MCP Server HTTP Tests', () {
    late MyMCPServer server;
    late HttpClient client;
    
    setUpAll(() async {
      server = MyMCPServer(); // Handlers auto-registered
      await server.serve(port: 8081); // Use different port for testing
      
      client = HttpClient();
    });
    
    tearDownAll(() async {
      await server.shutdown();
      client.close();
    });

    test('health check endpoint works', () async {
      final request = await client.get('localhost', 8081, '/health');
      final response = await request.close();
      
      expect(response.statusCode, equals(200));
      
      final body = await response.transform(utf8.decoder).join();
      final data = jsonDecode(body);
      expect(data['status'], equals('healthy'));
      expect(data['server'], equals('my-server'));
    });

    test('MCP endpoint works with Streamable HTTP', () async {
      final request = await client.post('localhost', 8081, '/mcp');
      request.headers.set('content-type', 'application/json');
      request.headers.set('mcp-protocol-version', '2025-11-25');
      request.write(jsonEncode({
        'jso

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Zfinix](https://github.com/Zfinix)
- **Source:** [Zfinix/mcp_server_dart](https://github.com/Zfinix/mcp_server_dart)
- **License:** MIT
- **Homepage:** https://pub.dev/packages/mcp_server_dart

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.