filmopen_mcp
Generated by scripts/package_digest.py; regenerate, never edit.
The MCP server for FilmOpen (the MCP Specification). It is a Dart command-line program that an agent’s MCP client spawns, and it drives a running FilmOpen agent build through Flutter’s driver extension. The MCP library (dart_mcp) lives here and nowhere in the app.
Flutter. 7 files, 2,219 lines under lib/; 98 tests in 7 files. Barrel: lib/filmopen_mcp.dart.
Depends on
Section titled “Depends on”- filmopen_automation (dev) — uses nothing by name the digest could see
Third-party: dart_mcp, stream_channel, vm_service, flutter_driver.
Used by
Section titled “Used by”No package of FilmOpen.
Public API
Section titled “Public API”What the barrel exports, file by file. A name is class, enum, mixin, extension, typedef, a top-level function, getter, setter or variable; under a class, its public constructors, fields, getters, setters and methods.
lib/src/app_link.dart
Section titled “lib/src/app_link.dart”- class
AppLink— The server’s line to one running FilmOpen.Future<String> requestData(String message)— Sends one message on the data channel and answers the app’s reply.Future<Uint8List> screenshot()— A PNG of the app’s whole view as Flutter rendered it.Future<void> waitIdle()— Waits until the app has no animation running.Future<void> enterText(String text)— Types [text] into the box that has the focus, replacing what it holds, through the driver’s own text entry.Future<void> close()— Closes the connection; the app goes on running.
- variable
const String kDriverExtension— The name the driver extension answers to in an agent build’s isolate. - class
DriverLink— The [AppLink] of a running agent build: Flutter’s own driver, handed a connection this link made itself.DriverLink(this._driver, {this.requestTimeout = const Duration(seconds: 45)})static Future<DriverLink> connect(String vmServiceUrl, { Duration timeout = const Duration(seconds: 10), Duration requestTimeout = const Duration(s…— Connects to the agent build whose VM service answers at [vmServiceUrl].final Duration requestTimeout— The longest a request waits for its reply.
- function
bool isLocalServiceUrl(String url)— Whether [url] is a VM service URL on this machine:httpon the loopback, the only place an app’s service listens. - class
ServiceUnreachable— What a connection meets when nothing answers at a VM service URL: no app, or an app that has gone.const ServiceUnreachable()
- class
NotAnAgentBuild— What a connection meets when a service answers but none of its isolates carries the driver extension.const NotAnAgentBuild()
- function
Uri serviceWebSocketUri(String vmServiceUrl)— The WebSocket address of a VM service URL, as the driver derives it (vmservice_driver.dart). - function
Future<void> probeService(String vmServiceUrl, {Duration timeout = const Duration(seconds: 5)})— Opens and closes one WebSocket to the VM service at [vmServiceUrl]. - function
Future<bool> serviceGone(String vmServiceUrl, {Duration timeout = const Duration(seconds: 30)})— Waits until the VM service at [vmServiceUrl] stops answering, probing every half second for at most [timeout].
lib/src/cli.dart
Section titled “lib/src/cli.dart”- class
CliCommand— One run of the executable (bin/filmopen_mcp.dart), read from the words after its options.const CliCommand()
- class
ServeCommand—serve, and no words at all: MCP over stdio.const ServeCommand()
- class
OpCommand— One message on the data channel: an op, or the literalping.const OpCommand(this.message, {this.output})final String messagefinal String? output
- class
WindowShotCommand—screenshot [file]: the whole view as Flutter rendered it, dialogs included.const WindowShotCommand(this.output)final String output
- class
WaitIdleCommand—wait-idle.const WaitIdleCommand()
- class
EnterTextCommand—enter-text <text>: the driver’s own text entry into the box that has the focus — a dialog’s, tapped first — replacing what it holds.const EnterTextCommand(this.text)final String text
- class
LaunchCommand—launch [platform] [--size WxH] [--home folder]:flutter runin the foreground.const LaunchCommand(this.platform, {this.size, this.home, this.device})final String platformfinal String? size—--size <width>x<height>; null uses the runners’ 1280×720.final String? home— Names the private render-data home on either desktop.final String? device—--device <serial>on android, whichadb devicesnames; the emulator isemulator-5554.
- function
(String, List<String>) launchCommandLine(LaunchCommand command, {String? keysFolder})— The command line a parsed [LaunchCommand] runs, which is the one place it is built. - class
StopCommand—stop: asks the agent build to quit through its own channel, and waits for it to end.const StopCommand()
- class
CliUsageError— A command line the executable does not understand; [message] says why.const CliUsageError(this.message)final String message
- class
CliInvocation— A whole command line: the executable’s own options and the command.const CliInvocation({required this.command, this.vmServiceUrl, this.repository, this.help = false})final CliCommand commandfinal String? vmServiceUrl—--vm-service-url: the agent build to drive.final String? repository—--repo: the repositorylaunchruns in.final bool help—-h,--help.
- variable
const String kCliUsage— The commands, the options and what each takes, for the usage text. - function
CliInvocation parseArguments(List<String> arguments, {required String hostPlatform})— Reads the whole command line. - function
CliCommand parseCommand(List<String> words, {required String hostPlatform})— Reads [words], the command line without its options; [hostPlatform] is whatlaunchruns on when it names none.
lib/src/discovery.dart
Section titled “lib/src/discovery.dart”- variable
const String kAgentFileName— The name of the file an agent build writes into the application’s log folder once it runs (test_driver/agent_main.dart). - function
String? agentLogDirectory({Map<String, String>? environment, String? operatingSystem})— The application’s log folder, computed from the environment the wayfilmopen_platform’sapp_paths_io.dartcomputes it — the server is a command-line program and cannot import a Flutter plugin. - class
AgentAnnouncement— Whatagent.jsonsays about a running agent build: where its VM service answers, its process, and when it started.const AgentAnnouncement({required this.vmServiceUrl, required this.pid, this.startedAt})final String vmServiceUrlfinal int pid— The process, for a person reading the file; nothing is decided by it.final String? startedAtstatic AgentAnnouncement? parse(String text)— Reads the file’s text; null for anything that is not an announcement.
- function
Future<AgentAnnouncement?> discoverAgent({ String? directory, Future<bool> Function(AgentAnnouncement announcement)? answers, })— The running agent build announced in [directory] (the log folder by default), or null. - function
Future<bool> serviceAnswers(AgentAnnouncement announcement)— Whether the VM service an announcement names answers ([probeService]).
lib/src/launch_lock.dart
Section titled “lib/src/launch_lock.dart”- class
LaunchLock— The one build a checkout makes at a time (§4.3):flutter runbuilds into the checkout’s ownbuild/folder, so a second launch while the first builds would build into the bundle the first is about to run.LaunchLock(String repositoryRoot, {this.stale = const Duration(minutes: 10), DateTime Function()? now})— The lock of the checkout at [repositoryRoot].final File file— The file that says a launch is building.final Duration stale— How old a lock may be before it is taken for one a launch left behind.Future<bool> acquire({ Duration within = const Duration(minutes: 5), Duration every = const Duration(seconds: 1), bool Function()? stopped, })— Takes the lock, waiting at most [within] while another launch holds it; answers whether it waited.void release()— Lets the lock go, where it is still this launch’s.
lib/src/launcher.dart
Section titled “lib/src/launcher.dart”- variable
final RegExp kVmServiceLine— The lineflutter runprints once the app’s VM service answers. - function
String? parseWindowSize(String? spec)—<width>x<height>with each side in 320–4096. - class
LaunchFailed— Aflutter runthat ended, or ran out of time, before its app answered.const LaunchFailed(this.reason, {this.exitCode, this.output = const []})final String reasonfinal int? exitCodefinal List<String> output
- class
AppLauncher— An agent build the server started itself:flutter run -d <platform> -t test_driver/agent_main.dartfrom the repository root, undersetsid xvfb-run -aon Linux.AppLauncher({required this.repositoryRoot, this.flutter = 'flutter'})final String repositoryRoot— The folder holdingpubspec.yamlandtest_driver/agent_main.dart.final String flutter— The Flutter tool to run.static const int outputLines— How many offlutter run’s last lines a [LaunchFailed] carries.bool get isRunning— Whether an app this launcher started is still running.static (String, List<String>) commandFor(String platform, { String flutter = 'flutter', String size = '1280x720', String? keysFolder, String? devic…— The command line [launch] runs for [platform]:setsid xvfb-runon Linux, with the Xvfb screen matching [size], this machine’s build-time keys, and the moment it is built.static String? dartDefinesFile({String? keysFolder})— This machine’sdart-defines.json, or null where there is none.static String makeAgentHome({String? parent})— Makes a fresh private desktop home: under [parent] where given (Windows: the repository’sbuild/sandbox-home/, since the sandbox refuses the temporary folder), else under the temporary directory’sfilmopen-agent/.static (String?, bool) desktopHome(String platform, {String? home, required String repositoryRoot})— The home a desktop launch on [platform] runs under, and whether it was made for this launch.static String prepareAgentHome(String home)— Creates the private desktop home and its data children.static Map<String, String> launchEnvironment({ required String platform, required String size, String? agentHome, bool realHome = false, bool owned…— Gives the launched desktop app its window size and private render data, and logslaunch.home.static String? repositoryOf(Uri script)— The repository an executable at [script] belongs to:bin/../../.., when that folder holds the agent entrypoint.static Future<void> killGroup(int pid, {Duration grace = const Duration(seconds: 10)})— TERM, then KILL after [grace], the process group led by [pid].String? get home— The private home held by this desktop launch, or null.static void removeAgentHome(String path)— Removes a private home made for a desktop launch.Future<String> launch({ required String platform, String size = '1280x720', String? home, String? device, Duration timeout = const Duration(minutes…— Starts the app on [platform] and answers its VM service URL as soon asflutter runprints it.static bool get privateBusAvailable— Whether this machine can give a launched app a session bus of its own (dbus-run-session).static bool get keyringAvailable— Whether this machine can give that bus a secret store of its own (gnome-keyring-daemon).static const unlockedKeyring— The shell text that starts the keyring unlocked in the private bus, then runs the rest of the command.Future<bool> stop({Duration timeout = const Duration(seconds: 30)})— Quits the app asflutter run’s ownqdoes, and answers whether it ended on that.
lib/src/server.dart
Section titled “lib/src/server.dart”- typedef
typedef LinkOpener— Opens an [AppLink] to the agent build whose VM service answers at a URL. - typedef
typedef AgentFinder— Finds a running agent build nobody named (agent.json). - typedef
typedef GoneWaiter— Waits until the VM service at a URL stops answering; answers whether it did. - class
FilmOpenMcpServer— The MCP server for a FilmOpen agent build: a tool per op of the app’s data channel, plus a screenshot of the whole view, the wait for an idle frame, andlaunchandstop.FilmOpenMcpServer(super.channel, { this.vmServiceUrl, this.repositoryRoot, LinkOpener? openLink, AgentFinder? findAgent, AppLauncher Function(Strin…final String? vmServiceUrl— The URL named when the server started (--vm-service-url,VM_SERVICE_URL).final String? repositoryRoot— The repositorylaunchrunsflutter runin; else the one this executable belongs to.static final List<OpTool> opTools— The tools that send one op each.static CallToolResult answerOf(String reply, {required bool image})— The app’s JSON answer as a tool result.
- class
OpTool— A tool that sends one op of the data channel.const OpTool(this.name, this.tool, {String? op, this.image = false})final String name— The tool’s name.final String op— The op it sends: its own name, butpage_shotsendsscreenshot.final Tool toolfinal bool image— Whether the result is a PNG, answered as image content.
- class
ToolError— A tool’s refusal: a code and a detail, like the app’s own.const ToolError(this.code, [this.detail, this.extra = const {}])const ToolError.launched(this.code, [this.detail, this.extra = const {}])— A refusal afterlaunchstarted the app, which goes on running: the answer says so, names the instance where it has one, andstopends it.factory ToolError.of(CallToolResult result)— The code and the detail of an error result [FilmOpenMcpServer.answerOf] made.final String codefinal String? detailfinal bool launchedfinal Map<String, Object?> extra— Further fields of the answer: a failed launch’s exit code and output.CallToolResult get result— The error result that carries this refusal.