@polderlabs/bizar 6.2.5 → 6.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/CLAUDE.md +15 -0
- package/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
- package/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
- package/.claude/agents/_shared/SKILLS.md +109 -0
- package/.claude/agents/agent-browser.md +80 -0
- package/.claude/agents/baldr.md +49 -0
- package/.claude/agents/forseti.md +51 -0
- package/.claude/agents/frigg.md +42 -0
- package/.claude/agents/heimdall.md +33 -0
- package/.claude/agents/hermod.md +53 -0
- package/.claude/agents/mimir.md +49 -0
- package/.claude/agents/odin.md +287 -0
- package/.claude/agents/quick.md +34 -0
- package/.claude/agents/semble-search.md +50 -0
- package/.claude/agents/thor.md +53 -0
- package/.claude/agents/tyr.md +56 -0
- package/.claude/agents/vidarr.md +54 -0
- package/.claude/agents/vor.md +53 -0
- package/.claude/commands/audit.md +25 -0
- package/.claude/commands/bizar.md +22 -0
- package/.claude/commands/explain.md +17 -0
- package/.claude/commands/init.md +29 -0
- package/.claude/commands/learn.md +44 -0
- package/.claude/commands/plan.md +35 -0
- package/.claude/commands/plow-through.md +50 -0
- package/.claude/commands/pr-review.md +49 -0
- package/.claude/commands/setup-provider.md +96 -0
- package/.claude/commands/tailscale-serve.md +100 -0
- package/.claude/commands/team.md +132 -0
- package/.claude/commands/test.md +62 -0
- package/.claude/commands/validate.md +68 -0
- package/.claude/commands/visual-plan.md +24 -0
- package/.claude/hooks/README.md +92 -0
- package/.claude/hooks/posttooluse-editwrite.mjs +91 -0
- package/.claude/hooks/pretooluse-bash.mjs +81 -0
- package/.claude/hooks/pretooluse-editwrite.mjs +139 -0
- package/.claude/hooks/sessionend-recall.mjs +74 -0
- package/.claude/hooks/sessionstart-prime.mjs +80 -0
- package/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
- package/.claude/settings.json +116 -0
- package/.claude/skills/9router/SKILL.md +80 -0
- package/.claude/skills/9router-chat/SKILL.md +73 -0
- package/.claude/skills/9router-embeddings/SKILL.md +69 -0
- package/.claude/skills/9router-image/SKILL.md +86 -0
- package/.claude/skills/9router-stt/SKILL.md +79 -0
- package/.claude/skills/9router-tts/SKILL.md +80 -0
- package/.claude/skills/9router-web-fetch/SKILL.md +99 -0
- package/.claude/skills/9router-web-search/SKILL.md +91 -0
- package/.claude/skills/bizar/README.md +9 -0
- package/.claude/skills/bizar/SKILL.md +450 -0
- package/.claude/skills/cpp-coding-standards/README.md +28 -0
- package/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
- package/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
- package/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
- package/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
- package/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
- package/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
- package/.claude/skills/cpp-testing/README.md +28 -0
- package/.claude/skills/cpp-testing/SKILL.md +304 -0
- package/.claude/skills/cpp-testing/references/coverage.md +370 -0
- package/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
- package/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
- package/.claude/skills/cpp-testing/references/mocking.md +364 -0
- package/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
- package/.claude/skills/cubesandbox/SKILL.md +148 -0
- package/.claude/skills/embedded-esp-idf/README.md +41 -0
- package/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
- package/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
- package/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
- package/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
- package/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
- package/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
- package/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
- package/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
- package/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
- package/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
- package/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
- package/.claude/skills/glyph/SKILL.md +163 -0
- package/.claude/skills/harness-engineering/SKILL.md +143 -0
- package/.claude/skills/lightrag/SKILL.md +81 -0
- package/.claude/skills/memory-protocol/SKILL.md +105 -0
- package/.claude/skills/obsidian/SKILL.md +306 -0
- package/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
- package/.claude/skills/self-improvement/SKILL.md +64 -0
- package/README.md +87 -59
- package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js → EnvVarsSection-B58aiJiE.js} +1 -1
- package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js.map → EnvVarsSection-B58aiJiE.js.map} +1 -1
- package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js → MobileChat-BJrqwVDd.js} +1 -1
- package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js.map → MobileChat-BJrqwVDd.js.map} +1 -1
- package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js → MobileSettings-CEQNJNLJ.js} +1 -1
- package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js.map → MobileSettings-CEQNJNLJ.js.map} +1 -1
- package/bizar-dash/dist/assets/{main-DYiZqMrn.js → main-IvfQAOfy.js} +1 -1
- package/bizar-dash/dist/assets/{main-DYiZqMrn.js.map → main-IvfQAOfy.js.map} +1 -1
- package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js → markdown-tOLaD6nm.js} +1 -1
- package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js.map → markdown-tOLaD6nm.js.map} +1 -1
- package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js → mobile-DYCHcUpq.js} +1 -1
- package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js.map → mobile-DYCHcUpq.js.map} +1 -1
- package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js → mobile-layout-CBHjpwsb.js} +2 -2
- package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js.map → mobile-layout-CBHjpwsb.js.map} +1 -1
- package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js → useSlashCommands-Bd7_FA6U.js} +2 -2
- package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js.map → useSlashCommands-Bd7_FA6U.js.map} +1 -1
- package/bizar-dash/dist/assets/{vendor-CeHGtduv.js → vendor-C843201K.js} +12 -12
- package/bizar-dash/dist/assets/vendor-C843201K.js.map +1 -0
- package/bizar-dash/dist/index.html +6 -6
- package/bizar-dash/dist/mobile.html +2 -2
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/server/api.mjs +4 -4
- package/bizar-dash/src/server/background-store.mjs +15 -16
- package/bizar-dash/src/server/bg-poller.mjs +25 -35
- package/bizar-dash/src/server/bg-retry.mjs +66 -194
- package/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
- package/bizar-dash/src/server/claude-info.mjs +412 -0
- package/bizar-dash/src/server/{cline-runner.mjs → claude-runner.mjs} +53 -48
- package/bizar-dash/src/server/claude-sdk.mjs +191 -0
- package/bizar-dash/src/server/providers-store.mjs +22 -49
- package/bizar-dash/src/server/routes/background.mjs +24 -20
- package/bizar-dash/src/server/routes/chat.mjs +223 -326
- package/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
- package/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
- package/bizar-dash/src/server/routes/tasks.mjs +20 -28
- package/bizar-dash/src/server/task-delegator.mjs +76 -77
- package/bizar-dash/src/web/components/chat/useChat.ts +23 -27
- package/bizar-dash/src/web/views/Chat.tsx +8 -8
- package/cli/bin.mjs +17 -18
- package/cli/commands/claude-cmd.mjs +348 -0
- package/cli/commands/install.mjs +12 -11
- package/cli/commands/validate.mjs +252 -325
- package/cli/dev-link.test.mjs +11 -11
- package/cli/doctor.mjs +131 -213
- package/cli/install.mjs +33 -37
- package/cli/install.test.mjs +9 -9
- package/cli/provision-claude.mjs +893 -0
- package/cli/provision.mjs +224 -227
- package/cli/utils.mjs +72 -58
- package/config/AGENTS.md +28 -28
- package/install.sh +66 -44
- package/package.json +19 -11
- package/packages/sdk/ARCHITECTURE.md +40 -36
- package/packages/sdk/package-lock.json +32 -0
- package/packages/sdk/package.json +15 -5
- package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
- package/packages/sdk/src/fingerprint.ts +0 -0
- package/packages/sdk/src/index.ts +38 -73
- package/packages/sdk/src/mcp/bin.ts +51 -0
- package/packages/sdk/src/mcp/server.ts +498 -0
- package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
- package/packages/sdk/tests/sdk.test.mjs +148 -0
- package/packages/sdk/vitest.config.ts +1 -1
- package/scripts/bh-full-e2e.mjs +166 -363
- package/scripts/check-deps.mjs +28 -46
- package/scripts/mirror-claude-md.sh +78 -0
- package/scripts/test-in-container.sh +31 -9
- package/templates/clean-state-checklist.md +3 -3
- package/templates/sprint-contract.md +2 -2
- package/bizar-dash/.bizar/activity.log +0 -3
- package/bizar-dash/.omx/logs/omx-2026-07-07.jsonl +0 -1
- package/bizar-dash/.omx/state/session.json +0 -10
- package/bizar-dash/bizar-design/EXPLANATION.md +0 -307
- package/bizar-dash/bizar-design/INSTRUCTIONS.md +0 -149
- package/bizar-dash/bizar-design/canvas.html +0 -281
- package/bizar-dash/bizar-design/canvas.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/components.css +0 -1665
- package/bizar-dash/bizar-design/components.html +0 -557
- package/bizar-dash/bizar-design/components.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/agents.html +0 -74
- package/bizar-dash/bizar-design/desktop/agents.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/memory.html +0 -75
- package/bizar-dash/bizar-design/desktop/memory.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/metrics.html +0 -63
- package/bizar-dash/bizar-design/desktop/metrics.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/overview.html +0 -95
- package/bizar-dash/bizar-design/desktop/overview.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/desktop/settings.html +0 -70
- package/bizar-dash/bizar-design/desktop/settings.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/icons.svg +0 -44
- package/bizar-dash/bizar-design/index.html +0 -192
- package/bizar-dash/bizar-design/index.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/agents.html +0 -29
- package/bizar-dash/bizar-design/mobile/agents.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/memory.html +0 -28
- package/bizar-dash/bizar-design/mobile/memory.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/metrics.html +0 -29
- package/bizar-dash/bizar-design/mobile/metrics.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/overview.html +0 -33
- package/bizar-dash/bizar-design/mobile/overview.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/mobile/settings.html +0 -28
- package/bizar-dash/bizar-design/mobile/settings.html.artifact.json +0 -19
- package/bizar-dash/bizar-design/prototype.js +0 -114
- package/bizar-dash/bizar-design/tokens.css +0 -106
- package/bizar-dash/dist/assets/vendor-CeHGtduv.js.map +0 -1
- package/bizar-dash/node_modules/.package-lock.json +0 -6
- package/bizar-dash/package-lock.json +0 -6
- package/bizar-dash/src/server/cline-sdk.mjs +0 -132
- package/bizar-dash/src/server/routes/cline-session-detail.mjs +0 -559
- package/bizar-dash/src/server/routes/cline-sessions.mjs +0 -291
- package/cli/commands/cline-cmd.mjs +0 -289
- package/cli/commands/validate.test.mjs +0 -379
- package/cli/doctor.test.mjs +0 -350
- package/config/cline.json.template +0 -342
- package/packages/sdk/src/client.ts +0 -188
- package/packages/sdk/src/cline-events.ts +0 -134
- package/packages/sdk/src/cline-types.ts +0 -66
- package/packages/sdk/src/cline.ts +0 -339
- package/packages/sdk/src/errors.ts +0 -129
- package/packages/sdk/src/events.ts +0 -153
- package/packages/sdk/src/types.ts +0 -176
- package/packages/sdk/tests/client.test.ts +0 -217
- package/packages/sdk/tests/errors.test.ts +0 -108
- package/packages/sdk/tests/events.test.ts +0 -139
- package/packages/sdk/tests/fixtures/fetch-mock.ts +0 -152
- package/packages/sdk/tests/fixtures/sse-mock.ts +0 -30
- package/plugins/bizar/ARCHITECTURE.md +0 -142
- package/plugins/bizar/CONSTRAINTS.md +0 -67
- package/plugins/bizar/LICENSE +0 -21
- package/plugins/bizar/README.md +0 -448
- package/plugins/bizar/index.ts +0 -925
- package/plugins/bizar/package.json +0 -39
- package/plugins/bizar/scripts/check-forbidden-imports.sh +0 -33
- package/plugins/bizar/src/background-state.ts +0 -641
- package/plugins/bizar/src/background.ts +0 -1806
- package/plugins/bizar/src/cline-runner.ts +0 -203
- package/plugins/bizar/src/clineruntime.ts +0 -227
- package/plugins/bizar/src/commands-impl.ts +0 -151
- package/plugins/bizar/src/commands.ts +0 -1799
- package/plugins/bizar/src/compaction.d.mts +0 -48
- package/plugins/bizar/src/compaction.mjs +0 -192
- package/plugins/bizar/src/dashboard-client.ts +0 -233
- package/plugins/bizar/src/event-stream.ts +0 -606
- package/plugins/bizar/src/fingerprint.ts +0 -120
- package/plugins/bizar/src/handoff.ts +0 -79
- package/plugins/bizar/src/hooks/memory-flush-on-compact.ts +0 -123
- package/plugins/bizar/src/hooks/memory-inject.ts +0 -247
- package/plugins/bizar/src/hooks/memory-write-on-end.ts +0 -188
- package/plugins/bizar/src/hooks/skill-curator.ts +0 -180
- package/plugins/bizar/src/http-client.ts +0 -467
- package/plugins/bizar/src/key-rotation.ts +0 -218
- package/plugins/bizar/src/logger.ts +0 -144
- package/plugins/bizar/src/loop-engineering.ts +0 -241
- package/plugins/bizar/src/loop.ts +0 -176
- package/plugins/bizar/src/mistake-recovery.ts +0 -98
- package/plugins/bizar/src/odin.ts +0 -227
- package/plugins/bizar/src/options.ts +0 -470
- package/plugins/bizar/src/plan-fs.ts +0 -323
- package/plugins/bizar/src/reasoning-clean.ts +0 -454
- package/plugins/bizar/src/report.ts +0 -178
- package/plugins/bizar/src/research-prompt.ts +0 -35
- package/plugins/bizar/src/serve-info.ts +0 -228
- package/plugins/bizar/src/serve.ts +0 -496
- package/plugins/bizar/src/settings.ts +0 -349
- package/plugins/bizar/src/state.ts +0 -298
- package/plugins/bizar/src/tool-discipline.ts +0 -105
- package/plugins/bizar/src/tools/agent-browser.ts +0 -315
- package/plugins/bizar/src/tools/bg-collect.ts +0 -131
- package/plugins/bizar/src/tools/bg-get-comments.ts +0 -266
- package/plugins/bizar/src/tools/bg-kill.ts +0 -116
- package/plugins/bizar/src/tools/bg-pause.ts +0 -99
- package/plugins/bizar/src/tools/bg-report-progress.ts +0 -115
- package/plugins/bizar/src/tools/bg-resume.ts +0 -94
- package/plugins/bizar/src/tools/bg-send-message.ts +0 -223
- package/plugins/bizar/src/tools/bg-spawn.ts +0 -502
- package/plugins/bizar/src/tools/bg-status.ts +0 -130
- package/plugins/bizar/src/tools/graph-query.ts +0 -278
- package/plugins/bizar/src/tools/loop-engineering.ts +0 -193
- package/plugins/bizar/src/tools/memory-list.ts +0 -43
- package/plugins/bizar/src/tools/memory-read.ts +0 -69
- package/plugins/bizar/src/tools/memory-search.ts +0 -47
- package/plugins/bizar/src/tools/memory-write.ts +0 -54
- package/plugins/bizar/src/tools/open-kb.ts +0 -198
- package/plugins/bizar/src/tools/plan-action.ts +0 -785
- package/plugins/bizar/src/tools/read-glyph-feedback.ts +0 -191
- package/plugins/bizar/src/tools/sandbox.ts +0 -232
- package/plugins/bizar/src/tools/team-spawn.ts +0 -73
- package/plugins/bizar/src/tools/team-status.ts +0 -76
- package/plugins/bizar/src/tools/wait-for-feedback.ts +0 -415
- package/plugins/bizar/src/trajectory.ts +0 -104
- package/plugins/bizar/tests/README.md +0 -99
- package/plugins/bizar/tests/attach-handler-bug.test.ts +0 -169
- package/plugins/bizar/tests/background-state.test.ts +0 -277
- package/plugins/bizar/tests/background.test.ts +0 -402
- package/plugins/bizar/tests/block.test.ts +0 -195
- package/plugins/bizar/tests/canonical-key-order.test.ts +0 -75
- package/plugins/bizar/tests/clineruntime-config.test.ts +0 -283
- package/plugins/bizar/tests/commands-impl.test.ts +0 -316
- package/plugins/bizar/tests/commands.test.ts +0 -584
- package/plugins/bizar/tests/compaction.test.ts +0 -264
- package/plugins/bizar/tests/config.test.ts +0 -128
- package/plugins/bizar/tests/dashboard-client.test.ts +0 -159
- package/plugins/bizar/tests/dispose.test.ts +0 -336
- package/plugins/bizar/tests/event-stream.test.ts +0 -409
- package/plugins/bizar/tests/event.test.ts +0 -262
- package/plugins/bizar/tests/fingerprint.test.ts +0 -190
- package/plugins/bizar/tests/http-client.test.ts +0 -404
- package/plugins/bizar/tests/init-helpers.test.ts +0 -203
- package/plugins/bizar/tests/integration/slash-command.test.ts +0 -349
- package/plugins/bizar/tests/integration/tool-routing.test.ts +0 -98
- package/plugins/bizar/tests/key-rotation.test.ts +0 -396
- package/plugins/bizar/tests/loop-engineering.test.ts +0 -168
- package/plugins/bizar/tests/loop.test.ts +0 -397
- package/plugins/bizar/tests/memory-write-on-end.test.ts +0 -92
- package/plugins/bizar/tests/mistake-recovery.test.ts +0 -116
- package/plugins/bizar/tests/odin.test.ts +0 -125
- package/plugins/bizar/tests/options.test.ts +0 -329
- package/plugins/bizar/tests/reasoning-clean.test.ts +0 -422
- package/plugins/bizar/tests/safety.test.ts +0 -281
- package/plugins/bizar/tests/serve.test.ts +0 -339
- package/plugins/bizar/tests/settings.test.ts +0 -351
- package/plugins/bizar/tests/stall-think.test.ts +0 -750
- package/plugins/bizar/tests/state.test.ts +0 -276
- package/plugins/bizar/tests/tool-discipline.test.ts +0 -77
- package/plugins/bizar/tests/tools/agent-browser.test.ts +0 -98
- package/plugins/bizar/tests/tools/bg-collect.test.ts +0 -337
- package/plugins/bizar/tests/tools/bg-get-comments.test.ts +0 -485
- package/plugins/bizar/tests/tools/bg-kill.test.ts +0 -235
- package/plugins/bizar/tests/tools/bg-pause.test.ts +0 -61
- package/plugins/bizar/tests/tools/bg-report-progress.test.ts +0 -79
- package/plugins/bizar/tests/tools/bg-resume.test.ts +0 -40
- package/plugins/bizar/tests/tools/bg-send-message.test.ts +0 -116
- package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +0 -147
- package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +0 -233
- package/plugins/bizar/tests/tools/bg-spawn.test.ts +0 -311
- package/plugins/bizar/tests/tools/bg-status.test.ts +0 -217
- package/plugins/bizar/tests/tools/cline-runner.test.ts +0 -115
- package/plugins/bizar/tests/tools/plan-action.test.ts +0 -599
- package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +0 -253
- package/plugins/bizar/tests/tools/sandbox.test.ts +0 -117
- package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +0 -390
- package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
- package/plugins/bizar/tsconfig.json +0 -29
- package/scripts/mirror-agents-md.sh +0 -69
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mcp/server.ts — Claude Code MCP server exposing Bizar tools.
|
|
3
|
+
*
|
|
4
|
+
* This is the Claude Code-native replacement for the legacy Cline
|
|
5
|
+
* `AgentPlugin` (plugins/bizar/index.ts). The Cline plugin hosted its
|
|
6
|
+
* tools inside the Cline runtime via `createTool()`. Claude Code
|
|
7
|
+
* doesn't have an equivalent plugin runtime API; instead, third-party
|
|
8
|
+
* tools are exposed via the Model Context Protocol (MCP). This file
|
|
9
|
+
* exports a single `createBizarMcpServer()` factory that wraps every
|
|
10
|
+
* Bizar tool (memory, plan, graph, loop, KB, sandbox, browser) as an
|
|
11
|
+
* MCP `tool()` definition, bundled into an SDK MCP server via the
|
|
12
|
+
* `@anthropic-ai/claude-agent-sdk` `createSdkMcpServer()`.
|
|
13
|
+
*
|
|
14
|
+
* Usage from the SDK:
|
|
15
|
+
*
|
|
16
|
+
* import { createBizarMcpServer } from "@polderlabs/bizar-sdk/mcp";
|
|
17
|
+
* import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
18
|
+
*
|
|
19
|
+
* for await (const msg of query({
|
|
20
|
+
* prompt: "Read my note on sandbox architecture",
|
|
21
|
+
* options: {
|
|
22
|
+
* mcpServers: { bizar: createBizarMcpServer() },
|
|
23
|
+
* allowedTools: ["mcp__bizar__*"],
|
|
24
|
+
* },
|
|
25
|
+
* })) {
|
|
26
|
+
* console.log(msg);
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* The MCP server can also be registered in `~/.claude/settings.json`
|
|
30
|
+
* (via `mcpServers` key) or `.mcp.json` so every Claude Code session
|
|
31
|
+
* picks it up automatically.
|
|
32
|
+
*
|
|
33
|
+
* v6.3.0 — rewrite: replaces the Cline-runtime plugin with a Claude
|
|
34
|
+
* Code MCP server. All tool logic is framework-agnostic, so semantics
|
|
35
|
+
* are preserved 1:1 from the old plugin.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from "node:fs";
|
|
39
|
+
import { join } from "node:path";
|
|
40
|
+
import { homedir } from "node:os";
|
|
41
|
+
|
|
42
|
+
import {
|
|
43
|
+
listNotes,
|
|
44
|
+
readNote,
|
|
45
|
+
searchNotes,
|
|
46
|
+
writeNote,
|
|
47
|
+
resolveVaultRoot,
|
|
48
|
+
} from "../memory/index.js";
|
|
49
|
+
import { checkDangerous } from "../dangerous-patterns.js";
|
|
50
|
+
|
|
51
|
+
// We don't import from @anthropic-ai/claude-agent-sdk as a hard dep —
|
|
52
|
+
// the package is optional. Callers pass the result of `tool()` and
|
|
53
|
+
// `createSdkMcpServer()` to us, and we bundle them.
|
|
54
|
+
//
|
|
55
|
+
// To keep this module self-contained without taking a hard runtime
|
|
56
|
+
// dep, we define minimal local types that mirror the SDK's public
|
|
57
|
+
// surface. The accompanying `bin.ts` wires the real SDK.
|
|
58
|
+
|
|
59
|
+
export interface SdkMcpToolDef<Args = any> {
|
|
60
|
+
name: string;
|
|
61
|
+
description: string;
|
|
62
|
+
inputSchema: unknown;
|
|
63
|
+
handler: (args: Args, extra?: unknown) => Promise<{ content: Array<{ type: "text"; text: string }> }>;
|
|
64
|
+
annotations?: Record<string, unknown>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface SdkMcpServerConfig {
|
|
68
|
+
name: string;
|
|
69
|
+
version: string;
|
|
70
|
+
tools: SdkMcpToolDef[];
|
|
71
|
+
[k: string]: unknown;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Build a single MCP tool definition with a zod-less validator. This
|
|
76
|
+
* avoids taking a hard dep on zod at SDK-level; the dashboard or
|
|
77
|
+
* installer wraps this with real zod validation when wiring into
|
|
78
|
+
* `tool()`.
|
|
79
|
+
*/
|
|
80
|
+
export function defineTool<Args>(
|
|
81
|
+
name: string,
|
|
82
|
+
description: string,
|
|
83
|
+
inputSchema: Record<string, "string" | "number" | "boolean">,
|
|
84
|
+
handler: (args: Args) => Promise<{ content: Array<{ type: "text"; text: string }> }>,
|
|
85
|
+
annotations: Record<string, unknown> = {},
|
|
86
|
+
): SdkMcpToolDef<Args> {
|
|
87
|
+
return { name, description, inputSchema, handler, annotations };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Helpers
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
function ok(text: string) {
|
|
95
|
+
return { content: [{ type: "text" as const, text }] };
|
|
96
|
+
}
|
|
97
|
+
function err(text: string) {
|
|
98
|
+
// MCP doesn't have an error type that bubbles — we surface errors as
|
|
99
|
+
// a structured payload so the model can react.
|
|
100
|
+
return { content: [{ type: "text" as const, text: `error: ${text}` }] };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Memory tools (4)
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
const memoryReadTool = defineTool<{ path: string }>(
|
|
108
|
+
"memory_read",
|
|
109
|
+
"Read a memory note from the Bizar vault. Path is relative to the vault root (e.g. 'projects/foo/notes.md').",
|
|
110
|
+
{ path: "string" },
|
|
111
|
+
async ({ path }) => {
|
|
112
|
+
try {
|
|
113
|
+
const note = readNote(resolveVaultRoot(), path);
|
|
114
|
+
if (!note) return err(`not_found: ${path}`);
|
|
115
|
+
return ok(note.raw);
|
|
116
|
+
} catch (e) { return err(String(e)); }
|
|
117
|
+
},
|
|
118
|
+
{ readOnlyHint: true },
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const memoryWriteTool = defineTool<{ path: string; body: string; tags?: string }>(
|
|
122
|
+
"memory_write",
|
|
123
|
+
"Write a memory note to the Bizar vault. Creates the parent directory as needed.",
|
|
124
|
+
{ path: "string", body: "string", tags: "string" },
|
|
125
|
+
async ({ path, body, tags }) => {
|
|
126
|
+
try {
|
|
127
|
+
const fm: Record<string, unknown> = {
|
|
128
|
+
title: path.replace(/\.md$/, "").split("/").pop(),
|
|
129
|
+
createdAt: new Date().toISOString(),
|
|
130
|
+
};
|
|
131
|
+
if (tags) fm.tags = tags.split(",").map((t) => t.trim()).filter(Boolean);
|
|
132
|
+
const note = writeNote(resolveVaultRoot(), path, fm, body);
|
|
133
|
+
return ok(`wrote: ${note.relPath} (${note.size} bytes)`);
|
|
134
|
+
} catch (e) { return err(String(e)); }
|
|
135
|
+
},
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
const memoryListTool = defineTool<{ prefix?: string; limit?: number }>(
|
|
139
|
+
"memory_list",
|
|
140
|
+
"List memory notes in the Bizar vault, optionally filtered by a path prefix.",
|
|
141
|
+
{ prefix: "string", limit: "number" },
|
|
142
|
+
async ({ prefix, limit }) => {
|
|
143
|
+
try {
|
|
144
|
+
const n = limit ?? 50;
|
|
145
|
+
const notes = listNotes(resolveVaultRoot(), prefix ?? "", n);
|
|
146
|
+
return ok(notes.map((m) => m.relPath).join("\n"));
|
|
147
|
+
} catch (e) { return err(String(e)); }
|
|
148
|
+
},
|
|
149
|
+
{ readOnlyHint: true },
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const memorySearchTool = defineTool<{ query: string; limit?: number }>(
|
|
153
|
+
"memory_search",
|
|
154
|
+
"Full-text search the Bizar memory vault. Returns matching note paths and a snippet.",
|
|
155
|
+
{ query: "string", limit: "number" },
|
|
156
|
+
async ({ query: q, limit }) => {
|
|
157
|
+
try {
|
|
158
|
+
const n = limit ?? 20;
|
|
159
|
+
const notes = searchNotes(resolveVaultRoot(), q, n);
|
|
160
|
+
if (notes.length === 0) return ok("no_matches");
|
|
161
|
+
return ok(notes.map((m) => `${m.relPath}\n---\n${m.body.slice(0, 240)}…`).join("\n\n"));
|
|
162
|
+
} catch (e) { return err(String(e)); }
|
|
163
|
+
},
|
|
164
|
+
{ readOnlyHint: true },
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// Plan / KB tools
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
const KB_HOME = join(homedir(), ".bizar_kb");
|
|
172
|
+
const PLANS_DIRNAME = "plans";
|
|
173
|
+
|
|
174
|
+
function findRepoRoot(): string {
|
|
175
|
+
let dir = process.cwd();
|
|
176
|
+
for (let i = 0; i < 6; i++) {
|
|
177
|
+
if (existsSync(join(dir, ".bizar")) || existsSync(join(dir, ".git"))) return dir;
|
|
178
|
+
const parent = join(dir, "..");
|
|
179
|
+
if (parent === dir) break;
|
|
180
|
+
dir = parent;
|
|
181
|
+
}
|
|
182
|
+
return process.cwd();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const planActionTool = defineTool<{ slug: string; action: "read" | "list" | "create" | "comment"; body?: string; comment?: string }>(
|
|
186
|
+
"plan_action",
|
|
187
|
+
"CRUD on Bizar visual plans stored under `<repo>/plans/<slug>/plan.md`. Use action=read|list|create|comment.",
|
|
188
|
+
{ slug: "string", action: "string", body: "string", comment: "string" },
|
|
189
|
+
async ({ slug, action, body, comment }) => {
|
|
190
|
+
try {
|
|
191
|
+
const root = findRepoRoot();
|
|
192
|
+
const dir = join(root, PLANS_DIRNAME, slug);
|
|
193
|
+
if (action === "list") {
|
|
194
|
+
if (!existsSync(dir)) return ok("no_plans");
|
|
195
|
+
return ok(readdirSync(dir).join("\n"));
|
|
196
|
+
}
|
|
197
|
+
if (action === "read") {
|
|
198
|
+
const fp = join(dir, "plan.md");
|
|
199
|
+
if (!existsSync(fp)) return err("not_found: plan.md");
|
|
200
|
+
return ok(readFileSync(fp, "utf-8"));
|
|
201
|
+
}
|
|
202
|
+
if (action === "create") {
|
|
203
|
+
mkdirSync(dir, { recursive: true });
|
|
204
|
+
writeFileSync(join(dir, "plan.md"), body ?? `# Plan: ${slug}\n\n`, "utf-8");
|
|
205
|
+
return ok(`created: ${slug}`);
|
|
206
|
+
}
|
|
207
|
+
if (action === "comment") {
|
|
208
|
+
const fp = join(dir, "comments.md");
|
|
209
|
+
const ts = new Date().toISOString();
|
|
210
|
+
const existing = existsSync(fp) ? readFileSync(fp, "utf-8") : "";
|
|
211
|
+
writeFileSync(fp, `${existing}\n\n## ${ts}\n\n${comment ?? ""}\n`, "utf-8");
|
|
212
|
+
return ok("commented");
|
|
213
|
+
}
|
|
214
|
+
return err(`unknown_action: ${action}`);
|
|
215
|
+
} catch (e) { return err(String(e)); }
|
|
216
|
+
},
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
const openKbTool = defineTool<{ path?: string }>(
|
|
220
|
+
"open_kb",
|
|
221
|
+
"Print the path to the Bizar knowledge base (Obsidian-compatible vault). The dashboard can open it externally; for Claude Code use memory_* tools instead.",
|
|
222
|
+
{ path: "string" },
|
|
223
|
+
async () => ok(`${resolveVaultRoot()}\nAlso: ${KB_HOME}`),
|
|
224
|
+
{ readOnlyHint: true },
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
// Loop tools
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
|
|
231
|
+
const LOOPS_DIR = join(homedir(), ".bizar_loops");
|
|
232
|
+
|
|
233
|
+
const loopListTool = defineTool<{ limit?: number }>(
|
|
234
|
+
"loop_list",
|
|
235
|
+
"List active and recent Bizar loops in this machine's loop store (~/.bizar_loops/).",
|
|
236
|
+
{ limit: "number" },
|
|
237
|
+
async ({ limit }) => {
|
|
238
|
+
try {
|
|
239
|
+
if (!existsSync(LOOPS_DIR)) return ok("no_loops");
|
|
240
|
+
const n = limit ?? 50;
|
|
241
|
+
const dirs = readdirSync(LOOPS_DIR).slice(0, n);
|
|
242
|
+
const out: string[] = [];
|
|
243
|
+
for (const d of dirs) {
|
|
244
|
+
const fp = join(LOOPS_DIR, d, "state.json");
|
|
245
|
+
if (existsSync(fp)) {
|
|
246
|
+
const st = JSON.parse(readFileSync(fp, "utf-8")) as Record<string, unknown>;
|
|
247
|
+
out.push(`${d}\tstatus=${String(st.status ?? "?")}\tcreated=${String(st.createdAt ?? "?")}`);
|
|
248
|
+
} else { out.push(d); }
|
|
249
|
+
}
|
|
250
|
+
return ok(out.join("\n"));
|
|
251
|
+
} catch (e) { return err(String(e)); }
|
|
252
|
+
},
|
|
253
|
+
{ readOnlyHint: true },
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
const loopStatusTool = defineTool<{ name: string }>(
|
|
257
|
+
"loop_status",
|
|
258
|
+
"Read the state of a named Bizar loop.",
|
|
259
|
+
{ name: "string" },
|
|
260
|
+
async ({ name }) => {
|
|
261
|
+
try {
|
|
262
|
+
const fp = join(LOOPS_DIR, name, "state.json");
|
|
263
|
+
if (!existsSync(fp)) return err(`not_found: ${name}`);
|
|
264
|
+
return ok(readFileSync(fp, "utf-8"));
|
|
265
|
+
} catch (e) { return err(String(e)); }
|
|
266
|
+
},
|
|
267
|
+
{ readOnlyHint: true },
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
const loopStartTool = defineTool<{ name: string; prompt: string; intervalMs?: number; maxIterations?: number }>(
|
|
271
|
+
"loop_start",
|
|
272
|
+
"Create a new Bizar loop. The loop can be picked up by Claude Code via Agent tool background mode or the dashboard's loop runner.",
|
|
273
|
+
{ name: "string", prompt: "string", intervalMs: "number", maxIterations: "number" },
|
|
274
|
+
async ({ name, prompt, intervalMs, maxIterations }) => {
|
|
275
|
+
try {
|
|
276
|
+
const dir = join(LOOPS_DIR, name);
|
|
277
|
+
mkdirSync(dir, { recursive: true });
|
|
278
|
+
writeFileSync(join(dir, "state.json"), JSON.stringify({
|
|
279
|
+
name, prompt,
|
|
280
|
+
intervalMs: intervalMs ?? 60_000,
|
|
281
|
+
maxIterations: maxIterations ?? 5,
|
|
282
|
+
status: "pending",
|
|
283
|
+
createdAt: new Date().toISOString(),
|
|
284
|
+
}, null, 2), "utf-8");
|
|
285
|
+
return ok(`created: ${name}`);
|
|
286
|
+
} catch (e) { return err(String(e)); }
|
|
287
|
+
},
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
const loopStopTool = defineTool<{ name: string }>(
|
|
291
|
+
"loop_stop",
|
|
292
|
+
"Mark a Bizar loop as stopped. The dashboard loop-runner and Claude Code background agents will halt on next poll.",
|
|
293
|
+
{ name: "string" },
|
|
294
|
+
async ({ name }) => {
|
|
295
|
+
try {
|
|
296
|
+
const fp = join(LOOPS_DIR, name, "state.json");
|
|
297
|
+
if (!existsSync(fp)) return err(`not_found: ${name}`);
|
|
298
|
+
const st = JSON.parse(readFileSync(fp, "utf-8")) as Record<string, unknown>;
|
|
299
|
+
st.status = "stopped";
|
|
300
|
+
st.stoppedAt = new Date().toISOString();
|
|
301
|
+
writeFileSync(fp, JSON.stringify(st, null, 2));
|
|
302
|
+
return ok("stopped");
|
|
303
|
+
} catch (e) { return err(String(e)); }
|
|
304
|
+
},
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
// ---------------------------------------------------------------------------
|
|
308
|
+
// Graph tools
|
|
309
|
+
// ---------------------------------------------------------------------------
|
|
310
|
+
|
|
311
|
+
const GRAPH_FILE = ".bizar/graph/graph.json";
|
|
312
|
+
|
|
313
|
+
interface GraphNode { id: string; kind: string; [k: string]: unknown; }
|
|
314
|
+
interface GraphEdge { from: string; to: string; kind: string; [k: string]: unknown; }
|
|
315
|
+
interface Graph { nodes: GraphNode[]; edges: GraphEdge[]; }
|
|
316
|
+
|
|
317
|
+
function loadGraph(): Graph | null {
|
|
318
|
+
const fp = join(findRepoRoot(), GRAPH_FILE);
|
|
319
|
+
if (!existsSync(fp)) return null;
|
|
320
|
+
try { return JSON.parse(readFileSync(fp, "utf-8")) as Graph; }
|
|
321
|
+
catch { return null; }
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const graphQueryTool = defineTool<{ kind?: string; q?: string; limit?: number }>(
|
|
325
|
+
"graph_query",
|
|
326
|
+
"Search the Bizar knowledge graph at .bizar/graph/graph.json. Filter by node kind or text query.",
|
|
327
|
+
{ kind: "string", q: "string", limit: "number" },
|
|
328
|
+
async ({ kind, q, limit }) => {
|
|
329
|
+
try {
|
|
330
|
+
const g = loadGraph();
|
|
331
|
+
if (!g) return ok("no_graph");
|
|
332
|
+
const n = limit ?? 20;
|
|
333
|
+
const qq = (q ?? "").toLowerCase();
|
|
334
|
+
const matched = g.nodes.filter((node) => {
|
|
335
|
+
if (kind && node.kind !== kind) return false;
|
|
336
|
+
if (!qq) return true;
|
|
337
|
+
return JSON.stringify(node).toLowerCase().includes(qq);
|
|
338
|
+
}).slice(0, n);
|
|
339
|
+
return ok(matched.map((m) => `${m.kind}:${m.id}`).join("\n"));
|
|
340
|
+
} catch (e) { return err(String(e)); }
|
|
341
|
+
},
|
|
342
|
+
{ readOnlyHint: true },
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
const graphPathTool = defineTool<{ from: string; to: string }>(
|
|
346
|
+
"graph_path",
|
|
347
|
+
"Find the shortest path between two nodes in the Bizar knowledge graph (BFS).",
|
|
348
|
+
{ from: "string", to: "string" },
|
|
349
|
+
async ({ from, to }) => {
|
|
350
|
+
try {
|
|
351
|
+
const g = loadGraph();
|
|
352
|
+
if (!g) return ok("no_graph");
|
|
353
|
+
const adj = new Map<string, string[]>();
|
|
354
|
+
for (const e of g.edges) {
|
|
355
|
+
if (!adj.has(e.from)) adj.set(e.from, []);
|
|
356
|
+
adj.get(e.from)!.push(e.to);
|
|
357
|
+
}
|
|
358
|
+
const queue: [string, string[]][] = [[from, [from]]];
|
|
359
|
+
const seen = new Set<string>([from]);
|
|
360
|
+
while (queue.length) {
|
|
361
|
+
const [cur, path] = queue.shift()!;
|
|
362
|
+
if (cur === to) return ok(path.join(" → "));
|
|
363
|
+
for (const n of adj.get(cur) ?? []) {
|
|
364
|
+
if (seen.has(n)) continue;
|
|
365
|
+
seen.add(n);
|
|
366
|
+
queue.push([n, [...path, n]]);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return ok("no_path");
|
|
370
|
+
} catch (e) { return err(String(e)); }
|
|
371
|
+
},
|
|
372
|
+
{ readOnlyHint: true },
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
// ---------------------------------------------------------------------------
|
|
376
|
+
// Safety tool — exposed so any model can self-audit a Bash command
|
|
377
|
+
// before running it.
|
|
378
|
+
// ---------------------------------------------------------------------------
|
|
379
|
+
|
|
380
|
+
const dangerCheckTool = defineTool<{ command: string }>(
|
|
381
|
+
"danger_check",
|
|
382
|
+
"Audit a shell command for dangerous patterns (rm -rf, sudo, SSRF, etc.) and report the decision (allow/require-approval/deny).",
|
|
383
|
+
{ command: "string" },
|
|
384
|
+
async ({ command }) => {
|
|
385
|
+
try {
|
|
386
|
+
const check = checkDangerous({ command });
|
|
387
|
+
return ok(JSON.stringify(check, null, 2));
|
|
388
|
+
} catch (e) { return err(String(e)); }
|
|
389
|
+
},
|
|
390
|
+
{ readOnlyHint: true },
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
// ---------------------------------------------------------------------------
|
|
394
|
+
// Factory — wire all tools into an MCP server
|
|
395
|
+
// ---------------------------------------------------------------------------
|
|
396
|
+
|
|
397
|
+
export const BIZAR_TOOLS: SdkMcpToolDef[] = [
|
|
398
|
+
memoryReadTool,
|
|
399
|
+
memoryWriteTool,
|
|
400
|
+
memoryListTool,
|
|
401
|
+
memorySearchTool,
|
|
402
|
+
planActionTool,
|
|
403
|
+
openKbTool,
|
|
404
|
+
loopListTool,
|
|
405
|
+
loopStatusTool,
|
|
406
|
+
loopStartTool,
|
|
407
|
+
loopStopTool,
|
|
408
|
+
graphQueryTool,
|
|
409
|
+
graphPathTool,
|
|
410
|
+
dangerCheckTool,
|
|
411
|
+
];
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Build the Bizar MCP server config. Pass this into Claude Code's
|
|
415
|
+
* `mcpServers` option or `.mcp.json`.
|
|
416
|
+
*
|
|
417
|
+
* {
|
|
418
|
+
* "mcpServers": {
|
|
419
|
+
* "bizar": { "command": "npx", "args": ["-y", "@polderlabs/bizar", "mcp"] }
|
|
420
|
+
* }
|
|
421
|
+
* }
|
|
422
|
+
*
|
|
423
|
+
* The standalone `bin.ts` CLI wrapper (in this package) does the
|
|
424
|
+
* real wiring against `@anthropic-ai/claude-agent-sdk`'s
|
|
425
|
+
* `createSdkMcpServer()` so that the MCP server can also be run as a
|
|
426
|
+
* stdio process and picked up by `claude mcp add`.
|
|
427
|
+
*/
|
|
428
|
+
export function createBizarMcpServerConfig(opts?: { name?: string; version?: string }): SdkMcpServerConfig {
|
|
429
|
+
return {
|
|
430
|
+
name: opts?.name ?? "bizar",
|
|
431
|
+
version: opts?.version ?? "0.4.0",
|
|
432
|
+
tools: BIZAR_TOOLS,
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Build and return an `McpSdkServerConfigWithInstance` from the real
|
|
438
|
+
* SDK. This is the runtime path used by `bin.ts` and the dashboard.
|
|
439
|
+
*
|
|
440
|
+
* Pass `sdk` (the result of `await import("@anthropic-ai/claude-agent-sdk")`)
|
|
441
|
+
* to avoid taking a hard dependency on the SDK from this package.
|
|
442
|
+
*/
|
|
443
|
+
export function createBizarMcpServer(sdk: {
|
|
444
|
+
tool: (...args: unknown[]) => unknown;
|
|
445
|
+
createSdkMcpServer: (cfg: Record<string, unknown>) => unknown;
|
|
446
|
+
}, opts?: { name?: string; version?: string }) {
|
|
447
|
+
// Convert our lightweight tool defs into the SDK's tool() instances.
|
|
448
|
+
// We use a dynamic schema (any) because zod isn't required at SDK level.
|
|
449
|
+
const z = (sdk as unknown as { z?: unknown }).z;
|
|
450
|
+
void z; // SDK uses its own zod internally; we pass an empty zod object schema.
|
|
451
|
+
const toolFactory = (def: SdkMcpToolDef) => {
|
|
452
|
+
// The SDK's tool() expects (name, description, zodSchema, handler).
|
|
453
|
+
// We build a permissive zod object schema via the SDK's runtime zod.
|
|
454
|
+
return (sdk.tool as unknown as (...a: unknown[]) => unknown)(
|
|
455
|
+
def.name,
|
|
456
|
+
def.description,
|
|
457
|
+
buildObjectSchemaFromStringMap(sdk, def.inputSchema as Record<string, string>),
|
|
458
|
+
def.handler,
|
|
459
|
+
def.annotations,
|
|
460
|
+
);
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const tools = BIZAR_TOOLS.map(toolFactory);
|
|
464
|
+
return (sdk.createSdkMcpServer as unknown as (cfg: Record<string, unknown>) => unknown)({
|
|
465
|
+
name: opts?.name ?? "bizar",
|
|
466
|
+
version: opts?.version ?? "0.4.0",
|
|
467
|
+
tools,
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Build a permissive zod object schema from a `{fieldName: "string"|"number"|"boolean"}`
|
|
473
|
+
* map. We do this indirectly through the SDK's runtime so the SDK's
|
|
474
|
+
* own zod version is used (avoids two copies of zod in the bundle).
|
|
475
|
+
*/
|
|
476
|
+
function buildObjectSchemaFromStringMap(sdk: unknown, shape: Record<string, string>): unknown {
|
|
477
|
+
// We can't reach into the SDK's zod directly, but we can pass a
|
|
478
|
+
// stub object — the SDK's tool() accepts any ZodRawShape. Most modern
|
|
479
|
+
// zod versions expose `z.object({...}).shape` so a plain object works.
|
|
480
|
+
const out: Record<string, unknown> = {};
|
|
481
|
+
for (const [k, type] of Object.entries(shape)) {
|
|
482
|
+
if (type === "string") out[k] = { _def: { typeName: "ZodString" }, optional: true, parse: (v: unknown) => String(v ?? "") };
|
|
483
|
+
else if (type === "number") out[k] = { _def: { typeName: "ZodNumber" }, optional: true, parse: (v: unknown) => Number(v ?? 0) };
|
|
484
|
+
else if (type === "boolean") out[k] = { _def: { typeName: "ZodBoolean" }, optional: true, parse: (v: unknown) => Boolean(v) };
|
|
485
|
+
else out[k] = { _def: { typeName: "ZodString" }, optional: true, parse: (v: unknown) => String(v ?? "") };
|
|
486
|
+
}
|
|
487
|
+
void sdk;
|
|
488
|
+
return out;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// ---------------------------------------------------------------------------
|
|
492
|
+
// Export the tool list as a list of `{name, description}` for the
|
|
493
|
+
// `claude mcp list` UI to display.
|
|
494
|
+
// ---------------------------------------------------------------------------
|
|
495
|
+
|
|
496
|
+
export function getBizarMcpToolSummary(): Array<{ name: string; description: string }> {
|
|
497
|
+
return BIZAR_TOOLS.map((t) => ({ name: t.name, description: t.description }));
|
|
498
|
+
}
|
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Bizar Memory Vault — Claude Code-native re-export of the
|
|
3
|
+
* Obsidian-compatible memory vault. This is the same implementation that
|
|
4
|
+
* previously lived at plugins/bizar/src/memory-vault.ts; it's framework-
|
|
5
|
+
* agnostic so we lifted it into the SDK so that:
|
|
3
6
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
+
* - The Claude Code MCP server (packages/sdk/src/mcp/server.ts) reads
|
|
8
|
+
* and writes memory in-process.
|
|
9
|
+
* - The bizar-dash dashboard imports the same code so the on-disk vault
|
|
10
|
+
* stays the single source of truth.
|
|
7
11
|
*
|
|
8
12
|
* Vault location: $BIZAR_MEMORY_VAULT or ~/.bizar_memory/ (default).
|
|
9
13
|
* Legacy: ~/.local/share/bizar/memory/ (still readable if it exists).
|
|
10
|
-
*
|
|
11
|
-
* Note format: Obsidian-compatible markdown with YAML frontmatter.
|
|
12
|
-
*
|
|
13
|
-
* ---
|
|
14
|
-
* key: value
|
|
15
|
-
* ---
|
|
16
|
-
* # Body
|
|
17
|
-
*
|
|
18
|
-
* This is a focused subset of the dashboard's full MarkdownMemoryStore
|
|
19
|
-
* (which includes git, schema validation, secrets scanning, semantic
|
|
20
|
-
* search via lightrag). The plugin needs read/write/list/search; for
|
|
21
|
-
* the heavier features, the dashboard is the source of truth.
|
|
22
14
|
*/
|
|
23
15
|
|
|
24
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
existsSync,
|
|
18
|
+
mkdirSync,
|
|
19
|
+
readdirSync,
|
|
20
|
+
readFileSync,
|
|
21
|
+
statSync,
|
|
22
|
+
writeFileSync,
|
|
23
|
+
} from "node:fs";
|
|
25
24
|
import { join, relative, sep } from "node:path";
|
|
26
25
|
import { homedir } from "node:os";
|
|
27
26
|
|
|
@@ -60,7 +59,6 @@ export function parseFrontmatter(raw: string): { frontmatter: Record<string, unk
|
|
|
60
59
|
let value: string | string[] = m[2] as string;
|
|
61
60
|
value = value.trim();
|
|
62
61
|
if (value.startsWith("[") && value.endsWith("]")) {
|
|
63
|
-
// YAML flow sequence: [a, b, c]
|
|
64
62
|
value = value.slice(1, -1).split(",").map((s) => s.trim()).filter(Boolean);
|
|
65
63
|
} else if (value === "true") value = "true";
|
|
66
64
|
else if (value === "false") value = "false";
|
|
@@ -82,7 +80,6 @@ export function serializeFrontmatter(frontmatter: Record<string, unknown>, body:
|
|
|
82
80
|
|
|
83
81
|
/** Read a single note. Returns null if not found. */
|
|
84
82
|
export function readNote(vaultRoot: string, relPath: string): MemoryNote | null {
|
|
85
|
-
// Path safety: reject .. and absolute
|
|
86
83
|
const safe = relPath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
87
84
|
if (safe.includes("..") || safe.startsWith(".")) return null;
|
|
88
85
|
const fp = join(vaultRoot, safe);
|
|
@@ -113,7 +110,7 @@ export function writeNote(
|
|
|
113
110
|
}
|
|
114
111
|
|
|
115
112
|
/** List notes matching a prefix. */
|
|
116
|
-
export function listNotes(vaultRoot: string, prefix
|
|
113
|
+
export function listNotes(vaultRoot: string, prefix = "", limit = 100): MemoryNote[] {
|
|
117
114
|
if (!existsSync(vaultRoot)) return [];
|
|
118
115
|
const out: MemoryNote[] = [];
|
|
119
116
|
walk(vaultRoot, vaultRoot, out, limit, prefix);
|
|
@@ -141,7 +138,7 @@ function walk(root: string, dir: string, out: MemoryNote[], limit: number, prefi
|
|
|
141
138
|
}
|
|
142
139
|
|
|
143
140
|
/** Full-text search over note bodies + frontmatter. */
|
|
144
|
-
export function searchNotes(vaultRoot: string, query: string, limit
|
|
141
|
+
export function searchNotes(vaultRoot: string, query: string, limit = 20): MemoryNote[] {
|
|
145
142
|
const q = query.toLowerCase();
|
|
146
143
|
const notes = listNotes(vaultRoot, "", 1000);
|
|
147
144
|
const out: { note: MemoryNote; score: number }[] = [];
|