3.1 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, limit, offset. Planned:
guildId, authorId, after, before, 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_scrapeandmode: "download"needadmin. - 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_mediareturns the warning and needs a second call withconfirm: 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
MediaServiceis constructed once in the daemon and passed to both the Web UI routes and the MCP registration. No globals.ScrapeJobandMediaItemare plain JSON-serializable objects, the same shape the Web UI consumes.- The job queue exposes
start,stop,list, andeventsso MCP and the UI can subscribe to the same stream. - Storage accounting is a service method, not UI code, so the MCP limit check uses the same numbers as the Settings bar.