memmy

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 30, 2026 License: MIT Imports: 13 Imported by: 0

README

memmy

memmy is an LLM memory system written in Go (toolchain Go 1.26.2). It exposes Hebbian-reinforced, decay-aware memory to one or more agents over MCP (with gRPC and HTTP transport adapters reserved for future work). The reference storage backend is Neo4j via the Bolt protocol — both the Hebbian memory graph and the HNSW navigation graph (Neo4j's native vector index) live in one database, and many memmy processes can share one Neo4j instance natively. The Bolt driver (github.com/neo4j/neo4j-go-driver/v5) is pure-Go; memmy has no CGO dependencies.

The load-bearing design principle is one source of truth: the database. Vectors, the HNSW navigation graph, nodes, messages, and Hebbian memory edges all live in Neo4j — there is no in-memory index, no secondary search engine, no parallel cache. memmy itself is stateless across requests: only connection pools, configuration, and process-local rate limiters are kept in-memory. This is what lets N memmy instances scale out behind a multi-writer Neo4j without coordination.

Documents

  • DESIGN.md — architecture, data model, retrieval pipeline, decay math, and the load-bearing principles in §0.
  • CLAUDE.md — coding conventions and architectural rules to follow when changing the codebase.
  • IMPLEMENTATION.md — the running implementation checklist.

Setup

memmy needs a running Neo4j instance reachable over Bolt. Quick options:

  • Docker: docker run -p 7687:7687 -e NEO4J_AUTH=neo4j/<your-password> neo4j:2026.04
  • macOS: brew install neo4j && brew services start neo4j
  • Linux/desktop: download Neo4j Desktop or install the community tarball.

Default connection: bolt://localhost:7687, user neo4j. Neo4j requires the password to be at least 8 characters; tests and the example config read it from $NEO4J_PASSWORD.

Build & migrate & run

go build ./cmd/memmy
cp memmy.example.yaml memmy.yaml   # then edit; password reads ${NEO4J_PASSWORD} by default
NEO4J_PASSWORD=<yours> ./memmy migrate --config memmy.yaml   # apply schema, idempotent
NEO4J_PASSWORD=<yours> ./memmy serve   --config memmy.yaml   # run the server

memmy serve is the default subcommand, so ./memmy --config memmy.yaml is equivalent to ./memmy serve --config memmy.yaml. The server refuses to start if the database's schema version doesn't match the binary; the fix is always memmy migrate.

No transport is enabled by default — server.transports must explicitly declare which transport(s) to run, or the config fails validation. memmy.example.yaml ships with the streamable MCP HTTP transport enabled on port 8765 and the stdio transport disabled. Switch embedder.backend to gemini and provide embedder.gemini.api_key for production use.

memmy also supports the MCP stdio transport for use as a child process under an MCP-aware host (editor or agent runtime). Set server.transports.stdio.enabled: true and disable every other transport — stdio is mutually exclusive with HTTP listeners because it owns the process's stdin/stdout. Logs always go to stderr.

An optional tenant schema (tenant: block in the config) constrains the shape of the tenant field on every memory.* call. The schema is rendered into the MCP tool's inputSchema so the LLM sees the rules during tool listing, and invalid calls return a structured corrective error. See memmy.example.yaml for a worked example using project (absolute path) and scope: "global" (cross-project) keys, and DESIGN.md §3.1 for semantics. Without a schema, any string-keyed tuple is accepted (today's default).

Use as a library

memmy ships a small facade at the module root for in-process embedding. The daemon (cmd/memmy) and the library use the same MemoryService underneath; the facade just skips the transport layer.

import (
    "context"
    "os"

    "github.com/Cidan/memmy"
)

