diff --git a/packages/flutter_tools/lib/src/vmservice.dart b/packages/flutter_tools/lib/src/vmservice.dart
new file mode 100644
index 0000000..569a35e
--- /dev/null
+++ b/packages/flutter_tools/lib/src/vmservice.dart
@@ -0,0 +1,355 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert' show BASE64;
+import 'dart:io';
+
+import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
+import 'package:web_socket_channel/io.dart';
+
+import 'globals.dart';
+
+// TODO(johnmccutchan): Rename this class to ServiceProtocol or VmService.
+class VMService {
+  VMService._(this.peer, this.port, this.httpAddress) {
+    peer.registerMethod('streamNotify', (rpc.Parameters event) {
+      _handleStreamNotify(event.asMap);
+    });
+
+    onIsolateEvent.listen((Event event) {
+      if (event.kind == 'IsolateStart') {
+        _addIsolate(event.isolate);
+      } else if (event.kind == 'IsolateExit') {
+        String removedId = event.isolate.id;
+        isolates.removeWhere((IsolateRef ref) => ref.id == removedId);
+      }
+    });
+  }
+
+  static Future<VMService> connect(int port) async {
+    Uri uri = new Uri(scheme: 'ws', host: '127.0.0.1', port: port, path: 'ws');
+    WebSocket ws = await WebSocket.connect(uri.toString());
+    rpc.Peer peer = new rpc.Peer(new IOWebSocketChannel(ws));
+    peer.listen();
+    Uri httpAddress = new Uri(scheme: 'http', host: '127.0.0.1', port: port);
+    return new VMService._(peer, port, httpAddress);
+  }
+  final Uri httpAddress;
+  final rpc.Peer peer;
+  final int port;
+
+  List<IsolateRef> isolates = <IsolateRef>[];
+  Completer<IsolateRef> _waitFirstIsolateCompleter;
+
+  Map<String, StreamController<Event>> _eventControllers = <String, StreamController<Event>>{};
+
+  Set<String> _listeningFor = new Set<String>();
+
+  bool get isClosed => peer.isClosed;
+  Future<Null> get done => peer.done;
+
+  String get firstIsolateId => isolates.isEmpty ? null : isolates.first.id;
+
+  // Events
+
+  Stream<Event> get onExtensionEvent => onEvent('Extension');
+  // IsolateStart, IsolateRunnable, IsolateExit, IsolateUpdate, ServiceExtensionAdded
+  Stream<Event> get onIsolateEvent => onEvent('Isolate');
+  Stream<Event> get onTimelineEvent => onEvent('Timeline');
+
+  // Listen for a specific event name.
+  Stream<Event> onEvent(String streamId) {
+    streamListen(streamId);
+    return _getEventController(streamId).stream;
+  }
+
+  StreamController<Event> _getEventController(String eventName) {
+    StreamController<Event> controller = _eventControllers[eventName];
+    if (controller == null) {
+      controller = new StreamController<Event>.broadcast();
+      _eventControllers[eventName] = controller;
+    }
+    return controller;
+  }
+
+  void _handleStreamNotify(Map<String, dynamic> data) {
+    Event event = new Event(data['event']);
+    _getEventController(data['streamId']).add(event);
+  }
+
+  Future<Null> populateIsolateInfo() async {
+    // Calling this has the side effect of populating the isolate information.
+    await waitFirstIsolate;
+  }
+
+  Future<IsolateRef> get waitFirstIsolate async {
+    if (isolates.isNotEmpty)
+      return isolates.first;
+
+    _waitFirstIsolateCompleter ??= new Completer<IsolateRef>();
+
+    getVM().then((VM vm) {
+      for (IsolateRef isolate in vm.isolates)
+        _addIsolate(isolate);
+    });
+
+    return _waitFirstIsolateCompleter.future;
+  }
+
+  // Requests
+
+  Future<Response> sendRequest(String method, [Map<String, dynamic> args]) {
+    return peer.sendRequest(method, args).then((dynamic result) => new Response(result));
+  }
+
+  Future<Null> streamListen(String streamId) async {
+    if (!_listeningFor.contains(streamId)) {
+      _listeningFor.add(streamId);
+      sendRequest('streamListen', <String, dynamic>{ 'streamId': streamId });
+    }
+  }
+
+  Future<VM> getVM() {
+    return peer.sendRequest('getVM').then((dynamic result) {
+      return new VM(result);
+    });
+  }
+
+  Future<Map<String, dynamic>> reloadSources(String isolateId) async {
+    try {
+      Response response =
+          await sendRequest('_reloadSources',
+                            <String, dynamic>{ 'isolateId': isolateId });
+      return response.response;
+    } catch (e) {
+      return new Future<Map<String, dynamic>>.error(e.data['details']);
+    }
+  }
+
+  Future<List<Map<String, String>>> getViewList() async {
+    Map<String, dynamic> response = await peer.sendRequest('_flutter.listViews');
+    List<Map<String, String>> views = response['views'];
+    return views;
+  }
+
+  Future<String> getFirstViewId() async {
+    List<Map<String, String>> views = await getViewList();
+    return views[0]['id'];
+  }
+
+  Future<Null> runInView(String viewId,
+                         String main,
+                         String packages,
+                         String assetsDirectory) async {
+    await peer.sendRequest('_flutter.runInView',
+                           <String, dynamic> {
+                             'viewId': viewId,
+                             'mainScript': main,
+                             'packagesFile': packages,
+                             'assetDirectory': assetsDirectory
+                           });
+    return null;
+  }
+
+  Future<Response> clearVMTimeline() => sendRequest('_clearVMTimeline');
+
+  Future<Response> setVMTimelineFlags(List<String> recordedStreams) {
+    assert(recordedStreams != null);
+
+    return sendRequest('_setVMTimelineFlags', <String, dynamic> {
+      'recordedStreams': recordedStreams
+    });
+  }
+
+  Future<Response> getVMTimeline() => sendRequest('_getVMTimeline');
+
+  // DevFS / VM virtual file system methods
+
+  /// Create a new file system.
+  Future<CreateDevFSResponse> createDevFS(String fsName) async {
+    Response response = await sendRequest('_createDevFS', <String, dynamic> { 'fsName': fsName });
+    return new CreateDevFSResponse(response.response);
+  }
+
+  /// List the available file systems.
+  Future<List<String>> listDevFS() {
+    return sendRequest('_listDevFS').then((Response response) {
+      return response.response['fsNames'];
+    });
+  }
+
+  // Write one file into a file system.
+  Future<Response> writeDevFSFile(String fsName, {
+    String path,
+    List<int> fileContents
+  }) {
+    assert(path != null);
+    assert(fileContents != null);
+
+    return sendRequest('_writeDevFSFile', <String, dynamic> {
+      'fsName': fsName,
+      'path': path,
+      'fileContents': BASE64.encode(fileContents)
+    });
+  }
+
+  // Read one file from a file system.
+  Future<List<int>> readDevFSFile(String fsName, String path) {
+    return sendRequest('_readDevFSFile', <String, dynamic> {
+      'fsName': fsName,
+      'path': path
+    }).then((Response response) {
+      return BASE64.decode(response.response['fileContents']);
+    });
+  }
+
+  /// The complete list of a file system.
+  Future<List<String>> listDevFSFiles(String fsName) {
+    return sendRequest('_listDevFSFiles', <String, dynamic> {
+      'fsName': fsName
+    }).then((Response response) {
+      return response.response['files'];
+    });
+  }
+
+  /// Delete an existing file system.
+  Future<Response> deleteDevFS(String fsName) {
+    return sendRequest('_deleteDevFS', <String, dynamic> { 'fsName': fsName });
+  }
+
+  // Flutter extension methods.
+
+  Future<Response> flutterDebugDumpApp(String isolateId) {
+    return peer.sendRequest('ext.flutter.debugDumpApp', <String, dynamic>{
+      'isolateId': isolateId
+    }).then((dynamic result) => new Response(result));
+  }
+
+  Future<Response> flutterDebugDumpRenderTree(String isolateId) {
+    return peer.sendRequest('ext.flutter.debugDumpRenderTree', <String, dynamic>{
+      'isolateId': isolateId
+    }).then((dynamic result) => new Response(result));
+  }
+
+  // Loader page extension methods.
+
+  Future<Response> flutterLoaderShowMessage(String isolateId, String message) {
+    return peer.sendRequest('ext.flutter.loaderShowMessage', <String, dynamic>{
+      'isolateId': isolateId,
+      'value': message
+    }).then(
+      (dynamic result) => new Response(result),
+      onError: (dynamic exception) { printTrace('ext.flutter.loaderShowMessage: $exception'); }
+    );
+  }
+
+  Future<Response> flutterLoaderSetProgress(String isolateId, double progress) {
+    return peer.sendRequest('ext.flutter.loaderSetProgress', <String, dynamic>{
+      'isolateId': isolateId,
+      'loaderSetProgress': progress
+    }).then(
+      (dynamic result) => new Response(result),
+      onError: (dynamic exception) { printTrace('ext.flutter.loaderSetProgress: $exception'); }
+    );
+  }
+
+  Future<Response> flutterLoaderSetProgressMax(String isolateId, double max) {
+    return peer.sendRequest('ext.flutter.loaderSetProgressMax', <String, dynamic>{
+      'isolateId': isolateId,
+      'loaderSetProgressMax': max
+    }).then(
+      (dynamic result) => new Response(result),
+      onError: (dynamic exception) { printTrace('ext.flutter.loaderSetProgressMax: $exception'); }
+    );
+  }
+
+  /// Causes the application to pick up any changed code.
+  Future<Response> flutterReassemble(String isolateId) {
+    return peer.sendRequest('ext.flutter.reassemble', <String, dynamic>{
+      'isolateId': isolateId
+    }).then((dynamic result) => new Response(result));
+  }
+
+  Future<Response> flutterEvictAsset(String isolateId, String assetPath) {
+    return peer.sendRequest('ext.flutter.evict', <String, dynamic>{
+      'isolateId': isolateId,
+      'value': assetPath
+    }).then((dynamic result) => new Response(result));
+  }
+
+  Future<Response> flutterExit(String isolateId) {
+    return peer
+      .sendRequest('ext.flutter.exit', <String, dynamic>{ 'isolateId': isolateId })
+      .then((dynamic result) => new Response(result))
+      .timeout(new Duration(seconds: 2), onTimeout: () => null);
+  }
+
+  void _addIsolate(IsolateRef isolate) {
+    if (!isolates.contains(isolate)) {
+      isolates.add(isolate);
+
+      if (_waitFirstIsolateCompleter != null) {
+        _waitFirstIsolateCompleter.complete(isolate);
+        _waitFirstIsolateCompleter = null;
+      }
+    }
+  }
+}
+
+class Response {
+  Response(this.response);
+
+  final Map<String, dynamic> response;
+
+  String get type => response['type'];
+
+  dynamic operator[](String key) => response[key];
+
+  @override
+  String toString() => response.toString();
+}
+
+class CreateDevFSResponse extends Response {
+  CreateDevFSResponse(Map<String, dynamic> response) : super(response);
+
+  String get name => response['name'];
+  String get uri => response['uri'];
+}
+
+class VM extends Response {
+  VM(Map<String, dynamic> response) : super(response);
+
+  List<IsolateRef> get isolates => response['isolates'].map((dynamic ref) => new IsolateRef(ref)).toList();
+}
+
+class Event extends Response {
+  Event(Map<String, dynamic> response) : super(response);
+
+  String get kind => response['kind'];
+  IsolateRef get isolate => new IsolateRef.from(response['isolate']);
+
+  /// Only valid for [kind] == `Extension`.
+  String get extensionKind => response['extensionKind'];
+}
+
+class IsolateRef extends Response {
+  IsolateRef(Map<String, dynamic> response) : super(response);
+  factory IsolateRef.from(dynamic ref) => ref == null ? null : new IsolateRef(ref);
+
+  String get id => response['id'];
+
+  @override
+  bool operator ==(dynamic other) {
+    if (identical(this, other))
+      return true;
+    if (other is! IsolateRef)
+      return false;
+    final IsolateRef typedOther = other;
+    return id == typedOther.id;
+  }
+
+  @override
+  int get hashCode => id.hashCode;
+}
