zeph_file
Upload and deliver text content such as logs, reports, or code snippets as a file push to the user's device.
Instructions
Send a text file to the user's device. The content is uploaded and delivered as a file push. Use for logs, reports, code snippets, or any text content.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| fileName | Yes | File name with extension (e.g., "report.txt", "output.json") | |
| content | Yes | Text content of the file | |
| title | No | Notification title (defaults to fileName) | |
| targetDeviceId | No | Target device ID. Omit to use configured default or send to all devices. |
Implementation Reference
- src/tools/file.ts:25-49 (handler)The main handler function for the zeph_file tool. It: 1) infers MIME type from filename, 2) requests an upload URL from the API, 3) uploads the content to S3, 4) sends a file push notification to the target device.
async ({ fileName, content, title, targetDeviceId }) => { try { const fileType = inferMimeType(fileName); const fileSize = new TextEncoder().encode(content).byteLength; // Step 1: Request upload URL const upload = await client.requestUpload({ fileName, fileType, fileSize }); // Step 2: Upload content to S3 await client.uploadToS3(upload.data.uploadUrl, content, fileType); // Step 3: Send file push const result = await client.sendPush({ title: title ?? fileName, type: 'file', files: [{ fileKey: upload.data.fileKey, fileName, fileSize, fileType }], targetDeviceId: targetDeviceId ?? config.deviceId, }); return textResult({ pushId: result.data.pushId, fileKey: upload.data.fileKey, fileSize }); } catch (err) { return formatToolError(err); } }, ); - src/tools/file.ts:18-23 (schema)Input schema for the zeph_file tool: fileName (string, required), content (string, required), title (string, optional), targetDeviceId (string, optional).
inputSchema: { fileName: z.string().describe('File name with extension (e.g., "report.txt", "output.json")'), content: z.string().describe('Text content of the file'), title: z.string().optional().describe('Notification title (defaults to fileName)'), targetDeviceId: z.string().optional().describe('Target device ID. Omit to use configured default or send to all devices.'), }, - src/tools/file.ts:7-50 (registration)The registerFileTool function that registers the tool with the MCP server under the name 'zeph_file' with description, annotations, input schema, and the handler callback.
export const registerFileTool = (server: McpServer, client: ZephApiClient, config: McpServerConfig) => { server.registerTool( 'zeph_file', { description: 'Send a text file to the user\'s device. The content is uploaded and delivered as a file push. Use for logs, reports, code snippets, or any text content.', annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true, }, inputSchema: { fileName: z.string().describe('File name with extension (e.g., "report.txt", "output.json")'), content: z.string().describe('Text content of the file'), title: z.string().optional().describe('Notification title (defaults to fileName)'), targetDeviceId: z.string().optional().describe('Target device ID. Omit to use configured default or send to all devices.'), }, }, async ({ fileName, content, title, targetDeviceId }) => { try { const fileType = inferMimeType(fileName); const fileSize = new TextEncoder().encode(content).byteLength; // Step 1: Request upload URL const upload = await client.requestUpload({ fileName, fileType, fileSize }); // Step 2: Upload content to S3 await client.uploadToS3(upload.data.uploadUrl, content, fileType); // Step 3: Send file push const result = await client.sendPush({ title: title ?? fileName, type: 'file', files: [{ fileKey: upload.data.fileKey, fileName, fileSize, fileType }], targetDeviceId: targetDeviceId ?? config.deviceId, }); return textResult({ pushId: result.data.pushId, fileKey: upload.data.fileKey, fileSize }); } catch (err) { return formatToolError(err); } }, ); }; - src/index.ts:66-66 (registration)Registration call in the main server setup: registerFileTool(server, client, config) wires the tool into the MCP server.
registerFileTool(server, client, config); - src/tools/file.ts:52-70 (helper)Helper function inferMimeType that maps file extensions to MIME types (e.g., .txt→text/plain, .json→application/json). Defaults to text/plain.
const inferMimeType = (fileName: string): string => { const ext = fileName.split('.').pop()?.toLowerCase(); const map: Record<string, string> = { txt: 'text/plain', json: 'application/json', csv: 'text/csv', md: 'text/markdown', html: 'text/html', xml: 'text/xml', yaml: 'text/yaml', yml: 'text/yaml', log: 'text/plain', ts: 'text/typescript', js: 'text/javascript', py: 'text/x-python', sh: 'text/x-shellscript', }; return map[ext ?? ''] ?? 'text/plain'; };