Skip to content
MarimerLLCPublic

About

Find a meeting time across people and organizations without sharing calendars: an MCP server, web UI and email, where everyone votes on the organizer's proposed slots.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Scheduler

Find a meeting time across people and organizations without anyone sharing their calendar.

The organizer (or their AI agent) proposes candidate times that already work for them. Everyone invited votes preferred, if necessary or no on each time, from whichever MCP-capable agent they use (Claude Desktop, Claude Code, GitHub Copilot, RockBot, ...) or from a web page linked in the invitation email. The server never reads a calendar: each person's own agent checks their own calendar, and the server only ever learns the votes.

See docs/design.md for the full design, and docs/identity-setup.md for setting up sign-in on a deployed server.

Works well with Adjutant

Scheduler deliberately never sees a calendar, so each person's agent needs calendar tools of its own. Adjutant (calendar-mcp) is an MCP server that gives an agent email, calendar and contacts across Microsoft 365, Outlook.com, Google Workspace and IMAP accounts. With both connected, an agent can do the whole loop:

  • Organizing: find free times with Adjutant's find_available_times, then propose them with Scheduler's create_event. Once a time is picked (finalize_event), create the real meeting with Adjutant's create_event and report it back with record_calendar_event.
  • Being invited: find Scheduler's invitation emails (subjects start with [sched:CODE]) with Adjutant's search_emails, check each proposed time against get_calendar_events, then vote, and accept the organizer's real invitation later with respond_to_event.

Neither needs the other: any calendar MCP server works, and people without an agent vote from the link in the invitation email.

Status

Version 1 is complete (roadmap steps 1 to 5 in the design doc) and runs in production:

  • MCP endpoint (/mcp) with every tool, both prompts and the server instructions
  • Sign-in: Microsoft and Google for the browser, OAuth for MCP clients (this app is its own authorization server, federating to the same providers), personal access tokens for headless agents such as RockBot, and an emailed link for addresses a provider doesn't verify
  • Web UI: the voting page opened from the invitation email, the organizer's dashboard, compose and event pages (live as votes arrive), account and admin pages
  • Email: plain-text and HTML messages through an outbox and any SMTP relay, one-click unsubscribe, and reminder, deadline, retention and time-zone jobs
  • Rate limits, per-organizer limits, and the Kubernetes deployment (k8s/, docs/deployment.md)

Next (v1.1 in the design doc): a long-running wait_for_update task, RockBot integration, and an .ics invite for organizers without a calendar MCP server.

Layout

Path What
src/Scheduler.Core Domain model and rules. No infrastructure dependencies.
src/Scheduler.Data EF Core SchedulerDbContext and the ISchedulingService implementation
src/Scheduler.Web ASP.NET Core host: Blazor UI, MCP endpoint, email, background workers
src/Scheduler.ServiceDefaults Aspire defaults: OpenTelemetry, health checks, resilience
src/Scheduler.AppHost Aspire AppHost for local development (PostgreSQL + Mailpit)
tests/Scheduler.Core.Tests MSTest unit tests for the domain rules
tests/Scheduler.Data.Tests Integration tests for SchedulingService against PostgreSQL (Testcontainers)
tests/Scheduler.Web.Tests The MCP OAuth flow end to end with the MCP SDK client, the organizer pages (prerendered), the voting page, HTML emails and unsubscribing, emailed sign-in and address links, rate limits, plus the identity rules
docs/design.md Design document
docs/identity-setup.md Operations: Microsoft and Google app registrations, token certificates, Kubernetes settings
docs/deployment.md Operations: deploying to lhotkalake (database, SMTP relay and DNS, secrets, build and deploy, checks)
k8s/ Kubernetes manifests and the build and deploy scripts

Build and test

Requires the .NET 10 SDK (pinned by global.json).

dotnet build Scheduler.slnx
dotnet test Scheduler.slnx

Scheduler.Data.Tests and Scheduler.Web.Tests need Docker: each starts a PostgreSQL container and gives each test its own freshly migrated database.

Migrations

dotnet-ef is pinned in the repo's tool manifest.

dotnet tool restore
dotnet ef migrations add <Name> --project src/Scheduler.Data --startup-project src/Scheduler.Data --output-dir Migrations

In Development the web app applies migrations at startup.

Run locally

Requires Docker (Aspire starts PostgreSQL and Mailpit containers).

dotnet run --project src/Scheduler.AppHost

The Aspire dashboard links to the web app, pgAdmin and the Mailpit inbox. In Development:

  • an MCP client can act as any address without signing in by sending an X-Dev-Email header, and the browser can sign in as any address at /dev/signin (both ignored in every other environment). An MCP client without the header goes through the real OAuth flow, with the development sign-in offered on /signin, so connecting Claude Code or VS Code to http://localhost:<port>/mcp works locally;
  • Microsoft and Google sign-in appear once Identity:Microsoft or Identity:Google has a ClientId and ClientSecret (user secrets), with /signin/callback/microsoft or /signin/callback/google registered as the redirect URI;
  • anyone may organize (Scheduler:Organizers is ["*"] in appsettings.Development.json), and admin@localhost.test is an admin, so /admin/organizers and the admin MCP tools can be tried;
  • voting links use a random key that changes on every restart unless Scheduler:MagicLinkKey is set.

Line endings

All text files are LF in the repo and in the working tree, on every platform (.gitattributes sets eol=lf, overriding core.autocrlf; .editorconfig makes editors create LF files). Only .bat and .cmd files are CRLF.

License

MIT © Marimer LLC

About

Find a meeting time across people and organizations without sharing calendars: an MCP server, web UI and email, where everyone votes on the organizer's proposed slots.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages