Skip to content

Conversation

therealnb
Copy link

@therealnb therealnb commented Oct 2, 2025

Deep Linking Implementation for ToolHive Studio

Closes #956

🎯 Goal

Enable one-click navigation from error messages or documentation directly to ToolHive Studio's server installation page, providing a seamless UX when handling missing secrets or configuration issues.

Use Case

When an MCP server reports a missing secret or configuration issue, provide a clickable link that:

  1. Opens ToolHive Studio (or focuses if already open)
  2. Navigates to the correct server installation page
  3. Opens the installation dialog automatically

UX Improvement

Before: User sees error → Must manually open Studio → Navigate to Registry → Search for server → Click install (5 steps)
After: User sees error → Clicks link → Done! (1 click) ✨


📋 Changes Overview

New Files Created

Core Implementation

  • main/src/deep-link.ts - Core deep linking logic
    • Protocol handler (toolhive:// URL scheme)
    • URL parsing with support for server names and registries
    • Deep link generation utilities
    • Navigation handling logic
  • main/src/control-server.ts - HTTP control endpoint for programmatic navigation
    • Runs on http://127.0.0.1:51234
    • GET /health - Health check endpoint
    • POST /navigate - Navigate with JSON body
    • GET /navigate?url=<encoded> - Navigate with query parameter
    • Graceful handling when port is already in use
  • renderer/src/common/hooks/use-deep-link.tsx - React hook for deep link navigation
    • Listens for deep link events from main process
    • Handles router navigation to server installation page
    • Automatically opens installation dialog

Testing & Documentation

  • main/src/tests/deep-link.test.ts - Comprehensive unit tests
    • URL parsing tests
    • Link generation tests
    • Edge case handling (8 tests, all passing)
  • docs/deep-linking.md - Complete user documentation
    • Protocol specification
    • Usage examples
    • Integration guide for MCP server authors
    • HTTP control API reference

Modified Files

main/src/main.ts

Changes:

  • Import deep link functions (handleDeepLink, registerProtocol, generateInstallServerLink, generateCliCommand)
  • Register toolhive:// protocol on app startup
  • Start HTTP control server when app is ready
  • Stop control server on app quit and during shutdown
  • Add open-url event handler (macOS deep link support)
  • Add second-instance event handler (Windows/Linux deep link support)
  • Add IPC handlers:
    • deep-link:generate-install-link - Generate deep link URLs
    • deep-link:generate-cli-command - Generate equivalent CLI commands
  • Fixed Vite compatibility: use import.meta.env instead of process.env for Sentry DSN

preload/src/preload.ts

Changes:

  • Expose deep link API to renderer process
  • Add deepLink.onNavigate() listener registration
  • Add deepLink.generateInstallLink() method
  • Add deepLink.generateCliCommand() method

renderer/src/routes/__root.tsx

Changes:

  • Import and initialize useDeepLink hook at the root level
  • Ensures deep link handling works throughout the app

renderer/src/routes/(registry)/registry_.$name.tsx

Changes:

  • Enhanced to automatically open install dialog when navigating via deep link
  • Checks for server search parameter in URL
  • Preserves existing functionality while adding deep link support

Configuration Files

  • .gitignore - Added .vscode/ to ignore VS Code settings
  • knip.ts - Added ignoreExportsUsedInFile config for test files
  • vitest.setup.ts - Added mocks for electron and electron-log to fix test execution

🎯 Functionality Implemented

1. Custom URL Protocol (toolhive://)

  • Registered on all platforms (macOS, Windows, Linux)
  • Supported Action:
    • install-server - Navigate to server installation page with auto-opening dialog

Example:

toolhive://install-server?server=github&registry=official

2. HTTP Control Endpoint

When ToolHive Studio is running, a local HTTP server on http://127.0.0.1:51234 provides programmatic navigation:

Endpoints:

  • GET /health - Check if control server is running
  • POST /navigate - Navigate using JSON body {"url": "toolhive://..."}
  • GET /navigate?url=<encoded-url> - Navigate using query parameter

Example:

curl -X POST http://127.0.0.1:51234/navigate \
  -H "Content-Type: application/json" \
  -d '{"url": "toolhive://install-server?server=github"}'

3. Link & CLI Command Generation

Helper functions to generate deep links and equivalent CLI commands:

// Generate deep link
const link = await window.electronAPI.deepLink.generateInstallLink('github', 'official')
// Returns: "toolhive://install-server?server=github&registry=official"

// Generate CLI command
const cmd = await window.electronAPI.deepLink.generateCliCommand('github', 'official')
// Returns: "thv run --registry official github"

4. Automatic Dialog Opening

When navigating via deep link, the registry page automatically:

  1. Navigates to the correct server's registry page
  2. Opens the installation dialog
  3. User can immediately fill in configuration and install

🧪 Testing

  1. Deep link from terminal:

    open "toolhive://install-server?server=github"
  2. HTTP control endpoint:

    curl -X POST http://127.0.0.1:51234/navigate \
      -H "Content-Type: application/json" \
      -d '{"url": "toolhive://install-server?server=github"}'
  3. App not running: Deep link launches app and navigates

  4. App already running: Deep link focuses app and navigates


🎨 User Experience

The implementation focuses on simplicity and reliability:

  1. Minimal friction: From error message to installation dialog in one click
  2. Automatic dialog opening: No need to search or navigate manually
  3. Fallback to HTTP: If custom protocol fails, HTTP endpoint provides alternative
  4. CLI command generation: For users who prefer command-line workflows

Result: 5 manual steps → 1 click!

- Add deep link handler and control server
- Add deep link React components and hooks
- Update main window and toolhive manager for deep linking
- Add comprehensive documentation
- Fix linting errors (unused variables, require imports)
@Copilot Copilot AI review requested due to automatic review settings October 2, 2025 09:44
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements deep linking functionality for ToolHive Studio, enabling one-click navigation from external sources (error messages, documentation) directly to the server installation page. The implementation includes a custom toolhive:// protocol handler, HTTP control server for programmatic navigation, and comprehensive UI integration.

Key changes include:

  • Custom protocol registration for toolhive:// URLs with cross-platform support
  • HTTP control server running on localhost:51234 for programmatic navigation when the app is running
  • React hooks and UI components for handling deep link navigation and automatically opening installation dialogs

Reviewed Changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
main/src/main.ts Adds deep link protocol registration, IPC handlers, and control server lifecycle management
main/src/deep-link.ts Core deep linking logic with URL parsing and link generation utilities
main/src/control-server.ts HTTP control endpoint for programmatic navigation with health checks
renderer/src/common/hooks/use-deep-link.tsx React hook for handling deep link events and router navigation
renderer/src/routes/__root.tsx Initializes deep link handling at the root level
renderer/src/routes/(registry)/registry_.$name.tsx Enhanced to auto-open install dialog when navigating via deep links
preload/src/preload.ts Exposes deep link API to renderer process
main/src/tests/deep-link.test.ts Comprehensive unit tests for URL parsing and link generation
docs/deep-linking.md Complete documentation with usage examples and API reference
Comments suppressed due to low confidence (2)

renderer/src/features/deep-link/components/deep-link-generator.tsx:1

  • This catch block appears to be in the wrong file. It contains server response code but this is a React component file. This code should be in main/src/control-server.ts instead.
import { useState } from 'react'

main/src/toolhive-manager.ts:1

  • [nitpick] The ternary operator formatting is inconsistent with the existing codebase pattern. The closing parenthesis on line 32 should align with the opening condition on line 18 for better readability.
import { spawn } from 'node:child_process'

- Format docs/deep-linking.md with prettier
- Remove unused deep-link-generator component
- Add ignoreExportsUsedInFile config to knip
- Mock electron and electron-log in vitest setup to fix test failures
@therealnb therealnb changed the title feat: Deep Linking Implementation for ToolHive Studio feat: deep linking implementation for ToolHive Studio Oct 2, 2025
- Add @public JSDoc tags to exported functions in control-server.ts to tell knip they are public API
- Add deepLink API mock to vitest.setup.ts to fix registry tests
- Use standard URLSearchParams instead of router's useSearch hook
- Avoids test failures due to missing search params schema
- All tests now pass (483 passed)
broken in check fixes...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Story] Deep Linking for ToolHive Studio

1 participant