fantastical-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,38 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.egg-info/
7
+ *.egg
8
+ dist/
9
+ build/
10
+ *.whl
11
+
12
+ # Virtual environments
13
+ .venv/
14
+ venv/
15
+ env/
16
+
17
+ # Environment variables
18
+ .env
19
+
20
+ # IDE
21
+ .vscode/
22
+ .idea/
23
+ *.swp
24
+ *.swo
25
+ *~
26
+
27
+ # macOS
28
+ .DS_Store
29
+
30
+ # Testing
31
+ .pytest_cache/
32
+ htmlcov/
33
+ .coverage
34
+ .coverage.*
35
+
36
+ # Project
37
+ TODO.md
38
+ *.mcpb
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "fantastical": {
4
+ "command": "uv",
5
+ "args": ["run", "--directory", "/Users/kerrj/Documents/Development/fantastical-mcp", "fantastical-mcp"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,45 @@
1
+ # CLAUDE.md
2
+
3
+ ## Project Overview
4
+
5
+ **fantastical-mcp** is a Python MCP (Model Context Protocol) server that gives AI assistants read/write access to the Fantastical calendar on macOS. It reads events directly from Fantastical's local SQLite database and creates events via Fantastical's `x-fantastical3://` URL scheme. No TCC permissions or API keys are needed.
6
+
7
+ ## Architecture
8
+
9
+ | Module | Responsibility |
10
+ |--------|---------------|
11
+ | `src/fantastical_mcp/server.py` | FastMCP server entry point, 12 tool definitions, transport config |
12
+ | `src/fantastical_mcp/db.py` | Read-only SQLite access to Fantastical's YapDatabase store. Three-tier read strategy: secondary index, FTS5, blob decode with FTS fallback. |
13
+ | `src/fantastical_mcp/formatters.py` | Plain-text output formatters. Australian English throughout. UTC to local time conversion on display. |
14
+ | `src/fantastical_mcp/url_scheme.py` | URL scheme helpers for event creation and date navigation |
15
+
16
+ ## Documentation
17
+
18
+ - `docs/tools.md` -- Detailed tool reference with parameters and example output
19
+ - `docs/configuration.md` -- Environment variables, Claude Code/Desktop config, calendar exclusion
20
+ - `docs/how-it-works.md` -- Technical architecture: YapDatabase, NSKeyedArchiver, NSDate epoch, URL scheme, TCC avoidance
21
+ - `docs/development.md` -- Project structure, testing, blob decoding, adding tools, known quirks
22
+
23
+ ## Development
24
+
25
+ - Python >=3.12, managed with `uv`
26
+ - Install: `uv pip install -e ".[test]"`
27
+ - Activate venv: `source .venv/bin/activate`
28
+ - Unit tests (no Fantastical required): `pytest tests/ --ignore=tests/integration -v`
29
+ - Integration tests (require Fantastical): `pytest tests/integration/ -v -m integration`
30
+ - All tests: `pytest -v`
31
+
32
+ ## Conventions
33
+
34
+ - **Australian English** in all display text and documentation (Licence, Organiser, serialisation, etc.)
35
+ - All timestamps stored in UTC, converted to local time only on display
36
+ - Database opened read-only (`?mode=ro`) to prevent corruption
37
+ - Environment variables documented in `env.example`
38
+ - Follow the FastMCP patterns for tool definitions
39
+
40
+ ## Key Design Decisions
41
+
42
+ - Direct database read avoids TCC permission issues that plague EventKit and AppleScript approaches
43
+ - FTS fallback path ensures graceful degradation if `NSKeyedArchiver` blob format changes
44
+ - Writes use URL scheme to delegate parsing, validation, and persistence to Fantastical itself
45
+ - Default calendar exclusions hide system calendars (Weather, Openings, etc.) from cluttering results
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jayden Kerr
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: fantastical-mcp
3
+ Version: 0.1.0
4
+ Summary: Fantastical calendar MCP server — read events from Fantastical's local database, create via URL scheme
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Keywords: calendar,fantastical,macos,mcp,model-context-protocol
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: MacOS X
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: MacOS
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Office/Business :: Scheduling
17
+ Requires-Python: >=3.12
18
+ Requires-Dist: fastmcp>=2.0.0
19
+ Provides-Extra: test
20
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'test'
21
+ Requires-Dist: pytest>=8.0.0; extra == 'test'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Fantastical MCP
25
+
26
+ An MCP server that gives AI assistants read/write access to your Fantastical calendar on macOS.
27
+
28
+ ## What it does
29
+
30
+ fantastical-mcp reads calendar events directly from Fantastical's local SQLite database and creates events via Fantastical's `x-fantastical3://` URL scheme. No TCC permissions, no API keys, no network access -- it works entirely offline using the data Fantastical already stores on your Mac.
31
+
32
+ - **Read** -- Query events by date range, calendar, or full-text search
33
+ - **Write** -- Create events using Fantastical's natural language parser
34
+ - **Navigate** -- Open Fantastical to a specific date
35
+
36
+ ## Requirements
37
+
38
+ - macOS
39
+ - [Fantastical](https://flexibits.com/fantastical) installed with at least one calendar
40
+ - Python 3.12+
41
+
42
+ ## Quick start
43
+
44
+ ### Claude Desktop (1-click install)
45
+
46
+ 1. Download `fantastical-mcp-0.1.0.mcpb` from the [latest release](https://github.com/jaydenk/fantastical-mcp/releases/latest)
47
+ 2. Double-click the file
48
+ 3. Done — Fantastical tools are now available in Claude Desktop
49
+
50
+ ### Install from PyPI
51
+
52
+ ```bash
53
+ uvx fantastical-mcp
54
+ ```
55
+
56
+ ### Local development
57
+
58
+ ```bash
59
+ git clone https://github.com/jaydenk/fantastical-mcp.git
60
+ cd fantastical-mcp
61
+ uv venv && uv pip install -e ".[test]"
62
+ ```
63
+
64
+ ## Configuration
65
+
66
+ ### Claude Code
67
+
68
+ Add to your `.claude/settings.json` (or project-level settings):
69
+
70
+ **Published package:**
71
+
72
+ ```json
73
+ {
74
+ "mcpServers": {
75
+ "fantastical": {
76
+ "command": "uvx",
77
+ "args": ["fantastical-mcp"]
78
+ }
79
+ }
80
+ }
81
+ ```
82
+
83
+ **Local development:**
84
+
85
+ ```json
86
+ {
87
+ "mcpServers": {
88
+ "fantastical": {
89
+ "command": "uv",
90
+ "args": ["run", "--directory", "/path/to/fantastical-mcp", "fantastical-mcp"]
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ### Claude Desktop
97
+
98
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
99
+
100
+ ```json
101
+ {
102
+ "mcpServers": {
103
+ "fantastical": {
104
+ "command": "uvx",
105
+ "args": ["fantastical-mcp"]
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ See [docs/configuration.md](docs/configuration.md) for environment variables, calendar exclusion, and transport options.
112
+
113
+ ## Available tools
114
+
115
+ | Tool | Description |
116
+ |------|-------------|
117
+ | `get_today` | All events for today, grouped by calendar |
118
+ | `get_upcoming` | Events for the next N days, grouped by date |
119
+ | `get_calendars` | List all calendars with event counts |
120
+ | `get_event` | Full details for a specific event by ID |
121
+ | `search_events` | Full-text search across titles, locations, notes, attendees |
122
+ | `get_events_by_calendar` | Events from a specific calendar |
123
+ | `get_availability` | Free/busy time slots for a date |
124
+ | `get_recurring` | Upcoming recurring events, optionally filtered by calendar |
125
+ | `get_invitations` | Pending event invitations that need a response |
126
+ | `get_recent` | Most recently added or synced events |
127
+ | `create_event` | Create an event using natural language |
128
+ | `show_date` | Open Fantastical's mini calendar to a date |
129
+
130
+ See [docs/tools.md](docs/tools.md) for parameters, types, defaults, and example output.
131
+
132
+ ## Limitations
133
+
134
+ - **No update or delete** -- Fantastical's URL scheme only supports event creation. Modification and deletion require EventKit, which needs TCC permissions.
135
+ - **macOS only** -- Relies on Fantastical's macOS database location and the `open` command.
136
+ - **Read-only database access** -- The database is opened in `?mode=ro` to prevent any risk of corruption.
137
+ - **Blob format dependency** -- The `NSKeyedArchiver` serialisation format is an internal detail of Fantastical and could change between versions. An FTS fallback path mitigates this.
138
+
139
+ ## Documentation
140
+
141
+ - [Tool reference](docs/tools.md) -- Detailed parameters and example output for every tool
142
+ - [Configuration guide](docs/configuration.md) -- Environment variables, transport options, calendar exclusion
143
+ - [How it works](docs/how-it-works.md) -- Technical architecture and design decisions
144
+ - [Development guide](docs/development.md) -- Project structure, testing, and contributing
145
+
146
+ ## Licence
147
+
148
+ [MIT](LICENSE)
@@ -0,0 +1,125 @@
1
+ # Fantastical MCP
2
+
3
+ An MCP server that gives AI assistants read/write access to your Fantastical calendar on macOS.
4
+
5
+ ## What it does
6
+
7
+ fantastical-mcp reads calendar events directly from Fantastical's local SQLite database and creates events via Fantastical's `x-fantastical3://` URL scheme. No TCC permissions, no API keys, no network access -- it works entirely offline using the data Fantastical already stores on your Mac.
8
+
9
+ - **Read** -- Query events by date range, calendar, or full-text search
10
+ - **Write** -- Create events using Fantastical's natural language parser
11
+ - **Navigate** -- Open Fantastical to a specific date
12
+
13
+ ## Requirements
14
+
15
+ - macOS
16
+ - [Fantastical](https://flexibits.com/fantastical) installed with at least one calendar
17
+ - Python 3.12+
18
+
19
+ ## Quick start
20
+
21
+ ### Claude Desktop (1-click install)
22
+
23
+ 1. Download `fantastical-mcp-0.1.0.mcpb` from the [latest release](https://github.com/jaydenk/fantastical-mcp/releases/latest)
24
+ 2. Double-click the file
25
+ 3. Done — Fantastical tools are now available in Claude Desktop
26
+
27
+ ### Install from PyPI
28
+
29
+ ```bash
30
+ uvx fantastical-mcp
31
+ ```
32
+
33
+ ### Local development
34
+
35
+ ```bash
36
+ git clone https://github.com/jaydenk/fantastical-mcp.git
37
+ cd fantastical-mcp
38
+ uv venv && uv pip install -e ".[test]"
39
+ ```
40
+
41
+ ## Configuration
42
+
43
+ ### Claude Code
44
+
45
+ Add to your `.claude/settings.json` (or project-level settings):
46
+
47
+ **Published package:**
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "fantastical": {
53
+ "command": "uvx",
54
+ "args": ["fantastical-mcp"]
55
+ }
56
+ }
57
+ }
58
+ ```
59
+
60
+ **Local development:**
61
+
62
+ ```json
63
+ {
64
+ "mcpServers": {
65
+ "fantastical": {
66
+ "command": "uv",
67
+ "args": ["run", "--directory", "/path/to/fantastical-mcp", "fantastical-mcp"]
68
+ }
69
+ }
70
+ }
71
+ ```
72
+
73
+ ### Claude Desktop
74
+
75
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
76
+
77
+ ```json
78
+ {
79
+ "mcpServers": {
80
+ "fantastical": {
81
+ "command": "uvx",
82
+ "args": ["fantastical-mcp"]
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ See [docs/configuration.md](docs/configuration.md) for environment variables, calendar exclusion, and transport options.
89
+
90
+ ## Available tools
91
+
92
+ | Tool | Description |
93
+ |------|-------------|
94
+ | `get_today` | All events for today, grouped by calendar |
95
+ | `get_upcoming` | Events for the next N days, grouped by date |
96
+ | `get_calendars` | List all calendars with event counts |
97
+ | `get_event` | Full details for a specific event by ID |
98
+ | `search_events` | Full-text search across titles, locations, notes, attendees |
99
+ | `get_events_by_calendar` | Events from a specific calendar |
100
+ | `get_availability` | Free/busy time slots for a date |
101
+ | `get_recurring` | Upcoming recurring events, optionally filtered by calendar |
102
+ | `get_invitations` | Pending event invitations that need a response |
103
+ | `get_recent` | Most recently added or synced events |
104
+ | `create_event` | Create an event using natural language |
105
+ | `show_date` | Open Fantastical's mini calendar to a date |
106
+
107
+ See [docs/tools.md](docs/tools.md) for parameters, types, defaults, and example output.
108
+
109
+ ## Limitations
110
+
111
+ - **No update or delete** -- Fantastical's URL scheme only supports event creation. Modification and deletion require EventKit, which needs TCC permissions.
112
+ - **macOS only** -- Relies on Fantastical's macOS database location and the `open` command.
113
+ - **Read-only database access** -- The database is opened in `?mode=ro` to prevent any risk of corruption.
114
+ - **Blob format dependency** -- The `NSKeyedArchiver` serialisation format is an internal detail of Fantastical and could change between versions. An FTS fallback path mitigates this.
115
+
116
+ ## Documentation
117
+
118
+ - [Tool reference](docs/tools.md) -- Detailed parameters and example output for every tool
119
+ - [Configuration guide](docs/configuration.md) -- Environment variables, transport options, calendar exclusion
120
+ - [How it works](docs/how-it-works.md) -- Technical architecture and design decisions
121
+ - [Development guide](docs/development.md) -- Project structure, testing, and contributing
122
+
123
+ ## Licence
124
+
125
+ [MIT](LICENSE)
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+ # Build the MCPB bundle for Claude Desktop 1-click install.
3
+ # Requires: npm install -g @anthropic-ai/mcpb
4
+ set -euo pipefail
5
+
6
+ VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
7
+ OUTPUT="fantastical-mcp-${VERSION}.mcpb"
8
+
9
+ mcpb pack mcpb "$OUTPUT"
10
+ echo "Built: $OUTPUT"
@@ -0,0 +1,165 @@
1
+ # Configuration Guide
2
+
3
+ ## Environment Variables
4
+
5
+ | Variable | Default | Description |
6
+ |----------|---------|-------------|
7
+ | `FANTASTICAL_DB_PATH` | Auto-detected | Override the auto-discovered database path. Must point to an existing `.fcdata` file. |
8
+ | `FANTASTICAL_EXCLUDE_CALENDARS` | `Weather,Openings,RSVP Invitations,Proposals,Notifications` | Comma-separated calendar names to hide from all query results. Replaces the default exclusion list entirely when set. |
9
+ | `FANTASTICAL_RECURRING_EXCLUDE_CALENDARS` | `Birthdays,Anniversaries` | Comma-separated calendar names to additionally exclude from `get_recurring` results. Replaces the default recurring exclusion list when set. |
10
+ | `FANTASTICAL_MCP_TRANSPORT` | `stdio` | Transport mode: `stdio` (default for CLI tools) or `sse` (HTTP server). |
11
+ | `FANTASTICAL_MCP_HOST` | `127.0.0.1` | Host address for SSE transport. |
12
+ | `FANTASTICAL_MCP_PORT` | `8000` | Port for SSE transport. |
13
+
14
+ An example `.env` file is provided as `env.example` in the project root.
15
+
16
+ ---
17
+
18
+ ## Claude Code
19
+
20
+ ### Published package
21
+
22
+ Add to `.claude/settings.json` (user-level) or `.claude/settings.local.json` (project-level):
23
+
24
+ ```json
25
+ {
26
+ "mcpServers": {
27
+ "fantastical": {
28
+ "command": "uvx",
29
+ "args": ["fantastical-mcp"]
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ ### Local development
36
+
37
+ Use `uv run --directory` to point at the cloned repository:
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "fantastical": {
43
+ "command": "uv",
44
+ "args": ["run", "--directory", "/Users/you/path/to/fantastical-mcp", "fantastical-mcp"]
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ ### With environment variables
51
+
52
+ ```json
53
+ {
54
+ "mcpServers": {
55
+ "fantastical": {
56
+ "command": "uv",
57
+ "args": ["run", "--directory", "/Users/you/path/to/fantastical-mcp", "fantastical-mcp"],
58
+ "env": {
59
+ "FANTASTICAL_EXCLUDE_CALENDARS": "Weather,Openings,RSVP Invitations"
60
+ }
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Claude Desktop
69
+
70
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
71
+
72
+ ```json
73
+ {
74
+ "mcpServers": {
75
+ "fantastical": {
76
+ "command": "uvx",
77
+ "args": ["fantastical-mcp"]
78
+ }
79
+ }
80
+ }
81
+ ```
82
+
83
+ For local development:
84
+
85
+ ```json
86
+ {
87
+ "mcpServers": {
88
+ "fantastical": {
89
+ "command": "uv",
90
+ "args": ["run", "--directory", "/Users/you/path/to/fantastical-mcp", "fantastical-mcp"]
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ---
97
+
98
+ ## Calendar Exclusion
99
+
100
+ By default, several Fantastical system calendars are hidden from results:
101
+
102
+ - Weather
103
+ - Openings
104
+ - RSVP Invitations
105
+ - Proposals
106
+ - Notifications
107
+
108
+ ### Override via environment variable
109
+
110
+ Setting `FANTASTICAL_EXCLUDE_CALENDARS` **replaces** the default list entirely. To exclude only Weather and Proposals:
111
+
112
+ ```bash
113
+ FANTASTICAL_EXCLUDE_CALENDARS="Weather,Proposals"
114
+ ```
115
+
116
+ To exclude nothing (show all calendars):
117
+
118
+ ```bash
119
+ FANTASTICAL_EXCLUDE_CALENDARS=""
120
+ ```
121
+
122
+ ### Override via constructor
123
+
124
+ When using `FantasticalDB` directly (e.g. in tests), pass `exclude_calendars`:
125
+
126
+ ```python
127
+ db = FantasticalDB(db_path, exclude_calendars={"Weather"})
128
+ ```
129
+
130
+ Priority order:
131
+ 1. `exclude_calendars` constructor parameter (highest)
132
+ 2. `FANTASTICAL_EXCLUDE_CALENDARS` environment variable
133
+ 3. Built-in default set (lowest)
134
+
135
+ ### Recurring Event Exclusion
136
+
137
+ The `get_recurring` tool additionally excludes Birthdays and Anniversaries calendars by default, since these dominate recurring results without adding scheduling value.
138
+
139
+ Override with `FANTASTICAL_RECURRING_EXCLUDE_CALENDARS`:
140
+
141
+ ```bash
142
+ # Include birthdays in recurring results
143
+ FANTASTICAL_RECURRING_EXCLUDE_CALENDARS=""
144
+
145
+ # Exclude different calendars
146
+ FANTASTICAL_RECURRING_EXCLUDE_CALENDARS="Birthdays,Holidays in Australia"
147
+ ```
148
+
149
+ ---
150
+
151
+ ## Transport Options
152
+
153
+ ### stdio (default)
154
+
155
+ Used by Claude Code and Claude Desktop. The MCP client spawns the server as a subprocess and communicates over stdin/stdout. No configuration needed beyond the MCP server entry.
156
+
157
+ ### SSE (Server-Sent Events)
158
+
159
+ For use cases where the server runs as a persistent HTTP process:
160
+
161
+ ```bash
162
+ FANTASTICAL_MCP_TRANSPORT=sse FANTASTICAL_MCP_HOST=127.0.0.1 FANTASTICAL_MCP_PORT=8000 fantastical-mcp
163
+ ```
164
+
165
+ The server will listen on `http://127.0.0.1:8000` and serve the MCP protocol over SSE. This is useful for development, debugging, or connecting from MCP clients that support HTTP transport.