@fortemate/vega-vvd-driver 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +2 -0
  2. package/dist/mcp.js +25 -4
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -92,6 +92,8 @@ Then ask, for example: "Open Settings in the app on the Virtual Device, turn the
92
92
 
93
93
  A model chooses the arguments, so they are bounded: at most 100 key presses per call, recordings of up to 600 seconds, and `record_video` writes only a new `.mp4`, `.mov` or `.mkv` file, unless it is told to `overwrite` one. When the client cancels a call, its presses, wait or recording stop. `vvd mcp --pid <n>` ties the server to one device.
94
94
 
95
+ Each tool declares MCP annotations, for a client that asks before a call that changes something. Four tools only read. `enable_grpc` only turns on the emulator's gRPC endpoint. `press_keys` and `record_video` are marked destructive: a key press can confirm a delete in the app on screen, and `overwrite` replaces a file. None reaches beyond the local device.
96
+
95
97
  ## As a library
96
98
 
97
99
  ```ts
package/dist/mcp.js CHANGED
@@ -71,7 +71,7 @@ export const createServer = (options = {}) => {
71
71
  server.registerTool('list_devices', {
72
72
  title: 'List running Vega Virtual Devices',
73
73
  description: 'Lists the running Vega Virtual Devices whose gRPC endpoint is on. An empty list usually means gRPC is off: call enable_grpc.',
74
- annotations: { readOnlyHint: true },
74
+ annotations: { readOnlyHint: true, openWorldHint: false },
75
75
  }, async () => {
76
76
  const devices = findEmulators({ directories: options.directories }).map(({ pid, grpcPort, consolePort, avdName }) => ({
77
77
  pid,
@@ -101,6 +101,12 @@ export const createServer = (options = {}) => {
101
101
  .optional()
102
102
  .describe('The emulator console, an even port; default 5554'),
103
103
  },
104
+ annotations: {
105
+ readOnlyHint: false,
106
+ destructiveHint: false,
107
+ idempotentHint: true,
108
+ openWorldHint: false,
109
+ },
104
110
  }, async ({ grpc_port, console_port }) => {
105
111
  try {
106
112
  await enableGrpc(grpc_port ?? 8554, { port: console_port });
@@ -136,6 +142,14 @@ export const createServer = (options = {}) => {
136
142
  .optional()
137
143
  .describe('Return a screenshot once the keys are pressed'),
138
144
  },
145
+ // A key press can confirm anything the app on screen offers, a delete
146
+ // included.
147
+ annotations: {
148
+ readOnlyHint: false,
149
+ destructiveHint: true,
150
+ idempotentHint: false,
151
+ openWorldHint: false,
152
+ },
139
153
  }, async ({ keys, gap_ms, screenshot_after }, { signal }) => {
140
154
  try {
141
155
  const steps = parseKeys(keys); // a typo fails before any device is touched
@@ -155,7 +169,7 @@ export const createServer = (options = {}) => {
155
169
  server.registerTool('screenshot', {
156
170
  title: 'Take a screenshot',
157
171
  description: 'Returns the current screen of the Vega Virtual Device as a PNG image (1920x1080).',
158
- annotations: { readOnlyHint: true },
172
+ annotations: { readOnlyHint: true, openWorldHint: false },
159
173
  }, async ({ signal }) => {
160
174
  try {
161
175
  return { content: [await screen(connected(), signal)] };
@@ -176,7 +190,7 @@ export const createServer = (options = {}) => {
176
190
  .optional()
177
191
  .describe('Default 5000'),
178
192
  },
179
- annotations: { readOnlyHint: true },
193
+ annotations: { readOnlyHint: true, openWorldHint: false },
180
194
  }, async ({ timeout_ms }, { signal }) => {
181
195
  try {
182
196
  const d = connected();
@@ -211,6 +225,13 @@ export const createServer = (options = {}) => {
211
225
  .optional()
212
226
  .describe('Replace an existing file; default false'),
213
227
  },
228
+ // Destructive only with overwrite, which replaces an existing file.
229
+ annotations: {
230
+ readOnlyHint: false,
231
+ destructiveHint: true,
232
+ idempotentHint: false,
233
+ openWorldHint: false,
234
+ },
214
235
  }, async ({ file, seconds, fps, audio, overwrite }, { signal }) => {
215
236
  try {
216
237
  const path = videoPath(file, overwrite);
@@ -243,7 +264,7 @@ export const createServer = (options = {}) => {
243
264
  .optional()
244
265
  .describe('Fraction of each edge, default 0.05'),
245
266
  },
246
- annotations: { readOnlyHint: true },
267
+ annotations: { readOnlyHint: true, openWorldHint: false },
247
268
  }, async ({ background, margin }, { signal }) => {
248
269
  try {
249
270
  const frame = await connected().screenshot('rgb', { signal });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fortemate/vega-vvd-driver",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Unofficial driver for the Vega Virtual Device: remote keys, screenshots and video with sound, from scripts and AI agents. CLI, Node library and MCP server.",
5
5
  "keywords": [
6
6
  "vega",