Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions openspec/changes/add-daemon-management/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Design: Daemon Management

## Context

The docs-mcp-server needs to run as a persistent background process to provide continuous MCP service to AI clients. Currently, users must manually start the server in a terminal, which is inconvenient for daily use and doesn't survive system reboots.

**Stakeholders**: End users running docs-mcp-server locally or on servers.

**Constraints**:
- Must support macOS, Windows, and Linux
- Must not require native module compilation (pure JavaScript)
- Must work with the existing CLI framework (Yargs)
- Service management requires elevated privileges

## Goals / Non-Goals

### Goals
- Provide simple CLI commands to install/uninstall the server as a system daemon
- Support all three major platforms with native service mechanisms
- Allow configuration of server options (port, host) at install time
- Provide status, start, stop, restart commands for lifecycle management
- Handle permission requirements gracefully with clear error messages

### Non-Goals
- Container/Docker orchestration (separate concern)
- Cluster/multi-instance management
- GUI installer
- Auto-update mechanism

## Decisions

### Decision 1: Use node-windows/node-mac/node-linux Package Family

**What**: Use the established `node-windows`, `node-mac`, and `node-linux` packages by Corey Butler for cross-platform daemon management.

**Why**:
- Mature, battle-tested packages (2.9k+ stars for node-windows)
- Pure JavaScript (no native compilation required)
- Consistent API across all three packages
- MIT licensed
- Handles platform-specific details (launchd, Windows Services, systemd/init.d)
- Built-in service monitoring with configurable restart behavior

**Alternatives considered**:
1. **Manual platform scripts**: Would require maintaining separate bash/powershell/plist scripts. High maintenance burden.
2. **PM2**: Designed for Node.js process management but not native OS services. Adds complexity and another background process.
3. **systemd-only on Linux**: Would limit Linux support to systemd-based distros.

### Decision 2: Subcommand Pattern (`daemon <action>`)

**What**: Group all daemon operations under a `daemon` parent command.

**Why**:
- Aligns with existing CLI patterns (though current commands are flat, `daemon` is a logical grouping)
- Avoids namespace conflicts (`install`, `start`, `stop`, `status` are generic terms)
- Enables discoverability (`docs-mcp-server daemon --help`)
- Follows precedent from Docker, systemctl, npm, etc.

**Command structure**:
```
daemon install [--port] [--host] [--resume] [--read-only] [--store-path]
daemon uninstall
daemon status
daemon start
daemon stop
daemon restart
```

### Decision 3: Configuration Persistence via Environment Variables

**What**: Pass server configuration to the daemon via environment variables set in the service definition.

**Why**:
- The node-* packages natively support environment variable configuration
- Avoids needing a separate config file for daemon-specific settings
- Consistent with 12-factor app principles
- Configuration travels with the service definition

**Implementation**:
```javascript
const svc = new Service({
name: 'docs-mcp-server',
script: '/path/to/dist/index.js',
env: [
{ name: 'DOCS_MCP_PORT', value: '3000' },
{ name: 'DOCS_MCP_HOST', value: '0.0.0.0' },
{ name: 'DOCS_MCP_STORE_PATH', value: '/path/to/store' },
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The example environment variable configuration is incomplete. According to tasks.md (lines 51-57), the daemon should also support DOCS_MCP_RESUME and DOCS_MCP_READ_ONLY environment variables. Consider updating this example to include all the environment variables that will be passed to the daemon service, or reference tasks.md section 4.1 for the complete list.

Suggested change
{ name: 'DOCS_MCP_STORE_PATH', value: '/path/to/store' },
{ name: 'DOCS_MCP_STORE_PATH', value: '/path/to/store' },
{ name: 'DOCS_MCP_RESUME', value: 'false' },
{ name: 'DOCS_MCP_READ_ONLY', value: 'false' },

Copilot uses AI. Check for mistakes.
]
});
```

### Decision 4: Platform-Agnostic DaemonService Abstraction

**What**: Create a `DaemonService` class that provides a unified API across all platforms.

**Why**:
- Encapsulates platform detection and package selection
- Single interface for CLI commands to use
- Easier testing via dependency injection
- Future-proofs against package API changes

**Structure**:
```
src/daemon/
├── DaemonService.ts # Main abstraction class
├── types.ts # DaemonOptions, DaemonStatus interfaces
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The directory structure shown here is missing the barrel export file (index.ts) that is mentioned in tasks.md section 2.3. Consider adding "├── index.ts # Barrel export" to this structure for completeness and consistency with the task breakdown.

Suggested change
├── types.ts # DaemonOptions, DaemonStatus interfaces
├── types.ts # DaemonOptions, DaemonStatus interfaces
├── index.ts # Barrel export

Copilot uses AI. Check for mistakes.
└── DaemonService.test.ts # Unit tests
```

### Decision 5: Service Name

**What**: Use `docs-mcp-server` as the fixed service name.

**Why**:
- Matches the npm package name for consistency
- Unique enough to avoid conflicts
- Clear identification in system tools (Activity Monitor, Services, systemctl)

## Risks / Trade-offs

### Risk 1: Elevated Privileges Required
- **Risk**: Install/uninstall operations require sudo/admin, which may fail or confuse users.
- **Mitigation**: Clear error messages explaining the permission requirement. Documentation with example commands.

### Risk 2: Windows WSL Confusion
- **Risk**: Users in WSL might try to install a Windows service, which won't work.
- **Mitigation**: Detect WSL environment and provide appropriate guidance to use Linux service or native Windows outside WSL.

### Risk 3: Package Maintenance
- **Risk**: The node-* packages may become unmaintained.
- **Mitigation**: The packages are stable (minimal updates needed for mature OS APIs). Fork if necessary. The abstraction layer isolates the CLI from direct package dependencies.

### Risk 4: Service Recovery Loops
- **Risk**: If the server has a fatal bug, the service might restart endlessly.
- **Mitigation**: Use the built-in `maxRestarts` and `maxRetries` configuration to cap restart attempts. Default to sensible limits (e.g., 5 restarts in 60 seconds).
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

Minor terminology inconsistency: The spec (line 191) uses "5 restarts per 60 seconds" while the design uses "5 restarts in 60 seconds". Consider using "per" instead of "in" to match the spec's terminology.

Suggested change
- **Mitigation**: Use the built-in `maxRestarts` and `maxRetries` configuration to cap restart attempts. Default to sensible limits (e.g., 5 restarts in 60 seconds).
- **Mitigation**: Use the built-in `maxRestarts` and `maxRetries` configuration to cap restart attempts. Default to sensible limits (e.g., 5 restarts per 60 seconds).

Copilot uses AI. Check for mistakes.

## Migration Plan

This is a new feature with no migration required. Users can adopt it optionally.

**Rollout**:
1. Implement and test on all three platforms
2. Document in README with platform-specific notes
3. Add to CLI help text

**Rollback**: Simply don't use the daemon commands; manual startup continues to work.

## Open Questions

1. **Log file location**: Should we configure a specific log location for daemon output, or use the platform defaults?
- **Proposed answer**: Use platform defaults initially (`/Library/Logs/` on macOS, Event Log on Windows, `/var/log/` on Linux). Document locations.

2. **Multiple instances**: Should we support running multiple daemon instances with different names/ports?
- **Proposed answer**: Out of scope for initial implementation. Single instance with fixed name. Can be extended later if needed.

3. **Auto-start on install**: Should `daemon install` automatically start the service?
- **Proposed answer**: Yes, this matches user expectation and the node-* package default behavior.
52 changes: 52 additions & 0 deletions openspec/changes/add-daemon-management/proposal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Change: Add Daemon Management CLI Commands

## Why

Currently, users must manually start the docs-mcp-server by running `./dist/index.js` or `docs-mcp-server` in a terminal window. This requires keeping the terminal open and remembering to restart the server after reboots. A daemon/service installation feature would allow the server to run as a persistent background process that starts automatically on system boot, providing a seamless always-on experience.

## What Changes

- **New CLI command group**: `daemon` with subcommands (`install`, `uninstall`, `status`, `start`, `stop`, `restart`)
- **New dependencies**: `node-mac`, `node-windows`, `node-linux` packages for cross-platform service management
- **New module**: `src/daemon/` containing platform-agnostic daemon service abstraction
- **Configuration storage**: Persist daemon configuration (port, host, etc.) for service startup

### Command Structure

```
docs-mcp-server daemon install [options] # Install as system service
docs-mcp-server daemon uninstall # Remove system service
docs-mcp-server daemon status # Show daemon running status
docs-mcp-server daemon start # Start the daemon
docs-mcp-server daemon stop # Stop the daemon
docs-mcp-server daemon restart # Restart the daemon
```

### Platform Support

| Platform | Mechanism | Service Location |
|----------|-----------|------------------|
| macOS | launchd | `/Library/LaunchDaemons/` (plist) |
| Windows | Windows Service Manager | Windows Services (winsw) |
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The table mentions "(winsw)" for Windows, which is an implementation detail. Since this is a proposal document describing the user-facing feature, consider removing the "(winsw)" reference to keep the focus on what the feature does rather than how it's implemented internally.

Suggested change
| Windows | Windows Service Manager | Windows Services (winsw) |
| Windows | Windows Service Manager | Windows Services |

Copilot uses AI. Check for mistakes.
| Linux | systemd/init.d | `/etc/init.d/` or systemd unit |

### Options for `daemon install`

The install command mirrors key server options to configure the daemon:

- `--port` - Server port (default: from config)
- `--host` - Server host (default: from config)
- `--resume` - Resume interrupted jobs on startup
- `--read-only` - Run in read-only mode
- `--store-path` - Custom data storage directory

## Impact

- **Affected specs**: None (new capability)
- **Affected code**:
- `src/cli/commands/` - New daemon.ts command
- `src/cli/index.ts` - Register daemon command
- `src/daemon/` - New module for service management
- `package.json` - New dependencies
- **User experience**: Significantly improved for production/daily use
- **Permissions**: Requires elevated privileges (sudo/admin) for install/uninstall
Loading