@maadb/core 0.0.1 → 0.7.9
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/LICENSE +21 -0
- package/README.md +371 -3
- package/dist/architect.d.ts +2 -0
- package/dist/architect.d.ts.map +1 -0
- package/dist/architect.js +273 -0
- package/dist/architect.js.map +1 -0
- package/dist/auth/resolve.d.ts +36 -0
- package/dist/auth/resolve.d.ts.map +1 -0
- package/dist/auth/resolve.js +77 -0
- package/dist/auth/resolve.js.map +1 -0
- package/dist/auth/token-store.d.ts +82 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +464 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/auth/types.d.ts +75 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +15 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/backend/adapter.d.ts +57 -0
- package/dist/backend/adapter.d.ts.map +1 -0
- package/dist/backend/adapter.js +6 -0
- package/dist/backend/adapter.js.map +1 -0
- package/dist/backend/index.d.ts +3 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +2 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/sqlite/index.d.ts +63 -0
- package/dist/backend/sqlite/index.d.ts.map +1 -0
- package/dist/backend/sqlite/index.js +521 -0
- package/dist/backend/sqlite/index.js.map +1 -0
- package/dist/backend/sqlite/schema.d.ts +2 -0
- package/dist/backend/sqlite/schema.d.ts.map +1 -0
- package/dist/backend/sqlite/schema.js +88 -0
- package/dist/backend/sqlite/schema.js.map +1 -0
- package/dist/claude-md.d.ts +2 -0
- package/dist/claude-md.d.ts.map +1 -0
- package/dist/claude-md.js +97 -0
- package/dist/claude-md.js.map +1 -0
- package/dist/cli/commands/audit.d.ts +4 -0
- package/dist/cli/commands/audit.d.ts.map +1 -0
- package/dist/cli/commands/audit.js +39 -0
- package/dist/cli/commands/audit.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +8 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +242 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/discover.d.ts +5 -0
- package/dist/cli/commands/discover.d.ts.map +1 -0
- package/dist/cli/commands/discover.js +48 -0
- package/dist/cli/commands/discover.js.map +1 -0
- package/dist/cli/commands/maintain.d.ts +6 -0
- package/dist/cli/commands/maintain.d.ts.map +1 -0
- package/dist/cli/commands/maintain.js +168 -0
- package/dist/cli/commands/maintain.js.map +1 -0
- package/dist/cli/commands/read.d.ts +7 -0
- package/dist/cli/commands/read.d.ts.map +1 -0
- package/dist/cli/commands/read.js +139 -0
- package/dist/cli/commands/read.js.map +1 -0
- package/dist/cli/commands/write.d.ts +4 -0
- package/dist/cli/commands/write.d.ts.map +1 -0
- package/dist/cli/commands/write.js +99 -0
- package/dist/cli/commands/write.js.map +1 -0
- package/dist/cli/helpers.d.ts +8 -0
- package/dist/cli/helpers.d.ts.map +1 -0
- package/dist/cli/helpers.js +17 -0
- package/dist/cli/helpers.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +296 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +1 -0
- package/dist/engine/audit.d.ts +15 -0
- package/dist/engine/audit.d.ts.map +1 -0
- package/dist/engine/audit.js +42 -0
- package/dist/engine/audit.js.map +1 -0
- package/dist/engine/composites.d.ts +6 -0
- package/dist/engine/composites.d.ts.map +1 -0
- package/dist/engine/composites.js +102 -0
- package/dist/engine/composites.js.map +1 -0
- package/dist/engine/context.d.ts +47 -0
- package/dist/engine/context.d.ts.map +1 -0
- package/dist/engine/context.js +55 -0
- package/dist/engine/context.js.map +1 -0
- package/dist/engine/docid-safe.d.ts +8 -0
- package/dist/engine/docid-safe.d.ts.map +1 -0
- package/dist/engine/docid-safe.js +0 -0
- package/dist/engine/docid-safe.js.map +1 -0
- package/dist/engine/helpers.d.ts +8 -0
- package/dist/engine/helpers.d.ts.map +1 -0
- package/dist/engine/helpers.js +102 -0
- package/dist/engine/helpers.js.map +1 -0
- package/dist/engine/index.d.ts +209 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +489 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/indexing.d.ts +14 -0
- package/dist/engine/indexing.d.ts.map +1 -0
- package/dist/engine/indexing.js +225 -0
- package/dist/engine/indexing.js.map +1 -0
- package/dist/engine/journal.d.ts +32 -0
- package/dist/engine/journal.d.ts.map +1 -0
- package/dist/engine/journal.js +111 -0
- package/dist/engine/journal.js.map +1 -0
- package/dist/engine/logger.d.ts +19 -0
- package/dist/engine/logger.d.ts.map +1 -0
- package/dist/engine/logger.js +40 -0
- package/dist/engine/logger.js.map +1 -0
- package/dist/engine/maintenance.d.ts +15 -0
- package/dist/engine/maintenance.d.ts.map +1 -0
- package/dist/engine/maintenance.js +87 -0
- package/dist/engine/maintenance.js.map +1 -0
- package/dist/engine/mutex.d.ts +24 -0
- package/dist/engine/mutex.d.ts.map +1 -0
- package/dist/engine/mutex.js +50 -0
- package/dist/engine/mutex.js.map +1 -0
- package/dist/engine/pathguard.d.ts +16 -0
- package/dist/engine/pathguard.d.ts.map +1 -0
- package/dist/engine/pathguard.js +41 -0
- package/dist/engine/pathguard.js.map +1 -0
- package/dist/engine/reads.d.ts +24 -0
- package/dist/engine/reads.d.ts.map +1 -0
- package/dist/engine/reads.js +701 -0
- package/dist/engine/reads.js.map +1 -0
- package/dist/engine/types.d.ts +350 -0
- package/dist/engine/types.d.ts.map +1 -0
- package/dist/engine/types.js +5 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/engine/writes.d.ts +10 -0
- package/dist/engine/writes.d.ts.map +1 -0
- package/dist/engine/writes.js +606 -0
- package/dist/engine/writes.js.map +1 -0
- package/dist/engine.d.ts +3 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +6 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.d.ts +20 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +17 -0
- package/dist/errors.js.map +1 -0
- package/dist/extractor/fields.d.ts +3 -0
- package/dist/extractor/fields.d.ts.map +1 -0
- package/dist/extractor/fields.js +58 -0
- package/dist/extractor/fields.js.map +1 -0
- package/dist/extractor/index.d.ts +7 -0
- package/dist/extractor/index.d.ts.map +1 -0
- package/dist/extractor/index.js +22 -0
- package/dist/extractor/index.js.map +1 -0
- package/dist/extractor/normalizers.d.ts +22 -0
- package/dist/extractor/normalizers.d.ts.map +1 -0
- package/dist/extractor/normalizers.js +250 -0
- package/dist/extractor/normalizers.js.map +1 -0
- package/dist/extractor/objects.d.ts +3 -0
- package/dist/extractor/objects.d.ts.map +1 -0
- package/dist/extractor/objects.js +33 -0
- package/dist/extractor/objects.js.map +1 -0
- package/dist/extractor/relationships.d.ts +3 -0
- package/dist/extractor/relationships.d.ts.map +1 -0
- package/dist/extractor/relationships.js +58 -0
- package/dist/extractor/relationships.js.map +1 -0
- package/dist/git/commit.d.ts +63 -0
- package/dist/git/commit.d.ts.map +1 -0
- package/dist/git/commit.js +161 -0
- package/dist/git/commit.js.map +1 -0
- package/dist/git/diff.d.ts +4 -0
- package/dist/git/diff.d.ts.map +1 -0
- package/dist/git/diff.js +56 -0
- package/dist/git/diff.js.map +1 -0
- package/dist/git/index.d.ts +41 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/index.js +86 -0
- package/dist/git/index.js.map +1 -0
- package/dist/git/log.d.ts +13 -0
- package/dist/git/log.d.ts.map +1 -0
- package/dist/git/log.js +116 -0
- package/dist/git/log.js.map +1 -0
- package/dist/git/snapshot.d.ts +4 -0
- package/dist/git/snapshot.d.ts.map +1 -0
- package/dist/git/snapshot.js +65 -0
- package/dist/git/snapshot.js.map +1 -0
- package/dist/instance/config.d.ts +19 -0
- package/dist/instance/config.d.ts.map +1 -0
- package/dist/instance/config.js +107 -0
- package/dist/instance/config.js.map +1 -0
- package/dist/instance/pool.d.ts +138 -0
- package/dist/instance/pool.d.ts.map +1 -0
- package/dist/instance/pool.js +335 -0
- package/dist/instance/pool.js.map +1 -0
- package/dist/instance/session.d.ts +140 -0
- package/dist/instance/session.d.ts.map +1 -0
- package/dist/instance/session.js +267 -0
- package/dist/instance/session.js.map +1 -0
- package/dist/logging.d.ts +108 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +120 -0
- package/dist/logging.js.map +1 -0
- package/dist/maad-md.d.ts +11 -0
- package/dist/maad-md.d.ts.map +1 -0
- package/dist/maad-md.js +252 -0
- package/dist/maad-md.js.map +1 -0
- package/dist/mcp/bulk-cap.d.ts +10 -0
- package/dist/mcp/bulk-cap.d.ts.map +1 -0
- package/dist/mcp/bulk-cap.js +37 -0
- package/dist/mcp/bulk-cap.js.map +1 -0
- package/dist/mcp/config.d.ts +18 -0
- package/dist/mcp/config.d.ts.map +1 -0
- package/dist/mcp/config.js +20 -0
- package/dist/mcp/config.js.map +1 -0
- package/dist/mcp/ctx.d.ts +17 -0
- package/dist/mcp/ctx.d.ts.map +1 -0
- package/dist/mcp/ctx.js +7 -0
- package/dist/mcp/ctx.js.map +1 -0
- package/dist/mcp/guardrails.d.ts +21 -0
- package/dist/mcp/guardrails.d.ts.map +1 -0
- package/dist/mcp/guardrails.js +39 -0
- package/dist/mcp/guardrails.js.map +1 -0
- package/dist/mcp/idempotency.d.ts +69 -0
- package/dist/mcp/idempotency.d.ts.map +1 -0
- package/dist/mcp/idempotency.js +168 -0
- package/dist/mcp/idempotency.js.map +1 -0
- package/dist/mcp/instance-reload.d.ts +23 -0
- package/dist/mcp/instance-reload.d.ts.map +1 -0
- package/dist/mcp/instance-reload.js +126 -0
- package/dist/mcp/instance-reload.js.map +1 -0
- package/dist/mcp/kinds.d.ts +22 -0
- package/dist/mcp/kinds.d.ts.map +1 -0
- package/dist/mcp/kinds.js +110 -0
- package/dist/mcp/kinds.js.map +1 -0
- package/dist/mcp/lifecycle.d.ts +8 -0
- package/dist/mcp/lifecycle.d.ts.map +1 -0
- package/dist/mcp/lifecycle.js +65 -0
- package/dist/mcp/lifecycle.js.map +1 -0
- package/dist/mcp/notifications.d.ts +87 -0
- package/dist/mcp/notifications.d.ts.map +1 -0
- package/dist/mcp/notifications.js +154 -0
- package/dist/mcp/notifications.js.map +1 -0
- package/dist/mcp/query-depth.d.ts +28 -0
- package/dist/mcp/query-depth.d.ts.map +1 -0
- package/dist/mcp/query-depth.js +43 -0
- package/dist/mcp/query-depth.js.map +1 -0
- package/dist/mcp/rate-limit.d.ts +60 -0
- package/dist/mcp/rate-limit.d.ts.map +1 -0
- package/dist/mcp/rate-limit.js +203 -0
- package/dist/mcp/rate-limit.js.map +1 -0
- package/dist/mcp/reload-signal.d.ts +13 -0
- package/dist/mcp/reload-signal.d.ts.map +1 -0
- package/dist/mcp/reload-signal.js +68 -0
- package/dist/mcp/reload-signal.js.map +1 -0
- package/dist/mcp/response.d.ts +109 -0
- package/dist/mcp/response.d.ts.map +1 -0
- package/dist/mcp/response.js +132 -0
- package/dist/mcp/response.js.map +1 -0
- package/dist/mcp/roles.d.ts +7 -0
- package/dist/mcp/roles.d.ts.map +1 -0
- package/dist/mcp/roles.js +56 -0
- package/dist/mcp/roles.js.map +1 -0
- package/dist/mcp/server.d.ts +33 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +242 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/shutdown.d.ts +32 -0
- package/dist/mcp/shutdown.d.ts.map +1 -0
- package/dist/mcp/shutdown.js +130 -0
- package/dist/mcp/shutdown.js.map +1 -0
- package/dist/mcp/tools/audit.d.ts +4 -0
- package/dist/mcp/tools/audit.d.ts.map +1 -0
- package/dist/mcp/tools/audit.js +45 -0
- package/dist/mcp/tools/audit.js.map +1 -0
- package/dist/mcp/tools/auth.d.ts +4 -0
- package/dist/mcp/tools/auth.d.ts.map +1 -0
- package/dist/mcp/tools/auth.js +181 -0
- package/dist/mcp/tools/auth.js.map +1 -0
- package/dist/mcp/tools/discover.d.ts +4 -0
- package/dist/mcp/tools/discover.d.ts.map +1 -0
- package/dist/mcp/tools/discover.js +83 -0
- package/dist/mcp/tools/discover.js.map +1 -0
- package/dist/mcp/tools/instance.d.ts +15 -0
- package/dist/mcp/tools/instance.d.ts.map +1 -0
- package/dist/mcp/tools/instance.js +207 -0
- package/dist/mcp/tools/instance.js.map +1 -0
- package/dist/mcp/tools/maintain.d.ts +4 -0
- package/dist/mcp/tools/maintain.d.ts.map +1 -0
- package/dist/mcp/tools/maintain.js +118 -0
- package/dist/mcp/tools/maintain.js.map +1 -0
- package/dist/mcp/tools/read.d.ts +4 -0
- package/dist/mcp/tools/read.d.ts.map +1 -0
- package/dist/mcp/tools/read.js +260 -0
- package/dist/mcp/tools/read.js.map +1 -0
- package/dist/mcp/tools/write.d.ts +4 -0
- package/dist/mcp/tools/write.d.ts.map +1 -0
- package/dist/mcp/tools/write.js +342 -0
- package/dist/mcp/tools/write.js.map +1 -0
- package/dist/mcp/transport/auth.d.ts +41 -0
- package/dist/mcp/transport/auth.d.ts.map +1 -0
- package/dist/mcp/transport/auth.js +115 -0
- package/dist/mcp/transport/auth.js.map +1 -0
- package/dist/mcp/transport/http.d.ts +62 -0
- package/dist/mcp/transport/http.d.ts.map +1 -0
- package/dist/mcp/transport/http.js +357 -0
- package/dist/mcp/transport/http.js.map +1 -0
- package/dist/mcp/transport/pin.d.ts +15 -0
- package/dist/mcp/transport/pin.d.ts.map +1 -0
- package/dist/mcp/transport/pin.js +71 -0
- package/dist/mcp/transport/pin.js.map +1 -0
- package/dist/mcp/transport/telemetry.d.ts +79 -0
- package/dist/mcp/transport/telemetry.d.ts.map +1 -0
- package/dist/mcp/transport/telemetry.js +97 -0
- package/dist/mcp/transport/telemetry.js.map +1 -0
- package/dist/mcp/with-session.d.ts +26 -0
- package/dist/mcp/with-session.d.ts.map +1 -0
- package/dist/mcp/with-session.js +275 -0
- package/dist/mcp/with-session.js.map +1 -0
- package/dist/parser/annotations.d.ts +3 -0
- package/dist/parser/annotations.d.ts.map +1 -0
- package/dist/parser/annotations.js +41 -0
- package/dist/parser/annotations.js.map +1 -0
- package/dist/parser/blocks.d.ts +3 -0
- package/dist/parser/blocks.d.ts.map +1 -0
- package/dist/parser/blocks.js +99 -0
- package/dist/parser/blocks.js.map +1 -0
- package/dist/parser/frontmatter.d.ts +9 -0
- package/dist/parser/frontmatter.d.ts.map +1 -0
- package/dist/parser/frontmatter.js +33 -0
- package/dist/parser/frontmatter.js.map +1 -0
- package/dist/parser/index.d.ts +11 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +54 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/matter.d.ts +3 -0
- package/dist/parser/matter.d.ts.map +1 -0
- package/dist/parser/matter.js +32 -0
- package/dist/parser/matter.js.map +1 -0
- package/dist/parser/tags.d.ts +3 -0
- package/dist/parser/tags.d.ts.map +1 -0
- package/dist/parser/tags.js +32 -0
- package/dist/parser/tags.js.map +1 -0
- package/dist/parser/verbatim.d.ts +4 -0
- package/dist/parser/verbatim.d.ts.map +1 -0
- package/dist/parser/verbatim.js +121 -0
- package/dist/parser/verbatim.js.map +1 -0
- package/dist/parser/yaml-profile.d.ts +4 -0
- package/dist/parser/yaml-profile.d.ts.map +1 -0
- package/dist/parser/yaml-profile.js +73 -0
- package/dist/parser/yaml-profile.js.map +1 -0
- package/dist/registry/index.d.ts +2 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +2 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/loader.d.ts +4 -0
- package/dist/registry/loader.d.ts.map +1 -0
- package/dist/registry/loader.js +147 -0
- package/dist/registry/loader.js.map +1 -0
- package/dist/registry/types.d.ts +2 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +5 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/scanner.d.ts +57 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +223 -0
- package/dist/scanner.js.map +1 -0
- package/dist/schema/index.d.ts +3 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +3 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/loader.d.ts +4 -0
- package/dist/schema/loader.d.ts.map +1 -0
- package/dist/schema/loader.js +303 -0
- package/dist/schema/loader.js.map +1 -0
- package/dist/schema/precision.d.ts +6 -0
- package/dist/schema/precision.d.ts.map +1 -0
- package/dist/schema/precision.js +59 -0
- package/dist/schema/precision.js.map +1 -0
- package/dist/schema/validator.d.ts +21 -0
- package/dist/schema/validator.d.ts.map +1 -0
- package/dist/schema/validator.js +200 -0
- package/dist/schema/validator.js.map +1 -0
- package/dist/schema-md.d.ts +8 -0
- package/dist/schema-md.d.ts.map +1 -0
- package/dist/schema-md.js +98 -0
- package/dist/schema-md.js.map +1 -0
- package/dist/skill-files.d.ts +3 -0
- package/dist/skill-files.d.ts.map +1 -0
- package/dist/skill-files.js +362 -0
- package/dist/skill-files.js.map +1 -0
- package/dist/skills-scaffold.d.ts +10 -0
- package/dist/skills-scaffold.d.ts.map +1 -0
- package/dist/skills-scaffold.js +52 -0
- package/dist/skills-scaffold.js.map +1 -0
- package/dist/types.d.ts +309 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +111 -0
- package/dist/types.js.map +1 -0
- package/dist/writer/index.d.ts +7 -0
- package/dist/writer/index.d.ts.map +1 -0
- package/dist/writer/index.js +32 -0
- package/dist/writer/index.js.map +1 -0
- package/dist/writer/serializer.d.ts +4 -0
- package/dist/writer/serializer.d.ts.map +1 -0
- package/dist/writer/serializer.js +103 -0
- package/dist/writer/serializer.js.map +1 -0
- package/dist/writer/template.d.ts +3 -0
- package/dist/writer/template.d.ts.map +1 -0
- package/dist/writer/template.js +27 -0
- package/dist/writer/template.js.map +1 -0
- package/package.json +59 -7
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Instance tools — maad_projects, maad_use_project, maad_use_projects,
|
|
3
|
+
// maad_current_session
|
|
4
|
+
//
|
|
5
|
+
// These four tools operate at the instance level (no project binding required).
|
|
6
|
+
// They let clients discover and bind to projects served by this MCP instance.
|
|
7
|
+
// ============================================================================
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { successResponse, errorResponse } from '../response.js';
|
|
10
|
+
import { resolveSessionId } from '../../instance/session.js';
|
|
11
|
+
import { performInstanceReload } from '../instance-reload.js';
|
|
12
|
+
import { roleSatisfies } from '../roles.js';
|
|
13
|
+
import { maadError } from '../../errors.js';
|
|
14
|
+
import { collectSubscriptions } from '../notifications.js';
|
|
15
|
+
const ROLE_ENUM = z.enum(['reader', 'writer', 'admin']);
|
|
16
|
+
export function register(server, ctx) {
|
|
17
|
+
server.registerTool('maad_projects', {
|
|
18
|
+
description: 'Lists projects declared in this MCP instance. Returns name, description, configured role, and whether the current session has access. Call this before maad_use_project.',
|
|
19
|
+
inputSchema: z.object({}),
|
|
20
|
+
}, async (_args, extra) => {
|
|
21
|
+
const sessionId = resolveSessionId(extra);
|
|
22
|
+
const state = ctx.sessions.get(sessionId);
|
|
23
|
+
const projects = ctx.instance.projects.map((p) => ({
|
|
24
|
+
name: p.name,
|
|
25
|
+
description: p.description ?? null,
|
|
26
|
+
role: p.role,
|
|
27
|
+
accessible: state?.mode === null || !state
|
|
28
|
+
? null
|
|
29
|
+
: state.mode === 'single'
|
|
30
|
+
? state.activeProject === p.name
|
|
31
|
+
: (state.whitelist ?? []).includes(p.name),
|
|
32
|
+
}));
|
|
33
|
+
return successResponse({
|
|
34
|
+
instance: ctx.instance.name,
|
|
35
|
+
source: ctx.instance.source,
|
|
36
|
+
projects,
|
|
37
|
+
sessionBound: state?.mode !== null && state !== undefined,
|
|
38
|
+
}, 'maad_projects');
|
|
39
|
+
});
|
|
40
|
+
server.registerTool('maad_use_project', {
|
|
41
|
+
description: 'Binds the current session to a single project. Every subsequent tool call routes to this project. Optional `as` downgrades the session role below the project\'s configured role (e.g. bind an admin project in reader mode for safety). Once bound, a session cannot rebind — disconnect and reconnect instead.',
|
|
42
|
+
inputSchema: z.object({
|
|
43
|
+
name: z.string().describe('Project name (from maad_projects)'),
|
|
44
|
+
as: ROLE_ENUM.optional().describe('Optional role downgrade. Cannot exceed the project\'s configured role.'),
|
|
45
|
+
}),
|
|
46
|
+
}, async (args, extra) => {
|
|
47
|
+
const sessionId = resolveSessionId(extra);
|
|
48
|
+
if (!ctx.sessions.get(sessionId))
|
|
49
|
+
ctx.sessions.create(sessionId);
|
|
50
|
+
const opts = args.as ? { as: args.as } : {};
|
|
51
|
+
const result = ctx.sessions.bindSingle(sessionId, args.name, opts);
|
|
52
|
+
if (!result.ok)
|
|
53
|
+
return errorResponse(result.errors);
|
|
54
|
+
const state = result.value;
|
|
55
|
+
return successResponse({
|
|
56
|
+
mode: state.mode,
|
|
57
|
+
activeProject: state.activeProject,
|
|
58
|
+
effectiveRole: state.effectiveRoles.get(args.name),
|
|
59
|
+
}, 'maad_use_project');
|
|
60
|
+
});
|
|
61
|
+
server.registerTool('maad_use_projects', {
|
|
62
|
+
description: 'Binds the current session to a whitelist of projects (multi-project mode). Every subsequent tool call must pass `project=<name>` to pick one. Optional `as` downgrades the role uniformly across all listed projects. Once bound, a session cannot rebind.',
|
|
63
|
+
inputSchema: z.object({
|
|
64
|
+
names: z.array(z.string()).min(1).describe('Project names from maad_projects'),
|
|
65
|
+
as: ROLE_ENUM.optional().describe('Optional role downgrade. Cannot exceed any project\'s configured role.'),
|
|
66
|
+
}),
|
|
67
|
+
}, async (args, extra) => {
|
|
68
|
+
const sessionId = resolveSessionId(extra);
|
|
69
|
+
if (!ctx.sessions.get(sessionId))
|
|
70
|
+
ctx.sessions.create(sessionId);
|
|
71
|
+
const opts = args.as ? { as: args.as } : {};
|
|
72
|
+
const result = ctx.sessions.bindMulti(sessionId, args.names, opts);
|
|
73
|
+
if (!result.ok)
|
|
74
|
+
return errorResponse(result.errors);
|
|
75
|
+
const state = result.value;
|
|
76
|
+
const effectiveRoles = {};
|
|
77
|
+
for (const [name, role] of state.effectiveRoles)
|
|
78
|
+
effectiveRoles[name] = role;
|
|
79
|
+
return successResponse({
|
|
80
|
+
mode: state.mode,
|
|
81
|
+
whitelist: state.whitelist,
|
|
82
|
+
effectiveRoles,
|
|
83
|
+
}, 'maad_use_projects');
|
|
84
|
+
});
|
|
85
|
+
server.registerTool('maad_current_session', {
|
|
86
|
+
description: 'Returns the current session state: mode, bound project(s), effective role per project, and binding_source (how the session was bound — client_tool or gateway_pin). Useful for debugging routing issues and detecting pinned sessions.',
|
|
87
|
+
inputSchema: z.object({}),
|
|
88
|
+
}, async (_args, extra) => {
|
|
89
|
+
const sessionId = resolveSessionId(extra);
|
|
90
|
+
const state = ctx.sessions.get(sessionId);
|
|
91
|
+
if (!state) {
|
|
92
|
+
return successResponse({ sessionId, mode: null, binding_source: null, note: 'no session registered yet' }, 'maad_current_session');
|
|
93
|
+
}
|
|
94
|
+
const effectiveRoles = {};
|
|
95
|
+
for (const [name, role] of state.effectiveRoles)
|
|
96
|
+
effectiveRoles[name] = role;
|
|
97
|
+
return successResponse({
|
|
98
|
+
sessionId: state.sessionId,
|
|
99
|
+
mode: state.mode,
|
|
100
|
+
activeProject: state.activeProject ?? null,
|
|
101
|
+
whitelist: state.whitelist ?? null,
|
|
102
|
+
effectiveRoles,
|
|
103
|
+
binding_source: state.bindingSource,
|
|
104
|
+
createdAt: state.createdAt.toISOString(),
|
|
105
|
+
lastActivityAt: state.lastActivityAt.toISOString(),
|
|
106
|
+
subscription: state.subscription
|
|
107
|
+
? { docTypes: state.subscription.docTypes, project: state.subscription.project, createdAt: state.subscription.createdAt.toISOString() }
|
|
108
|
+
: null,
|
|
109
|
+
}, 'maad_current_session');
|
|
110
|
+
});
|
|
111
|
+
server.registerTool('maad_subscribe', {
|
|
112
|
+
description: 'Subscribe the current session to live notifications on durable writes. Optional filters: docTypes (array), project (string). Emits notifications/resources/updated with uri=maad://records/<docId> + extra params. One subscription per session; re-subscribe to replace filter.',
|
|
113
|
+
inputSchema: z.object({
|
|
114
|
+
docTypes: z.array(z.string()).optional().describe('Allowlist of doc types; omit for all types'),
|
|
115
|
+
project: z.string().optional().describe('Restrict to one project; defaults to session\'s bound scope'),
|
|
116
|
+
}),
|
|
117
|
+
}, async (args, extra) => {
|
|
118
|
+
const sessionId = resolveSessionId(extra);
|
|
119
|
+
if (!ctx.sessions.get(sessionId))
|
|
120
|
+
ctx.sessions.create(sessionId);
|
|
121
|
+
const state = ctx.sessions.get(sessionId);
|
|
122
|
+
const docTypes = (args.docTypes && args.docTypes.length > 0) ? args.docTypes : null;
|
|
123
|
+
const project = args.project ?? null;
|
|
124
|
+
state.subscription = { docTypes, project, createdAt: new Date() };
|
|
125
|
+
return successResponse({
|
|
126
|
+
subscribed: true,
|
|
127
|
+
filter: { docTypes, project },
|
|
128
|
+
note: 'Notifications fire only on durable commits. Use maad_changes_since for historical catch-up on reconnect.',
|
|
129
|
+
}, 'maad_subscribe');
|
|
130
|
+
});
|
|
131
|
+
server.registerTool('maad_unsubscribe', {
|
|
132
|
+
description: 'Releases the current session\'s live-update subscription. No-op if not subscribed.',
|
|
133
|
+
inputSchema: z.object({}),
|
|
134
|
+
}, async (_args, extra) => {
|
|
135
|
+
const sessionId = resolveSessionId(extra);
|
|
136
|
+
const state = ctx.sessions.get(sessionId);
|
|
137
|
+
const wasSubscribed = state?.subscription !== undefined;
|
|
138
|
+
if (state)
|
|
139
|
+
delete state.subscription;
|
|
140
|
+
return successResponse({ subscribed: false, wasSubscribed }, 'maad_unsubscribe');
|
|
141
|
+
});
|
|
142
|
+
return 6;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Registers the admin-only `maad_instance_reload` tool separately from the
|
|
146
|
+
* base instance tools. Called regardless of instance source so synthetic
|
|
147
|
+
* instances can surface a clear INSTANCE_RELOAD_SYNTHETIC error rather than
|
|
148
|
+
* an opaque "unknown tool" response.
|
|
149
|
+
*
|
|
150
|
+
* Role gate lives inside the handler (engine-less tools bypass the `withEngine`
|
|
151
|
+
* role check). Requires admin effective role on EVERY project in the session's
|
|
152
|
+
* binding — least privilege, since reload is instance-wide.
|
|
153
|
+
*/
|
|
154
|
+
export function registerReload(server, ctx) {
|
|
155
|
+
server.registerTool('maad_instance_reload', {
|
|
156
|
+
description: 'Reloads instance.yaml from disk. Picks up added projects, evicts removed, cancels bound sessions. Admin on every bound project required. Path/role mutations rejected until 0.9.0.',
|
|
157
|
+
inputSchema: z.object({}),
|
|
158
|
+
}, async (_args, extra) => {
|
|
159
|
+
const sessionId = resolveSessionId(extra);
|
|
160
|
+
const state = ctx.sessions.get(sessionId);
|
|
161
|
+
// Session must be bound before an admin check makes sense.
|
|
162
|
+
if (!state || state.mode === null) {
|
|
163
|
+
return errorResponse([maadError('SESSION_UNBOUND', 'Session is not bound to any project. Call maad_use_project(s) before maad_instance_reload.')]);
|
|
164
|
+
}
|
|
165
|
+
// Admin on EVERY project in the binding. In single mode that's one project;
|
|
166
|
+
// in multi mode it's the whole whitelist. Prevents an operator who only
|
|
167
|
+
// has admin on one subproject from reloading the whole instance and
|
|
168
|
+
// affecting other tenants.
|
|
169
|
+
for (const [projectName, role] of state.effectiveRoles) {
|
|
170
|
+
if (!roleSatisfies(role, 'admin')) {
|
|
171
|
+
return errorResponse([maadError('INSUFFICIENT_ROLE', `maad_instance_reload requires admin on every project in the session binding; session has "${role}" on "${projectName}".`)]);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const result = await performInstanceReload(ctx, 'tool');
|
|
175
|
+
if (!result.ok)
|
|
176
|
+
return errorResponse(result.errors);
|
|
177
|
+
return successResponse({
|
|
178
|
+
source: result.value.source,
|
|
179
|
+
projectsAdded: result.value.projectsAdded,
|
|
180
|
+
projectsRemoved: result.value.projectsRemoved,
|
|
181
|
+
sessionsCancelled: result.value.sessionsCancelled.length,
|
|
182
|
+
sessionsPruned: result.value.sessionsPruned.length,
|
|
183
|
+
durationMs: result.value.durationMs,
|
|
184
|
+
}, 'maad_instance_reload');
|
|
185
|
+
});
|
|
186
|
+
server.registerTool('maad_subscriptions', {
|
|
187
|
+
description: 'Admin tool: returns live-subscription inventory across all sessions as { totalSubscriptions, subscriptions[], byProject, byDocType }. Requires admin on every project in the session binding.',
|
|
188
|
+
inputSchema: z.object({}),
|
|
189
|
+
}, async (_args, extra) => {
|
|
190
|
+
const sessionId = resolveSessionId(extra);
|
|
191
|
+
const callerState = ctx.sessions.get(sessionId);
|
|
192
|
+
if (!callerState || callerState.mode === null) {
|
|
193
|
+
return errorResponse([maadError('SESSION_UNBOUND', 'Session is not bound to any project. Call maad_use_project(s) before maad_subscriptions.')]);
|
|
194
|
+
}
|
|
195
|
+
// Admin on EVERY project in the binding — same model as maad_instance_reload.
|
|
196
|
+
// The tool leaks instance-wide state, so require admin across the caller's full scope.
|
|
197
|
+
for (const [projectName, role] of callerState.effectiveRoles) {
|
|
198
|
+
if (!roleSatisfies(role, 'admin')) {
|
|
199
|
+
return errorResponse([maadError('INSUFFICIENT_ROLE', `maad_subscriptions requires admin on every project in the session binding; session has "${role}" on "${projectName}".`)]);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const inventory = collectSubscriptions(ctx.sessions);
|
|
203
|
+
return successResponse(inventory, 'maad_subscriptions');
|
|
204
|
+
});
|
|
205
|
+
return 2;
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=instance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance.js","sourceRoot":"","sources":["../../../src/mcp/tools/instance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintain.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/maintain.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI7C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,MAAM,CAgHpE"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Maintain tools — maad_delete, maad_reindex, maad_reload, maad_health
|
|
3
|
+
// ============================================================================
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { docId } from '../../types.js';
|
|
6
|
+
import { resultToResponse, successResponse, getProvenanceMode, attachDurability } from '../response.js';
|
|
7
|
+
import { notifyWrite } from '../notifications.js';
|
|
8
|
+
import { isDryRun, dryRunResponse, auditToolCall } from '../guardrails.js';
|
|
9
|
+
import { withEngine } from '../with-session.js';
|
|
10
|
+
import { getTransportSnapshot, isInitialized as telemetryInitialized } from '../transport/telemetry.js';
|
|
11
|
+
export function register(server, ctx) {
|
|
12
|
+
server.registerTool('maad_delete', {
|
|
13
|
+
description: 'Deletes a record. Soft: renames file with _deleted prefix. Hard: removes file entirely.',
|
|
14
|
+
inputSchema: z.object({
|
|
15
|
+
docId: z.string().describe('Document ID to delete'),
|
|
16
|
+
mode: z.enum(['soft', 'hard']).default('soft').describe('soft=rename, hard=remove file'),
|
|
17
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
18
|
+
}),
|
|
19
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_delete', args, async ({ engine, projectName }) => {
|
|
20
|
+
auditToolCall('maad_delete', args);
|
|
21
|
+
if (isDryRun())
|
|
22
|
+
return dryRunResponse('maad_delete', args);
|
|
23
|
+
const result = await engine.deleteDocument(docId(args.docId), args.mode);
|
|
24
|
+
const response = resultToResponse(result);
|
|
25
|
+
if (!result.ok)
|
|
26
|
+
return response;
|
|
27
|
+
const value = result.value;
|
|
28
|
+
if (value.writeDurable) {
|
|
29
|
+
await notifyWrite(ctx, {
|
|
30
|
+
action: 'delete',
|
|
31
|
+
docId: String(value.docId),
|
|
32
|
+
docType: String(value.docType),
|
|
33
|
+
project: projectName,
|
|
34
|
+
updatedAt: new Date().toISOString(),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return attachDurability(response, value.writeDurable, value.commitFailure);
|
|
38
|
+
}));
|
|
39
|
+
server.registerTool('maad_reindex', {
|
|
40
|
+
description: 'Rebuilds the SQLite index from markdown files. Use after external file changes or to recover from stale state. Auto-detects per-type schema-index changes and rebuilds affected types even when files are byte-identical (rebuiltTypes lists them in the response).',
|
|
41
|
+
inputSchema: z.object({
|
|
42
|
+
force: z.boolean().optional().default(false).describe('Force full rebuild (skip both hash check and the schema-fingerprint shortcut). Rarely needed since 0.7.4 — the engine now auto-rebuilds types whose indexed-field set changed.'),
|
|
43
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
44
|
+
}),
|
|
45
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_reindex', args, async ({ engine }) => {
|
|
46
|
+
return resultToResponse(await engine.reindex({ force: args.force }));
|
|
47
|
+
}));
|
|
48
|
+
server.registerTool('maad_reload', {
|
|
49
|
+
description: 'Reloads the engine — picks up new registry, schemas, and type directories without restarting the server. Use after changing _registry/ or _schema/ files.',
|
|
50
|
+
inputSchema: z.object({
|
|
51
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
52
|
+
}),
|
|
53
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_reload', args, async ({ engine }) => {
|
|
54
|
+
auditToolCall('maad_reload', {});
|
|
55
|
+
return resultToResponse(await engine.reload());
|
|
56
|
+
}));
|
|
57
|
+
server.registerTool('maad_health', {
|
|
58
|
+
description: 'Engine health + transport + session telemetry + instance reload stats. sessions block: {active, pinned, subscribed, byProject: {<project>:{<role>:count}}, byIdentity: {<agent_id|anonymous>:count}, ...lifecycle counters}. instance block: {source, configPath?, projectCount, reload counters}.',
|
|
59
|
+
inputSchema: z.object({
|
|
60
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
61
|
+
}),
|
|
62
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_health', args, ({ engine }) => {
|
|
63
|
+
const health = engine.health();
|
|
64
|
+
const provMode = getProvenanceMode();
|
|
65
|
+
// Telemetry may be uninitialized in test contexts that build an engine
|
|
66
|
+
// without going through startServer. Fall back gracefully so maad_health
|
|
67
|
+
// stays useful in those environments.
|
|
68
|
+
const pinnedCount = ctx.sessions.snapshot().filter(s => s.bindingSource === 'gateway_pin').length;
|
|
69
|
+
const telemetry = telemetryInitialized()
|
|
70
|
+
? getTransportSnapshot(ctx.sessions.size(), pinnedCount)
|
|
71
|
+
: null;
|
|
72
|
+
// 0.6.12 — subscribed-session counter for cheap observability. Admins
|
|
73
|
+
// grep `subscribed > 0` to confirm push-based delivery is in use at all;
|
|
74
|
+
// full inventory is the admin-only maad_subscriptions tool.
|
|
75
|
+
const subscribedCount = ctx.sessions.snapshot().filter(s => s.subscription !== undefined).length;
|
|
76
|
+
// 0.7.0 — byProject + byIdentity aggregates (spec v2 fix #4: byProject
|
|
77
|
+
// replaces the ambiguous flat byRole because multi-project sessions
|
|
78
|
+
// carry different roles per project). byProject counts session×project
|
|
79
|
+
// pairs grouped by role so the inner sums can exceed `active` when
|
|
80
|
+
// multi-mode sessions exist. byIdentity counts DISTINCT sessions per
|
|
81
|
+
// agent_id; sessions with no token bucket under 'anonymous'.
|
|
82
|
+
const byProject = {};
|
|
83
|
+
const byIdentity = {};
|
|
84
|
+
for (const state of ctx.sessions.snapshot()) {
|
|
85
|
+
for (const [projectName, role] of state.effectiveRoles) {
|
|
86
|
+
const bucket = byProject[projectName] ?? (byProject[projectName] = {});
|
|
87
|
+
bucket[role] = (bucket[role] ?? 0) + 1;
|
|
88
|
+
}
|
|
89
|
+
const ident = state.token?.agentId ?? 'anonymous';
|
|
90
|
+
byIdentity[ident] = (byIdentity[ident] ?? 0) + 1;
|
|
91
|
+
}
|
|
92
|
+
// 0.6.9 — instance reload stats, always included. Operators watching
|
|
93
|
+
// hot-reload behavior (cohort expansion, tenant churn) filter on this
|
|
94
|
+
// block to verify their last reload landed + projectCount is current.
|
|
95
|
+
const reloadStats = ctx.pool.reloadStats();
|
|
96
|
+
const instanceBlock = {
|
|
97
|
+
name: ctx.instance.name,
|
|
98
|
+
source: ctx.instance.source,
|
|
99
|
+
configPath: ctx.instance.configPath ?? null,
|
|
100
|
+
projectCount: ctx.instance.projects.length,
|
|
101
|
+
lastReloadAt: reloadStats.lastReloadAt ? reloadStats.lastReloadAt.toISOString() : null,
|
|
102
|
+
reloadsAttempted: reloadStats.reloadsAttempted,
|
|
103
|
+
reloadsSucceeded: reloadStats.reloadsSucceeded,
|
|
104
|
+
reloadsFailed: reloadStats.reloadsFailed,
|
|
105
|
+
projectsAdded: reloadStats.projectsAdded,
|
|
106
|
+
projectsRemoved: reloadStats.projectsRemoved,
|
|
107
|
+
};
|
|
108
|
+
const sessionsBlock = telemetry
|
|
109
|
+
? { ...telemetry.sessions, subscribed: subscribedCount, byProject, byIdentity }
|
|
110
|
+
: { subscribed: subscribedCount, byProject, byIdentity };
|
|
111
|
+
const payload = telemetry
|
|
112
|
+
? { ...health, provenance: provMode, transport: telemetry.transport, sessions: sessionsBlock, instance: instanceBlock }
|
|
113
|
+
: { ...health, provenance: provMode, sessions: sessionsBlock, instance: instanceBlock };
|
|
114
|
+
return successResponse(payload, 'maad_health');
|
|
115
|
+
}));
|
|
116
|
+
return 4;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=maintain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintain.js","sourceRoot":"","sources":["../../../src/mcp/tools/maintain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/read.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAI7C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,MAAM,CAyOpE"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// Read tools — maad_get, maad_query, maad_search, maad_related, maad_schema,
|
|
3
|
+
// maad_aggregate, maad_verify, maad_join
|
|
4
|
+
// ============================================================================
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { docId, docType } from '../../types.js';
|
|
7
|
+
import { resultToResponse, attachMeta, guardResponseSize } from '../response.js';
|
|
8
|
+
import { withEngine } from '../with-session.js';
|
|
9
|
+
import { hydrateQueryRows } from '../query-depth.js';
|
|
10
|
+
export function register(server, ctx) {
|
|
11
|
+
server.registerTool('maad_get', {
|
|
12
|
+
description: 'Reads a markdown-backed record at increasing depth: hot (frontmatter), warm (+block), cold (full body), full (resolved refs+objects+related, provisional composite).',
|
|
13
|
+
inputSchema: z.object({
|
|
14
|
+
docId: z.string().describe('Document ID to read'),
|
|
15
|
+
depth: z.enum(['hot', 'warm', 'cold', 'full']).default('hot')
|
|
16
|
+
.describe('hot=frontmatter, warm=+block, cold=full body, full=resolved refs+objects+related'),
|
|
17
|
+
block: z.string().optional().describe('Block ID or heading (warm depth only)'),
|
|
18
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
19
|
+
}),
|
|
20
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_get', args, async ({ engine }) => {
|
|
21
|
+
if (args.depth === 'full') {
|
|
22
|
+
return resultToResponse(await engine.getDocumentFull(docId(args.docId)), 'maad_get');
|
|
23
|
+
}
|
|
24
|
+
return resultToResponse(await engine.getDocument(docId(args.docId), args.depth, args.block ?? undefined), 'maad_get');
|
|
25
|
+
}));
|
|
26
|
+
server.registerTool('maad_query', {
|
|
27
|
+
description: 'Finds documents by type with optional field filters and projection. Filters support shorthand eq, single-op, between shortcut, and array-of-ops (AND semantics). Use fields to return frontmatter values inline instead of chasing IDs. Set depth=cold to return record bodies inline (kills query-then-N-gets pattern), depth=full to return full composite (refs+objects+related) per row.',
|
|
28
|
+
inputSchema: z.object({
|
|
29
|
+
docType: z.string().describe('Document type to query'),
|
|
30
|
+
filters: z.any().optional().describe('Field filters. Shorthand: { status: "active" }. Single op: { opened_at: { op: "gte", value: "2026-01-01" } }. Range shortcut: { opened_at: { op: "between", value: ["2026-03-01", "2026-03-31"] } }. Array-of-ops (AND): { opened_at: [{op: "gte", value: "2026-03-01"}, {op: "lte", value: "2026-03-31"}] }. Ops: eq, neq, gt, gte, lt, lte, in, contains, between.'),
|
|
31
|
+
fields: z.array(z.string()).optional().describe('Field names to return inline (e.g. ["name", "status"]). Indexed fields only.'),
|
|
32
|
+
sortBy: z.string().optional().describe('Indexed field to sort by'),
|
|
33
|
+
sortOrder: z.enum(['asc', 'desc']).optional().describe('Sort direction (default desc)'),
|
|
34
|
+
limit: z.number().optional().describe('Max results (default 50, capped at 500). Over-requests are clamped silently with _meta.limit_clamped set.'),
|
|
35
|
+
offset: z.number().optional().describe('Skip first N results'),
|
|
36
|
+
depth: z.enum(['hot', 'cold', 'full']).optional().describe('hot (default) = pointer + projected fields only; cold = adds body to each row; full = adds resolved composite (refs+objects+related). cold/full bound by depth_max_results (default 50, capped at 100) to prevent payload blowups.'),
|
|
37
|
+
depthMaxResults: z.number().optional().describe('When depth=cold|full, hydrate at most N rows (default 50, capped at 100). Beyond cap, remaining rows return at hot depth.'),
|
|
38
|
+
includeFilePath: z.boolean().optional().describe('Include filePath in each result row (default false — omitted to trim response size)'),
|
|
39
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
40
|
+
}),
|
|
41
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_query', args, async ({ engine }) => {
|
|
42
|
+
const query = { docType: docType(args.docType) };
|
|
43
|
+
if (args.filters !== undefined)
|
|
44
|
+
query.filters = args.filters;
|
|
45
|
+
if (args.fields !== undefined)
|
|
46
|
+
query.fields = args.fields;
|
|
47
|
+
if (args.sortBy !== undefined)
|
|
48
|
+
query.sortBy = args.sortBy;
|
|
49
|
+
if (args.sortOrder !== undefined)
|
|
50
|
+
query.sortOrder = args.sortOrder;
|
|
51
|
+
if (args.limit !== undefined)
|
|
52
|
+
query.limit = args.limit;
|
|
53
|
+
if (args.offset !== undefined)
|
|
54
|
+
query.offset = args.offset;
|
|
55
|
+
const result = engine.findDocuments(query);
|
|
56
|
+
// 0.7.0 — default-strip filePath to trim response size. Clients that
|
|
57
|
+
// need the on-disk path opt in via includeFilePath:true. Backend still
|
|
58
|
+
// produces the field; we drop it at the MCP boundary.
|
|
59
|
+
let effective = result;
|
|
60
|
+
if (result.ok && args.includeFilePath !== true) {
|
|
61
|
+
const stripped = result.value.results.map(r => {
|
|
62
|
+
const { filePath, ...rest } = r;
|
|
63
|
+
void filePath;
|
|
64
|
+
return rest;
|
|
65
|
+
});
|
|
66
|
+
const newValue = {
|
|
67
|
+
total: result.value.total,
|
|
68
|
+
results: stripped,
|
|
69
|
+
};
|
|
70
|
+
if (result.value.limitClamped)
|
|
71
|
+
newValue.limitClamped = result.value.limitClamped;
|
|
72
|
+
effective = { ok: true, value: newValue };
|
|
73
|
+
}
|
|
74
|
+
// 0.7.3 (fup-2026-079[a]) — depth hydration. Composite that kills the
|
|
75
|
+
// query-then-N-gets agent pattern.
|
|
76
|
+
let depthMeta = null;
|
|
77
|
+
if (effective.ok && (args.depth === 'cold' || args.depth === 'full')) {
|
|
78
|
+
const hydrateOpts = { depth: args.depth };
|
|
79
|
+
if (args.depthMaxResults !== undefined)
|
|
80
|
+
hydrateOpts.depthMaxResults = args.depthMaxResults;
|
|
81
|
+
const outcome = await hydrateQueryRows(engine, effective.value.results, hydrateOpts);
|
|
82
|
+
const newValue = {
|
|
83
|
+
total: effective.value.total,
|
|
84
|
+
results: outcome.rows,
|
|
85
|
+
};
|
|
86
|
+
if (effective.value.limitClamped)
|
|
87
|
+
newValue.limitClamped = effective.value.limitClamped;
|
|
88
|
+
effective = { ok: true, value: newValue };
|
|
89
|
+
depthMeta = outcome.meta;
|
|
90
|
+
}
|
|
91
|
+
let response = resultToResponse(effective, 'maad_query');
|
|
92
|
+
// 0.7.1 — surface engine limit-clamping in _meta, then guard response size.
|
|
93
|
+
if (effective.ok && effective.value.limitClamped) {
|
|
94
|
+
response = attachMeta(response, { limit_clamped: effective.value.limitClamped });
|
|
95
|
+
}
|
|
96
|
+
if (depthMeta) {
|
|
97
|
+
response = attachMeta(response, { depth: depthMeta });
|
|
98
|
+
}
|
|
99
|
+
return guardResponseSize(response, { tool: 'maad_query' });
|
|
100
|
+
}));
|
|
101
|
+
server.registerTool('maad_search', {
|
|
102
|
+
description: 'Searches extracted objects across all documents. Filter by primitive + optional subtype, then narrow with query (substring) or value (exact). Without query or value, returns ALL objects matching primitive/subtype.',
|
|
103
|
+
inputSchema: z.object({
|
|
104
|
+
primitive: z.string().describe('Extraction primitive (entity, date, amount, etc.)'),
|
|
105
|
+
subtype: z.string().optional().describe('Subtype filter (person, org, attorney, etc.)'),
|
|
106
|
+
query: z.string().optional().describe('Substring match on values (e.g. "Attorney" matches "Lead Attorney")'),
|
|
107
|
+
value: z.string().optional().describe('Exact value match (must match the full extracted value)'),
|
|
108
|
+
contains: z.string().optional().describe('Alias for query — substring match on values'),
|
|
109
|
+
docId: z.string().optional().describe('Scope search to a single document'),
|
|
110
|
+
limit: z.number().optional().describe('Max results (default 50)'),
|
|
111
|
+
offset: z.number().optional().describe('Skip first N results'),
|
|
112
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
113
|
+
}),
|
|
114
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_search', args, ({ engine }) => {
|
|
115
|
+
const query = { primitive: args.primitive };
|
|
116
|
+
if (args.subtype !== undefined)
|
|
117
|
+
query.subtype = args.subtype;
|
|
118
|
+
if (args.value !== undefined)
|
|
119
|
+
query.value = args.value;
|
|
120
|
+
const containsValue = args.query ?? args.contains;
|
|
121
|
+
if (containsValue !== undefined)
|
|
122
|
+
query.contains = containsValue;
|
|
123
|
+
if (args.docId !== undefined)
|
|
124
|
+
query.docId = docId(args.docId);
|
|
125
|
+
if (args.limit !== undefined)
|
|
126
|
+
query.limit = args.limit;
|
|
127
|
+
if (args.offset !== undefined)
|
|
128
|
+
query.offset = args.offset;
|
|
129
|
+
return resultToResponse(engine.searchObjects(query), 'maad_search');
|
|
130
|
+
}));
|
|
131
|
+
server.registerTool('maad_related', {
|
|
132
|
+
description: 'Returns documents connected to a given doc via ref fields.',
|
|
133
|
+
inputSchema: z.object({
|
|
134
|
+
docId: z.string().describe('Document ID'),
|
|
135
|
+
direction: z.enum(['outgoing', 'incoming', 'both']).default('both')
|
|
136
|
+
.describe('outgoing=docs this references, incoming=docs that reference this, both=all'),
|
|
137
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
138
|
+
}),
|
|
139
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_related', args, ({ engine }) => {
|
|
140
|
+
return resultToResponse(engine.listRelated(docId(args.docId), args.direction), 'maad_related');
|
|
141
|
+
}));
|
|
142
|
+
server.registerTool('maad_schema', {
|
|
143
|
+
description: 'Returns field definitions, required fields, enum values, ID prefix, and format hints for a type. Use before create/update to know what fields to pass and how to format values.',
|
|
144
|
+
inputSchema: z.object({
|
|
145
|
+
docType: z.string().describe('Document type'),
|
|
146
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
147
|
+
}),
|
|
148
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_schema', args, ({ engine }) => {
|
|
149
|
+
return resultToResponse(engine.schemaInfo(docType(args.docType)), 'maad_schema');
|
|
150
|
+
}));
|
|
151
|
+
server.registerTool('maad_aggregate', {
|
|
152
|
+
description: 'Groups documents by a field and optionally computes a metric (count/sum/avg/min/max) on another field. Supports multi-hop ref chains in groupBy (e.g. "client->industry") for cross-doctype aggregates — resolves refs at query time, merges groups that collapse to the same leaf value. Use instead of iterating records for totals.',
|
|
153
|
+
inputSchema: z.object({
|
|
154
|
+
docType: z.string().optional().describe('Document type to scope (optional; required for ref-chain groupBy)'),
|
|
155
|
+
groupBy: z.string().describe('Field name or ref chain to group by. Single field: "status". Multi-hop chain: "client_id->industry" or "case_id->account_id->name". Each non-leaf segment must be a ref field on its parent type.'),
|
|
156
|
+
metric: z.object({
|
|
157
|
+
field: z.string().describe('Field to aggregate (must be indexed, numeric for sum/avg/min/max)'),
|
|
158
|
+
op: z.enum(['count', 'sum', 'avg', 'min', 'max']).describe('Aggregation operation'),
|
|
159
|
+
}).optional().describe('Optional metric to compute per group. Without this, returns count per group value.'),
|
|
160
|
+
filters: z.any().optional().describe('Field filters (same format as maad_query — shorthand, single-op, between shortcut, array-of-ops with AND semantics).'),
|
|
161
|
+
limit: z.number().optional().describe('Max groups to return (default 50, capped at 2000). Over-requests are clamped silently with _meta.limit_clamped set.'),
|
|
162
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
163
|
+
}),
|
|
164
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_aggregate', args, ({ engine }) => {
|
|
165
|
+
const query = {
|
|
166
|
+
groupBy: args.groupBy,
|
|
167
|
+
};
|
|
168
|
+
if (args.docType !== undefined)
|
|
169
|
+
query.docType = docType(args.docType);
|
|
170
|
+
if (args.metric !== undefined)
|
|
171
|
+
query.metric = args.metric;
|
|
172
|
+
if (args.filters !== undefined)
|
|
173
|
+
query.filters = args.filters;
|
|
174
|
+
if (args.limit !== undefined)
|
|
175
|
+
query.limit = args.limit;
|
|
176
|
+
const result = engine.aggregate(query);
|
|
177
|
+
let response = resultToResponse(result, 'maad_aggregate');
|
|
178
|
+
// 0.7.1 — surface engine limit-clamping in _meta, then guard response size.
|
|
179
|
+
if (result.ok && result.value.limitClamped) {
|
|
180
|
+
response = attachMeta(response, { limit_clamped: result.value.limitClamped });
|
|
181
|
+
}
|
|
182
|
+
return guardResponseSize(response, { tool: 'maad_aggregate' });
|
|
183
|
+
}));
|
|
184
|
+
server.registerTool('maad_verify', {
|
|
185
|
+
description: 'Fact-check a claim against the database. Two modes: (1) field — verify a specific field value on a document, (2) count — verify a document count for a type with optional filters. Use this BEFORE stating any number, date, amount, or count as fact.',
|
|
186
|
+
inputSchema: z.object({
|
|
187
|
+
mode: z.enum(['field', 'count']).describe('Verification mode'),
|
|
188
|
+
docId: z.string().optional().describe('Document ID (required for field mode)'),
|
|
189
|
+
field: z.string().optional().describe('Field name to verify (required for field mode)'),
|
|
190
|
+
expected: z.any().optional().describe('Expected value for the field (required for field mode)'),
|
|
191
|
+
docType: z.string().optional().describe('Document type (required for count mode)'),
|
|
192
|
+
expectedCount: z.number().optional().describe('Expected document count (required for count mode)'),
|
|
193
|
+
filters: z.any().optional().describe('Field filters for count mode (same format as maad_query)'),
|
|
194
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
195
|
+
}),
|
|
196
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_verify', args, async ({ engine }) => {
|
|
197
|
+
if (args.mode === 'field') {
|
|
198
|
+
if (!args.docId || !args.field || args.expected === undefined) {
|
|
199
|
+
return resultToResponse({ ok: false, errors: [{ code: 'INVALID_ARGS', message: 'field mode requires docId, field, and expected' }] }, 'maad_verify');
|
|
200
|
+
}
|
|
201
|
+
return resultToResponse(await engine.verifyField(docId(args.docId), args.field, args.expected), 'maad_verify');
|
|
202
|
+
}
|
|
203
|
+
if (args.mode === 'count') {
|
|
204
|
+
if (!args.docType || args.expectedCount === undefined) {
|
|
205
|
+
return resultToResponse({ ok: false, errors: [{ code: 'INVALID_ARGS', message: 'count mode requires docType and expectedCount' }] }, 'maad_verify');
|
|
206
|
+
}
|
|
207
|
+
return resultToResponse(engine.verifyCount(docType(args.docType), args.expectedCount, args.filters), 'maad_verify');
|
|
208
|
+
}
|
|
209
|
+
return resultToResponse({ ok: false, errors: [{ code: 'INVALID_ARGS', message: 'mode must be "field" or "count"' }] }, 'maad_verify');
|
|
210
|
+
}));
|
|
211
|
+
server.registerTool('maad_join', {
|
|
212
|
+
description: 'Queries documents and follows ref fields to return projected fields from both source and target records in one call. Eliminates N+1 round-trips. Example: all cases with their client name and attorney name.',
|
|
213
|
+
inputSchema: z.object({
|
|
214
|
+
docType: z.string().describe('Source document type to query'),
|
|
215
|
+
refs: z.array(z.string()).describe('Ref field names to follow (e.g. ["client", "assigned_attorney"])'),
|
|
216
|
+
fields: z.array(z.string()).optional().describe('Fields to return from source documents'),
|
|
217
|
+
refFields: z.record(z.string(), z.array(z.string())).optional().describe('Fields to return from each ref target: { "client": ["name", "industry"], "assigned_attorney": ["first_name"] }'),
|
|
218
|
+
filters: z.any().optional().describe('Field filters on source documents (same format as maad_query)'),
|
|
219
|
+
limit: z.number().optional().describe('Max results (default 50)'),
|
|
220
|
+
offset: z.number().optional().describe('Skip first N results'),
|
|
221
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
222
|
+
}),
|
|
223
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_join', args, ({ engine }) => {
|
|
224
|
+
const query = {
|
|
225
|
+
docType: docType(args.docType),
|
|
226
|
+
refs: args.refs,
|
|
227
|
+
};
|
|
228
|
+
if (args.fields !== undefined)
|
|
229
|
+
query.fields = args.fields;
|
|
230
|
+
if (args.refFields !== undefined)
|
|
231
|
+
query.refFields = args.refFields;
|
|
232
|
+
if (args.filters !== undefined)
|
|
233
|
+
query.filters = args.filters;
|
|
234
|
+
if (args.limit !== undefined)
|
|
235
|
+
query.limit = args.limit;
|
|
236
|
+
if (args.offset !== undefined)
|
|
237
|
+
query.offset = args.offset;
|
|
238
|
+
return resultToResponse(engine.join(query), 'maad_join');
|
|
239
|
+
}));
|
|
240
|
+
server.registerTool('maad_changes_since', {
|
|
241
|
+
description: 'Polling delta. Returns records with updated_at > cursor, ordered (updated_at ASC, doc_id ASC). Omit cursor to start. Pass nextCursor back verbatim to paginate; hasMore signals more pages. Operation: create | update (deletes not emitted).',
|
|
242
|
+
inputSchema: z.object({
|
|
243
|
+
cursor: z.string().optional().describe('Opaque cursor from a previous response. Omit on first call.'),
|
|
244
|
+
limit: z.number().int().positive().optional().describe('Max changes per page (default 100, max 1000).'),
|
|
245
|
+
docTypes: z.array(z.string()).optional().describe('Filter to these document types only.'),
|
|
246
|
+
project: z.string().optional().describe('Project name (multi-project mode only)'),
|
|
247
|
+
}),
|
|
248
|
+
}, async (args, extra) => withEngine(ctx, extra, 'maad_changes_since', args, ({ engine }) => {
|
|
249
|
+
const q = {};
|
|
250
|
+
if (args.cursor !== undefined)
|
|
251
|
+
q.cursor = args.cursor;
|
|
252
|
+
if (args.limit !== undefined)
|
|
253
|
+
q.limit = args.limit;
|
|
254
|
+
if (args.docTypes !== undefined)
|
|
255
|
+
q.docTypes = args.docTypes;
|
|
256
|
+
return resultToResponse(engine.changesSince(q), 'maad_changes_since');
|
|
257
|
+
}));
|
|
258
|
+
return 9;
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=read.js.map
|