5-minute quickstart
Add the App Use SDK to a .NET app, implement IAppUseSurface, and call AppUseHost.StartAsync at startup. From there, any MCP-capable agent on the same machine finds your app through apps.list — no bespoke per-app integration required.
Step 1 — packages
Reference the abstractions (the contracts you implement) and the SDK (the wire side that hosts your surface):
<PackageReference Include="AiAppUse.Abstractions" Version="0.8.0" />
<PackageReference Include="AiAppUse.Sdk" Version="0.8.0" />
Step 2 — implement the surface
IAppUseSurface is a handful of methods. Most are one-liners that delegate to your app's existing state — describe your screens and elements, then answer reads, value gets/sets, and invokes:
public sealed class HelloSurface : IAppUseSurface
{
private string _message = "";
public Task<AppSpec> DescribeAsync(CancellationToken ct = default) => Task.FromResult(AppSpec.Build(
appName: "Hello", appVersion: "1.0",
screens: new[] { new AppScreen("home", "Home", "Main page.") },
elements: new[]
{
new AppElement("home.message", "home", "TextBox", "Message text.",
Array.Empty<string>(), null, new[] { "set_value", "get_value", "focus" }),
new AppElement("home.send", "home", "Button", "Send the message.",
Array.Empty<string>(), null, new[] { "invoke" }),
}));
public Task<ScreenSnapshot> ReadScreenAsync(CancellationToken ct = default) =>
Task.FromResult(new ScreenSnapshot("home", new ElementState[]
{
new("home.message", "TextBox", _message, true, true),
}, Array.Empty<string>()));
public Task<AppUseResult> GetValueAsync(string k, CancellationToken ct = default)
=> Task.FromResult(k == "home.message" ? AppUseResult.Success(_message) : AppUseResult.Failure("unknown_key"));
public Task<AppUseResult> SetValueAsync(string k, string? v, CancellationToken ct = default)
{ if (k == "home.message") _message = v ?? ""; return Task.FromResult(AppUseResult.Success("ok")); }
public Task<AppUseResult> InvokeAsync(string k, CancellationToken ct = default)
{ if (k == "home.send") Console.WriteLine($"sending: {_message}"); return Task.FromResult(AppUseResult.Success("ok")); }
// remaining methods (navigation, window, key/link, capture) return
// AppUseResult.Success("ok") or NotSupported as appropriate
}
Step 3 — host it
Call AppUseHost.StartAsync once at startup, passing your app identity and the surface instance:
await using var host = await AppUseHost.StartAsync(new AppUseHostOptions
{
AppId = "hello",
AppName = "Hello",
AppVersion = "1.0",
Surface = new HelloSurface(),
});
Console.WriteLine($"App-Use endpoint: {host.Endpoint.Current!.Url}");
// ... your main loop ...
Step 4 — verify
StartAsync writes an instance-registration file at <AIAPPUSE_HOME>/instances/<id>.json containing the endpoint URL, bearer token, pid, and launch manifest. The hub watches that directory and now sees your app — so apps.list from any connected agent returns it:
$ ls $HOME/.aiappuse/instances/
8c2f...e1.json
$ curl -s -H "Authorization: Bearer <admin-bearer>" \
http://127.0.0.1:8766/instances | jq .[0].appName
"Hello"