Skip to content

Add MCP server for live Emanote model #645

@srid

Description

@srid

Summary

Add an MCP server to Emanote that runs in the same long-lived process as the live server, so MCP clients can query Emanote's in-memory notebook model directly instead of going through the filesystem.

We will use the Haskell dpella/mcp library for protocol and transport support, while keeping Emanote's own model/query/export code as the source of truth.

Goals

  • Run live server and MCP server in the same process
  • Reuse the existing reactive Emanote model
  • Expose notebook data primarily as MCP resources
  • Add a small set of read-only tools for structured queries
  • Ship this incrementally, one PR per phase

Non-goals

  • No write/edit tools in the first iteration
  • No separate notebook parser for MCP
  • No filesystem-first MCP layer that bypasses Emanote's model

Design direction

  • Ema remains responsible for keeping the in-memory model live and for normal site rendering.
  • MCP sits beside Ema, sharing the same current model snapshot.
  • MCP should not be forced through SiteRoute/Ema.Asset; it should read from Emanote's model/query/export layer directly.
  • Prefer MCP resources for notebook reads; use tools only for query-shaped operations.

Phases

Phase 1: Same-process MCP transport + minimal handshake — ✅ Shipped in #648

Scope:

  • Add dpella/mcp dependency
  • Add CLI/config plumbing to enable MCP HTTP transport alongside live server
  • Start MCP endpoint in the same long-running process as the live server
  • Implement minimum lifecycle/RPC surface:
    • initialize
    • resources/list
    • resources/read
    • tools/list
    • tools/call
  • Keep everything read-only

Acceptance criteria:

  • Emanote live server and MCP endpoint both start in one process
  • An MCP client can complete initialization and list resources/tools
  • No resource subscriptions yet

Phase 2: Core read-only resources

Scope:

  • Expose notebook state as MCP resources:
    • emanote://export/metadata
    • emanote://export/content
    • emanote://note/{path}
  • Back these with existing Emanote export/model code
  • Add resource templates where appropriate

Acceptance criteria:

  • Clients can read full-notebook metadata/content without going through the filesystem abstraction
  • Clients can fetch an individual note by path/route

Phase 3: Query tools

Scope:

  • Add a small set of read-only MCP tools:
    • find_notes
    • get_backlinks
    • resolve_wikilink
  • Back these with existing Emanote model/query/graph code
  • Keep input/output schemas narrow and predictable

Acceptance criteria:

  • Clients can ask structured questions without pulling the whole export blob
  • Tool results are derived from the live model

Phase 4: Live update support

Scope:

  • Add resource subscriptions for relevant URIs
  • Emit MCP notifications when resources change
  • Support at least:
    • note resources
    • export resources

Acceptance criteria:

  • An MCP client subscribed to a note/export resource can observe updates after notebook changes

Phase 5: Optional prompt surfaces

Scope:

  • Add prompts/list / prompts/get only if they prove useful
  • Possible prompts:
    • summarize note + backlinks
    • answer using notebook only
    • compare two notes

Acceptance criteria:

  • Prompts are optional sugar on top of the resource/tool API, not a replacement for it

Suggested PR breakdown

  1. PR 1: runtime wiring + minimal MCP lifecycle
  2. PR 2: notebook resources
  3. PR 3: query tools
  4. PR 4: subscriptions/notifications
  5. PR 5: optional prompts

Open questions

  • Exact CLI shape: separate subcommand vs emanote run --mcp-http
  • Best way to share the current model snapshot between the Ema live server and MCP handlers
  • Whether authentication should be deferred until after the local same-process workflow is stable

Notes

The existing Emanote exports and model/query layers already provide most of the read-side surface we need; the main architectural work is sharing the live model cleanly between Ema and the MCP server runtime.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions