From d5c7cbfdc142dfb10209edfead5e362d7a390540 Mon Sep 17 00:00:00 2001 From: pasie15 Date: Mon, 8 Dec 2025 22:38:34 -0500 Subject: [PATCH 1/9] feat: Add get_session_downloads tool to retrieve files from browser sessions - Add new get_session_downloads tool to retrieve downloaded files from HyperBrowser sessions - Add saveDownloads option to sessionOptions schema - Include comprehensive documentation and examples - Supports both URL retrieval and automatic local download - Fully backward compatible with existing tools - Version bump to 1.2.0 --- DOWNLOADS_FEATURE.md | 229 +++++++++++++++++++++++++++ IMPLEMENTATION_SUMMARY.md | 234 +++++++++++++++++++++++++++ README.md | 1 + examples/download-files-example.md | 244 +++++++++++++++++++++++++++++ package.json | 2 +- src/tools/get-downloads.ts | 157 +++++++++++++++++++ src/tools/tool-types.ts | 29 ++++ src/transports/setup_server.ts | 15 ++ 8 files changed, 910 insertions(+), 1 deletion(-) create mode 100644 DOWNLOADS_FEATURE.md create mode 100644 IMPLEMENTATION_SUMMARY.md create mode 100644 examples/download-files-example.md create mode 100644 src/tools/get-downloads.ts diff --git a/DOWNLOADS_FEATURE.md b/DOWNLOADS_FEATURE.md new file mode 100644 index 0000000..b8e867c --- /dev/null +++ b/DOWNLOADS_FEATURE.md @@ -0,0 +1,229 @@ +# Session Downloads Feature + +This document explains how to use the `get_session_downloads` tool to retrieve files downloaded during a HyperBrowser session. + +## Overview + +The `get_session_downloads` tool allows you to retrieve files that were downloaded by the browser during a HyperBrowser session. This is useful for automating downloads of reports, documents, images, or any other files from websites. + +## Prerequisites + +For this feature to work, you **must** enable download tracking when creating your session: + +```json +{ + "task": "Download the latest report from example.com", + "sessionOptions": { + "saveDownloads": true + } +} +``` + +The `saveDownloads: true` option tells HyperBrowser to capture and store any files downloaded during the session. + +## How It Works + +1. **Create a session with downloads enabled**: Use any browser automation tool (browser_use_agent, openai_computer_use_agent, claude_computer_use_agent) with `saveDownloads: true` in sessionOptions +2. **Complete the task**: Let the agent complete the task that involves downloading files +3. **Retrieve the downloads**: Use `get_session_downloads` with the session ID to get access to the downloaded files + +## API Response + +When you call the HyperBrowser downloads API, you get a response like: + +```json +{ + "status": "completed", + "downloadsUrl": "https://temporary-url-to-downloads.zip", + "error": null +} +``` + +### Status Values + +- `pending`: Session is still running +- `in_progress`: Downloads are being processed +- `completed`: Downloads are ready to retrieve +- `failed`: Something went wrong + +## Using the Tool + +### Basic Usage (Get Download URL) + +```json +{ + "sessionId": "session_abc123xyz" +} +``` + +This returns the status and a temporary URL to download the zip file containing all session downloads. + +### Download Files Locally + +```json +{ + "sessionId": "session_abc123xyz", + "downloadZip": true, + "outputPath": "./downloads/my-session-files.zip" +} +``` + +This will: +1. Get the downloads URL from the API +2. Download the zip file +3. Save it to the specified local path + +## Complete Example Workflow + +### Step 1: Create a session and download files + +```typescript +// Using browser_use_agent +{ + "task": "Go to https://example.com/reports and download the Q4 2024 report", + "sessionOptions": { + "saveDownloads": true // IMPORTANT: Enable download tracking + }, + "maxSteps": 25 +} + +// Response includes session ID +{ + "sessionId": "session_abc123xyz", + // ... other response data +} +``` + +### Step 2: Retrieve the downloaded files + +```typescript +// Option A: Just get the download URL +{ + "sessionId": "session_abc123xyz" +} + +// Response +{ + "status": "completed", + "downloadsUrl": "https://temporary-storage.hyperbrowser.ai/downloads/abc123.zip" +} + +// Option B: Download the zip file locally +{ + "sessionId": "session_abc123xyz", + "downloadZip": true, + "outputPath": "./reports/q4-2024-report.zip" +} + +// Response +{ + "status": "completed", + "message": "Downloads zip file saved to: ./reports/q4-2024-report.zip" +} +``` + +## Important Notes + +1. **Temporary URLs**: The `downloadsUrl` is temporary and will expire after some time. Download the file promptly if you need it. + +2. **Session Options**: You must set `saveDownloads: true` in the session options BEFORE running the task. You cannot enable it retroactively. + +3. **File Format**: All downloaded files are packaged into a single ZIP file. + +4. **Tool Compatibility**: The `saveDownloads` option works with all browser automation tools: + - `browser_use_agent` + - `openai_computer_use_agent` + - `claude_computer_use_agent` + +5. **Path Requirements**: When using `downloadZip: true`, you must provide an `outputPath`. The directory will be created automatically if it doesn't exist. + +## Error Handling + +### Common Errors + +**"No downloads available"** +- The session hasn't completed yet, or +- No files were actually downloaded during the session, or +- `saveDownloads` was not enabled for the session + +**"Session not found"** +- Invalid session ID +- Session has expired + +**"API Error: 404"** +- The session ID doesn't exist +- Downloads have expired + +## Use Cases + +1. **Report Downloads**: Automate downloading financial reports, analytics dashboards, or business intelligence exports +2. **Data Collection**: Download CSV/Excel files from data portals +3. **Document Retrieval**: Download PDFs, invoices, or contracts from web applications +4. **Media Downloads**: Save images, videos, or audio files from websites +5. **Batch Processing**: Download multiple files in a single session and process them locally + +## Example: Downloading Multiple Files + +```typescript +// Step 1: Create session with multiple downloads +{ + "task": "Go to https://example.com/documents, download all PDFs from January 2024", + "sessionOptions": { + "saveDownloads": true + }, + "maxSteps": 50 +} + +// Step 2: Wait for completion, then retrieve +{ + "sessionId": "session_xyz789", + "downloadZip": true, + "outputPath": "./jan-2024-documents.zip" +} + +// Step 3: Extract and process locally +// All downloaded PDFs will be in the zip file +``` + +## Technical Details + +### API Endpoint + +The tool uses the HyperBrowser API endpoint: +``` +GET https://api.hyperbrowser.ai/v1/sessions/{sessionId}/downloads +``` + +### Authentication + +Uses the same API key as other HyperBrowser tools (from environment variables `HB_API_KEY` or `HYPERBROWSER_API_KEY`). + +### Dependencies + +- `axios`: For making HTTP requests +- Node.js `fs` module: For file system operations when downloading zip files +- Node.js `path` module: For handling file paths + +## Troubleshooting + +**Q: I'm getting "No downloads available" but files were downloaded** + +A: Make sure you set `saveDownloads: true` in the sessionOptions when creating the session. This cannot be added after the session starts. + +**Q: The download URL expired** + +A: Download URLs are temporary. Use the `downloadZip: true` option immediately after the session completes, or download from the URL quickly. + +**Q: Can I retrieve downloads from an old session?** + +A: There's a retention period for session downloads. Very old sessions may have expired downloads. Check with HyperBrowser documentation for the current retention policy. + +**Q: The zip file is empty** + +A: This means no files were actually downloaded during the session. Verify that your automation task correctly triggered file downloads in the browser. + +## Support + +For issues specific to the HyperBrowser API or download functionality, consult: +- [HyperBrowser Documentation](https://docs.hyperbrowser.ai/) +- [HyperBrowser API Reference](https://docs.hyperbrowser.ai/api-reference) diff --git a/IMPLEMENTATION_SUMMARY.md b/IMPLEMENTATION_SUMMARY.md new file mode 100644 index 0000000..c7ed10e --- /dev/null +++ b/IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,234 @@ +# Implementation Summary: Session Downloads Feature + +## Overview + +Successfully implemented the `get_session_downloads` tool for the HyperBrowser MCP server, enabling users to retrieve files downloaded during browser automation sessions. + +## Changes Made + +### 1. New Tool Implementation (`src/tools/get-downloads.ts`) + +Created a new tool that: +- Calls the HyperBrowser API endpoint: `GET /v1/sessions/{sessionId}/downloads` +- Retrieves download status and temporary download URL +- Optionally downloads the ZIP file to local filesystem +- Handles errors gracefully with detailed error messages + +**Key Features:** +- Returns session download status (pending, in_progress, completed, failed) +- Provides temporary URL to download ZIP containing all session downloads +- Can automatically download and save ZIP file locally when `downloadZip: true` +- Creates output directories automatically if they don't exist + +### 2. Schema Definitions (`src/tools/tool-types.ts`) + +**Added `getDownloadsToolParamSchemaRaw`:** +- `sessionId` (required): The HyperBrowser session ID +- `downloadZip` (optional, default false): Whether to download the ZIP file locally +- `outputPath` (optional): Local path for saving the ZIP file (required if downloadZip is true) + +**Added `saveDownloads` to `sessionOptionsSchema`:** +- New optional boolean field (default: false) +- Must be enabled when creating a session to track downloads +- Works with all browser automation tools + +### 3. Server Registration (`src/transports/setup_server.ts`) + +Registered the new tool with: +- Tool name: `get_session_downloads` +- Tool description: Comprehensive documentation of usage +- Parameter schema: Validation rules +- Tool handler: The implementation function + +### 4. Documentation + +**README.md:** +- Added tool to the list of available tools + +**DOWNLOADS_FEATURE.md (new):** +- Comprehensive guide to using the downloads feature +- Prerequisites and how it works +- API response format +- Usage examples (basic and advanced) +- Error handling and troubleshooting +- Technical details + +**examples/download-files-example.md (new):** +- Complete working examples +- Step-by-step workflows +- Code snippets for different scenarios +- Tips and best practices + +## How It Works + +### Workflow + +1. **Enable downloads**: User creates a browser session with `saveDownloads: true` in sessionOptions +2. **Perform task**: Browser agent completes the task that involves downloading files +3. **Retrieve downloads**: User calls `get_session_downloads` with the session ID +4. **Get files**: Tool retrieves download URL or downloads the ZIP file locally + +### API Integration + +The tool uses the HyperBrowser REST API directly via axios: +```typescript +GET https://api.hyperbrowser.ai/v1/sessions/{sessionId}/downloads +Authorization: Bearer {api_key} +``` + +Response format: +```json +{ + "status": "completed", + "downloadsUrl": "https://...", + "error": null +} +``` + +## Testing Recommendations + +### Manual Testing + +1. **Basic retrieval test:** + ```javascript + // Step 1: Create session with downloads + browser_use_agent({ + task: "Go to example.com and download a file", + sessionOptions: { saveDownloads: true } + }) + + // Step 2: Get download URL + get_session_downloads({ + sessionId: "session_xxx" + }) + ``` + +2. **Local download test:** + ```javascript + get_session_downloads({ + sessionId: "session_xxx", + downloadZip: true, + outputPath: "./test-downloads/files.zip" + }) + ``` + +3. **Error handling test:** + - Test with invalid session ID + - Test with session where saveDownloads was false + - Test with session still in progress + +### Integration Testing + +- Test with all three browser agents (browser_use, openai_cua, claude_computer_use) +- Test with profile usage +- Test with multiple file downloads +- Test with different file types (PDFs, images, CSVs, etc.) + +## Dependencies + +No new external dependencies were added. The implementation uses: +- Existing `axios` (already in package.json) +- Node.js built-in modules: `fs`, `path` +- Existing `@hyperbrowser/sdk` for client initialization + +## Backward Compatibility + +✅ **Fully backward compatible** + +- All changes are additive (new tool, new optional parameter) +- Existing tools and functionality remain unchanged +- No breaking changes to existing schemas +- `saveDownloads` defaults to `false`, maintaining existing behavior + +## Security Considerations + +1. **API Key**: Uses existing API key from environment variables +2. **File System Access**: Downloads are saved to user-specified paths (user must ensure paths are safe) +3. **Temporary URLs**: Download URLs are temporary and expire after some time +4. **No Data Exposure**: Session IDs must be provided explicitly; no session enumeration possible + +## Future Enhancements (Optional) + +Potential improvements that could be added later: + +1. **Stream processing**: Stream large ZIP files instead of loading into memory +2. **Selective extraction**: Extract specific files from ZIP instead of downloading entire archive +3. **Webhook notifications**: Get notified when downloads are ready +4. **Download metadata**: Include file names, sizes, and types in response +5. **Retry logic**: Built-in retry for failed downloads +6. **Progress reporting**: For large files, report download progress + +## Files Modified/Created + +### Created: +- `src/tools/get-downloads.ts` - Main tool implementation +- `DOWNLOADS_FEATURE.md` - Comprehensive documentation +- `examples/download-files-example.md` - Usage examples +- `IMPLEMENTATION_SUMMARY.md` - This file + +### Modified: +- `src/tools/tool-types.ts` - Added schema definitions +- `src/transports/setup_server.ts` - Registered new tool +- `README.md` - Updated tool list + +### Build Artifacts: +- `dist/` - TypeScript compilation output (generated on build) + +## Build and Deployment + +The implementation successfully compiles with TypeScript: +```bash +npx tsc # Exits with code 0 (success) +``` + +To deploy: +```bash +npm run build +npm start +``` + +Or for development: +```bash +node dist/server.js +``` + +## Verification Checklist + +- [x] TypeScript compilation successful +- [x] Tool registered in server setup +- [x] Schema validation rules defined +- [x] Error handling implemented +- [x] Documentation written +- [x] Examples provided +- [x] README updated +- [x] No breaking changes +- [x] Uses existing dependencies +- [x] Follows existing code patterns + +## Usage Example + +```javascript +// 1. Download files in a browser session +const session = await mcpClient.callTool('browser_use_agent', { + task: 'Download Q4 report from example.com', + sessionOptions: { + saveDownloads: true // Enable download tracking + } +}); + +// 2. Retrieve the downloaded files +const downloads = await mcpClient.callTool('get_session_downloads', { + sessionId: session.sessionId, + downloadZip: true, + outputPath: './reports/q4-report.zip' +}); + +console.log('Downloaded:', downloads.message); +``` + +## Support + +For questions or issues: +- Review `DOWNLOADS_FEATURE.md` for detailed usage information +- Check `examples/download-files-example.md` for working examples +- Consult HyperBrowser API docs: https://docs.hyperbrowser.ai/ diff --git a/README.md b/README.md index 8966b08..4d2f069 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ This is an example config for the Hyperbrowser MCP server for the Claude Desktop * `create_profile` - Creates a new persistent Hyperbrowser profile. * `delete_profile` - Deletes an existing persistent Hyperbrowser profile. * `list_profiles` - Lists existing persistent Hyperbrowser profiles. +* `get_session_downloads` - Retrieve files downloaded during a HyperBrowser session (requires saveDownloads: true in sessionOptions) ### Installing via Smithery diff --git a/examples/download-files-example.md b/examples/download-files-example.md new file mode 100644 index 0000000..991a666 --- /dev/null +++ b/examples/download-files-example.md @@ -0,0 +1,244 @@ +# Example: Downloading Files with HyperBrowser MCP + +This example demonstrates how to use the HyperBrowser MCP server to automate file downloads from a website. + +## Scenario + +Download a report from a website and save it locally. + +## Step 1: Create a Browser Session with Downloads Enabled + +First, use one of the browser automation agents to perform the download task. The key is to set `saveDownloads: true` in the session options. + +### Using browser_use_agent + +```json +{ + "tool": "browser_use_agent", + "params": { + "task": "Navigate to https://example.com/reports, find the 'Q4 2024 Financial Report' and download it", + "sessionOptions": { + "saveDownloads": true + }, + "maxSteps": 30 + } +} +``` + +### Response + +The agent will complete the task and return a response that includes the session ID: + +```json +{ + "status": "completed", + "sessionId": "session_abc123xyz456", + "result": "Successfully downloaded Q4 2024 Financial Report", + "steps": [...], + ... +} +``` + +**Important**: Make note of the `sessionId` - you'll need it in the next step. + +## Step 2: Retrieve the Downloaded Files + +Now use the `get_session_downloads` tool to retrieve the files that were downloaded during the session. + +### Option A: Get the Download URL Only + +```json +{ + "tool": "get_session_downloads", + "params": { + "sessionId": "session_abc123xyz456" + } +} +``` + +**Response:** +```json +{ + "status": "completed", + "downloadsUrl": "https://hyperbrowser-storage.s3.amazonaws.com/downloads/abc123.zip?expires=..." +} +``` + +You can then download the file manually from this URL, or pass it to another tool for processing. + +### Option B: Download the Files Locally (Recommended) + +```json +{ + "tool": "get_session_downloads", + "params": { + "sessionId": "session_abc123xyz456", + "downloadZip": true, + "outputPath": "./reports/q4-2024-financial-report.zip" + } +} +``` + +**Response:** +```json +{ + "status": "completed", + "message": "Downloads zip file saved to: ./reports/q4-2024-financial-report.zip" +} +``` + +The ZIP file now contains all files downloaded during the session. You can extract it: + +```bash +unzip ./reports/q4-2024-financial-report.zip -d ./reports/q4-2024/ +``` + +## Complete Workflow in Code + +If you're calling this programmatically, here's a complete Node.js example: + +```javascript +// 1. Start browser session and download files +const browserResult = await mcpClient.callTool('browser_use_agent', { + task: 'Go to https://example.com/reports and download the Q4 2024 report', + sessionOptions: { + saveDownloads: true + }, + maxSteps: 30 +}); + +// Extract session ID from response +const sessionId = browserResult.data.sessionId; +console.log('Browser session completed:', sessionId); + +// 2. Retrieve the downloaded files +const downloadResult = await mcpClient.callTool('get_session_downloads', { + sessionId: sessionId, + downloadZip: true, + outputPath: './reports/q4-report.zip' +}); + +console.log('Files downloaded:', downloadResult); + +// 3. Now you can process the downloaded files +// Extract, parse, analyze, etc. +``` + +## Advanced Example: Downloading Multiple Files + +Download all monthly reports from a dashboard: + +```json +{ + "tool": "browser_use_agent", + "params": { + "task": "Go to https://example.com/dashboard, navigate to the Reports section, and download all monthly reports for 2024 (January through December)", + "sessionOptions": { + "saveDownloads": true + }, + "maxSteps": 100 + } +} +``` + +Then retrieve all downloads in a single ZIP file: + +```json +{ + "tool": "get_session_downloads", + "params": { + "sessionId": "session_xyz789", + "downloadZip": true, + "outputPath": "./reports/2024-monthly-reports.zip" + } +} +``` + +The resulting ZIP will contain all 12 monthly reports that were downloaded during the session. + +## Using with Claude Computer Use Agent + +You can also use the more sophisticated Claude Computer Use agent for complex download scenarios: + +```json +{ + "tool": "claude_computer_use_agent", + "params": { + "task": "Go to https://data.example.com, log in with the credentials I provided earlier, navigate to Data Exports, select 'All Data' and 'CSV format', then download the export", + "sessionOptions": { + "saveDownloads": true, + "profile": { + "id": "my-profile-with-credentials" + } + }, + "maxSteps": 50 + } +} +``` + +Then retrieve the export: + +```json +{ + "tool": "get_session_downloads", + "params": { + "sessionId": "session_data_export_123", + "downloadZip": true, + "outputPath": "./exports/data-export-$(date +%Y%m%d).zip" + } +} +``` + +## Error Handling + +Always check the status before attempting to download: + +```javascript +const downloadResult = await mcpClient.callTool('get_session_downloads', { + sessionId: sessionId +}); + +if (downloadResult.status === 'completed') { + // Now download the zip + const zipResult = await mcpClient.callTool('get_session_downloads', { + sessionId: sessionId, + downloadZip: true, + outputPath: './downloads/files.zip' + }); + console.log('Downloaded:', zipResult); +} else if (downloadResult.status === 'pending' || downloadResult.status === 'in_progress') { + console.log('Session still processing, try again later'); +} else { + console.error('Download failed:', downloadResult.error); +} +``` + +## Tips + +1. **Enable saveDownloads Early**: Always set `saveDownloads: true` when creating the session. You can't enable it later. + +2. **Use Descriptive Paths**: Name your output files descriptively so you know what they contain: + ``` + ./downloads/financial-reports/q4-2024-report.zip + ./exports/customer-data-2024-12-09.zip + ``` + +3. **Handle Timeouts**: If the download task takes a long time, the session might timeout. Increase `maxSteps` if needed. + +4. **Extract and Verify**: After downloading, extract the ZIP and verify the contents: + ```javascript + const extract = require('extract-zip'); + await extract('./reports/q4-report.zip', { dir: './reports/q4-extracted' }); + ``` + +5. **Clean Up**: Delete the ZIP files after extraction to save disk space. + +6. **Retry Logic**: If downloads fail, implement retry logic with exponential backoff. + +## Next Steps + +- Integrate this into your automation pipelines +- Set up scheduled downloads with cron jobs +- Process downloaded files automatically (parse PDFs, load CSVs into databases, etc.) +- Send notifications when downloads complete +- Archive downloaded files to cloud storage diff --git a/package.json b/package.json index fc1b1ae..30de82b 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.1.0", + "version": "1.2.0", "description": "Hyperbrowser Model Context Protocol Server", "name": "hyperbrowser-mcp", "main": "./dist/server.js", diff --git a/src/tools/get-downloads.ts b/src/tools/get-downloads.ts new file mode 100644 index 0000000..49e7c2a --- /dev/null +++ b/src/tools/get-downloads.ts @@ -0,0 +1,157 @@ +import { + CallToolResult, + ServerRequest, + ServerNotification, +} from "@modelcontextprotocol/sdk/types.js"; +import { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js"; +import { getClient } from "../utils"; +import { getDownloadsToolParamSchemaType } from "./tool-types"; +import axios from "axios"; + +export async function getDownloadsTool( + params: getDownloadsToolParamSchemaType, + extra: RequestHandlerExtra +): Promise { + const { sessionId, downloadZip, outputPath } = params; + + let apiKey: string | undefined = undefined; + if (extra.authInfo && extra.authInfo.extra?.isSSE) { + apiKey = extra.authInfo.token; + } + + try { + const client = await getClient({ hbApiKey: apiKey }); + + // Make API call to get downloads URL + // Based on the HyperBrowser API: GET /v1/sessions/{sessionId}/downloads + const apiKeyToUse = + apiKey || process.env.HB_API_KEY || process.env.HYPERBROWSER_API_KEY; + + if (!apiKeyToUse) { + throw new Error("No API key provided or found in environment variables"); + } + + const response = await axios.get( + `https://api.hyperbrowser.ai/v1/sessions/${sessionId}/downloads`, + { + headers: { + Authorization: `Bearer ${apiKeyToUse}`, + }, + } + ); + + const { status, downloadsUrl, error } = response.data; + + if (error) { + return { + isError: true, + content: [ + { + type: "text", + text: `Error retrieving downloads: ${error}`, + }, + ], + }; + } + + const result: CallToolResult = { + content: [], + isError: false, + }; + + // Add status information + result.content.push({ + type: "text", + text: `Session download status: ${status}`, + }); + + // If downloadsUrl is available and downloadZip is true, download the zip file + if (downloadsUrl && downloadZip && outputPath) { + try { + const fs = await import("fs"); + const path = await import("path"); + + // Download the zip file + const zipResponse = await axios.get(downloadsUrl, { + responseType: "arraybuffer", + }); + + // Ensure output directory exists + const outputDir = path.dirname(outputPath); + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } + + // Write the zip file + fs.writeFileSync(outputPath, Buffer.from(zipResponse.data)); + + result.content.push({ + type: "text", + text: `Downloads zip file saved to: ${outputPath}`, + }); + } catch (downloadError) { + result.content.push({ + type: "text", + text: `Error downloading zip file: ${ + downloadError instanceof Error + ? downloadError.message + : String(downloadError) + }`, + }); + } + } else if (downloadsUrl) { + // Just return the URL + result.content.push({ + type: "text", + text: `Downloads URL: ${downloadsUrl}`, + }); + } else { + result.content.push({ + type: "text", + text: "No downloads available yet. The session may still be in progress or no files were downloaded.", + }); + } + + return result; + } catch (error) { + if (axios.isAxiosError(error)) { + return { + content: [ + { + type: "text", + text: `API Error: ${error.response?.status} - ${ + error.response?.data?.error || error.message + }`, + }, + ], + isError: true, + }; + } + + return { + content: [{ type: "text", text: `${error}` }], + isError: true, + }; + } +} + +export const getDownloadsToolName = "get_session_downloads"; +export const getDownloadsToolDescription = ` +Retrieve files that were downloaded during a HyperBrowser session. This tool accesses the session's downloads via the HyperBrowser API. + +Prerequisites: +- The session must have been created with saveDownloads: true option +- The session must be completed (or at least have downloads available) + +Parameters: +- sessionId: The ID of the HyperBrowser session to retrieve downloads from +- downloadZip: (Optional) If true, downloads the zip file containing all session downloads +- outputPath: (Optional) Required if downloadZip is true. Local path where the zip file should be saved + +Returns: +- Session download status (pending, in_progress, completed, failed) +- Downloads URL (temporary URL to download zip file) +- If downloadZip is true and outputPath is provided: Confirmation of local zip file saved + +Note: The downloads URL is temporary and will expire after some time. Download the zip file promptly if needed. +`.trim(); diff --git a/src/tools/tool-types.ts b/src/tools/tool-types.ts index 2770b5f..83030c7 100644 --- a/src/tools/tool-types.ts +++ b/src/tools/tool-types.ts @@ -26,6 +26,12 @@ export const sessionOptionsSchema = z .describe( "Whether to automatically close the accept cookies popup. Recommended false." ), + saveDownloads: z + .boolean() + .default(false) + .describe( + "Whether to save files downloaded during the session. When enabled, downloaded files can be retrieved via the get_session_downloads tool after the session completes. Recommended false unless you need to retrieve downloaded files." + ), profile: z .object({ id: z @@ -289,3 +295,26 @@ export const listProfilesToolParamSchema = z.object( export type listProfilesToolParamSchemaType = z.infer< typeof listProfilesToolParamSchema >; + +// Get Session Downloads + +export const getDownloadsToolParamSchemaRaw = { + sessionId: z.string().describe("The ID of the HyperBrowser session to retrieve downloads from"), + downloadZip: z + .boolean() + .optional() + .default(false) + .describe("If true, downloads the zip file containing all session downloads to the local filesystem"), + outputPath: z + .string() + .optional() + .describe("Required if downloadZip is true. Local file path where the downloads zip file should be saved (e.g., './downloads/session-files.zip')"), +}; + +export const getDownloadsToolParamSchema = z.object( + getDownloadsToolParamSchemaRaw +); + +export type getDownloadsToolParamSchemaType = z.infer< + typeof getDownloadsToolParamSchema +>; diff --git a/src/transports/setup_server.ts b/src/transports/setup_server.ts index 9073bf3..261a9fb 100644 --- a/src/transports/setup_server.ts +++ b/src/transports/setup_server.ts @@ -71,7 +71,14 @@ import { import { deleteProfileToolParamSchemaRaw, listProfilesToolParamSchemaRaw, + getDownloadsToolParamSchemaRaw, } from "../tools/tool-types"; +// Import get downloads tool +import { + getDownloadsTool, + getDownloadsToolDescription, + getDownloadsToolName, +} from "../tools/get-downloads"; function setupServer(server: McpServer) { @@ -141,6 +148,14 @@ function setupServer(server: McpServer) { listProfilesTool ); + // Register get downloads tool + server.tool( + getDownloadsToolName, + getDownloadsToolDescription, + getDownloadsToolParamSchemaRaw, + getDownloadsTool + ); + server.server.setRequestHandler(ListResourcesRequestSchema, listAllResources); server.server.setRequestHandler(ReadResourceRequestSchema, getResource); From 0efa4a10196537fa78ed7618654707db4af5c953 Mon Sep 17 00:00:00 2001 From: pasie15 Date: Mon, 8 Dec 2025 22:45:55 -0500 Subject: [PATCH 2/9] fix: Make build scripts cross-platform compatible for Windows --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 30de82b..299af90 100644 --- a/package.json +++ b/package.json @@ -13,14 +13,14 @@ "access": "public" }, "scripts": { - "build": "rm -rf dist && tsc && node -e \"require('fs').chmodSync('dist/server.js', '755')\"", + "build": "node -e \"const fs=require('fs');if(fs.existsSync('dist'))fs.rmSync('dist',{recursive:true})\" && tsc && node -e \"try{require('fs').chmodSync('dist/server.js','755')}catch(e){}\"", "start": "node dist/server.js", "lint": "eslint src/**/*.ts", "lint:fix": "eslint src/**/*.ts --fix", "format": "prettier --write .", "build-resources": "node --loader ts-node/esm scripts/build_resources.ts && cp summarized.json src/resources/static/data/summarized.json && rm summarized.json && rm static_data.json", "prepare": "npm run build", - "publish": "rm -rf dist && rm -rf node_modules && npm i && npm run build && npm publish" + "publish": "node -e \"const fs=require('fs');['dist','node_modules'].forEach(d=>{if(fs.existsSync(d))fs.rmSync(d,{recursive:true})})\" && npm i && npm run build && npm publish" }, "dependencies": { "@hyperbrowser/sdk": "^0.48.1", From 1947c2921555fcef64dc13e2bc4b6892985ac179 Mon Sep 17 00:00:00 2001 From: pasie15 Date: Mon, 8 Dec 2025 22:47:36 -0500 Subject: [PATCH 3/9] chore: Rename package to @version6media/hyperbrowser-mcp scoped package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 299af90..4d68bd7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "version": "1.2.0", "description": "Hyperbrowser Model Context Protocol Server", - "name": "hyperbrowser-mcp", + "name": "@version6media/hyperbrowser-mcp", "main": "./dist/server.js", "bin": { "hyperbrowser-mcp": "dist/server.js" From 01d8936ec25592a85e0fafbb05959210d12266ce Mon Sep 17 00:00:00 2001 From: pasie15 Date: Mon, 8 Dec 2025 22:54:58 -0500 Subject: [PATCH 4/9] chore: Rename package to hyperbrowserai-mcp-server v1.3.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4d68bd7..0a3f681 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "version": "1.2.0", + "version": "1.3.0", "description": "Hyperbrowser Model Context Protocol Server", - "name": "@version6media/hyperbrowser-mcp", + "name": "hyperbrowserai-mcp-server", "main": "./dist/server.js", "bin": { "hyperbrowser-mcp": "dist/server.js" From 7e00293f1f5e60ff40e3382cef8462beaf7cfbb0 Mon Sep 17 00:00:00 2001 From: pasie15 Date: Mon, 8 Dec 2025 23:00:07 -0500 Subject: [PATCH 5/9] chore: Update package-lock.json after npm publish --- package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index affb603..49a6809 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { - "name": "hyperbrowser-mcp", - "version": "1.1.0", + "name": "hyperbrowserai-mcp-server", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "hyperbrowser-mcp", - "version": "1.1.0", + "name": "hyperbrowserai-mcp-server", + "version": "1.3.0", "license": "ISC", "dependencies": { "@hyperbrowser/sdk": "^0.48.1", From a6e2062b26fccb5ed9c67c8b2ddc7faff6b6b75c Mon Sep 17 00:00:00 2001 From: pasie15 Date: Mon, 8 Dec 2025 23:12:04 -0500 Subject: [PATCH 6/9] Update README.md with improved documentation --- README.md | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 4d2f069..0e1fc60 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,10 @@ -# Hyperbrowser MCP Server -[![smithery badge](https://smithery.ai/badge/@hyperbrowserai/mcp)](https://smithery.ai/server/@hyperbrowserai/mcp) +# HyperBrowser AI MCP Server ![Frame 5](https://github.com/user-attachments/assets/3309a367-e94b-418a-a047-1bf1ad549c0a) -This is Hyperbrowser's Model Context Protocol (MCP) Server. It provides various tools to scrape, extract structured data, and crawl webpages. It also provides easy access to general purpose browser agents like OpenAI's CUA, Anthropic's Claude Computer Use, and Browser Use. +An enhanced Model Context Protocol (MCP) Server for HyperBrowser with additional features including session file downloads. This server provides various tools to scrape, extract structured data, and crawl webpages. It also provides easy access to general purpose browser agents like OpenAI's CUA, Anthropic's Claude Computer Use, and Browser Use. -More information about the Hyperbrowser can be found [here](https://docs.hyperbrowser.ai/). The hyperbrowser API supports a superset of features present in the mcp server. +More information about HyperBrowser can be found [here](https://docs.hyperbrowser.ai/). The HyperBrowser API supports a superset of features present in the MCP server. More information about the Model Context Protocol can be found [here](https://modelcontextprotocol.io/introduction). @@ -19,11 +18,16 @@ More information about the Model Context Protocol can be found [here](https://mo ## Installation -### Manual Installation -To install the server, run: +### NPM Installation +Install globally: ```bash -npx hyperbrowser-mcp +npm install -g hyperbrowserai-mcp-server +``` + +Or run directly with npx: +```bash +npx hyperbrowserai-mcp-server ``` ## Running on Cursor @@ -31,9 +35,9 @@ Add to `~/.cursor/mcp.json` like this: ```json { "mcpServers": { - "hyperbrowser": { + "hyperbrowserai": { "command": "npx", - "args": ["-y", "hyperbrowser-mcp"], + "args": ["-y", "hyperbrowserai-mcp-server"], "env": { "HYPERBROWSER_API_KEY": "YOUR-API-KEY" } @@ -47,9 +51,9 @@ Add to your `./codeium/windsurf/model_config.json` like this: ```json { "mcpServers": { - "hyperbrowser": { + "hyperbrowserai": { "command": "npx", - "args": ["-y", "hyperbrowser-mcp"], + "args": ["-y", "hyperbrowserai-mcp-server"], "env": { "HYPERBROWSER_API_KEY": "YOUR-API-KEY" } @@ -82,15 +86,15 @@ For development purposes, you can run the server directly from the source code. node dist/server.js ``` -## Claude Desktop app -This is an example config for the Hyperbrowser MCP server for the Claude Desktop client. +## Claude Desktop App +This is an example config for the HyperBrowser AI MCP server for the Claude Desktop client. ```json { "mcpServers": { - "hyperbrowser": { + "hyperbrowserai": { "command": "npx", - "args": ["--yes", "hyperbrowser-mcp"], + "args": ["-y", "hyperbrowserai-mcp-server"], "env": { "HYPERBROWSER_API_KEY": "your-api-key" } @@ -113,13 +117,14 @@ This is an example config for the Hyperbrowser MCP server for the Claude Desktop * `list_profiles` - Lists existing persistent Hyperbrowser profiles. * `get_session_downloads` - Retrieve files downloaded during a HyperBrowser session (requires saveDownloads: true in sessionOptions) -### Installing via Smithery +## Additional Features -To install Hyperbrowser MCP Server for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@hyperbrowserai/mcp): +This enhanced version includes: +- **Session Downloads**: Retrieve files downloaded during browser automation sessions +- **Cross-platform compatibility**: Improved Windows support +- **Enhanced documentation**: Comprehensive guides and examples -```bash -npx -y @smithery/cli install @hyperbrowserai/mcp --client claude -``` +See [DOWNLOADS_FEATURE.md](./DOWNLOADS_FEATURE.md) for detailed information about the session downloads feature. ## Resources From 290dcac661b05a3b4660cf88fe9c2ecb0abc1a84 Mon Sep 17 00:00:00 2001 From: pasie15 Date: Mon, 8 Dec 2025 23:12:48 -0500 Subject: [PATCH 7/9] 1.3.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 49a6809..e53e850 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "hyperbrowserai-mcp-server", - "version": "1.3.0", + "version": "1.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "hyperbrowserai-mcp-server", - "version": "1.3.0", + "version": "1.3.1", "license": "ISC", "dependencies": { "@hyperbrowser/sdk": "^0.48.1", diff --git a/package.json b/package.json index 0a3f681..e588cd7 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.3.0", + "version": "1.3.1", "description": "Hyperbrowser Model Context Protocol Server", "name": "hyperbrowserai-mcp-server", "main": "./dist/server.js", From cae4082ca43478cd4838e8c5bdfec53009fd96e2 Mon Sep 17 00:00:00 2001 From: pasie15 Date: Mon, 8 Dec 2025 23:13:36 -0500 Subject: [PATCH 8/9] 1.3.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e53e850..03afb6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "hyperbrowserai-mcp-server", - "version": "1.3.1", + "version": "1.3.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "hyperbrowserai-mcp-server", - "version": "1.3.1", + "version": "1.3.2", "license": "ISC", "dependencies": { "@hyperbrowser/sdk": "^0.48.1", diff --git a/package.json b/package.json index e588cd7..7025030 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.3.1", + "version": "1.3.2", "description": "Hyperbrowser Model Context Protocol Server", "name": "hyperbrowserai-mcp-server", "main": "./dist/server.js", From d79bbc9ac5347eda395e1468551449896a1e7621 Mon Sep 17 00:00:00 2001 From: pasie15 Date: Mon, 8 Dec 2025 23:14:32 -0500 Subject: [PATCH 9/9] 1.3.3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 03afb6e..1af60c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "hyperbrowserai-mcp-server", - "version": "1.3.2", + "version": "1.3.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "hyperbrowserai-mcp-server", - "version": "1.3.2", + "version": "1.3.3", "license": "ISC", "dependencies": { "@hyperbrowser/sdk": "^0.48.1", diff --git a/package.json b/package.json index 7025030..7beea02 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.3.2", + "version": "1.3.3", "description": "Hyperbrowser Model Context Protocol Server", "name": "hyperbrowserai-mcp-server", "main": "./dist/server.js",