Skip to content

Read and write files from a tool

Some tools need the file, not a description of it — parse the spreadsheet the user uploaded, or hand back a generated report. DioscHub exposes two HTTP endpoints your MCP server calls directly for this: one to fetch a file, one to write one back. The bytes travel between your server and DioscHub over HTTP; they never pass through the model’s context.

Both endpoints are authenticated with a DioscHub admin API key, presented in the x-api-key header. Mint a key for your server scoped to just the two file permissions:

  • mcp-files:read — to fetch files.
  • mcp-files:write — to write files.

A key minted with only these scopes carries no other admin authority. Keep it server-side, never expose it to the model, and give each MCP server its own key.

POST /api/mcp/files/fetch returns a file’s bytes by exact name:

const res = await fetch('https://your-hub.example.com/api/mcp/files/fetch', {
method: 'POST',
headers: {
'x-api-key': process.env.DIOSC_MCP_FILES_KEY,
'x-session-id': sessionId, // from the call's _meta
'content-type': 'application/json',
},
body: JSON.stringify({ name: 'q3-orders.xlsx' }),
});
// res.body is the raw file stream

The request is keyed by name — there is deliberately no listing or search endpoint. A name that does not exist returns 404 with no hint about what else is there. Your tool works with names it already knows (from the conversation, or a put_file it made earlier).

POST /api/mcp/files/upload stores a file into the user’s library and returns the stored name:

const form = new FormData();
form.append('file', new Blob([reportBytes]), 'q3-summary.pdf');
const res = await fetch('https://your-hub.example.com/api/mcp/files/upload', {
method: 'POST',
headers: { 'x-api-key': process.env.DIOSC_MCP_FILES_KEY, 'x-session-id': sessionId },
body: form,
});
const { filename } = await res.json(); // may be disambiguated on a name collision

If the name already exists, DioscHub keeps both and returns the disambiguated name — an MCP server can never clobber a user’s existing file. The stored file is indexed, so the Assistant can find and reference it by name afterward.

The file scope is resolved from the session, never from anything your server asserts. Pass the session id (it arrives in the call’s _meta) in the x-session-id header, and DioscHub resolves the file library from the Assistant and the signed-in user on that session. Your server reaches only that user’s own chat-file library for that Assistant — not another user’s files, and not the Knowledge base.

The file bytes flow only between your server and DioscHub over these HTTP endpoints. The model sees whatever text your tool chooses to return — a summary, a row count, a reference to the written file — but never the file’s contents and never the API key. This keeps large or sensitive files out of the model’s context by construction, the same way Credential Blind keeps auth out of it.


Next: wire identity so your tools know who the user is — Identity & auth.