npm package: @gonzih/screen-time-mcp
Description: MCP server enforcing AI usage limits for children — daily caps, quiet hours, weekly budgets, cool-down periods, gamified streaks, parent override
Author: Gonzih
Latest version: 0.1.0

# screen-time-mcp

An MCP (Model Context Protocol) server that enforces AI usage limits for children. Set daily time caps, quiet hours, weekly budgets, cool-down periods between sessions, gamified streaks, and receive weekly parent reports via Telegram — all without modifying the AI assistant itself.

## Features

- **Daily time caps** — hard stop when the child's daily AI minutes are used up
- **Per-session limits** — cap individual sessions to encourage breaks between focused work
- **Weekly budget** — soft warning when the weekly total is reached
- **Quiet hours** — block AI access at night and in the morning (fully configurable, supports ranges that cross midnight)
- **Cool-down periods** — require a break between sessions so children step away from the screen
- **Parent PIN overrides** — grant temporary extra time without changing permanent settings
- **Gamified streaks** — track consecutive days within limit and celebrate milestones
- **Banked minutes** — optionally carry unused daily minutes forward as a bonus
- **Weekly reports** — auto-generate and send a parent summary via Telegram
- **Daily summaries** — optional end-of-day Telegram digest for parents
- **Child-friendly messages** — warm, encouraging block messages (never punitive)
- **Multi-profile support** — run separate profiles for multiple children
- **SQLite storage** — lightweight, local, no external database required

## Installation

### From npm

```bash
npm install -g @gonzih/screen-time-mcp
```

### From source

```bash
git clone https://github.com/gonzih/screen-time-mcp
cd screen-time-mcp
npm install
npm run build
```

## Configuration

Copy `.env.example` to `.env` and edit to match your family's needs:

```bash
cp .env.example .env
```

### Environment Variables

| Variable | Default | Description |
|---|---|---|
| `SCREEN_TIME_PROFILE_ID` | `default` | Child profile identifier (use separate IDs per child) |
| `SCREEN_TIME_CHILD_NAME` | `Child` | Child's name, used in reports and messages |
| `SCREEN_TIME_DB` | `~/.screen-time-mcp/usage.sqlite` | Path to the SQLite database file |
| `DAILY_LIMIT_MINS` | `45` | Daily AI time cap in minutes |
| `SESSION_LIMIT_MINS` | `30` | Per-session cap in minutes |
| `WEEKLY_BUDGET_MINS` | `240` | Weekly total budget in minutes (4 hours) |
| `COOL_DOWN_MINS` | `30` | Required break between sessions in minutes |
| `PARENT_OVERRIDE_PIN` | `1234` | PIN required to grant temporary extra time |
| `QUIET_HOURS` | `21:00-07:00` | Comma-separated time ranges; ranges crossing midnight supported |
| `TELEGRAM_BOT_TOKEN` | _(none)_ | Telegram bot token for parent reports |
| `TELEGRAM_PARENT_CHAT_ID` | _(none)_ | Parent's Telegram chat ID |
| `REPORT_DAY` | `sunday` | Day of week to send the weekly report |
| `DAILY_REPORT` | `false` | Set to `true` to send a Telegram summary after each day |
| `BANK_UNUSED_TIME` | `false` | Set to `true` to carry unused daily minutes forward |

### Quiet Hours format

Quiet hours are comma-separated `HH:MM-HH:MM` ranges. Ranges that cross midnight are fully supported:

```
# Night + morning blocks
QUIET_HOURS=21:00-07:00,07:00-08:00

# Night block only
QUIET_HOURS=22:00-07:00

# Multiple blocks
QUIET_HOURS=21:00-07:00,12:00-13:00
```

### Setting up Telegram reports

