Three lines and your agent handles files

forge-media adds file management to Forge in three lines. Alt text is enforced at the upload boundary from every source -- which means images are correctly labelled across all four delivery channels automatically.

forge-media is a separate module. Registering it takes three lines:

store := forgemedia.NewLocalMediaStore(app)
mediaSrv := forgemedia.Register(app, store)
mcpSrv := forgemcp.New(app, forgemcp.WithModule(mediaSrv))

After this, your agent has four MCP tools. The same tools are available to any authenticated operator with the right role.

Alt text at the upload boundary

Every upload -- from any source -- requires a description field. The MCP tool schema marks it as required. An HTTP upload without it is rejected. There is no path through the upload boundary that produces an unlabelled file.

This is the connection to the four-audiences model. Alt text enforcement at upload does not just serve accessibility on the browser side. It ensures that images referenced in .aidoc responses and /llms-full.txt carry correct labels regardless of which client uploaded them. An agent that reads your content via the AI formats encounters properly described images because the requirement was enforced at the source -- not as a post-processing step, not as a convention the uploader is trusted to follow.

The MediaStore interface

LocalMediaStore stores files on the local filesystem and is the current implementation. MediaStore is an interface -- switching to a different backend requires changing one line (the store initialisation). The MCP tools, the template helpers, and the upload boundary enforcement do not change.

LocalMediaStore ships today. S3 is Phase 4 -- the interface is already there.

What your agent can do

With forge-media registered and a token with the right role:

create_file   -- upload a file with required description  (Author+)
list_files    -- list all files, filter with ?type=        (Editor+)
get_file      -- fetch a single file record by ID          (Editor+)
delete_file   -- delete a file by ID                       (Editor+)

The same token and role model from forge-mcp applies. No media-specific bypass.