func main() {
    ctx := context.Background()

    emb, err := memmy.NewGeminiEmbedder(ctx, memmy.GeminiEmbedderOptions{
        APIKey: "...",
        Model:  "gemini-embedding-2",
        Dim:    3072,
    })
    if err != nil { /* ... */ }

    schema, err := memmy.NewTenantSchema(memmy.TenantSchemaConfig{
        Keys: map[string]memmy.TenantKeyConfig{
            "user":  {Required: true, Pattern: `^[a-zA-Z0-9_.-]+$`},
            "scope": {Enum: []string{"chat", "code"}},
        },
    })
    if err != nil { /* ... */ }

    neo4j := memmy.Neo4jOptions{
        URI:      "bolt://localhost:7687",
        User:     "neo4j",
        Password: os.Getenv("NEO4J_PASSWORD"),
        Database: "neo4j",
    }

    // Migrate once at deployment time, before Open. Idempotent.
    if err := memmy.Migrate(ctx, memmy.MigrationOptions{
        Neo4j: neo4j,
        Dim:   emb.Dim(),
    }); err != nil { /* ... */ }

    svc, closer, err := memmy.Open(ctx, memmy.Options{
        Neo4j:        neo4j,
        Embedder:     emb,
        TenantSchema: schema,
    })
    if err != nil { /* ... */ }
    defer closer.Close()

    if _, err := svc.Write(ctx, memmy.WriteRequest{
        Tenant:  map[string]string{"user": "alice", "scope": "chat"},
        Message: "Antonio prefers terse PR titles.",
    }); err != nil { /* ... */ }

    res, err := svc.Recall(ctx, memmy.RecallRequest{
        Tenant: map[string]string{"user": "alice", "scope": "chat"},
        Query:  "what does antonio like in PRs",
        K:      8,
    })
    _ = res
}

Notes:

  • Embedder is required and pluggable. Use memmy.NewFakeEmbedder(dim) for tests or supply any type satisfying the memmy.Embedder interface.
  • TenantSchema is optional. Pass nil (or call NewTenantSchema with an empty TenantSchemaConfig) to accept any tuple shape.
  • closer.Close() releases the Neo4j driver pool. The embedder's lifecycle is the caller's; Close does not touch it.
  • Open enforces schema version. If the database is older than what this binary expects, Open returns an error directing you to memmy.Migrate(ctx, ...). Tests can pass Options.SkipMigrationCheck: true when they manage migrations themselves.
  • No transports start. The facade is library-only — to expose MemoryService over MCP / HTTP, run cmd/memmy with a YAML config instead.
  • Tunable overrides use a pointer. Options.ServiceConfig is *ServiceConfignil means "use defaults," and any non-nil value is treated as a complete config. To change one knob, start from memmy.DefaultServiceConfig(), mutate, and pass the address. The facade does not field-merge because some service tunables (RefractoryPeriod, LogDampening) accept zero as an intentional disable signal.

The full surface (request/result types, EdgeKind, EmbedTask, tunable ServiceConfig) is re-exported as type aliases on the memmy package; package internals stay under internal/.

MCP tool surface

Seven tools, all rooted at the configured MemoryService:

Tool When the LLM should call it
memory.write Save a fact, decision, preference, or pattern worth remembering across conversations.
memory.recall Retrieve relevant memories before answering. Every call reinforces what it surfaces (Hebbian co-retrieval).
memory.reinforce A specific recalled hit was actually useful in the answer.
memory.demote A specific recalled hit was misleading or wrong. Soft-inhibits without deleting.
memory.mark A stretch of recent context turned out to matter — retroactively boost the window.
memory.forget Erase outright. Use only for corrected misinformation, secrets, or explicit user request.
memory.stats Counts and average weights for one tenant or in aggregate.

Reinforce/Demote/Mark go through a per-node refractory window (default 60 s) so a stuck or over-eager caller can't double-count or saturate the corpus. Demote clamps at node_floor and never deletes — forget is the hard-delete path. See DESIGN.md §8.2 for the implicit-vs-explicit reinforcement split.

Tests

Storage and service tests connect to a real Neo4j; tenant isolation is per-test (each test gets a unique tenant prefix and a t.Cleanup that DETACH DELETEs everything written under it). Tests skip cleanly when NEO4J_PASSWORD is not set, so go test ./... succeeds on hosts without a Neo4j.

NEO4J_PASSWORD=<yours> go test ./...
NEO4J_PASSWORD=<yours> go test -race ./...

