Skip to main content
Glama

joshua421

"When your children ask in time to come, 'What do these stones mean?' then you shall let your children know..." (Joshua 4:21–22)

In Joshua 4, Israel crosses the Jordan and piles twelve stones into a memorial, so that later, when the question comes, the story of God's faithfulness gets retold. That memory, carried into the rhythm of a life, is the spirit of this project.

joshua421 is a provider-agnostic MCP server that lets your own LLM help you reflect on your day and set it before the Lord, then writes what you approve into your Google Calendar. It makes no model calls of its own and stores nothing on a server: your calendar is the database.

Stack: TypeScript (Node, ESM) · Model Context Protocol SDK (stdio server, tools, prompts, resources) · Google Calendar and Gmail (send-only) APIs via googleapis · node-cron and macOS launchd for scheduled nudges · Zod · node:test (151 tests).

What it is

It is not a devotional you read passively. You reflect, actively, with your own LLM (Claude, ChatGPT, a local model); joshua421 is the tools, the memory, and the write-surface. The loop: an email nudges you, a link opens your LLM, it helps you reflect and set the day up for the Lord, with your approval it writes notes into your calendar, and joshua421 records that you reflected, never what you said.

Four promises:

  • Behaviour, not content. joshua421 itself stores nothing at all: no server, no database, nothing on your machine. A reflected day is one empty Marker entry. Anything with words in it (a note, a day summary, a rollup, your grounding) is written only where you approved it, in your calendar, as private as your calendar is.

  • Additive. It never rewrites or deletes your words.

  • Permission at the boundary. Nothing is written without your approval in chat. Today that is held by the companion's instructions, not yet by the protocol.

  • Grace, not guilt. A memorial to God's faithfulness, not a scorecard.

Presence holds; the ask scales. A quiet stretch changes how much the nudge asks of you, never whether it arrives. How you want to be met on the way back is something you name once, in plain words; nothing is ever inferred from how you behave. See ADR 0006.

Because joshua421 makes no model calls of its own, you bring whichever assistant you like and no LLM key is needed. docs/design.md has the full vision and privacy model.

Related MCP server: ppdiary

How you use it

You never call joshua421 directly. You talk to your assistant; the assistant calls the tools.

Once. npm run setup connects joshua421 to your assistant. Then run the begin prompt (in your client's prompt picker): a gentle conversation that establishes your intention, tone, weekly rhythm, church day and quiet time, and saves them with set_grounding as one entry in your own calendar, still yours to edit by hand.

Each day. A nudge email arrives, a morning setup and an evening summary, the morning one carrying yesterday's summary back to you in your own words. It offers two ways in: a link that opens the conversation already prefilled (into Claude Desktop, where the MCP is connected and your diary can be written; the ChatGPT link reflects with you but writes nothing), or two questions you can paste into any assistant. In the conversation, yours reads your grounding (get_grounding) and your day (read_day) and reflects with you on this day: your actual events, your own words. When something is worth keeping it drafts it, you approve it, and apply_day_notes writes it, appended under a marker inside the event, or as a private side-entry in the same slot when the event is shared, so a reflection of yours never lands on someone else's invite. Every write is reversible. undo_write strips only joshua421's block from your event, or deletes an entry joshua421 created; your real meetings are structurally out of reach.

Now and then. On your church evening, at a month or season genuinely turning, or whenever you ask: look_back gathers that period's stones (the days you showed up, the summaries you kept, the rollups already written) and your assistant weaves the memorial with you: look how faithful God has been. If it lands somewhere true, save_rollup keeps it as that period's own entry. "Your year with God" is the headline stone.

Practices. Six guided practices live in skills/ as portable SKILL.md files: morning offering, evening examen, lament, discernment, church-day lookback and memorial rollup. The server exposes each one as an MCP resource and through the load_skill tool, so the assistant takes on the practice's shape before running it.

That is the whole surface: one setup, an email, a conversation. Everything written lands in your calendar; joshua421 keeps only that you reflected, and your grounding, by your choice.

Run it

  • npm run setup: the one guided path. It creates .env, walks you through a free Google OAuth client, mints your token, proves each pipe, and connects your assistant. docs/setup.md is the click-by-click, including the two gotchas: the 7-day token trap and connecting Claude Desktop.

  • npm run doctor: re-check every pipe, read-only, any time something looks off.

  • npm run worker:install: run the daily nudges in the background (macOS launchd). npm run worker runs them in the foreground instead; worker:status and worker:uninstall manage the agents.

  • npm run auth: re-run Google consent and write a fresh refresh token, for when a token expires or is revoked.

  • npm run migrate: one-time, for pre-cutover installs. It moves the old local log and grounding file into your calendar.

Config lives in .env (see .env.example): your Google OAuth and calendar choices, and JOSHUA421_LINK_BASE, the https page the email's Claude link goes through. Gmail refuses to carry a raw claude:// link, so the default is the project's own bounce page, served from docs/go/ on GitHub Pages. The prompt travels in the URL fragment, so that page never sees your day. docs/setup.md, "Why the link goes via a web page", has the details.

Develop

npm install
npm test            # node:test over src/**/*.test.ts, TZ=UTC
npm run typecheck
npm run build
npm run dev         # worker in watch mode
npm run skills:build  # re-stamp the shared centre into skills/*/SKILL.md

.mcp.json connects joshua421 to Claude Code sessions started in this repo.

How the repo is organised

src/
  core/         the pure engine: ports (Mailer · Diary · Log · Grounding ·
                Journal), flows, cadence, persona; no I/O
  adapters/     the impure edges: Google (calendar + Gmail send-only), the
                Journal-backed Log and Grounding (the calendar as database),
                legacy SQLite/file adapters kept as migration sources
  setup/        the guided path: setup wizard, OAuth flow, .env writer,
                one-time migration, worker installer, path helpers
  mcp.ts        entrypoint: the stdio MCP server your LLM calls
  worker.ts     entrypoint: the scheduled nudge emails
  prod-deps.ts  the one production wiring of ports to adapters
  env.ts        resolves .env and paths by file location, never cwd
  testing/      in-memory fakes for the ports
skills/         the six practices as portable SKILL.md files
docs/
  design.md     the vision, promises, architecture, direction
  status.md     built vs. decided vs. planned
  setup.md      click-by-click setup, troubleshooting
  glossary.md   the fixed vocabulary (Diary, Journal, Grounding, Marker, …)
  adr/          decision records: the "why" that must not be re-litigated
  go/           the email's Claude door: an https page that bounces to the
                claude:// scheme, because Gmail deletes non-http hrefs
.mcp.json       connects joshua421 to Claude Code sessions started in this repo

The shape follows the design: everything in core/ is pure and talks only to ports; everything impure is an adapter; the two entrypoints and prod-deps.ts are the only places wiring happens. Tests live beside the file they test.

Scope

Dogfood first: me, my own tokens, no account system. Self-hosting is open to anyone today. npm run setup has every user bring their own free Google OAuth client and hold their own tokens, so no one, this project included, ever holds them. A hosted service (us holding tokens: custody, minimal scopes, verification) is a deliberate, later step. See docs/status.md for where the build is.

License & use

joshua421 is a gift: free for noncommercial use, including individuals; personal, study, and hobby use; religious observance; and any charitable, educational, research, health, or government organization, regardless of funding. Commercial use requires written permission, so please get in touch.

Licensed under the PolyForm Noncommercial License 1.0.0. See LICENSE and NOTICE. If you build on or share it, keep the licence and the Required Notice with it. (Plain intent, not legal advice; the LICENSE text governs.)

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      A
      quality
      D
      maintenance
      Enables AI-powered journaling in Obsidian with dynamic reflection prompts generated from recent entries and automatic backlinks between related diary entries. Supports adaptive templates that learn from writing patterns and smart content similarity linking.
      5
      5
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI-assisted diary management through natural language, allowing you to create, read, update, delete, and search diary entries stored locally in SQLite.
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables developers to maintain a local engineering journal, log work manually or from git history, and let AI assistants query, summarize, and draft standup updates, changelogs, and retro notes.
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables local-first logging of daily activities and generation of daily summaries, weekly article ideas, and platform-specific social posts via Claude, storing everything in a single SQLite file.
      1
      MIT