Flutter SDK

Native Flutter SDK for screenshots, crash reporting, screen recording, session replay, and feature requests.

Installation

Download Flutter SDK

Source package — add as a local path dependency. pub.dev coming soon.

Download .zip
Download sample app (Flutter demo project)

Unzip the download, place the flutter-sdk/ folder alongside your project, then add it as a path dependency:

# pubspec.yaml

dependencies:

mcpfeedback:

path: ../flutter-sdk

# then run

flutter pub get

Minimum Flutter SDK: 3.10  •  Dart SDK: 3.0  •  iOS: 13.0+  •  Android: API 24+

Quick Start

Get your first feedback submission in under 5 minutes.

1

Install the SDK

Add the SDK to your Flutter project using pub.

terminal
# Download the SDK zip from the Flutter docs page, unzip it,
# then add to pubspec.yaml:
dependencies:
  mcpfeedback:
    path: ../flutter-sdk

flutter pub get
2

Get your API key

Create an account and generate an API key in your dashboard.

3

Initialize in main()

Initialize before calling runApp().

lib/main.dart
import 'package:mcpfeedback/mcpfeedback.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await McpFeedback.initialize(
    siteKey: 'your-site-key',
    config: McpFeedbackConfig(
      shakeEnabled: true,
      floatingButtonEnabled: true,
    ),
  );
  runApp(const MyApp());
}
4

Verify it works

Shake your device or tap the floating button. Submit a test report and check your MCPFeedback dashboard.

API Key Setup

Your site key is available in Dashboard > Settings > API Keys. Each site has its own key — use the key for the app you are instrumenting.

// Never hard-code production keys in source control. // Use environment variables or --dart-define: // flutter run --dart-define=MCP_SITE_KEY=your-key const siteKey = String.fromEnvironment('MCP_SITE_KEY'); await McpFeedback.initialize(siteKey: siteKey);

Configuration

Pass a McpFeedbackConfig to McpFeedback.initialize().

ParameterTypeDefaultDescription
siteKeyStringrequiredYour site identifier from the dashboard
apiBaseUrlString?nullCustom API base URL — defaults to production
shakeEnabledbooltrueEnable shake-to-report gesture
floatingButtonEnabledbooltrueShow persistent floating feedback button
screenshotDetectEnabledbooltrueDetect screenshot gesture and prompt feedback
twoFingerSwipeEnabledboolfalseTwo-finger swipe up to trigger feedback
networkLoggingEnabledbooltrueAutomatically capture HTTP requests with each report
crashReportingEnabledbooltrueCapture uncaught exceptions and submit on next launch
sessionReplayEnabledboolfalseCapture UI-change screenshots as a replay timeline
privacyTierPrivacyTierstandardstrict | standard | relaxed — controls what is masked in replays
accentColorColor?nullOverride SDK UI accent color
maxNetworkBodyBytesint10240Max request/response body bytes captured per log entry
urlFilterList<RegExp>?nullURL patterns to exclude from network logging

Screenshot Capture

The SDK uses Flutter's RenderRepaintBoundary to capture the current widget tree into a PNG at the moment feedback is triggered. The capture happens before the SDK UI is rendered so the SDK overlay is never included.

// Screenshots are captured automatically when show() is called. // You can also capture manually: final screenshot = await McpFeedback.captureScreenshot(); // Attach to a programmatic submission: await McpFeedback.submit( FeedbackData( title: 'Layout broken on this screen', screenshot: screenshot, ), );

Annotation Tools

After screenshot capture, users can annotate before submitting. Three tools are available:

  • Pen — freehand drawing in configurable color and stroke width
  • Highlight — translucent rectangle to draw attention to a region
  • Blur — blurs a rectangular region for privacy (redacts PII before upload)

Annotations are rasterized into the final PNG upload — the dashboard displays the annotated image.

Invocation Methods

Six ways users or your code can open the feedback form:

Shake to report

Enabled by default. Detects shake gesture via accelerometer.

// shakeEnabled: true in McpFeedbackConfig (default)

Floating button

Persistent overlay button. Configurable position and color.

floatingButtonEnabled: true // default

Screenshot detection

Detects when the user takes a system screenshot and prompts for feedback.

screenshotDetectEnabled: true // default

Programmatic

Trigger from your own UI — e.g., a Help menu item.

await McpFeedback.show(context);

Two-finger swipe

Two-finger swipe upward to open feedback.

twoFingerSwipeEnabled: true

Network Logging

The SDK intercepts HTTP requests via a custom HttpOverrides and attaches the last N requests to each feedback report.

McpFeedbackConfig( networkLoggingEnabled: true, maxNetworkBodyBytes: 10240, // 10 KB per request body urlFilter: [ RegExp(r'analytics\.'), // exclude analytics endpoints RegExp(r'/health'), ], redactHeaders: ['Authorization', 'Cookie'], )

Request and response bodies above maxNetworkBodyBytes are truncated. Authorization headers are redacted by default.

Crash Reporting

The SDK registers a FlutterError.onError handler and an isolate error listener to capture all unhandled exceptions and errors. Reports are queued locally and submitted on next app launch.

// Crash reporting is enabled by default. // For Flutter errors: McpFeedbackConfig(crashReportingEnabled: true) // To catch async errors outside the Flutter zone: void main() { runZonedGuarded(() async { WidgetsFlutterBinding.ensureInitialized(); await McpFeedback.initialize(siteKey: 'your-key'); runApp(const MyApp()); }, McpFeedback.recordError); }

Each crash report includes: exception message, stack trace, device info, OS version, app version, and the last 20 network log entries captured before the crash.

Screen Recording

Users can attach a short screen recording to feedback reports. On iOS the SDK uses ReplayKit; on Android it uses MediaProjection. Recordings are MP4 (H.264) capped at 30 seconds by default.

McpFeedbackConfig( screenRecordingEnabled: true, maxRecordingDurationSeconds: 30, recordingQuality: RecordingQuality.medium, // low | medium | high )
// Platform setup — add to android/app/src/main/AndroidManifest.xml: <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" /> // iOS — add to ios/Runner/Info.plist: <key>NSMicrophoneUsageDescription</key> <string>Used for optional audio capture during screen recordings.</string>

Privacy masking applies to all recordings — views marked with McpFeedbackMask are blurred before upload.

Session Replay

Session Replay captures lightweight UI-change screenshots (not video) and assembles them into a scrubable timeline visible in the dashboard alongside each feedback report.

McpFeedbackConfig( sessionReplayEnabled: true, privacyTier: PrivacyTier.standard, // strict | standard | relaxed replaySamplingInterval: Duration(seconds: 2), replayMaxFrames: 120, )
Privacy TierBehavior
strictMask all text and images — only layout structure captured
standardMask text fields and images marked private; show UI structure
relaxedOnly mask views explicitly wrapped in McpFeedbackMask

Feature Requests

The Feature Requests module lets users submit, browse, vote on, and comment on feature ideas without leaving your app. Votes and status changes appear in real-time in the dashboard.

// Open the feature request board: await McpFeedback.showFeatureRequests(context); // Or submit a feature request programmatically: await McpFeedback.submitFeatureRequest( title: 'Dark mode support', description: 'App should respect system dark mode setting.', userEmail: 'user@example.com', );

Feature requests submitted here appear under Feature Requests in your MCPFeedback dashboard and are accessible via the MCP list_feature_requests tool.

Privacy Masking

Wrap any widget with McpFeedbackMask to prevent it from appearing in screenshots, recordings, and replays.

// Wrap sensitive widgets: McpFeedbackMask( child: CreditCardWidget(number: card.number), ) // Password fields are auto-masked regardless of privacy tier. // You can also mark a widget via the extension: Text(user.ssn).mcpMasked()

Masking is enforced at capture time — masked regions are replaced with a solid block before the image leaves the device.

Offline Queue

All submissions (feedback, crash reports, feature requests) are persisted to a local SQLite queue before being sent. If the device is offline or the upload fails, the SDK retries with exponential backoff on reconnect.

McpFeedbackConfig( offlineQueueMaxItems: 50, // max queued submissions before oldest is dropped offlineQueueMaxAgeDays: 7, // drop items older than 7 days )

API Reference

The full API reference is auto-generated from Dart doc comments using dart doc.

Flutter API Reference

Auto-generated from source code comments — always up to date with the latest SDK version.

View Flutter API Reference →

To regenerate locally: bash scripts/generate-api-docs.sh