v0.2.0: workspace redesign, coursework tracking, and MCP server#15
Merged
Conversation
Introduce Debug app/file-provider xcconfigs and a gitignored Signing.local.xcconfig (with a committed .example) so local builds sign with a developer team without re-selecting it after each xcodegen run. Align the Nightly and Release configs.
Add MoodleCourse.imageURL for the Moodle overview/banner image, and new MoodleAssignment, MoodleGradeItem, MoodleQuiz, and MoodleQuizAttempt models backing read-only coursework tracking.
Add a read-only open mode for the MCP server (read-write handle with PRAGMA query_only for WAL visibility, no schema mutation), an image_url column and per-course item fetch (schema v12), and tables plus save/fetch operations for assignments, grades, quizzes, and quiz attempts (schema v13).
Decode overviewfiles to surface the course cover image, and add read-only tracking calls: assignments, submission status, grades, quizzes, and quiz attempts.
Publish per-course sync state and downloaded cover images, group courses by tag for the sidebar and gallery, expose course content snapshots for the detail view, and refresh coursework tracking in the background after each sync.
Move Settings to the standard window and fold Diagnostics into it, add a Books-style course gallery with cover tiles, rebuild the course detail view with an elastic cover header and an inline visual editor, surface per-course sync status in the sidebar, and de-duplicate the sync toolbar buttons.
A local stdio MCP server that exposes the synced Moodle corpus to agents without manual uploads. Catalog tools (list_courses, get_course_contents, search_items, get_item, get_moodle_url), on-demand content reading and full-text search (read_item, search_text, index_course), and read-only coursework tracking (list_deadlines, get_submission_status, get_grades, get_quiz_attempts). Reads the shared database read-only, materializes files through the File Provider (the token stays in the extension), and keeps its own FTS5 index so the app remains the single writer of the shared DB.
- refreshTracking: never persist a failed fetch (a transient network/ token error would otherwise wipe stored deadlines/grades via the replace-all save); run independent per-item calls with bounded concurrency instead of serially. - MCP read_item: distinguish an unreadable file from an empty one so a read failure is surfaced for retry rather than cached as empty text; disambiguate File Provider path matching by longest-prefix to avoid resolving a sibling course/folder. - MCP search_text: CAST course_id for correct per-course filtering. - Covers: percent-encode image URLs (accented/spaced filenames), key the cache file by site, and discard non-image downloads. - Clear per-course caches on sign-out to prevent cross-site id collisions. - Course detail: refresh content counts on app reactivation, restore the Hidden-course badge, and drop the per-frame DateFormatter allocation.
On-device embeddings via NaturalLanguage sentence models (zero footprint, nothing downloaded). index_course now chunks and embeds each file's text alongside the full-text index; semantic_search embeds the query and ranks chunks by brute-force cosine similarity, returning the most relevant passages. Embeddings are language-tagged so a query is only compared against chunks in the same model's space.
The MCP server can't sync directly (no token, read-only DB), so the new trigger_sync tool opens a findle://sync[?course=<id>] URL; the app — which holds the token — handles it in onOpenURL and runs the sync (launching if needed). Fire-and-forget: the agent re-queries after the app finishes.
- Bundle FindleMCP inside the app (Contents/MacOS) with a runpath to the app's embedded frameworks, so it ships with the .dmg/Homebrew app and Claude can point at a stable path. - Add a one-click Claude integration: register the bundled MCP server with Claude Desktop and Claude Code by merging a findle entry into their config files (preserving all other keys), passing the app's real database path so the helper reads the right App Group. Permitted by a scoped temporary-exception entitlement; falls back to copying the snippet to the clipboard if the sandboxed write is blocked. - Replace WhatsNewKit with a custom, animated What's New showcase that hosts the Connect-to-Claude actions and supports richer content.
Run the MCP server over HTTP (for tunnelling to remote clients like ChatGPT) with: --http <port> --token <secret> (token may also come from FINDLE_MCP_TOKEN). stdio remains the default. A minimal Network.framework listener bound to 127.0.0.1 serves JSON-RPC over HTTP POST (no SSE; GET returns 405), gated by a bearer token — refuses to start without one. The tool dispatch is now shared between the stdio and HTTP front-ends. trigger_sync is excluded from the HTTP surface since it's a local side effect a remote client can't observe.
Add ClaudeIntegration.isInstalled(_:) (reads the config for an existing findle entry) and reflect it in the What's New buttons: they show 'Added to …' with a checkmark when present and report 'Updated' on re-add, instead of always offering a fresh 'Add'.
A reusable window (same visual language as What's New) for connecting the bundled MCP server to assistants, openable any time from the menu bar and Settings — not just from the one-time What's New sheet. - Claude: the one-click Add/Added buttons for Desktop and Code. - ChatGPT: a friendly guided setup — a generated bearer token (with regenerate), a copy-ready Terminal command pinned to the app's helper path and database, the ngrok command, and the steps to add it in ChatGPT. Copy buttons throughout.
29 unit tests covering the MCP server logic, compiled into a test bundle (the @main entry is excluded). Covers: catalog + tracking tools against a seeded temp database, the FTS5 index and embedding round-trips, the embedder's chunking and cosine, text extraction and File Provider path disambiguation, and HTTP request parsing. Makes IndexStore's path injectable and opens two helpers for testing.
The helper was ad-hoc-signed while the app's embedded frameworks are team-signed; the hardened runtime's library validation then refuses to load them (different Team IDs), so Claude Code's launch failed with a dyld error. Give FindleMCP a config that pulls in the local Team ID (via the gitignored Signing.local.xcconfig) so it signs with the same team.
The Release archive builds FindleMCP as a standalone tool target before the app embeds it. On CI there is no Signing.local.xcconfig, so MCP.xcconfig resolved to the Automatic/Apple Development fallback, which the runner can't satisfy and the archive failed. Write a Manual Developer ID config for the helper so it signs with the same team as the frameworks it loads.
Nightly BuildDownload Findle Nightly (unsigned) Built from 667a03b. Important This build is unsigned. macOS will block it on first launch. To open it:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v0.2.0
A workspace redesign plus a local MCP server that lets AI assistants query
synced coursework without re-downloading it.
Workspace & UI
courses, and keeps the sidebar list alongside it.
overviewfiles, cached per site.displayed course title.
reusable Connect to AI window.
Coursework tracking
and quizzes (
mod_assign,gradereport_user,mod_quiz).refresh that never overwrites good data on a transient failure.
MCP server (FindleMCP)
Context Protocol (14 tools): catalog, full-text search (FTS5,
diacritic-insensitive), semantic search (NLEmbedding), read/extract, Moodle
links, deadlines/grades/quizzes, and
trigger_sync.bearer-token auth for connecting ChatGPT via a tunnel (
trigger_syncexcluded from HTTP).
already-registered detection.
FindleMCPTests).Release plumbing
same team as the frameworks it loads, so the hardened runtime's library
validation accepts it and notarization passes.