1. Message [@BotFather](https://t.me/botfather) on Telegram and create a new bot. Copy the bot token.
2. Start a conversation with your new bot, then visit `https://api.telegram.org/bot<TOKEN>/getUpdates` to find your chat ID.
3. Set `TELEGRAM_BOT_TOKEN` and `TELEGRAM_PARENT_CHAT_ID` in your `.env`.

## Claude Desktop Integration

Add the server to your Claude Desktop configuration at `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "screen-time-mcp": {
      "command": "screen-time-mcp",
      "env": {
        "SCREEN_TIME_PROFILE_ID": "alex",
        "SCREEN_TIME_CHILD_NAME": "Alex",
        "DAILY_LIMIT_MINS": "45",
        "SESSION_LIMIT_MINS": "30",
        "WEEKLY_BUDGET_MINS": "240",
        "COOL_DOWN_MINS": "30",
        "PARENT_OVERRIDE_PIN": "9876",
        "QUIET_HOURS": "21:00-07:00,07:00-08:00",
        "TELEGRAM_BOT_TOKEN": "your-bot-token",
        "TELEGRAM_PARENT_CHAT_ID": "your-chat-id",
        "DAILY_REPORT": "true",
        "BANK_UNUSED_TIME": "true"
      }
    }
  }
}
```

If running from source, use the full path instead:

```json
{
  "mcpServers": {
    "screen-time-mcp": {
      "command": "node",
      "args": ["/path/to/screen-time-mcp/dist/index.js"],
      "env": {
        "SCREEN_TIME_PROFILE_ID": "alex"
      }
    }
  }
}
```

### Multi-child setup

Run one server instance per child, each with a distinct profile ID:

```json
{
  "mcpServers": {
    "screen-time-alex": {
      "command": "screen-time-mcp",
      "env": {
        "SCREEN_TIME_PROFILE_ID": "alex",
        "SCREEN_TIME_CHILD_NAME": "Alex",
        "DAILY_LIMIT_MINS": "45"
      }
    },
    "screen-time-jamie": {
      "command": "screen-time-mcp",
      "env": {
        "SCREEN_TIME_PROFILE_ID": "jamie",
        "SCREEN_TIME_CHILD_NAME": "Jamie",
        "DAILY_LIMIT_MINS": "60"
      }
    }
  }
}
```

## MCP Tools Reference

The AI assistant is expected to call these tools automatically according to the session flow described in `SKILL.md`.

### Child-facing tools

| Tool | Parameters | Description |
|---|---|---|
| `start_session` | `profileId: string` | Call at conversation start. Returns `allowed`, `sessionId`, and time remaining. If `allowed` is false, show the block message and stop. |
| `check_limits` | `profileId: string`, `sessionId: string` | Call every message. Returns `withinLimits`, current usage, and any `warning` to relay to the child. |
| `end_session` | `profileId: string`, `sessionId: string`, `messageCount?: number` | Call at conversation end. Updates daily usage, returns streak info and a closing message for the child. |

### Parent-facing tools (require PIN where noted)

| Tool | Parameters | Description |
|---|---|---|
| `get_usage` | `profileId: string`, `days?: number` | View daily usage history, totals, and streak data. |
| `update_limits` | `profileId: string`, `settings: object` | Update `dailyLimitMins`, `sessionLimitMins`, `weeklyBudgetMins`, or `coolDownMins` at runtime. Changes are in-memory only. |
| `override_limits` | `profileId: string`, `pin: string`, `extraMinutes: number` | Grant a temporary extension to today's daily limit. Requires parent PIN. |
| `send_report` | `profileId: string` | Generate the weekly report and send it via Telegram if configured. |

### Session flow

```
Conversation starts
      │
      ▼
start_session(profileId)
      │
      ├── allowed: false → show block message, end conversation
      │
      └── allowed: true → store sessionId
            │
            ▼ (every message)
      check_limits(profileId, sessionId)
            │
            ├── withinLimits: false → relay warning, wrap up gracefully
            ├── warning present → mention naturally in reply
            └── all good → continue
            │
            ▼ (conversation ends)
      end_session(profileId, sessionId, messageCount)
            │
            └── share streakMessage with child if present
```

## How It Works

### Block evaluation order

Limits are checked in this priority order:

1. **Quiet hours** — if the current time falls in a configured quiet range, block immediately with a tailored morning or night message
2. **Daily cap** — if today's accumulated minutes (including the current session) meet or exceed the daily limit, block
3. **Weekly budget** — if the weekly total is reached, allow but show a soft warning
4. **Cool-down period** — at session start only, check if enough time has passed since the last session ended
5. **5/10-minute warnings** — if the daily remaining time is under 10 minutes, emit a countdown warning

### Gamification

- A streak increments each day the child stays within the daily limit
- Streaks reset to 0 if the limit is exceeded
- Milestone messages trigger at day 1 (new streak), day 3, and day 7+
- If `BANK_UNUSED_TIME=true`, unused daily minutes accumulate as banked minutes that a parent can manually grant as a bonus session

### Parent reports

When `TELEGRAM_BOT_TOKEN` and `TELEGRAM_PARENT_CHAT_ID` are set:

- **Weekly report** — generated on the configured `REPORT_DAY` (or on demand via `send_report`). Includes total time, days within limit, session count, average session length, most active day, and a qualitative insight.
- **Daily summary** — if `DAILY_REPORT=true`, a brief digest is sent via Telegram after each session ends.

## Healthy Screen Time Guidelines (AAP)

The American Academy of Pediatrics recommends the following for digital media use:

**Ages 6–12**
- Set consistent daily limits on screen time, including AI tools
- Prioritize sleep (9–12 hours/night for ages 6–12) — AI time should end well before bedtime
- Ensure physical activity (60 minutes/day) is not displaced by screen time
- Use media together when possible; ask children what they're doing with AI

**Teens (13–17)**
- Negotiate consistent limits collaboratively — teens are more likely to follow rules they helped set
- Encourage awareness of how much time is spent, not just enforcement
- Keep devices and AI assistants out of the bedroom at night

**For parents**
- Model healthy use yourself — children notice how adults interact with technology
- Treat AI assistants as a tool to be used intentionally, not a constant companion
- Review weekly reports together with your child as a conversation starter, not a punishment

The default settings in this server (45 min/day, 30 min cool-down, 21:00 quiet hours) are calibrated for the 6–12 age range. Adjust for older children as appropriate.

## Suite Integration

`screen-time-mcp` is designed to work alongside a family of child-safety MCP servers:

### parental-control-mcp

Filters content and topics the AI is allowed to discuss. While `screen-time-mcp` controls *when* and *how long* a child can use AI, `parental-control-mcp` controls *what* they can discuss. Use both together for comprehensive guardrails.

```json
{
  "mcpServers": {
    "screen-time-mcp": { "command": "screen-time-mcp", "env": { ... } },
    "parental-control-mcp": { "command": "parental-control-mcp", "env": { ... } }
  }
}
```

### attachment-guard-mcp

Monitors for signs of unhealthy emotional attachment to the AI assistant — excessive dependency, replacing human relationships, or distress when access is limited. Complements `screen-time-mcp` by addressing the quality of AI use alongside the quantity.

### ai-mood-journal-mcp

Lets children optionally log how they're feeling after an AI session. Pairs well with `end_session` — after the streak message, invite the child to record a quick mood check-in. Parents can review mood trends alongside usage data from `get_usage`.

### Recommended combined configuration

```json
{
  "mcpServers": {
    "screen-time-mcp": {
      "command": "screen-time-mcp",
      "env": {
        "SCREEN_TIME_PROFILE_ID": "alex",
        "DAILY_LIMIT_MINS": "45",
        "BANK_UNUSED_TIME": "true",
        "TELEGRAM_BOT_TOKEN": "...",
        "TELEGRAM_PARENT_CHAT_ID": "..."
      }
    },
    "parental-control-mcp": {
      "command": "parental-control-mcp",
      "env": { "PROFILE_ID": "alex" }
    },
    "attachment-guard-mcp": {
      "command": "attachment-guard-mcp",
      "env": { "PROFILE_ID": "alex" }
    },
    "ai-mood-journal-mcp": {
      "command": "ai-mood-journal-mcp",
      "env": { "PROFILE_ID": "alex" }
    }
  }
}
```

## Development

```bash
# Run in development mode (no build step)
npm run dev

# Build TypeScript
npm run build

# Run the built server
npm start
```

The SQLite database is created automatically at the configured path on first run. No migrations are needed — the schema is applied idempotently via `CREATE TABLE IF NOT EXISTS`.

## Publishing to npm

```bash
# Build first
npm run build

# Verify the dist/ output looks correct
ls dist/

# Dry-run to see what will be published
npm publish --dry-run

# Publish (requires npm login)
npm login
npm publish --access public
```

The `files` field in `package.json` ensures only `dist/` is included in the published package. The `bin` entry makes `screen-time-mcp` available as a global CLI command after install.

## License

MIT — see [LICENSE](LICENSE) for details. Author: Maksim Soltan.