oh-my-second-brain 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +41 -0
- package/{adapters/claude-code/.claude-plugin → .claude-plugin}/plugin.json +7 -8
- package/{adapters/codex/.codex-plugin → .codex-plugin}/plugin.json +4 -4
- package/ACKNOWLEDGMENTS.md +154 -0
- package/CHANGELOG-assets.md +19 -0
- package/CHANGELOG-cli.md +15 -0
- package/CHANGELOG-kernel.md +25 -0
- package/CHANGELOG-mcp.md +26 -0
- package/CHANGELOG-vendors.md +22 -0
- package/CHANGELOG.md +24 -7
- package/README.ko.md +2 -2
- package/README.md +16 -16
- package/{adapters/claude-code → assets/claude}/CLAUDE.md +4 -4
- package/{adapters → assets}/codex/AGENTS.md +3 -3
- package/{adapters → assets}/codex/rules/oms.md +5 -5
- package/{adapters → assets}/hermes/README.md +1 -1
- package/{adapters → assets}/hermes/SOUL.md +3 -3
- package/{adapters/hermes/manifest.json → assets/hermes-manifest.json} +3 -4
- package/assets/skills/distill/SKILL.md +20 -0
- package/assets/skills/doctor/SKILL.md +23 -0
- package/assets/skills/link/SKILL.md +24 -0
- package/assets/skills/search/SKILL.md +25 -0
- package/assets/skills/status/SKILL.md +22 -0
- package/assets/skills/write/SKILL.md +30 -0
- package/core/ontology/schemas/README.md +20 -14
- package/dist/assets/shared-skills.d.ts +4 -0
- package/dist/assets/shared-skills.js +8 -0
- package/dist/assets/shared-skills.js.map +1 -0
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.js +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/audit.js +3 -3
- package/dist/cli/audit.js.map +1 -1
- package/dist/cli/claude-install-plan.js +2 -2
- package/dist/cli/claude-install-plan.js.map +1 -1
- package/dist/cli/doctor-lint.js +8 -8
- package/dist/cli/doctor-lint.js.map +1 -1
- package/dist/cli/global-writeback.js +1 -1
- package/dist/cli/global-writeback.js.map +1 -1
- package/dist/cli/host-commands.d.ts +1 -1
- package/dist/cli/host-commands.js +22 -4
- package/dist/cli/host-commands.js.map +1 -1
- package/dist/cli/link-command.d.ts +1 -1
- package/dist/cli/link-command.js +2 -2
- package/dist/cli/link-command.js.map +1 -1
- package/dist/cli/linkify.js +16 -71
- package/dist/cli/linkify.js.map +1 -1
- package/dist/cli/oms.js +20 -9
- package/dist/cli/oms.js.map +1 -1
- package/dist/cli/semantic-args.d.ts +1 -1
- package/dist/cli/semantic-http.js +3 -3
- package/dist/cli/semantic-http.js.map +1 -1
- package/dist/cli/semantic-usage.js +1 -1
- package/dist/cli/semantic-usage.js.map +1 -1
- package/dist/cli/semantic.js +1 -6
- package/dist/cli/semantic.js.map +1 -1
- package/dist/cli/setup-command.d.ts +1 -0
- package/dist/cli/setup-command.js +42 -147
- package/dist/cli/setup-command.js.map +1 -1
- package/dist/cli/update-notice.d.ts +1 -1
- package/dist/cli/update-notice.js +2 -2
- package/dist/cli/update-notice.js.map +1 -1
- package/dist/cli/usage.d.ts +1 -1
- package/dist/cli/usage.js +2 -2
- package/dist/cli/usage.js.map +1 -1
- package/dist/{capture → kernel/capture}/safe.d.ts +11 -1
- package/dist/{capture → kernel/capture}/safe.js +3 -3
- package/dist/kernel/capture/safe.js.map +1 -0
- package/dist/kernel/conventions/frontmatter.js.map +1 -0
- package/dist/kernel/conventions/lint.js.map +1 -0
- package/dist/kernel/conventions/report.js.map +1 -0
- package/dist/{conventions → kernel/conventions}/validate.d.ts +1 -1
- package/dist/kernel/conventions/validate.js.map +1 -0
- package/dist/kernel/conventions/vault-walk.js.map +1 -0
- package/dist/{conventions → kernel/conventions}/write-contract.d.ts +1 -1
- package/dist/kernel/conventions/write-contract.js.map +1 -0
- package/dist/kernel/conventions/write-protocol.js.map +1 -0
- package/dist/kernel/doctor/service.d.ts +71 -0
- package/dist/kernel/doctor/service.js +70 -0
- package/dist/kernel/doctor/service.js.map +1 -0
- package/dist/{engine → kernel/engine}/assemble.d.ts +24 -0
- package/dist/{engine → kernel/engine}/assemble.js +142 -4
- package/dist/kernel/engine/assemble.js.map +1 -0
- package/dist/{engine → kernel/engine}/conventions/vault-lint.d.ts +1 -1
- package/dist/{engine → kernel/engine}/conventions/vault-lint.js +1 -1
- package/dist/kernel/engine/conventions/vault-lint.js.map +1 -0
- package/dist/kernel/engine/embed/chunker.js.map +1 -0
- package/dist/kernel/engine/embed/deferred.js.map +1 -0
- package/dist/{engine → kernel/engine}/embed/hash-stub.test-helper.d.ts +1 -1
- package/dist/{engine → kernel/engine}/embed/hash-stub.test-helper.js +1 -1
- package/dist/kernel/engine/embed/hash-stub.test-helper.js.map +1 -0
- package/dist/kernel/engine/embed/identity.js.map +1 -0
- package/dist/kernel/engine/embed/provider.js.map +1 -0
- package/dist/{engine → kernel/engine}/embed/store.d.ts +8 -0
- package/dist/{engine → kernel/engine}/embed/store.js +212 -8
- package/dist/kernel/engine/embed/store.js.map +1 -0
- package/dist/{engine → kernel/engine}/embed/sync.d.ts +3 -1
- package/dist/{engine → kernel/engine}/embed/sync.js +5 -3
- package/dist/kernel/engine/embed/sync.js.map +1 -0
- package/dist/kernel/engine/graph/builder.js.map +1 -0
- package/dist/kernel/engine/graph/explore.js.map +1 -0
- package/dist/kernel/engine/graph/node.js.map +1 -0
- package/dist/kernel/engine/graph/resolver.js.map +1 -0
- package/dist/kernel/engine/graph/traverse.js.map +1 -0
- package/dist/kernel/engine/linkify/apply.js.map +1 -0
- package/dist/kernel/engine/linkify/josa.js.map +1 -0
- package/dist/kernel/engine/linkify/mask.js.map +1 -0
- package/dist/kernel/engine/linkify/suggest.js.map +1 -0
- package/dist/kernel/engine/linkify/types.js.map +1 -0
- package/dist/{engine → kernel/engine}/mcp/facade.d.ts +7 -1
- package/dist/{engine → kernel/engine}/mcp/facade.js +32 -11
- package/dist/kernel/engine/mcp/facade.js.map +1 -0
- package/dist/kernel/engine/mcp/op-mappers.js.map +1 -0
- package/dist/kernel/engine/mcp/query-mapper.js.map +1 -0
- package/dist/{engine → kernel/engine}/mcp/types.d.ts +5 -0
- package/dist/kernel/engine/mcp/types.js.map +1 -0
- package/dist/{engine → kernel/engine}/retrieval/dispatcher.d.ts +1 -1
- package/dist/{engine → kernel/engine}/retrieval/dispatcher.js +8 -6
- package/dist/kernel/engine/retrieval/dispatcher.js.map +1 -0
- package/dist/{engine → kernel/engine}/retrieval/index.d.ts +2 -0
- package/dist/{engine → kernel/engine}/retrieval/index.js +5 -2
- package/dist/kernel/engine/retrieval/index.js.map +1 -0
- package/dist/kernel/engine/retrieval/reranker.js.map +1 -0
- package/dist/kernel/engine/retrieval/rrf.js.map +1 -0
- package/dist/kernel/engine/tracer.js.map +1 -0
- package/dist/{engine → kernel/engine}/types.d.ts +4 -4
- package/dist/kernel/engine/types.js.map +1 -0
- package/dist/{graph → kernel/graph}/cache.d.ts +1 -1
- package/dist/{graph → kernel/graph}/cache.js +1 -1
- package/dist/kernel/graph/cache.js.map +1 -0
- package/dist/kernel/graph/explore.js.map +1 -0
- package/dist/{harness → kernel/harness}/surface-registry.d.ts +0 -1
- package/dist/kernel/harness/surface-registry.js +170 -0
- package/dist/kernel/harness/surface-registry.js.map +1 -0
- package/dist/{harness → kernel/harness}/validation.js +67 -4
- package/dist/kernel/harness/validation.js.map +1 -0
- package/dist/{index.d.ts → kernel/index.d.ts} +5 -6
- package/dist/kernel/index.js +12 -0
- package/dist/kernel/index.js.map +1 -0
- package/dist/{install → kernel/install}/adapter-source.d.ts +10 -1
- package/dist/kernel/install/adapter-source.js +76 -0
- package/dist/kernel/install/adapter-source.js.map +1 -0
- package/dist/kernel/install/common.js.map +1 -0
- package/dist/{install → kernel/install}/hosts.d.ts +3 -3
- package/dist/{install → kernel/install}/hosts.js +3 -22
- package/dist/kernel/install/hosts.js.map +1 -0
- package/dist/{core/ontology → kernel/install}/types.js.map +1 -1
- package/dist/{link → kernel/link}/convention-note.js +2 -2
- package/dist/kernel/link/convention-note.js.map +1 -0
- package/dist/kernel/link/global-config.js.map +1 -0
- package/dist/kernel/link/link.js.map +1 -0
- package/dist/kernel/link/workflow.d.ts +55 -0
- package/dist/kernel/link/workflow.js +107 -0
- package/dist/kernel/link/workflow.js.map +1 -0
- package/dist/{ontology → kernel/ontology}/active.d.ts +1 -1
- package/dist/{ontology → kernel/ontology}/active.js +2 -2
- package/dist/kernel/ontology/active.js.map +1 -0
- package/dist/kernel/ontology/loader.js.map +1 -0
- package/dist/kernel/ontology/resolver.js.map +1 -0
- package/dist/{install → kernel/ontology}/types.js.map +1 -1
- package/dist/kernel/plugin/index.d.ts +1 -0
- package/dist/kernel/plugin/index.js +2 -0
- package/dist/kernel/plugin/index.js.map +1 -0
- package/dist/{core → kernel}/runtime/assets.d.ts +2 -4
- package/dist/{core → kernel}/runtime/assets.js +1 -3
- package/dist/kernel/runtime/assets.js.map +1 -0
- package/dist/kernel/search/morning-test-fixtures.js.map +1 -0
- package/dist/{retrieve → kernel/search}/morning.d.ts +0 -1
- package/dist/kernel/search/morning.js.map +1 -0
- package/dist/kernel/search/semantic-contract.js.map +1 -0
- package/dist/kernel/searchbackend/engine-search-backend.d.ts +28 -0
- package/dist/kernel/searchbackend/engine-search-backend.js +67 -0
- package/dist/kernel/searchbackend/engine-search-backend.js.map +1 -0
- package/dist/kernel/searchbackend/index.d.ts +2 -0
- package/dist/kernel/searchbackend/index.js +2 -0
- package/dist/kernel/searchbackend/index.js.map +1 -0
- package/dist/kernel/searchbackend/search-backend.d.ts +47 -0
- package/dist/kernel/searchbackend/search-backend.js +49 -0
- package/dist/kernel/searchbackend/search-backend.js.map +1 -0
- package/dist/{mcp → kernel/semantic}/semantic-engine.d.ts +3 -2
- package/dist/{mcp → kernel/semantic}/semantic-engine.js +5 -5
- package/dist/kernel/semantic/semantic-engine.js.map +1 -0
- package/dist/{mcp → kernel/semantic}/semantic-retrieve-args.d.ts +2 -2
- package/dist/{mcp → kernel/semantic}/semantic-retrieve-args.js +0 -8
- package/dist/kernel/semantic/semantic-retrieve-args.js.map +1 -0
- package/dist/{mcp → kernel/semantic}/semantic-retrieve-schema.d.ts +0 -24
- package/dist/{mcp → kernel/semantic}/semantic-retrieve-schema.js +0 -8
- package/dist/kernel/semantic/semantic-retrieve-schema.js.map +1 -0
- package/dist/{mcp → kernel/semantic}/semantic-retrieve.js +5 -9
- package/dist/kernel/semantic/semantic-retrieve.js.map +1 -0
- package/dist/kernel/semantic/semantic-schemas.js.map +1 -0
- package/dist/{mcp → kernel/semantic}/semantic-tool-schemas.js +0 -28
- package/dist/kernel/semantic/semantic-tool-schemas.js.map +1 -0
- package/dist/{setup → kernel/setup}/axis.d.ts +1 -1
- package/dist/{setup → kernel/setup}/axis.js +1 -1
- package/dist/kernel/setup/axis.js.map +1 -0
- package/dist/{cli/setup-documents.d.ts → kernel/setup/documents.d.ts} +1 -1
- package/dist/{cli/setup-documents.js → kernel/setup/documents.js} +15 -49
- package/dist/kernel/setup/documents.js.map +1 -0
- package/dist/kernel/setup/service.d.ts +44 -0
- package/dist/kernel/setup/service.js +97 -0
- package/dist/kernel/setup/service.js.map +1 -0
- package/dist/kernel/update/update.js.map +1 -0
- package/dist/mcp/engine-morning-backend.d.ts +4 -4
- package/dist/mcp/engine-morning-backend.js +4 -18
- package/dist/mcp/engine-morning-backend.js.map +1 -1
- package/dist/mcp/link-tools.d.ts +9 -56
- package/dist/mcp/link-tools.js +5 -129
- package/dist/mcp/link-tools.js.map +1 -1
- package/dist/mcp/server.d.ts +9 -2
- package/dist/mcp/server.js +326 -327
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/update-notice.d.ts +1 -1
- package/dist/mcp/update-notice.js +1 -1
- package/dist/mcp/update-notice.js.map +1 -1
- package/dist/{install → vendors/claude}/claude-hooks.d.ts +1 -1
- package/dist/{install → vendors/claude}/claude-hooks.js +1 -1
- package/dist/vendors/claude/claude-hooks.js.map +1 -0
- package/dist/{install → vendors/claude}/claude-marketplace.d.ts +3 -3
- package/dist/{install → vendors/claude}/claude-marketplace.js +6 -9
- package/dist/vendors/claude/claude-marketplace.js.map +1 -0
- package/dist/{install → vendors/claude}/claude.d.ts +2 -2
- package/dist/{install → vendors/claude}/claude.js +2 -2
- package/dist/vendors/claude/claude.js.map +1 -0
- package/dist/{hook → vendors/claude/hook}/post-tool-use.js +5 -5
- package/dist/vendors/claude/hook/post-tool-use.js.map +1 -0
- package/dist/vendors/claude/hook/pre-tool-use.js.map +1 -0
- package/dist/vendors/claude/hook/stdin.js.map +1 -0
- package/dist/vendors/codex/codex.d.ts +10 -0
- package/dist/{install → vendors/codex}/codex.js +19 -37
- package/dist/vendors/codex/codex.js.map +1 -0
- package/dist/{install → vendors/hermes}/hermes.d.ts +2 -2
- package/dist/{install → vendors/hermes}/hermes.js +15 -7
- package/dist/vendors/hermes/hermes.js.map +1 -0
- package/docs/adapters.md +15 -0
- package/docs/install.md +10 -11
- package/package.json +21 -9
- package/adapters/README.md +0 -99
- package/adapters/claude-code/skills/compile/SKILL.md +0 -27
- package/adapters/claude-code/skills/define/SKILL.md +0 -51
- package/adapters/claude-code/skills/distill/SKILL.md +0 -28
- package/adapters/claude-code/skills/doctor/SKILL.md +0 -58
- package/adapters/claude-code/skills/link/SKILL.md +0 -87
- package/adapters/claude-code/skills/retrieve/SKILL.md +0 -99
- package/adapters/claude-code/skills/setup/SKILL.md +0 -78
- package/adapters/claude-code/skills/uninstall/SKILL.md +0 -34
- package/adapters/claude-code/skills/update/SKILL.md +0 -45
- package/adapters/claude-code/skills/vault-decision-record/SKILL.md +0 -52
- package/adapters/claude-code/skills/vault-lint/SKILL.md +0 -47
- package/adapters/claude-code/skills/vault-scaffold/SKILL.md +0 -47
- package/adapters/claude-code/skills/wiki/SKILL.md +0 -82
- package/adapters/claude-code/skills/write/SKILL.md +0 -16
- package/adapters/codex/skills/oms-compile/SKILL.md +0 -16
- package/adapters/codex/skills/oms-distill/SKILL.md +0 -14
- package/adapters/codex/skills/oms-doctor/SKILL.md +0 -14
- package/adapters/codex/skills/oms-install/SKILL.md +0 -19
- package/adapters/codex/skills/oms-link/SKILL.md +0 -35
- package/adapters/codex/skills/oms-retrieve/SKILL.md +0 -32
- package/adapters/codex/skills/oms-setup/SKILL.md +0 -34
- package/adapters/codex/skills/oms-uninstall/SKILL.md +0 -20
- package/adapters/codex/skills/oms-update/SKILL.md +0 -22
- package/adapters/codex/skills/oms-vault-lint/SKILL.md +0 -19
- package/adapters/codex/skills/oms-wiki/SKILL.md +0 -39
- package/adapters/codex/skills/oms-write/SKILL.md +0 -10
- package/adapters/hermes/skills/compile/SKILL.md +0 -13
- package/adapters/hermes/skills/distill/SKILL.md +0 -10
- package/adapters/hermes/skills/doctor/SKILL.md +0 -14
- package/adapters/hermes/skills/install/SKILL.md +0 -19
- package/adapters/hermes/skills/link/SKILL.md +0 -18
- package/adapters/hermes/skills/retrieve/SKILL.md +0 -32
- package/adapters/hermes/skills/setup/SKILL.md +0 -37
- package/adapters/hermes/skills/uninstall/SKILL.md +0 -20
- package/adapters/hermes/skills/update/SKILL.md +0 -22
- package/adapters/hermes/skills/wiki/SKILL.md +0 -14
- package/adapters/hermes/skills/write/SKILL.md +0 -10
- package/core/agents/librarian.md +0 -44
- package/core/agents/retriever.md +0 -62
- package/core/skills/compile/CHANGELOG.md +0 -24
- package/core/skills/compile/SKILL.md +0 -57
- package/core/skills/define/SKILL.md +0 -59
- package/core/skills/distill/CHANGELOG.md +0 -39
- package/core/skills/distill/SKILL.md +0 -62
- package/core/skills/doctor/SKILL.md +0 -49
- package/core/skills/link/SKILL.md +0 -130
- package/core/skills/retrieve/SKILL.md +0 -78
- package/core/skills/setup/CHANGELOG.md +0 -49
- package/core/skills/setup/SKILL.md +0 -246
- package/core/skills/uninstall/SKILL.md +0 -34
- package/core/skills/vault-decision-record/CHANGELOG.md +0 -24
- package/core/skills/vault-decision-record/SKILL.md +0 -93
- package/core/skills/vault-lint/CHANGELOG.md +0 -35
- package/core/skills/vault-lint/SKILL.md +0 -58
- package/core/skills/vault-scaffold/CHANGELOG.md +0 -21
- package/core/skills/vault-scaffold/SKILL.md +0 -72
- package/core/skills/wiki/CHANGELOG.md +0 -23
- package/core/skills/wiki/SKILL.md +0 -159
- package/core/skills/write/SKILL.md +0 -15
- package/dist/capture/safe.js.map +0 -1
- package/dist/cli/setup-documents.js.map +0 -1
- package/dist/conventions/frontmatter.js.map +0 -1
- package/dist/conventions/lint.js.map +0 -1
- package/dist/conventions/report.js.map +0 -1
- package/dist/conventions/validate.js.map +0 -1
- package/dist/conventions/vault-walk.js.map +0 -1
- package/dist/conventions/write-contract.js.map +0 -1
- package/dist/conventions/write-protocol.js.map +0 -1
- package/dist/core/ontology/loader.js.map +0 -1
- package/dist/core/ontology/resolver.js.map +0 -1
- package/dist/core/runtime/assets.js.map +0 -1
- package/dist/engine/assemble.js.map +0 -1
- package/dist/engine/conventions/vault-lint.js.map +0 -1
- package/dist/engine/embed/chunker.js.map +0 -1
- package/dist/engine/embed/deferred.js.map +0 -1
- package/dist/engine/embed/hash-stub.test-helper.js.map +0 -1
- package/dist/engine/embed/identity.js.map +0 -1
- package/dist/engine/embed/provider.js.map +0 -1
- package/dist/engine/embed/store.js.map +0 -1
- package/dist/engine/embed/sync.js.map +0 -1
- package/dist/engine/graph/builder.js.map +0 -1
- package/dist/engine/graph/explore.js.map +0 -1
- package/dist/engine/graph/node.js.map +0 -1
- package/dist/engine/graph/resolver.js.map +0 -1
- package/dist/engine/graph/traverse.js.map +0 -1
- package/dist/engine/linkify/apply.js.map +0 -1
- package/dist/engine/linkify/josa.js.map +0 -1
- package/dist/engine/linkify/mask.js.map +0 -1
- package/dist/engine/linkify/suggest.js.map +0 -1
- package/dist/engine/linkify/types.js.map +0 -1
- package/dist/engine/mcp/facade.js.map +0 -1
- package/dist/engine/mcp/op-mappers.js.map +0 -1
- package/dist/engine/mcp/query-mapper.js.map +0 -1
- package/dist/engine/mcp/types.js.map +0 -1
- package/dist/engine/retrieval/dispatcher.js.map +0 -1
- package/dist/engine/retrieval/index.js.map +0 -1
- package/dist/engine/retrieval/reranker.js.map +0 -1
- package/dist/engine/retrieval/rrf.js.map +0 -1
- package/dist/engine/tracer.js.map +0 -1
- package/dist/engine/types.js.map +0 -1
- package/dist/graph/cache.js.map +0 -1
- package/dist/graph/explore.js.map +0 -1
- package/dist/harness/surface-registry.js +0 -397
- package/dist/harness/surface-registry.js.map +0 -1
- package/dist/harness/validation.js.map +0 -1
- package/dist/hook/post-tool-use.js.map +0 -1
- package/dist/hook/pre-tool-use.js.map +0 -1
- package/dist/hook/stdin.js.map +0 -1
- package/dist/index.js +0 -13
- package/dist/index.js.map +0 -1
- package/dist/install/adapter-source.js +0 -45
- package/dist/install/adapter-source.js.map +0 -1
- package/dist/install/claude-hooks.js.map +0 -1
- package/dist/install/claude-marketplace.js.map +0 -1
- package/dist/install/claude.js.map +0 -1
- package/dist/install/codex.d.ts +0 -24
- package/dist/install/codex.js.map +0 -1
- package/dist/install/common.js.map +0 -1
- package/dist/install/hermes.js.map +0 -1
- package/dist/install/hosts.js.map +0 -1
- package/dist/link/convention-note.js.map +0 -1
- package/dist/link/global-config.js.map +0 -1
- package/dist/link/link.js.map +0 -1
- package/dist/mcp/semantic-engine.js.map +0 -1
- package/dist/mcp/semantic-retrieve-args.js.map +0 -1
- package/dist/mcp/semantic-retrieve-schema.js.map +0 -1
- package/dist/mcp/semantic-retrieve.js.map +0 -1
- package/dist/mcp/semantic-schemas.js.map +0 -1
- package/dist/mcp/semantic-tool-schemas.js.map +0 -1
- package/dist/ontology/active.js.map +0 -1
- package/dist/retrieve/morning-test-fixtures.js.map +0 -1
- package/dist/retrieve/morning.js.map +0 -1
- package/dist/retrieve/semantic-contract.js.map +0 -1
- package/dist/setup/axis.js.map +0 -1
- package/dist/update/update.js.map +0 -1
- package/docs/release.md +0 -188
- /package/{adapters/codex/.mcp.json → .mcp.codex.json} +0 -0
- /package/{adapters/claude-code/.mcp.json → .mcp.json} +0 -0
- /package/{adapters/claude-code → assets/claude}/hooks/oms-guard.mjs +0 -0
- /package/{adapters/claude-code → assets/claude}/hooks/oms-post-guard.mjs +0 -0
- /package/dist/{conventions → kernel/conventions}/frontmatter.d.ts +0 -0
- /package/dist/{conventions → kernel/conventions}/frontmatter.js +0 -0
- /package/dist/{conventions → kernel/conventions}/lint.d.ts +0 -0
- /package/dist/{conventions → kernel/conventions}/lint.js +0 -0
- /package/dist/{conventions → kernel/conventions}/report.d.ts +0 -0
- /package/dist/{conventions → kernel/conventions}/report.js +0 -0
- /package/dist/{conventions → kernel/conventions}/validate.js +0 -0
- /package/dist/{conventions → kernel/conventions}/vault-walk.d.ts +0 -0
- /package/dist/{conventions → kernel/conventions}/vault-walk.js +0 -0
- /package/dist/{conventions → kernel/conventions}/write-contract.js +0 -0
- /package/dist/{conventions → kernel/conventions}/write-protocol.d.ts +0 -0
- /package/dist/{conventions → kernel/conventions}/write-protocol.js +0 -0
- /package/dist/{engine → kernel/engine}/embed/chunker.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/embed/chunker.js +0 -0
- /package/dist/{engine → kernel/engine}/embed/deferred.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/embed/deferred.js +0 -0
- /package/dist/{engine → kernel/engine}/embed/identity.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/embed/identity.js +0 -0
- /package/dist/{engine → kernel/engine}/embed/provider.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/embed/provider.js +0 -0
- /package/dist/{engine → kernel/engine}/graph/builder.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/graph/builder.js +0 -0
- /package/dist/{engine → kernel/engine}/graph/explore.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/graph/explore.js +0 -0
- /package/dist/{engine → kernel/engine}/graph/node.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/graph/node.js +0 -0
- /package/dist/{engine → kernel/engine}/graph/resolver.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/graph/resolver.js +0 -0
- /package/dist/{engine → kernel/engine}/graph/traverse.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/graph/traverse.js +0 -0
- /package/dist/{engine → kernel/engine}/linkify/apply.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/linkify/apply.js +0 -0
- /package/dist/{engine → kernel/engine}/linkify/josa.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/linkify/josa.js +0 -0
- /package/dist/{engine → kernel/engine}/linkify/mask.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/linkify/mask.js +0 -0
- /package/dist/{engine → kernel/engine}/linkify/suggest.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/linkify/suggest.js +0 -0
- /package/dist/{engine → kernel/engine}/linkify/types.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/linkify/types.js +0 -0
- /package/dist/{engine → kernel/engine}/mcp/op-mappers.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/mcp/op-mappers.js +0 -0
- /package/dist/{engine → kernel/engine}/mcp/query-mapper.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/mcp/query-mapper.js +0 -0
- /package/dist/{engine → kernel/engine}/mcp/types.js +0 -0
- /package/dist/{engine → kernel/engine}/retrieval/reranker.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/retrieval/reranker.js +0 -0
- /package/dist/{engine → kernel/engine}/retrieval/rrf.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/retrieval/rrf.js +0 -0
- /package/dist/{engine → kernel/engine}/tracer.d.ts +0 -0
- /package/dist/{engine → kernel/engine}/tracer.js +0 -0
- /package/dist/{engine → kernel/engine}/types.js +0 -0
- /package/dist/{graph → kernel/graph}/explore.d.ts +0 -0
- /package/dist/{graph → kernel/graph}/explore.js +0 -0
- /package/dist/{harness → kernel/harness}/validation.d.ts +0 -0
- /package/dist/{install → kernel/install}/common.d.ts +0 -0
- /package/dist/{install → kernel/install}/common.js +0 -0
- /package/dist/{install → kernel/install}/types.d.ts +0 -0
- /package/dist/{core/ontology → kernel/install}/types.js +0 -0
- /package/dist/{link → kernel/link}/convention-note.d.ts +0 -0
- /package/dist/{link → kernel/link}/global-config.d.ts +0 -0
- /package/dist/{link → kernel/link}/global-config.js +0 -0
- /package/dist/{link → kernel/link}/link.d.ts +0 -0
- /package/dist/{link → kernel/link}/link.js +0 -0
- /package/dist/{core → kernel}/ontology/loader.d.ts +0 -0
- /package/dist/{core → kernel}/ontology/loader.js +0 -0
- /package/dist/{core → kernel}/ontology/resolver.d.ts +0 -0
- /package/dist/{core → kernel}/ontology/resolver.js +0 -0
- /package/dist/{core → kernel}/ontology/types.d.ts +0 -0
- /package/dist/{install → kernel/ontology}/types.js +0 -0
- /package/dist/{retrieve → kernel/search}/morning-test-fixtures.d.ts +0 -0
- /package/dist/{retrieve → kernel/search}/morning-test-fixtures.js +0 -0
- /package/dist/{retrieve → kernel/search}/morning.js +0 -0
- /package/dist/{retrieve → kernel/search}/semantic-contract.d.ts +0 -0
- /package/dist/{retrieve → kernel/search}/semantic-contract.js +0 -0
- /package/dist/{mcp → kernel/semantic}/semantic-retrieve.d.ts +0 -0
- /package/dist/{mcp → kernel/semantic}/semantic-schemas.d.ts +0 -0
- /package/dist/{mcp → kernel/semantic}/semantic-schemas.js +0 -0
- /package/dist/{mcp → kernel/semantic}/semantic-tool-schemas.d.ts +0 -0
- /package/dist/{update → kernel/update}/update.d.ts +0 -0
- /package/dist/{update → kernel/update}/update.js +0 -0
- /package/dist/{hook → vendors/claude/hook}/post-tool-use.d.ts +0 -0
- /package/dist/{hook → vendors/claude/hook}/pre-tool-use.d.ts +0 -0
- /package/dist/{hook → vendors/claude/hook}/pre-tool-use.js +0 -0
- /package/dist/{hook → vendors/claude/hook}/stdin.d.ts +0 -0
- /package/dist/{hook → vendors/claude/hook}/stdin.js +0 -0
package/dist/mcp/server.js
CHANGED
|
@@ -2,24 +2,26 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
-
import { CallToolRequestSchema,
|
|
6
|
-
import { parseNote } from "../conventions/frontmatter.js";
|
|
7
|
-
import { validateFrontmatter } from "../conventions/validate.js";
|
|
8
|
-
import { lintVault } from "../engine/conventions/vault-lint.js";
|
|
9
|
-
import { safeVaultNotePath, writeNote, } from "../capture/safe.js";
|
|
10
|
-
import {
|
|
11
|
-
import { readBundledPackageVersion } from "../
|
|
12
|
-
import { resolveActiveOntology } from "../ontology/active.js";
|
|
13
|
-
import { resolveConcept } from "../
|
|
14
|
-
import { retrieveMorningContext } from "../
|
|
5
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
import { parseNote } from "../kernel/conventions/frontmatter.js";
|
|
7
|
+
import { validateFrontmatter } from "../kernel/conventions/validate.js";
|
|
8
|
+
import { lintVault } from "../kernel/engine/conventions/vault-lint.js";
|
|
9
|
+
import { safeVaultNotePath, writeNote, } from "../kernel/capture/safe.js";
|
|
10
|
+
import { graphCacheStatus, lazyLoadNoteBody, } from "../kernel/graph/cache.js";
|
|
11
|
+
import { readBundledPackageVersion } from "../kernel/runtime/assets.js";
|
|
12
|
+
import { resolveActiveOntology } from "../kernel/ontology/active.js";
|
|
13
|
+
import { resolveConcept } from "../kernel/ontology/resolver.js";
|
|
14
|
+
import { retrieveMorningContext } from "../kernel/search/morning.js";
|
|
15
|
+
import { repairDoctor } from "../kernel/doctor/service.js";
|
|
15
16
|
import { makeEngineMorningBackend } from "./engine-morning-backend.js";
|
|
16
|
-
import { handleSemanticTool, isEngineSemanticOp, isEngineDocumentOp, isModelOptionalSemanticQueryOp,
|
|
17
|
-
import { assembleCoreSemanticEngine, assembleGraphOnlyEngine } from "../engine/assemble.js";
|
|
18
|
-
import { assembleFullSemanticEngine, embeddingConfigPresent } from "
|
|
17
|
+
import { handleSemanticTool, isEngineSemanticOp, isEngineDocumentOp, isModelOptionalSemanticQueryOp, semanticOptionsFromArgs, } from "../kernel/semantic/semantic-retrieve.js";
|
|
18
|
+
import { assembleEphemeralCoreSemanticEngine, assembleCoreSemanticEngineReadOnly, assembleCoreSemanticEngine, assembleEngineReadOnly, assembleGraphOnlyEngine, } from "../kernel/engine/assemble.js";
|
|
19
|
+
import { assembleFullSemanticEngine, embeddingConfigPresent, } from "../kernel/semantic/semantic-engine.js";
|
|
19
20
|
import { applyLinksForNote, linkApplyPayload, suggestLinksForNote } from "./link-tools.js";
|
|
21
|
+
import { EngineSearchBackend, requiresEmbeddings } from "../kernel/searchbackend/engine-search-backend.js";
|
|
20
22
|
import { buildServerInstructions, cachedUpdateNotice, scheduleUpdateNoticeRefresh, } from "./update-notice.js";
|
|
21
23
|
const SERVER_VERSION = readBundledPackageVersion();
|
|
22
|
-
export const BASE_SERVER_INSTRUCTIONS = "Oh My Second Brain exposes
|
|
24
|
+
export const BASE_SERVER_INSTRUCTIONS = "Oh My Second Brain exposes write, search, link, status, and doctor tools. oms_write and doctor repair operations are gated by a verified vault target (a vault inferred from the current directory is refused); oms_write also enforces vault confinement and contract validation.";
|
|
23
25
|
function jsonText(value) {
|
|
24
26
|
return {
|
|
25
27
|
content: [
|
|
@@ -41,6 +43,11 @@ function errorText(message) {
|
|
|
41
43
|
],
|
|
42
44
|
};
|
|
43
45
|
}
|
|
46
|
+
class SemanticIndexUnavailableError extends Error {
|
|
47
|
+
constructor() {
|
|
48
|
+
super("The semantic index has not been built yet. Run `oms semantic sync` to build it.");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
44
51
|
function isRecord(value) {
|
|
45
52
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
46
53
|
}
|
|
@@ -66,246 +73,59 @@ function conceptSummary(concept) {
|
|
|
66
73
|
})),
|
|
67
74
|
};
|
|
68
75
|
}
|
|
76
|
+
const string = { type: "string" };
|
|
77
|
+
const number = { type: "number" };
|
|
78
|
+
const boolean = { type: "boolean" };
|
|
79
|
+
const stringArray = { type: "array", items: string };
|
|
80
|
+
const searchProperties = {
|
|
81
|
+
query: string, searches: { type: "array", maxItems: 10, items: { type: "object", properties: { type: { ...string, enum: ["lex", "vec", "hyde"] }, query: string }, required: ["type", "query"] } },
|
|
82
|
+
collection: string, collections: stringArray, mode: { ...string, enum: ["query", "search", "vsearch"] }, limit: { ...number, default: 10 }, candidateLimit: number, rerank: { ...boolean, default: false }, minScore: { ...number, default: 0 }, intent: string, lex: string, vec: string, hyde: string, index: string,
|
|
83
|
+
target: string, targets: stringArray, fromLine: number, lineCount: number, lineLimit: number, maxBytes: number, lineNumbers: boolean, fullPath: boolean,
|
|
84
|
+
};
|
|
85
|
+
const contextProperties = { concept: string, folder: string, property: string, value: string, wikilink: string, query: string, limit: number, maxNeighbors: number, useCache: boolean,
|
|
86
|
+
semanticEnabled: boolean, semanticCollection: string, semanticLimit: number, semanticScope: { ...string, enum: ["global", "graph"] }, semanticMode: searchProperties.mode, semanticIntent: string, semanticSearches: searchProperties.searches, semanticLex: string, semanticVec: string, semanticHyde: string, semanticMinScore: number, semanticAll: boolean, semanticFormat: { ...string, enum: ["json", "files"] }, semanticFull: boolean, semanticLineNumbers: boolean, semanticFullPath: boolean, semanticIndex: string, semanticChunkStrategy: string, semanticCandidateLimit: number, semanticNoRerank: boolean, semanticHydrate: { ...string, enum: ["none", "top", "all", "targets"] }, semanticHydrateTargets: stringArray, semanticHydrateLineLimit: number, semanticHydrateMaxBytes: number, semanticHydrateFromLine: number, semanticHydrateLineCount: number };
|
|
87
|
+
// `folder` + `filename` is a supported addressing form that writeNote still
|
|
88
|
+
// accepts. With `additionalProperties: false` a strict schema is only as
|
|
89
|
+
// complete as its property list, so omitting them silently removed a real
|
|
90
|
+
// capability from every schema-driven client while raw SDK calls kept working.
|
|
91
|
+
const writeProperties = {
|
|
92
|
+
notePath: string,
|
|
93
|
+
folder: string,
|
|
94
|
+
filename: string,
|
|
95
|
+
concept: string,
|
|
96
|
+
frontmatter: { type: "object" },
|
|
97
|
+
body: string,
|
|
98
|
+
};
|
|
99
|
+
const operations = {
|
|
100
|
+
oms_write: [
|
|
101
|
+
{ op: "create", name: "write", properties: writeProperties },
|
|
102
|
+
{ op: "append", name: "write", properties: writeProperties },
|
|
103
|
+
{ op: "update", name: "write", properties: writeProperties },
|
|
104
|
+
],
|
|
105
|
+
oms_search: [{ op: "axis", name: "oms_retrieve_by_axis", properties: contextProperties }, { op: "context", name: "oms_retrieve_context", properties: contextProperties }, { op: "lazy-load", name: "oms_lazy_load_note", properties: { notePath: string }, required: ["notePath"] }, { op: "concepts", name: "oms_list_concepts" }, { op: "semantic-query", name: "oms_semantic_query", properties: searchProperties }, { op: "semantic-collections", name: "oms_semantic_collections", properties: { index: string } }, { op: "semantic-contexts", name: "oms_semantic_contexts", properties: { index: string } }, { op: "semantic-status", name: "oms_semantic_status", properties: { index: string } }, { op: "get-document", name: "oms_get_document", properties: searchProperties, required: ["target"] }, { op: "multi-get-documents", name: "oms_multi_get_documents", properties: searchProperties }],
|
|
106
|
+
oms_link: [{ op: "suggest", name: "oms_link_suggest", properties: { notePath: string, folder: string }, required: ["notePath"] }, { op: "apply", name: "oms_link_apply", properties: { notePath: string, folder: string, baseContentHash: string, candidateIds: stringArray }, required: ["notePath", "baseContentHash", "candidateIds"] }],
|
|
107
|
+
oms_status: [{ name: "oms_graph_status", direct: true }],
|
|
108
|
+
oms_doctor: [{ op: "audit", name: "oms_vault_audit", properties: { folder: string } }, { op: "validate", name: "oms_validate_contract", properties: { notePath: string }, required: ["notePath"] }, { op: "build-graph", name: "oms_graph_build" }, { op: "semantic-cleanup", name: "oms_semantic_cleanup", properties: { collection: string, index: string } }, { op: "sync-embeddings", name: "oms_sync_embeddings", properties: { collection: string, ensureCollection: boolean, update: boolean, embed: boolean, force: boolean, pull: boolean, index: string, chunkStrategy: string, maxDocsPerBatch: number, maxBatchMb: number } }],
|
|
109
|
+
};
|
|
110
|
+
function operationSchema(tool) {
|
|
111
|
+
const toolOperations = operations[tool];
|
|
112
|
+
if (!toolOperations)
|
|
113
|
+
throw new Error(`Missing MCP operation definition for ${tool}.`);
|
|
114
|
+
if (toolOperations.length === 1 && toolOperations[0]?.direct) {
|
|
115
|
+
const { properties = {}, required = [] } = toolOperations[0];
|
|
116
|
+
return { type: "object", additionalProperties: false, properties, required: [...required] };
|
|
117
|
+
}
|
|
118
|
+
return { type: "object", oneOf: toolOperations.map(({ op, properties = {}, required = [] }) => ({ additionalProperties: false, properties: { op: { ...string, const: op }, ...properties }, required: ["op", ...required] })) };
|
|
119
|
+
}
|
|
120
|
+
function resolveOperation(tool, op) {
|
|
121
|
+
return operations[tool]?.find((operation) => operation.direct || operation.op === op)?.name;
|
|
122
|
+
}
|
|
69
123
|
export const omsMcpTools = [
|
|
70
|
-
{
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
type: "object",
|
|
76
|
-
properties: {},
|
|
77
|
-
},
|
|
78
|
-
annotations: {
|
|
79
|
-
readOnlyHint: true,
|
|
80
|
-
destructiveHint: false,
|
|
81
|
-
idempotentHint: true,
|
|
82
|
-
openWorldHint: false,
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
name: "oms_graph_build",
|
|
87
|
-
title: "Oh My Second Brain graph build",
|
|
88
|
-
description: "Build the derived graph/search cache from markdown, frontmatter, folders, and wikilinks.",
|
|
89
|
-
inputSchema: {
|
|
90
|
-
type: "object",
|
|
91
|
-
properties: {},
|
|
92
|
-
},
|
|
93
|
-
annotations: {
|
|
94
|
-
readOnlyHint: false,
|
|
95
|
-
destructiveHint: false,
|
|
96
|
-
idempotentHint: true,
|
|
97
|
-
openWorldHint: false,
|
|
98
|
-
},
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
name: "oms_list_concepts",
|
|
102
|
-
title: "Oh My Second Brain list concepts",
|
|
103
|
-
description: "Read the active ontology concepts, frontmatter axes, folder bindings, and retrieval views.",
|
|
104
|
-
inputSchema: {
|
|
105
|
-
type: "object",
|
|
106
|
-
properties: {},
|
|
107
|
-
},
|
|
108
|
-
annotations: {
|
|
109
|
-
readOnlyHint: true,
|
|
110
|
-
destructiveHint: false,
|
|
111
|
-
idempotentHint: true,
|
|
112
|
-
openWorldHint: false,
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
name: "oms_retrieve_by_axis",
|
|
117
|
-
title: "Oh My Second Brain retrieve by axis",
|
|
118
|
-
description: "Axis-first retrieval over the derived cache; optional lexical query only ranks inside the narrowed candidate set.",
|
|
119
|
-
inputSchema: {
|
|
120
|
-
type: "object",
|
|
121
|
-
properties: {
|
|
122
|
-
concept: { type: "string" },
|
|
123
|
-
folder: { type: "string" },
|
|
124
|
-
property: { type: "string" },
|
|
125
|
-
value: { type: "string" },
|
|
126
|
-
wikilink: { type: "string" },
|
|
127
|
-
query: { type: "string" },
|
|
128
|
-
limit: { type: "number" },
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
annotations: {
|
|
132
|
-
readOnlyHint: true,
|
|
133
|
-
destructiveHint: false,
|
|
134
|
-
idempotentHint: true,
|
|
135
|
-
openWorldHint: false,
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
name: "oms_retrieve_context",
|
|
140
|
-
title: "Oh My Second Brain retrieve context",
|
|
141
|
-
description: "Live local graph retrieval with axis seeds, frontmatter/wikilink neighbors, optional OMS semantic candidates, and no warm-cache requirement.",
|
|
142
|
-
inputSchema: {
|
|
143
|
-
type: "object",
|
|
144
|
-
properties: {
|
|
145
|
-
concept: { type: "string" },
|
|
146
|
-
folder: { type: "string" },
|
|
147
|
-
property: { type: "string" },
|
|
148
|
-
value: { type: "string" },
|
|
149
|
-
wikilink: { type: "string" },
|
|
150
|
-
query: { type: "string" },
|
|
151
|
-
limit: { type: "number" },
|
|
152
|
-
maxNeighbors: { type: "number" },
|
|
153
|
-
useCache: { type: "boolean" },
|
|
154
|
-
...retrieveContextSemanticInputProperties,
|
|
155
|
-
},
|
|
156
|
-
},
|
|
157
|
-
annotations: {
|
|
158
|
-
readOnlyHint: false,
|
|
159
|
-
destructiveHint: false,
|
|
160
|
-
idempotentHint: true,
|
|
161
|
-
openWorldHint: false,
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
...semanticMcpTools,
|
|
165
|
-
{
|
|
166
|
-
name: "oms_lazy_load_note",
|
|
167
|
-
title: "Oh My Second Brain lazy-load note body",
|
|
168
|
-
description: "Load a selected note body only after axis/search narrowing has selected the note.",
|
|
169
|
-
inputSchema: {
|
|
170
|
-
type: "object",
|
|
171
|
-
properties: {
|
|
172
|
-
notePath: {
|
|
173
|
-
type: "string",
|
|
174
|
-
description: "Vault-relative markdown note path.",
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
required: ["notePath"],
|
|
178
|
-
},
|
|
179
|
-
annotations: {
|
|
180
|
-
readOnlyHint: true,
|
|
181
|
-
destructiveHint: false,
|
|
182
|
-
idempotentHint: true,
|
|
183
|
-
openWorldHint: false,
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
name: "oms_validate_contract",
|
|
188
|
-
title: "Oh My Second Brain validate contract",
|
|
189
|
-
description: "Read one vault note and validate its frontmatter against the active folder/concept contract.",
|
|
190
|
-
inputSchema: {
|
|
191
|
-
type: "object",
|
|
192
|
-
properties: {
|
|
193
|
-
notePath: {
|
|
194
|
-
type: "string",
|
|
195
|
-
description: "Vault-relative markdown note path, for example references/book.md.",
|
|
196
|
-
},
|
|
197
|
-
},
|
|
198
|
-
required: ["notePath"],
|
|
199
|
-
},
|
|
200
|
-
annotations: {
|
|
201
|
-
readOnlyHint: true,
|
|
202
|
-
destructiveHint: false,
|
|
203
|
-
idempotentHint: true,
|
|
204
|
-
openWorldHint: false,
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
name: "oms_vault_audit",
|
|
209
|
-
title: "Oh My Second Brain vault audit",
|
|
210
|
-
description: "Scan vault notes against the active ontology and return a structured violation report. Read-only; the CLI counterpart is `oms audit`.",
|
|
211
|
-
inputSchema: {
|
|
212
|
-
type: "object",
|
|
213
|
-
properties: {
|
|
214
|
-
folder: {
|
|
215
|
-
type: "string",
|
|
216
|
-
description: "Restrict the scan to one top-level vault folder, for example \"references\".",
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
},
|
|
220
|
-
annotations: {
|
|
221
|
-
readOnlyHint: true,
|
|
222
|
-
destructiveHint: false,
|
|
223
|
-
idempotentHint: true,
|
|
224
|
-
openWorldHint: false,
|
|
225
|
-
},
|
|
226
|
-
},
|
|
227
|
-
{
|
|
228
|
-
name: "oms_link_suggest",
|
|
229
|
-
title: "Oh My Second Brain link suggest",
|
|
230
|
-
description: "Propose [[wikilink]] insertions for one note against the vault's term notes. Read-only: returns ranked candidates plus the baseContentHash oms_link_apply requires.",
|
|
231
|
-
inputSchema: {
|
|
232
|
-
type: "object",
|
|
233
|
-
properties: {
|
|
234
|
-
notePath: {
|
|
235
|
-
type: "string",
|
|
236
|
-
description: "Vault-relative markdown note path to linkify, for example notes/sage.md.",
|
|
237
|
-
},
|
|
238
|
-
folder: {
|
|
239
|
-
type: "string",
|
|
240
|
-
description: "Restrict the term-note candidate universe to one top-level vault folder.",
|
|
241
|
-
},
|
|
242
|
-
},
|
|
243
|
-
required: ["notePath"],
|
|
244
|
-
},
|
|
245
|
-
annotations: {
|
|
246
|
-
readOnlyHint: true,
|
|
247
|
-
destructiveHint: false,
|
|
248
|
-
idempotentHint: true,
|
|
249
|
-
openWorldHint: false,
|
|
250
|
-
},
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
name: "oms_link_apply",
|
|
254
|
-
title: "Oh My Second Brain link apply",
|
|
255
|
-
description: "Splice accepted oms_link_suggest candidates into a note and persist through the write kernel. Refuses without writing when baseContentHash no longer matches the note.",
|
|
256
|
-
inputSchema: {
|
|
257
|
-
type: "object",
|
|
258
|
-
properties: {
|
|
259
|
-
notePath: {
|
|
260
|
-
type: "string",
|
|
261
|
-
description: "Vault-relative markdown note path returned by oms_link_suggest.",
|
|
262
|
-
},
|
|
263
|
-
baseContentHash: {
|
|
264
|
-
type: "string",
|
|
265
|
-
description: "The baseContentHash from the oms_link_suggest call the candidates came from.",
|
|
266
|
-
},
|
|
267
|
-
candidateIds: {
|
|
268
|
-
type: "array",
|
|
269
|
-
items: { type: "string" },
|
|
270
|
-
description: "Ids of the accepted candidates from that same oms_link_suggest call.",
|
|
271
|
-
},
|
|
272
|
-
folder: {
|
|
273
|
-
type: "string",
|
|
274
|
-
description: "Same candidate-universe folder scope used for the suggest call.",
|
|
275
|
-
},
|
|
276
|
-
},
|
|
277
|
-
required: ["notePath", "baseContentHash", "candidateIds"],
|
|
278
|
-
},
|
|
279
|
-
annotations: {
|
|
280
|
-
readOnlyHint: false,
|
|
281
|
-
destructiveHint: true,
|
|
282
|
-
idempotentHint: false,
|
|
283
|
-
openWorldHint: false,
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
name: "write",
|
|
288
|
-
title: "Oh My Second Brain write",
|
|
289
|
-
description: "Write a vault note through the kernel-owned .oms contract. Modes: create, append, update. Returns ask, inbox, written, or rejected.",
|
|
290
|
-
inputSchema: {
|
|
291
|
-
type: "object",
|
|
292
|
-
properties: {
|
|
293
|
-
mode: { type: "string", enum: ["create", "append", "update"] },
|
|
294
|
-
notePath: { type: "string" },
|
|
295
|
-
concept: { type: "string" },
|
|
296
|
-
folder: { type: "string" },
|
|
297
|
-
filename: { type: "string" },
|
|
298
|
-
frontmatter: { type: "object" },
|
|
299
|
-
body: { type: "string" },
|
|
300
|
-
},
|
|
301
|
-
},
|
|
302
|
-
annotations: {
|
|
303
|
-
readOnlyHint: false,
|
|
304
|
-
destructiveHint: false,
|
|
305
|
-
idempotentHint: false,
|
|
306
|
-
openWorldHint: false,
|
|
307
|
-
},
|
|
308
|
-
},
|
|
124
|
+
{ name: "oms_write", title: "Oh My Second Brain write", description: "Write a vault note through the kernel-owned .oms contract.", inputSchema: operationSchema("oms_write"), annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false } },
|
|
125
|
+
{ name: "oms_search", title: "Oh My Second Brain search", description: "Retrieve vault context, semantic search, ontology, and selected documents. `op` selects the operation.", inputSchema: operationSchema("oms_search"), annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: false } },
|
|
126
|
+
{ name: "oms_link", title: "Oh My Second Brain link", description: "Suggest or apply wikilinks; `op` selects the operation.", inputSchema: operationSchema("oms_link"), annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false } },
|
|
127
|
+
{ name: "oms_status", title: "Oh My Second Brain status", description: "Read-only health and statistics for the active vault.", inputSchema: operationSchema("oms_status"), annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false } },
|
|
128
|
+
{ name: "oms_doctor", title: "Oh My Second Brain doctor", description: "Diagnose or repair the vault; `op` selects the operation.", inputSchema: operationSchema("oms_doctor"), annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false } },
|
|
309
129
|
];
|
|
310
130
|
export function createOMSMcpServer(opts) {
|
|
311
131
|
const vault = path.resolve(opts.vault);
|
|
@@ -315,17 +135,12 @@ export function createOMSMcpServer(opts) {
|
|
|
315
135
|
// graph cache status scan the vault off the filesystem and need no model.
|
|
316
136
|
// No model load, no SQLite store, no watcher: side-effect-free per boot (R2).
|
|
317
137
|
const engine = assembleGraphOnlyEngine({ vault });
|
|
318
|
-
//
|
|
319
|
-
//
|
|
320
|
-
// engine SQLite store on construction and loads the embedding model on first
|
|
321
|
-
// embed(). Embedding selection is canonical and explicit: OMS_EMBEDDING_PROVIDER
|
|
322
|
-
// (e.g. gguf | upstage) + OMS_EMBEDDING_MODEL (path or model id). Absent either,
|
|
323
|
-
// assembleFullSemanticEngine throws a loud, actionable error (ADR-007: no
|
|
324
|
-
// hash/fake fallback, no auto-detect) that surfaces via the dispatch catch.
|
|
138
|
+
// Creating semantic engines are shared by all non-search tools, including
|
|
139
|
+
// doctor repairs which must initialize a missing store.
|
|
325
140
|
let semanticEngine = null;
|
|
326
141
|
const getSemanticEngine = () => {
|
|
327
142
|
if (semanticEngine === null) {
|
|
328
|
-
semanticEngine = assembleFullSemanticEngine(vault);
|
|
143
|
+
semanticEngine = assembleFullSemanticEngine(vault, opts.reranker);
|
|
329
144
|
}
|
|
330
145
|
return semanticEngine;
|
|
331
146
|
};
|
|
@@ -335,10 +150,47 @@ export function createOMSMcpServer(opts) {
|
|
|
335
150
|
let coreSemanticEngine = null;
|
|
336
151
|
const getCoreSemanticEngine = () => {
|
|
337
152
|
if (coreSemanticEngine === null) {
|
|
338
|
-
coreSemanticEngine = assembleCoreSemanticEngine({ vault });
|
|
153
|
+
coreSemanticEngine = assembleCoreSemanticEngine({ vault, reranker: opts.reranker });
|
|
339
154
|
}
|
|
340
155
|
return coreSemanticEngine;
|
|
341
156
|
};
|
|
157
|
+
// Search owns independent read-only slots so it cannot poison doctor repair.
|
|
158
|
+
let readOnlySemanticEngine;
|
|
159
|
+
const getReadOnlySemanticEngine = () => {
|
|
160
|
+
if (readOnlySemanticEngine === undefined) {
|
|
161
|
+
readOnlySemanticEngine = assembleEngineReadOnly({
|
|
162
|
+
vault,
|
|
163
|
+
embeddingProvider: process.env["OMS_EMBEDDING_PROVIDER"],
|
|
164
|
+
embeddingModel: process.env["OMS_EMBEDDING_MODEL"],
|
|
165
|
+
reranker: opts.reranker,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
return readOnlySemanticEngine;
|
|
169
|
+
};
|
|
170
|
+
let readOnlyCoreSemanticEngine;
|
|
171
|
+
const getReadOnlyCoreSemanticEngine = () => {
|
|
172
|
+
if (readOnlyCoreSemanticEngine === undefined) {
|
|
173
|
+
readOnlyCoreSemanticEngine = assembleCoreSemanticEngineReadOnly({ vault, reranker: opts.reranker });
|
|
174
|
+
}
|
|
175
|
+
return readOnlyCoreSemanticEngine;
|
|
176
|
+
};
|
|
177
|
+
let ephemeralCoreSemanticEngine = null;
|
|
178
|
+
let ephemeralCoreSemanticEnginePromise = null;
|
|
179
|
+
const getEphemeralCoreSemanticEngine = async () => {
|
|
180
|
+
if (ephemeralCoreSemanticEngine !== null)
|
|
181
|
+
return ephemeralCoreSemanticEngine;
|
|
182
|
+
if (ephemeralCoreSemanticEnginePromise === null) {
|
|
183
|
+
ephemeralCoreSemanticEnginePromise = (async () => {
|
|
184
|
+
const assembled = assembleEphemeralCoreSemanticEngine({ vault, reranker: opts.reranker });
|
|
185
|
+
ephemeralCoreSemanticEngine = assembled;
|
|
186
|
+
return assembled;
|
|
187
|
+
})().catch((error) => {
|
|
188
|
+
ephemeralCoreSemanticEnginePromise = null;
|
|
189
|
+
throw error;
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return ephemeralCoreSemanticEnginePromise;
|
|
193
|
+
};
|
|
342
194
|
// A real embedding provider is configured iff the canonical pair is set
|
|
343
195
|
// (ADR-007). The engine's model-OPTIONAL surface (document reads,
|
|
344
196
|
// retrieve_context's semantic leg, ReadResource) keys off this to decide
|
|
@@ -355,7 +207,51 @@ export function createOMSMcpServer(opts) {
|
|
|
355
207
|
// missing auth, store-open failure) must surface its error loudly rather than
|
|
356
208
|
// silently masquerade as a model-less host (ADR-007). The core fallback is
|
|
357
209
|
// strictly for the absent-config case.
|
|
358
|
-
const
|
|
210
|
+
const resolveCreatingDocumentAdapter = () => hasEmbeddingModel() ? getSemanticEngine().adapter : getCoreSemanticEngine().adapter;
|
|
211
|
+
const resolveReadOnlyDocumentAdapter = () => hasEmbeddingModel()
|
|
212
|
+
? getReadOnlySemanticEngine()?.adapter ?? engine.adapter
|
|
213
|
+
: getReadOnlyCoreSemanticEngine()?.adapter ?? engine.adapter;
|
|
214
|
+
const resolveDocumentAdapter = (publicName) => {
|
|
215
|
+
if (publicName === "oms_search")
|
|
216
|
+
return resolveReadOnlyDocumentAdapter();
|
|
217
|
+
return resolveCreatingDocumentAdapter();
|
|
218
|
+
};
|
|
219
|
+
const resolveReadOnlyIndexAdapter = () => {
|
|
220
|
+
const adapter = hasEmbeddingModel()
|
|
221
|
+
? getReadOnlySemanticEngine()?.adapter
|
|
222
|
+
: getReadOnlyCoreSemanticEngine()?.adapter;
|
|
223
|
+
if (adapter === undefined || adapter === null)
|
|
224
|
+
throw new SemanticIndexUnavailableError();
|
|
225
|
+
return adapter;
|
|
226
|
+
};
|
|
227
|
+
const resolveReadOnlyLexicalAdapter = async () => {
|
|
228
|
+
const adapter = hasEmbeddingModel()
|
|
229
|
+
? getReadOnlySemanticEngine()?.adapter
|
|
230
|
+
: getReadOnlyCoreSemanticEngine()?.adapter;
|
|
231
|
+
return adapter ?? (await getEphemeralCoreSemanticEngine()).adapter;
|
|
232
|
+
};
|
|
233
|
+
const hasExplicitEmbeddingIntent = (args) => requiresEmbeddings({
|
|
234
|
+
mode: args?.["mode"] === "vsearch" ? "vsearch" : undefined,
|
|
235
|
+
vec: stringArg(args, "vec"),
|
|
236
|
+
hyde: stringArg(args, "hyde"),
|
|
237
|
+
searches: Array.isArray(args?.["searches"])
|
|
238
|
+
? args["searches"].flatMap((search) => isRecord(search) &&
|
|
239
|
+
(search["type"] === "lex" || search["type"] === "vec" || search["type"] === "hyde") &&
|
|
240
|
+
typeof search["query"] === "string"
|
|
241
|
+
? [{ type: search["type"], query: search["query"] }]
|
|
242
|
+
: [])
|
|
243
|
+
: undefined,
|
|
244
|
+
});
|
|
245
|
+
const searchBackend = new EngineSearchBackend((requiresEmbeddings) => requiresEmbeddings
|
|
246
|
+
? (() => {
|
|
247
|
+
// Validate ADR-007 configuration before probing the read-only store:
|
|
248
|
+
// vector intent is actionable only after its required provider/model
|
|
249
|
+
// pair is present, regardless of whether an index exists yet.
|
|
250
|
+
if (!hasEmbeddingModel())
|
|
251
|
+
return getSemanticEngine().adapter;
|
|
252
|
+
return resolveReadOnlyIndexAdapter();
|
|
253
|
+
})()
|
|
254
|
+
: resolveReadOnlyIndexAdapter(), vault);
|
|
359
255
|
const server = new Server({ name: "oms", version: SERVER_VERSION }, {
|
|
360
256
|
capabilities: { tools: {}, resources: {} },
|
|
361
257
|
// Cache read only: construction must never touch the network. The
|
|
@@ -370,43 +266,35 @@ export function createOMSMcpServer(opts) {
|
|
|
370
266
|
if (coreSemanticEngine !== null) {
|
|
371
267
|
void coreSemanticEngine.dispose().catch(() => undefined);
|
|
372
268
|
}
|
|
269
|
+
if (readOnlySemanticEngine !== null && readOnlySemanticEngine !== undefined) {
|
|
270
|
+
void readOnlySemanticEngine.dispose().catch(() => undefined);
|
|
271
|
+
}
|
|
272
|
+
if (readOnlyCoreSemanticEngine !== null && readOnlyCoreSemanticEngine !== undefined) {
|
|
273
|
+
void readOnlyCoreSemanticEngine.dispose().catch(() => undefined);
|
|
274
|
+
}
|
|
275
|
+
if (ephemeralCoreSemanticEngine !== null) {
|
|
276
|
+
void ephemeralCoreSemanticEngine.dispose().catch(() => undefined);
|
|
277
|
+
}
|
|
373
278
|
};
|
|
374
279
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
375
280
|
tools: omsMcpTools,
|
|
376
281
|
}));
|
|
377
|
-
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({
|
|
378
|
-
resourceTemplates: [
|
|
379
|
-
{
|
|
380
|
-
uriTemplate: "qmd://{path}",
|
|
381
|
-
name: "QMD-compatible OMS semantic document",
|
|
382
|
-
description: "Read a native OMS semantic-index document by qmd:// vault-relative path.",
|
|
383
|
-
mimeType: "text/markdown",
|
|
384
|
-
},
|
|
385
|
-
],
|
|
386
|
-
}));
|
|
387
|
-
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
388
|
-
const uri = request.params.uri;
|
|
389
|
-
// Resource reads hydrate on the SAME backend the semantic ops use: the engine
|
|
390
|
-
// (file-based, qmd:// / oms:// scheme aware), vec-capable when a model is
|
|
391
|
-
// configured and core (lex + file reads) otherwise — so a retrieve_context
|
|
392
|
-
// docid resolves through the URI surface regardless of which backend produced it.
|
|
393
|
-
const result = await resolveDocumentAdapter().getDocument({ vault, target: uri });
|
|
394
|
-
if (!result.available || !result.documents[0]) {
|
|
395
|
-
throw new Error(!result.available && result.reason ? result.reason : "OMS semantic resource not found.");
|
|
396
|
-
}
|
|
397
|
-
return {
|
|
398
|
-
contents: [
|
|
399
|
-
{
|
|
400
|
-
uri,
|
|
401
|
-
mimeType: "text/markdown",
|
|
402
|
-
text: result.documents[0].content,
|
|
403
|
-
},
|
|
404
|
-
],
|
|
405
|
-
};
|
|
406
|
-
});
|
|
407
282
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
408
|
-
|
|
409
|
-
|
|
283
|
+
let args = isRecord(request.params.arguments) ? request.params.arguments : undefined;
|
|
284
|
+
const publicName = request.params.name;
|
|
285
|
+
const op = publicName === "oms_write" ? stringArg(args, "op") ?? "create" : stringArg(args, "op");
|
|
286
|
+
const name = resolveOperation(publicName, op);
|
|
287
|
+
if (!name)
|
|
288
|
+
return errorText(`Unknown Oh My Second Brain tool: ${publicName}`);
|
|
289
|
+
if (publicName === "oms_write")
|
|
290
|
+
args = { ...args, mode: op };
|
|
291
|
+
if (publicName === "oms_search" && op === "semantic-query") {
|
|
292
|
+
const searches = args?.["searches"];
|
|
293
|
+
if (typeof args?.["query"] === "string" && Array.isArray(searches)) {
|
|
294
|
+
return errorText('Provide exactly one of "query" or "searches" for semantic-query.');
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (name === "oms_graph_status") {
|
|
410
298
|
// The src/graph derived-cache ledger (M3 5-state staleness) is the source
|
|
411
299
|
// of truth for retrieve_context's optional warm cache and stays intact.
|
|
412
300
|
// engineGraph is additive: it surfaces the native engine's axis cache that
|
|
@@ -429,8 +317,8 @@ export function createOMSMcpServer(opts) {
|
|
|
429
317
|
derivedState: cacheStatus,
|
|
430
318
|
engineGraph,
|
|
431
319
|
writeTools: source === "cwd"
|
|
432
|
-
? "
|
|
433
|
-
: "
|
|
320
|
+
? "oms_write-disabled-target-unverified"
|
|
321
|
+
: "oms_write-gated-by-verified-target-and-contract",
|
|
434
322
|
readTools: omsMcpTools.map((tool) => tool.name),
|
|
435
323
|
});
|
|
436
324
|
}
|
|
@@ -453,27 +341,41 @@ export function createOMSMcpServer(opts) {
|
|
|
453
341
|
},
|
|
454
342
|
},
|
|
455
343
|
engineGraph,
|
|
456
|
-
writeTools: "disabled-invalid-ontology",
|
|
344
|
+
writeTools: "oms_write-disabled-invalid-ontology",
|
|
457
345
|
readTools: ["oms_graph_status"],
|
|
458
346
|
});
|
|
459
347
|
}
|
|
460
348
|
}
|
|
461
349
|
try {
|
|
462
|
-
if (
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
350
|
+
if (name === "oms_graph_build" || name === "oms_semantic_cleanup" || name === "oms_sync_embeddings") {
|
|
351
|
+
const operation = name === "oms_graph_build" ? "build-graph" : name === "oms_semantic_cleanup" ? "semantic-cleanup" : "sync-embeddings";
|
|
352
|
+
// A FACTORY, not a value. JavaScript evaluates an argument expression
|
|
353
|
+
// before entering the callee, so passing a constructed adapter here would
|
|
354
|
+
// open - and therefore create - `<vault>/.oms/engine-store.sqlite` before
|
|
355
|
+
// repairDoctor got the chance to run admission. On an invalid global
|
|
356
|
+
// target that means mutating a directory we are about to reject, which
|
|
357
|
+
// breaks the verified-target contract's requirement that admission
|
|
358
|
+
// precede ANY disk mutation. The kernel calls this only after admitting.
|
|
359
|
+
//
|
|
360
|
+
// Deliberately NOT re-checking admission here: two policy paths is how
|
|
361
|
+
// the check drifts. One authoritative decision, deferred dependency.
|
|
362
|
+
const resolveRepairAdapter = operation === "build-graph"
|
|
363
|
+
? undefined
|
|
364
|
+
: () => publicName === "oms_search"
|
|
365
|
+
? resolveReadOnlyDocumentAdapter()
|
|
366
|
+
: operation === "semantic-cleanup" || (operation === "sync-embeddings" && args?.["embed"] === false)
|
|
367
|
+
? resolveCreatingDocumentAdapter()
|
|
368
|
+
: getSemanticEngine().adapter;
|
|
369
|
+
const repair = await repairDoctor({
|
|
370
|
+
operation,
|
|
466
371
|
vault,
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
notes: cache.notes.length,
|
|
471
|
-
edges: cache.edges.length,
|
|
472
|
-
searchDocuments: cache.search.length,
|
|
473
|
-
sourceOfTruth: cache.sourceOfTruth,
|
|
372
|
+
source,
|
|
373
|
+
args,
|
|
374
|
+
resolveAdapter: resolveRepairAdapter,
|
|
474
375
|
});
|
|
376
|
+
return repair.kind === "error" ? errorText(repair.message) : jsonText(repair.value);
|
|
475
377
|
}
|
|
476
|
-
if (
|
|
378
|
+
if (name === "oms_list_concepts") {
|
|
477
379
|
const { ontology, source } = await resolveActiveOntology(vault);
|
|
478
380
|
return jsonText({
|
|
479
381
|
vault,
|
|
@@ -482,7 +384,7 @@ export function createOMSMcpServer(opts) {
|
|
|
482
384
|
concepts: Array.from(ontology.concepts.values()).map(conceptSummary),
|
|
483
385
|
});
|
|
484
386
|
}
|
|
485
|
-
if (
|
|
387
|
+
if (name === "oms_retrieve_by_axis") {
|
|
486
388
|
// Engine-owned (graph-only swap): axis-first retrieval over the native
|
|
487
389
|
// node index, built lazily off the filesystem — no embedding model needed.
|
|
488
390
|
const limitValue = args?.["limit"];
|
|
@@ -504,13 +406,24 @@ export function createOMSMcpServer(opts) {
|
|
|
504
406
|
...result,
|
|
505
407
|
});
|
|
506
408
|
}
|
|
507
|
-
if (
|
|
409
|
+
if (name === "oms_retrieve_context") {
|
|
508
410
|
// Graph + semantic fusion. The graph leg stays on the src/graph warm cache;
|
|
509
411
|
// the semantic leg routes to the native engine: vec-capable when a model is
|
|
510
412
|
// configured (parity ranking, real-path docids) and core (lex; vec/HyDE fail
|
|
511
413
|
// fast) otherwise. get/multi_get and ReadResource make the SAME choice, so a
|
|
512
414
|
// docid emitted here always hydrates on the backend that produced it.
|
|
513
|
-
const
|
|
415
|
+
const semantic = semanticOptionsFromArgs(args);
|
|
416
|
+
let contextAdapter = engine.adapter;
|
|
417
|
+
if (semantic?.enabled !== false) {
|
|
418
|
+
try {
|
|
419
|
+
contextAdapter = resolveDocumentAdapter(publicName);
|
|
420
|
+
}
|
|
421
|
+
catch (error) {
|
|
422
|
+
if (!(error instanceof SemanticIndexUnavailableError))
|
|
423
|
+
throw error;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
const semanticBackend = makeEngineMorningBackend(contextAdapter, vault);
|
|
514
427
|
const { ontology, source } = await resolveActiveOntology(vault);
|
|
515
428
|
const limitValue = args?.["limit"];
|
|
516
429
|
const maxNeighborsValue = args?.["maxNeighbors"];
|
|
@@ -527,7 +440,7 @@ export function createOMSMcpServer(opts) {
|
|
|
527
440
|
limit: typeof limitValue === "number" ? limitValue : undefined,
|
|
528
441
|
maxNeighbors: typeof maxNeighborsValue === "number" ? maxNeighborsValue : undefined,
|
|
529
442
|
useCache: typeof useCacheValue === "boolean" ? useCacheValue : undefined,
|
|
530
|
-
semantic
|
|
443
|
+
semantic,
|
|
531
444
|
}, semanticBackend);
|
|
532
445
|
return jsonText({
|
|
533
446
|
vault,
|
|
@@ -543,23 +456,93 @@ export function createOMSMcpServer(opts) {
|
|
|
543
456
|
// engine when a model is configured, else the core engine. Lex is a real
|
|
544
457
|
// model-free BM25/FTS feature, not an ADR-007 fake vector fallback.
|
|
545
458
|
// Every other tool never touches the engine here.
|
|
546
|
-
if (isEngineSemanticOp(
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
459
|
+
if (isEngineSemanticOp(name) || isEngineDocumentOp(name)) {
|
|
460
|
+
if (name === "oms_semantic_query") {
|
|
461
|
+
const query = stringArg(args, "query");
|
|
462
|
+
const vec = stringArg(args, "vec");
|
|
463
|
+
const hyde = stringArg(args, "hyde");
|
|
464
|
+
const noPersistentReadOnlyIndex = hasEmbeddingModel()
|
|
465
|
+
? getReadOnlySemanticEngine() === null
|
|
466
|
+
: getReadOnlyCoreSemanticEngine() === null;
|
|
467
|
+
if (query !== undefined && !hasExplicitEmbeddingIntent(args) && noPersistentReadOnlyIndex) {
|
|
468
|
+
const result = await (await getEphemeralCoreSemanticEngine()).adapter.semanticQuery({
|
|
469
|
+
vault,
|
|
470
|
+
query,
|
|
471
|
+
lex: stringArg(args, "lex") ?? query,
|
|
472
|
+
limit: typeof args?.["limit"] === "number" ? args["limit"] : undefined,
|
|
473
|
+
minScore: typeof args?.["minScore"] === "number" ? args["minScore"] : undefined,
|
|
474
|
+
intent: stringArg(args, "intent"),
|
|
475
|
+
collection: stringArg(args, "collection"),
|
|
476
|
+
index: stringArg(args, "index"),
|
|
477
|
+
});
|
|
478
|
+
return jsonText(result);
|
|
479
|
+
}
|
|
480
|
+
const requestOptions = {
|
|
481
|
+
limit: typeof args?.["limit"] === "number" ? args["limit"] : undefined,
|
|
482
|
+
candidateLimit: typeof args?.["candidateLimit"] === "number" ? args["candidateLimit"] : undefined,
|
|
483
|
+
rerank: typeof args?.["rerank"] === "boolean" ? args["rerank"] : undefined,
|
|
484
|
+
minScore: typeof args?.["minScore"] === "number" ? args["minScore"] : undefined,
|
|
485
|
+
intent: stringArg(args, "intent"),
|
|
486
|
+
collection: stringArg(args, "collection"),
|
|
487
|
+
collections: Array.isArray(args?.["collections"])
|
|
488
|
+
? args["collections"].filter((collection) => typeof collection === "string")
|
|
489
|
+
: undefined,
|
|
490
|
+
mode: stringArg(args, "mode"),
|
|
491
|
+
lex: stringArg(args, "lex"),
|
|
492
|
+
vec,
|
|
493
|
+
hyde,
|
|
494
|
+
index: stringArg(args, "index"),
|
|
495
|
+
};
|
|
496
|
+
const result = await searchBackend.search({
|
|
497
|
+
...requestOptions,
|
|
498
|
+
// `query` is the default lexical representation. An explicit vector
|
|
499
|
+
// or HyDE shorthand selects its own representation instead; only
|
|
500
|
+
// `query` plus typed `searches` is contradictory.
|
|
501
|
+
query: vec !== undefined || hyde !== undefined ? undefined : query,
|
|
502
|
+
searches: Array.isArray(args?.["searches"])
|
|
503
|
+
? args["searches"]
|
|
504
|
+
: undefined,
|
|
505
|
+
});
|
|
506
|
+
return jsonText(result);
|
|
507
|
+
}
|
|
508
|
+
const useEphemeralLexicalFallback = name === "oms_semantic_query" &&
|
|
509
|
+
publicName === "oms_search" &&
|
|
510
|
+
!hasExplicitEmbeddingIntent(args) &&
|
|
511
|
+
(hasEmbeddingModel()
|
|
512
|
+
? getReadOnlySemanticEngine() === null
|
|
513
|
+
: getReadOnlyCoreSemanticEngine() === null);
|
|
514
|
+
const semanticAdapter = useEphemeralLexicalFallback
|
|
515
|
+
? await resolveReadOnlyLexicalAdapter()
|
|
516
|
+
:
|
|
517
|
+
isEngineSemanticOp(name) &&
|
|
518
|
+
name !== "oms_semantic_cleanup" &&
|
|
519
|
+
!(name === "oms_sync_embeddings" && args?.["embed"] === false) &&
|
|
520
|
+
!isModelOptionalSemanticQueryOp(name, args, vault)
|
|
521
|
+
? publicName === "oms_search"
|
|
522
|
+
? resolveReadOnlyIndexAdapter()
|
|
523
|
+
: getSemanticEngine().adapter
|
|
524
|
+
: isEngineDocumentOp(name)
|
|
525
|
+
? resolveDocumentAdapter(publicName)
|
|
526
|
+
: publicName === "oms_search"
|
|
527
|
+
? resolveReadOnlyIndexAdapter()
|
|
528
|
+
: resolveDocumentAdapter(publicName);
|
|
529
|
+
const semanticToolResult = await handleSemanticTool(name, useEphemeralLexicalFallback
|
|
530
|
+
? { ...args, lex: stringArg(args, "query") }
|
|
531
|
+
: args, vault, semanticAdapter);
|
|
551
532
|
if (semanticToolResult) {
|
|
552
|
-
|
|
533
|
+
if (!semanticToolResult.ok)
|
|
534
|
+
return errorText(semanticToolResult.message);
|
|
535
|
+
return jsonText(semanticToolResult.value);
|
|
553
536
|
}
|
|
554
537
|
}
|
|
555
|
-
if (
|
|
538
|
+
if (name === "oms_lazy_load_note") {
|
|
556
539
|
const notePath = stringArg(args, "notePath");
|
|
557
540
|
if (!notePath) {
|
|
558
541
|
return errorText('Missing required string argument "notePath".');
|
|
559
542
|
}
|
|
560
543
|
return jsonText(await lazyLoadNoteBody(vault, notePath));
|
|
561
544
|
}
|
|
562
|
-
if (
|
|
545
|
+
if (name === "oms_validate_contract") {
|
|
563
546
|
const notePath = stringArg(args, "notePath");
|
|
564
547
|
if (!notePath) {
|
|
565
548
|
return errorText('Missing required string argument "notePath".');
|
|
@@ -603,7 +586,7 @@ export function createOMSMcpServer(opts) {
|
|
|
603
586
|
violations: result.violations,
|
|
604
587
|
});
|
|
605
588
|
}
|
|
606
|
-
if (
|
|
589
|
+
if (name === "oms_vault_audit") {
|
|
607
590
|
if (args !== undefined &&
|
|
608
591
|
Object.prototype.hasOwnProperty.call(args, "folder") &&
|
|
609
592
|
typeof args["folder"] !== "string") {
|
|
@@ -622,7 +605,7 @@ export function createOMSMcpServer(opts) {
|
|
|
622
605
|
violations: report.violations,
|
|
623
606
|
});
|
|
624
607
|
}
|
|
625
|
-
if (
|
|
608
|
+
if (name === "oms_link_suggest") {
|
|
626
609
|
const notePath = stringArg(args, "notePath");
|
|
627
610
|
if (!notePath) {
|
|
628
611
|
return errorText('Missing required string argument "notePath".');
|
|
@@ -631,7 +614,7 @@ export function createOMSMcpServer(opts) {
|
|
|
631
614
|
const suggestion = await suggestLinksForNote({ vault, source, ontology, notePath }, { folder: stringArg(args, "folder") });
|
|
632
615
|
return jsonText({ vault, ontologySource, ...suggestion });
|
|
633
616
|
}
|
|
634
|
-
if (
|
|
617
|
+
if (name === "oms_link_apply") {
|
|
635
618
|
const notePath = stringArg(args, "notePath");
|
|
636
619
|
if (!notePath) {
|
|
637
620
|
return errorText('Missing required string argument "notePath".');
|
|
@@ -648,10 +631,20 @@ export function createOMSMcpServer(opts) {
|
|
|
648
631
|
const outcome = await applyLinksForNote({ vault, source, ontology, notePath }, { baseContentHash, candidateIds: idsArg.filter((id) => typeof id === "string") }, { folder: stringArg(args, "folder") });
|
|
649
632
|
return jsonText({ vault, ontologySource, ...linkApplyPayload(outcome) });
|
|
650
633
|
}
|
|
651
|
-
if (
|
|
634
|
+
if (name === "write") {
|
|
652
635
|
const { ontology, source: ontologySource } = await resolveActiveOntology(vault);
|
|
653
636
|
const modeArg = stringArg(args, "mode");
|
|
654
637
|
const mode = isWriteMode(modeArg) ? modeArg : "create";
|
|
638
|
+
// `notePath` and `folder`/`filename` are two ways to address the same
|
|
639
|
+
// note. Supplying both is a contradiction the caller should hear about:
|
|
640
|
+
// silently preferring one produced a response that reported the concept
|
|
641
|
+
// implied by one form and the folder implied by the other, which reads as
|
|
642
|
+
// corruption rather than as the input error it is.
|
|
643
|
+
const hasNotePath = stringArg(args, "notePath") !== undefined;
|
|
644
|
+
const hasFolderForm = stringArg(args, "folder") !== undefined || stringArg(args, "filename") !== undefined;
|
|
645
|
+
if (hasNotePath && hasFolderForm) {
|
|
646
|
+
return errorText('Provide either "notePath" or "folder"/"filename" to address the note, not both.');
|
|
647
|
+
}
|
|
655
648
|
const frontmatterArg = args?.["frontmatter"];
|
|
656
649
|
const result = await writeNote({
|
|
657
650
|
target: { vault, source },
|
|
@@ -673,9 +666,15 @@ export function createOMSMcpServer(opts) {
|
|
|
673
666
|
resolutionSource: source,
|
|
674
667
|
});
|
|
675
668
|
}
|
|
676
|
-
return errorText(`Unknown Oh My Second Brain tool: ${
|
|
669
|
+
return errorText(`Unknown Oh My Second Brain tool: ${publicName}`);
|
|
677
670
|
}
|
|
678
671
|
catch (error) {
|
|
672
|
+
if (error instanceof SemanticIndexUnavailableError) {
|
|
673
|
+
return jsonText({
|
|
674
|
+
available: false,
|
|
675
|
+
reason: error.message,
|
|
676
|
+
});
|
|
677
|
+
}
|
|
679
678
|
return errorText(`Oh My Second Brain MCP error: ${error instanceof Error ? error.message : String(error)}`);
|
|
680
679
|
}
|
|
681
680
|
});
|