The cmd/memmy server is pure-Go and builds with CGO_ENABLED=0. The optional cmd/memmy-eval validation harness still depends on mattn/go-sqlite3 for its local data stores (corpus.sqlite, embedcache.sqlite, queries.sqlite); that's a tooling-only dependency unrelated to memmy's runtime storage.

Documentation

Overview

Package memmy is the embeddable library facade for the memmy LLM memory system. It is the only stable public surface; everything below it lives under internal/ and may change without notice.

Typical use:

emb := memmy.NewFakeEmbedder(64) // or NewGeminiEmbedder(ctx, opts)
svc, closer, err := memmy.Open(ctx, memmy.Options{
    Neo4j: memmy.Neo4jOptions{
        URI:      "bolt://localhost:7687",
        User:     "neo4j",
        Password: os.Getenv("NEO4J_PASSWORD"),
    },
    Embedder: emb,
})
if err != nil { ... }
defer closer.Close()

res, err := svc.Write(ctx, memmy.WriteRequest{
    Tenant:  map[string]string{"user": "alice"},
    Message: "the quick brown fox",
})

The schema is bundled in the binary via embed.FS but is NOT applied automatically — operators must call memmy.Migrate() (or the binary's `memmy migrate` subcommand) once before Open. Open refuses to start against a database whose schema version doesn't match what this library was built for.

Index

Constants

View Source
const (
	EdgeStructural  = types.EdgeStructural
	EdgeCoRetrieval = types.EdgeCoRetrieval
	EdgeCoTraversal = types.EdgeCoTraversal
)

EdgeKind values. See DESIGN.md §4.3.

View Source
const (
	EmbedTaskUnspecified        = embed.EmbedTaskUnspecified
	EmbedTaskRetrievalDocument  = embed.EmbedTaskRetrievalDocument
	EmbedTaskRetrievalQuery     = embed.EmbedTaskRetrievalQuery
	EmbedTaskSemanticSimilarity = embed.EmbedTaskSemanticSimilarity
	EmbedTaskClassification     = embed.EmbedTaskClassification
	EmbedTaskClustering         = embed.EmbedTaskClustering
	EmbedTaskCodeRetrievalQuery = embed.EmbedTaskCodeRetrievalQuery
	EmbedTaskQuestionAnswering  = embed.EmbedTaskQuestionAnswering
	EmbedTaskFactVerification   = embed.EmbedTaskFactVerification
)

EmbedTask constants.

Variables

This section is empty.

Functions

func Migrate added in v0.2.0

func Migrate(ctx context.Context, opts MigrationOptions) error

Migrate applies every embedded migration whose version is greater than the database's current applied version. Idempotent: re-running against an up-to-date database is a no-op.

opts.Dim sets the dimensionality the native vector index is created with on first migration; subsequent calls with a different dim are silently fine because the index is only created once. Callers that later switch embedder dims must drop the existing index manually (see DESIGN.md §13.1) and re-Migrate to re-create it.

Types

type Clock

type Clock = clock.Clock

Clock abstracts time so tests can advance it deterministically. Real{} is the production wall-clock implementation; tests should pass a *FakeClock from NewFakeClock.

type DemoteRequest

type DemoteRequest = types.DemoteRequest

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type DemoteResult

type DemoteResult = types.DemoteResult

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type EdgeKind

type EdgeKind = types.EdgeKind

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type EmbedTask

type EmbedTask = embed.EmbedTask

EmbedTask classifies how the embedded text will be used. memmy itself only emits RetrievalDocument (Write) and RetrievalQuery (Recall); the other values are reserved for callers passing their own embedder.

type Embedder

type Embedder = embed.Embedder

Embedder is the pluggable embedding-provider interface. Construct one with NewFakeEmbedder / NewGeminiEmbedder, or supply a custom implementation that conforms to the Embed/Dim contract.

func NewFakeEmbedder

func NewFakeEmbedder(dim int) Embedder

NewFakeEmbedder returns a deterministic test embedder of the given dimensionality. Equal inputs always produce equal vectors. Use in tests; do not use in production.

func NewGeminiEmbedder

func NewGeminiEmbedder(ctx context.Context, opts GeminiEmbedderOptions) (Embedder, error)

NewGeminiEmbedder constructs a Gemini-backed Embedder. It dials the Gemini API immediately to validate credentials.

type ErrTenantInvalid

type ErrTenantInvalid = service.ErrTenantInvalid

ErrTenantInvalid is the typed error returned when a tuple is rejected by the configured TenantSchema. Callers can errors.As() it to surface a corrective payload back to the originating client.

type FakeClock

type FakeClock = clock.Fake

FakeClock is a controllable Clock for tests.

func NewFakeClock

func NewFakeClock(t time.Time) *FakeClock

NewFakeClock returns a *FakeClock initialized to t.

type ForgetRequest

type ForgetRequest = types.ForgetRequest

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type ForgetResult

type ForgetResult = types.ForgetResult

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type GeminiEmbedderOptions

type GeminiEmbedderOptions = gemini.Options

GeminiEmbedderOptions configures NewGeminiEmbedder.

type MarkRequest

type MarkRequest = types.MarkRequest

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type MarkResult

type MarkResult = types.MarkResult

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type MigrationOptions added in v0.2.0

type MigrationOptions struct {
	Neo4j Neo4jOptions
	Dim   int
}

MigrationOptions configures Migrate. Neo4j configures the backend the migrations are applied to; Dim is the dimensionality the native vector index is created with on first migration.

type Neo4jOptions added in v0.2.0

type Neo4jOptions struct {
	// URI is the bolt:// (or neo4j+s://) address of the Neo4j
	// instance. Required.
	URI string

	// User / Password are the credentials for URI. Required.
	User     string
	Password string

	// Database selects the database within the Neo4j instance.
	// Optional; "neo4j" by default.
	Database string

	// ConnectTimeout caps the initial connectivity verification.
	// Optional; 10s by default.
	ConnectTimeout time.Duration
}

Neo4jOptions bundles the Neo4j backend credentials. The URI, User, and Password are required; everything else has a sensible default. The struct is shared between memmy.Open (Options.Neo4j) and memmy.Migrate (MigrationOptions.Neo4j) so callers configure the backend in one place regardless of which entry point they invoke.

type Options

type Options struct {
	// Neo4j configures the storage backend. URI, User, and Password
	// are required.
	Neo4j Neo4jOptions

	// Embedder produces vectors for Write inputs and Recall queries.
	// Construct via NewFakeEmbedder or NewGeminiEmbedder, or supply
	// your own implementation. Required.
	Embedder Embedder

	// Clock is the time source for decay and reinforcement math.
	// Optional; nil means RealClock{}.
	Clock Clock

	// ServiceConfig overrides chunking / retrieval / decay / reinforcement
	// tunables. nil → use DefaultServiceConfig(). Non-nil is treated as
	// the complete config — no field-by-field merging is performed (see
	// the ServiceConfig type doc for why). To override a subset:
	//
	//	cfg := memmy.DefaultServiceConfig()
	//	cfg.NodeDelta = 2.0
	//	opts.ServiceConfig = &cfg
	ServiceConfig *ServiceConfig

	// TenantSchema validates tenant tuples on every operation. Optional;
	// nil accepts any tuple shape (today's daemon default).
	TenantSchema *TenantSchema

	// FlatScanThreshold is the per-tenant size below which Recall uses a
	// linear scan instead of the native vector index. Optional; 0 → 5000
	// (DESIGN.md §6.1).
	FlatScanThreshold int

	// SkipMigrationCheck disables the schema-version guard at Open.
	// Tests-only — production callers should never set this. The
	// neo4jtest helper sets it because it manages migrations itself.
	SkipMigrationCheck bool
}

Options configures Open. Neo4j and Embedder are required; everything else has a sensible zero-value default.

type RealClock

type RealClock = clock.Real

RealClock is the production wall-clock implementation of Clock.

type RecallHit

type RecallHit = types.RecallHit

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type RecallRequest

type RecallRequest = types.RecallRequest

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type RecallResult

type RecallResult = types.RecallResult

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type ReinforceRequest

type ReinforceRequest = types.ReinforceRequest

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type ReinforceResult

type ReinforceResult = types.ReinforceResult

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type ScoreBreakdown

type ScoreBreakdown = types.ScoreBreakdown

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type Service

type Service = service.MemoryService

Service is the transport-neutral memory API (DESIGN.md §9.1). All operations take a tenant tuple; the underlying TenantID is derived deterministically from the (validated) tuple.

func Open

func Open(ctx context.Context, opts Options) (Service, io.Closer, error)

Open constructs a Service backed by Neo4j at opts.Neo4j.URI. The returned io.Closer must be invoked at shutdown to release the bolt driver connection pool. The Embedder's lifecycle is the caller's responsibility — Open does NOT close it.

Open does not start any transport (MCP / gRPC / HTTP); callers drive the returned Service directly. To run a transport, use the cmd/memmy binary with a YAML config instead.

Open refuses to start against a database whose schema version does not match what this build of memmy expects. The fix is to run memmy.Migrate (or the binary's `memmy migrate` subcommand) once.

type ServiceConfig

type ServiceConfig = service.Config

ServiceConfig bundles the runtime tunables for chunking, retrieval, decay, reinforcement, and pruning. See DESIGN.md §12.

Options.ServiceConfig is a *ServiceConfig: nil means "use DefaultServiceConfig()", non-nil means "use exactly this struct." To override a subset of fields, start from DefaultServiceConfig() and mutate the returned struct before taking its address. The facade deliberately does NOT do field-by-field merging because some fields (RefractoryPeriod, LogDampening) accept zero as an intentional "disable" signal that a merge-on-zero rule would silently override.

func DefaultServiceConfig

func DefaultServiceConfig() ServiceConfig

DefaultServiceConfig returns the documented service-tunable defaults.

type StatsRequest

type StatsRequest = types.StatsRequest

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type StatsResult

type StatsResult = types.StatsResult

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type TenantKeyConfig

type TenantKeyConfig = config.TenantKeyConfig

TenantKeyConfig is one declared key in a TenantSchemaConfig.

type TenantSchema

type TenantSchema = service.TenantSchema

TenantSchema validates incoming tenant tuples. Construct one via NewTenantSchema, or pass nil to Options.TenantSchema to accept any tuple shape.

func NewTenantSchema

func NewTenantSchema(cfg TenantSchemaConfig) (*TenantSchema, error)

NewTenantSchema compiles a TenantSchema from a config-shaped value. Returns (nil, nil) when cfg has no rules — the caller can pass that nil straight into Options.TenantSchema to mean "accept any tuple."

type TenantSchemaConfig

type TenantSchemaConfig = config.TenantSchemaConfig

TenantSchemaConfig describes the shape of a valid tenant tuple in the same shape the daemon accepts via YAML. Library callers usually construct it programmatically:

cfg := memmy.TenantSchemaConfig{
    Description: "single-user agent",
    Keys: map[string]memmy.TenantKeyConfig{
        "user":  {Required: true, Pattern: `^[a-zA-Z0-9_.-]+$`},
        "scope": {Enum: []string{"chat", "code"}},
    },
}

type WriteRequest

type WriteRequest = types.WriteRequest

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

type WriteResult

type WriteResult = types.WriteResult

Request and result value types — direct re-exports of the wire-neutral shapes defined in internal/types.

Directories

Path Synopsis
cmd
memmy command
Command memmy runs the memmy LLM-memory MCP server, plus the `migrate` subcommand that applies the bundled Neo4j schema.
Command memmy runs the memmy LLM-memory MCP server, plus the `migrate` subcommand that applies the bundled Neo4j schema.
memmy-eval command
Command memmy-eval is the validation harness CLI for memmy.
Command memmy-eval is the validation harness CLI for memmy.
internal
chunker
Package chunker splits a message into sentence-sliding-window chunks.
Package chunker splits a message into sentence-sliding-window chunks.
clock
Package clock provides a time abstraction so business logic can be tested deterministically.
Package clock provides a time abstraction so business logic can be tested deterministically.
config
Package config loads memmy's YAML configuration.
Package config loads memmy's YAML configuration.
embed
Package embed defines the Embedder interface and concrete implementations in subpackages.
Package embed defines the Embedder interface and concrete implementations in subpackages.
embed/fake
Package fake provides a deterministic Embedder for tests.
Package fake provides a deterministic Embedder for tests.
embed/gemini
Package gemini implements the Embedder interface against Google's Gemini embeddings API via go-genai (google.golang.org/genai).
Package gemini implements the Embedder interface against Google's Gemini embeddings API via go-genai (google.golang.org/genai).
eval/corpus
Package corpus extracts plain-text turns from Claude Code session transcripts (`~/.claude/projects/<project>/<sessionUUID>.jsonl`).
Package corpus extracts plain-text turns from Claude Code session transcripts (`~/.claude/projects/<project>/<sessionUUID>.jsonl`).
eval/dataset
Package dataset owns the on-disk layout for memmy-eval datasets.
Package dataset owns the on-disk layout for memmy-eval datasets.
eval/embedcache
Package embedcache caches embedding vectors keyed by (model_id, dim, sha256(text)) so repeated ingest runs over the same corpus do not re-embed unchanged chunks.
Package embedcache caches embedding vectors keyed by (model_id, dim, sha256(text)) so repeated ingest runs over the same corpus do not re-embed unchanged chunks.
eval/harness
Package harness is the composition layer that turns a Claude Code session directory into a memmy store, runs query batteries against it, and captures the per-node state changes that result.
Package harness is the composition layer that turns a Claude Code session directory into a memmy store, runs query batteries against it, and captures the per-node state changes that result.
eval/inspect
Package inspect is a read-only window into a memmy Neo4j database used by the eval harness to capture per-node state (weight, last touch, edge degree) before and after a query.
Package inspect is a read-only window into a memmy Neo4j database used by the eval harness to capture per-node state (weight, last touch, edge degree) before and after a query.
eval/manifest
Package manifest defines the on-disk metadata records that document what produced an eval dataset and what an eval run actually exercised.
Package manifest defines the on-disk metadata records that document what produced an eval dataset and what an eval run actually exercised.
eval/metrics
Package metrics computes the IR + dynamics scores the eval harness reports per run.
Package metrics computes the IR + dynamics scores the eval harness reports per run.
eval/queries
Package queries owns the labeled-query side of the eval framework.
Package queries owns the labeled-query side of the eval framework.
eval/sweep
Package sweep runs an eval harness over a matrix of memmy configs to find a parameter setting that scores best on a labeled query set.
Package sweep runs an eval harness over a matrix of memmy configs to find a parameter setting that scores best on a labeled query set.
graph
Package graph defines the Graph port-out interface used by the Memory Service to persist nodes, messages, and Hebbian memory edges.
Package graph defines the Graph port-out interface used by the Memory Service to persist nodes, messages, and Hebbian memory edges.
service
Package service implements the MemoryService — the transport-neutral input port (DESIGN.md §9.1).
Package service implements the MemoryService — the transport-neutral input port (DESIGN.md §9.1).
storage/neo4j
Package neo4jstore implements the Graph + VectorIndex ports (DESIGN.md §9.2) over a Neo4j database via the Bolt protocol.
Package neo4jstore implements the Graph + VectorIndex ports (DESIGN.md §9.2) over a Neo4j database via the Bolt protocol.
storage/neo4j/neo4jtest
Package neo4jtest is the test helper that opens a per-test Storage handle against the developer's local Neo4j and registers a t.Cleanup that DETACH DELETEs every node carrying the test's unique tenant prefix.
Package neo4jtest is the test helper that opens a per-test Storage handle against the developer's local Neo4j and registers a t.Cleanup that DETACH DELETEs every node carrying the test's unique tenant prefix.
transport/mcp
Package mcp adapts the MemoryService onto an MCP server using the official github.com/modelcontextprotocol/go-sdk.
Package mcp adapts the MemoryService onto an MCP server using the official github.com/modelcontextprotocol/go-sdk.
types
Package types holds the domain entities used throughout memmy.
Package types holds the domain entities used throughout memmy.
vectorindex
Package vectorindex defines the VectorIndex port-out interface used by the Memory Service to store vectors and run top-N similarity search.
Package vectorindex defines the VectorIndex port-out interface used by the Memory Service to store vectors and run top-N similarity search.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL