Files
Veskslop-t/docs/media-mcp.md
T

3.3 KiB

Media MCP surface

The media archive is designed for agent access. The daemon exposes one service, and the MCP tools are thin wrappers around it. The same service backs the Web UI routes, so the two clients cannot drift.

Status: implemented (C8). The tools are registered in poc/src/control-bridge.ts; read tools are also in run_commands. Advanced query_media filters (author, date, text) are planned; the index has the columns.

Service interface

interface MediaService {
    startScrape(input: { channelId: string; mode: "links" | "download"; backend?: "auto" | "slopbot" | "puppet" }): Promise<ScrapeJob>;
    getScrape(scrapeId: string): Promise<ScrapeJob | null>;
    listScrapes(): Promise<ScrapeJob[]>;
    stopScrape(scrapeId: string): Promise<ScrapeJob>;
    deleteScrape(scrapeId: string): Promise<void>;
    queryMedia(query: MediaQuery): Promise<{ items: MediaItem[]; nextCursor: string | null }>;
    getMediaItem(id: string): Promise<MediaItem | null>;
    storageStatus(): Promise<StorageStatus>;
}

MediaQuery (implemented): kind, source, scrapeId, channelId, authorId, aspect, resolution, after, before, limit, offset. The aspect and resolution values are the preset keys from filter-presets.ts; after/before are ISO times on posted_at. Planned: guildId, text.

StorageStatus: usedBytes, limitBytes, warnPercent, overrunPercent, byKind, scrapes: [{ id, bytes, state, createdAt }].

Tools

Tool Access Purpose
scrape_media trusted Start a scrape (channelId, mode)
list_media_scrapes trusted Every scrape with state, size, and counts
get_media_scrape trusted One scrape, live counters and cursor
stop_media_scrape trusted Stop the active scrape
query_media trusted Filter and page through media items
get_media_item trusted One item with sources and local path
get_media_storage trusted Usage against the limit, per-kind breakdown
delete_media_scrape admin Delete a scrape and its files

Read tools are cache-only against index.db and the scrape registry. They never call Discord. scrape_media and stop_media_scrape drive the same job queue as the chat command, so pacing and the action log apply.

Rules

  • Every tool goes through the existing trust tiers. delete_media_scrape and mode: "download" need admin.
  • Tool calls are written to the action log like any other daemon action.
  • The storage limit is enforced for the agent exactly as for the chat command: near the limit, scrape_media returns the warning and needs a second call with confirm: true.
  • Media bytes are never returned inline. Tools return metadata, the original URL, and the local path; an agent that wants the bytes reads the file through the daemon host.

Hooks to leave in place before C8

  1. MediaService is constructed once in the daemon and passed to both the Web UI routes and the MCP registration. No globals.
  2. ScrapeJob and MediaItem are plain JSON-serializable objects, the same shape the Web UI consumes.
  3. The job queue exposes start, stop, list, and events so MCP and the UI can subscribe to the same stream.
  4. Storage accounting is a service method, not UI code, so the MCP limit check uses the same numbers as the Settings bar.