@bevel-software/platform-core-backend 0.7.5 → 0.9.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/LICENSE +202 -202
- package/THIRD-PARTY-NOTICES.md +428 -454
- package/dist/core/core-ports.d.ts +8 -1
- package/dist/core/core-ports.d.ts.map +1 -1
- package/dist/core/core-ports.js.map +1 -1
- package/dist/core/create-core-server.d.ts.map +1 -1
- package/dist/core/create-core-server.js +75 -18
- package/dist/core/create-core-server.js.map +1 -1
- package/dist/core/create-core-services.d.ts +12 -5
- package/dist/core/create-core-services.d.ts.map +1 -1
- package/dist/core/create-core-services.js +69 -36
- package/dist/core/create-core-services.js.map +1 -1
- package/dist/modules/access/access-control.interface.d.ts +8 -7
- package/dist/modules/access/access-control.interface.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.d.ts +1 -1
- package/dist/modules/access/access-control.service.d.ts.map +1 -1
- package/dist/modules/access/access-control.service.js +6 -6
- package/dist/modules/access/access-control.service.js.map +1 -1
- package/dist/modules/access/access-declarations.d.ts +5 -5
- package/dist/modules/access/access-declarations.js +3 -3
- package/dist/modules/access/access-mutation.service.d.ts +3 -3
- package/dist/modules/access/access-mutation.service.d.ts.map +1 -1
- package/dist/modules/access/access-mutation.service.js +3 -3
- package/dist/modules/access/access-mutation.service.js.map +1 -1
- package/dist/modules/access/access-splice.js +4 -4
- package/dist/modules/access/access-splice.js.map +1 -1
- package/dist/modules/access/access.routes.d.ts +3 -1
- package/dist/modules/access/access.routes.d.ts.map +1 -1
- package/dist/modules/access/access.routes.js +22 -20
- package/dist/modules/access/access.routes.js.map +1 -1
- package/dist/modules/access/creator-access.d.ts +2 -2
- package/dist/modules/access/creator-access.js +5 -5
- package/dist/modules/access/creator-access.js.map +1 -1
- package/dist/modules/access/render-roles-yaml.d.ts +22 -0
- package/dist/modules/access/render-roles-yaml.d.ts.map +1 -0
- package/dist/modules/access/render-roles-yaml.js +56 -0
- package/dist/modules/access/render-roles-yaml.js.map +1 -0
- package/dist/modules/access/roles-admin.service.d.ts +33 -5
- package/dist/modules/access/roles-admin.service.d.ts.map +1 -1
- package/dist/modules/access/roles-admin.service.js +44 -19
- package/dist/modules/access/roles-admin.service.js.map +1 -1
- package/dist/modules/code-mode/code-mode-names.d.ts +5 -13
- package/dist/modules/code-mode/code-mode-names.d.ts.map +1 -1
- package/dist/modules/code-mode/code-mode-names.js +5 -27
- package/dist/modules/code-mode/code-mode-names.js.map +1 -1
- package/dist/modules/code-mode/code-mode.tool.d.ts.map +1 -1
- package/dist/modules/code-mode/code-mode.tool.js +29 -7
- package/dist/modules/code-mode/code-mode.tool.js.map +1 -1
- package/dist/modules/mcp/mcp.service.d.ts +11 -52
- package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
- package/dist/modules/mcp/mcp.service.js +33 -395
- package/dist/modules/mcp/mcp.service.js.map +1 -1
- package/dist/modules/plugins/index.d.ts +7 -0
- package/dist/modules/plugins/index.d.ts.map +1 -0
- package/dist/modules/plugins/index.js +6 -0
- package/dist/modules/plugins/index.js.map +1 -0
- package/dist/modules/plugins/join-proposals.d.ts +53 -0
- package/dist/modules/plugins/join-proposals.d.ts.map +1 -0
- package/dist/modules/plugins/join-proposals.js +67 -0
- package/dist/modules/plugins/join-proposals.js.map +1 -0
- package/dist/modules/plugins/join-requests.service.d.ts +81 -0
- package/dist/modules/plugins/join-requests.service.d.ts.map +1 -0
- package/dist/modules/plugins/join-requests.service.js +135 -0
- package/dist/modules/plugins/join-requests.service.js.map +1 -0
- package/dist/modules/plugins/plugin-provision.service.d.ts +134 -0
- package/dist/modules/plugins/plugin-provision.service.d.ts.map +1 -0
- package/dist/modules/plugins/plugin-provision.service.js +344 -0
- package/dist/modules/plugins/plugin-provision.service.js.map +1 -0
- package/dist/modules/plugins/plugins.contract.d.ts +106 -0
- package/dist/modules/plugins/plugins.contract.d.ts.map +1 -0
- package/dist/modules/plugins/plugins.contract.js +36 -0
- package/dist/modules/plugins/plugins.contract.js.map +1 -0
- package/dist/modules/plugins/plugins.routes.d.ts +42 -0
- package/dist/modules/plugins/plugins.routes.d.ts.map +1 -0
- package/dist/modules/plugins/plugins.routes.js +379 -0
- package/dist/modules/plugins/plugins.routes.js.map +1 -0
- package/dist/modules/plugins/plugins.service.d.ts +60 -0
- package/dist/modules/plugins/plugins.service.d.ts.map +1 -0
- package/dist/modules/plugins/plugins.service.js +172 -0
- package/dist/modules/plugins/plugins.service.js.map +1 -0
- package/dist/modules/settings/setup.routes.d.ts +10 -1
- package/dist/modules/settings/setup.routes.d.ts.map +1 -1
- package/dist/modules/settings/setup.routes.js +111 -6
- package/dist/modules/settings/setup.routes.js.map +1 -1
- package/dist/modules/skills/pending-skills.service.d.ts +2 -2
- package/dist/modules/skills/pending-skills.service.js +7 -7
- package/dist/modules/skills/pending-skills.service.js.map +1 -1
- package/dist/modules/skills/skills.contract.d.ts +4 -4
- package/dist/modules/skills/skills.contract.d.ts.map +1 -1
- package/dist/modules/skills/skills.contract.js +1 -1
- package/dist/modules/skills/skills.service.js +5 -5
- package/dist/modules/skills/skills.service.js.map +1 -1
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts +65 -0
- package/dist/modules/tool-manuals/mcp-json-discovery.d.ts.map +1 -0
- package/dist/modules/tool-manuals/mcp-json-discovery.js +276 -0
- package/dist/modules/tool-manuals/mcp-json-discovery.js.map +1 -0
- package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts +92 -0
- package/dist/modules/tool-manuals/mcp-server-edit.service.d.ts.map +1 -0
- package/dist/modules/tool-manuals/mcp-server-edit.service.js +328 -0
- package/dist/modules/tool-manuals/mcp-server-edit.service.js.map +1 -0
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts +38 -12
- package/dist/modules/tool-manuals/tool-manuals.contract.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.contract.js +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts +13 -2
- package/dist/modules/tool-manuals/tool-manuals.routes.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.routes.js +233 -2
- package/dist/modules/tool-manuals/tool-manuals.routes.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.d.ts.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.service.js +74 -37
- package/dist/modules/tool-manuals/tool-manuals.service.js.map +1 -1
- package/dist/modules/tool-manuals/tool-manuals.tools.js +6 -3
- package/dist/modules/tool-manuals/tool-manuals.tools.js.map +1 -1
- package/dist/modules/workflow/git/git.service.js +2 -2
- package/dist/modules/workflow/git/git.service.js.map +1 -1
- package/dist/modules/workspace/kb-seed.service.d.ts +2 -2
- package/dist/modules/workspace/kb-seed.service.d.ts.map +1 -1
- package/dist/modules/workspace/kb-seed.service.js +43 -10
- package/dist/modules/workspace/kb-seed.service.js.map +1 -1
- package/dist/modules/workspace/plugins-migration.d.ts +50 -0
- package/dist/modules/workspace/plugins-migration.d.ts.map +1 -0
- package/dist/modules/workspace/plugins-migration.js +379 -0
- package/dist/modules/workspace/plugins-migration.js.map +1 -0
- package/dist/modules/workspace/startup/kb-git.d.ts +23 -0
- package/dist/modules/workspace/startup/kb-git.d.ts.map +1 -0
- package/dist/modules/workspace/startup/kb-git.js +86 -0
- package/dist/modules/workspace/startup/kb-git.js.map +1 -0
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts +74 -0
- package/dist/modules/workspace/startup/kb-startup-runner.d.ts.map +1 -0
- package/dist/modules/workspace/startup/kb-startup-runner.js +528 -0
- package/dist/modules/workspace/startup/kb-startup-runner.js.map +1 -0
- package/dist/modules/workspace/startup/on-server-start.d.ts +105 -0
- package/dist/modules/workspace/startup/on-server-start.d.ts.map +1 -0
- package/dist/modules/workspace/startup/on-server-start.js +21 -0
- package/dist/modules/workspace/startup/on-server-start.js.map +1 -0
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts +46 -0
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.d.ts.map +1 -0
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js +492 -0
- package/dist/modules/workspace/startup/steps/groups-to-plugins.step.js.map +1 -0
- package/dist/modules/workspace/startup/steps/roles-yaml.step.d.ts +23 -0
- package/dist/modules/workspace/startup/steps/roles-yaml.step.d.ts.map +1 -0
- package/dist/modules/workspace/startup/steps/roles-yaml.step.js +69 -0
- package/dist/modules/workspace/startup/steps/roles-yaml.step.js.map +1 -0
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts +17 -0
- package/dist/modules/workspace/startup/steps/seed-tree.d.ts.map +1 -0
- package/dist/modules/workspace/startup/steps/seed-tree.js +109 -0
- package/dist/modules/workspace/startup/steps/seed-tree.js.map +1 -0
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts +103 -0
- package/dist/modules/workspace/startup/steps/template-files.step.d.ts.map +1 -0
- package/dist/modules/workspace/startup/steps/template-files.step.js +337 -0
- package/dist/modules/workspace/startup/steps/template-files.step.js.map +1 -0
- package/dist/modules/workspace/workspace.routes.js +3 -3
- package/dist/modules/workspace/workspace.routes.js.map +1 -1
- package/dist/modules/workspace/workspace.service.d.ts +0 -9
- package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
- package/dist/modules/workspace/workspace.service.js +2 -30
- package/dist/modules/workspace/workspace.service.js.map +1 -1
- package/dist/shared/kb-layout.test.js +3 -3
- package/dist/shared/kb-layout.test.js.map +1 -1
- package/dist/shared/utcp-namespace.d.ts +6 -27
- package/dist/shared/utcp-namespace.d.ts.map +1 -1
- package/dist/shared/utcp-namespace.js +6 -63
- package/dist/shared/utcp-namespace.js.map +1 -1
- package/dist/shared/variable-refs.d.ts +42 -0
- package/dist/shared/variable-refs.d.ts.map +1 -0
- package/dist/shared/variable-refs.js +60 -0
- package/dist/shared/variable-refs.js.map +1 -0
- package/kb-template/.bevelignore +1 -1
- package/kb-template/AGENTS.md +88 -35
- package/kb-template/KnowledgeBase/How to get started.md +10 -10
- package/kb-template/access.md +36 -36
- package/kb-template/gitignore.template +16 -0
- package/migrations/meta/0000_snapshot.json +1479 -1479
- package/package.json +5 -4
- package/src/assets.ts +25 -25
- package/src/core/core-ports.ts +113 -106
- package/src/core/create-core-server.ts +85 -20
- package/src/core/create-core-services.ts +83 -42
- package/src/index.ts +69 -69
- package/src/modules/access/__tests__/access-control.atref-batch.test.ts +98 -98
- package/src/modules/access/__tests__/access-declarations.test.ts +28 -28
- package/src/modules/access/__tests__/access-md-format.test.ts +18 -18
- package/src/modules/access/__tests__/access-mutation.service.test.ts +5 -5
- package/src/modules/access/__tests__/access-splice.test.ts +2 -2
- package/src/modules/access/__tests__/access.routes.overrides.test.ts +16 -16
- package/src/modules/access/__tests__/grant-sources.test.ts +12 -12
- package/src/modules/access/__tests__/roles-admin.service.test.ts +36 -2
- package/src/modules/access/access-control.interface.ts +8 -7
- package/src/modules/access/access-control.service.ts +7 -7
- package/src/modules/access/access-declarations.ts +5 -5
- package/src/modules/access/access-mutation.service.ts +3 -3
- package/src/modules/access/access-splice.ts +4 -4
- package/src/modules/access/access.routes.ts +23 -20
- package/src/modules/access/creator-access.ts +5 -5
- package/src/modules/access/render-roles-yaml.ts +65 -0
- package/src/modules/access/roles-admin.service.ts +45 -16
- package/src/modules/admin/admin-access.routes.ts +29 -29
- package/src/modules/auth/__tests__/auth.routes.test.ts +91 -91
- package/src/modules/auth/__tests__/rate-limit.test.ts +36 -36
- package/src/modules/auth/rate-limit.ts +45 -45
- package/src/modules/code-mode/__tests__/code-mode.tool.test.ts +67 -0
- package/src/modules/code-mode/code-mode-names.ts +10 -36
- package/src/modules/code-mode/code-mode.tool.ts +27 -7
- package/src/modules/database/connection.ts +15 -15
- package/src/modules/database/schema.ts +11 -11
- package/src/modules/diff/__tests__/diff.routes.rejectPathsLocked.test.ts +150 -150
- package/src/modules/mcp/mcp.service.ts +57 -435
- package/src/modules/{groups → plugins}/__tests__/join-proposals.test.ts +1 -1
- package/src/modules/{groups → plugins}/__tests__/join-requests.service.test.ts +7 -7
- package/src/modules/{groups/__tests__/group-index.service.test.ts → plugins/__tests__/plugin-index.service.test.ts} +41 -41
- package/src/modules/plugins/__tests__/plugin-provision.service.test.ts +312 -0
- package/src/modules/{groups/__tests__/groups.routes.test.ts → plugins/__tests__/plugins.routes.test.ts} +100 -100
- package/src/modules/plugins/index.ts +17 -0
- package/src/modules/{groups → plugins}/join-proposals.ts +2 -2
- package/src/modules/{groups → plugins}/join-requests.service.ts +8 -8
- package/src/modules/{groups/group-provision.service.ts → plugins/plugin-provision.service.ts} +139 -69
- package/src/modules/{groups/groups.contract.ts → plugins/plugins.contract.ts} +26 -26
- package/src/modules/{groups/groups.routes.ts → plugins/plugins.routes.ts} +102 -102
- package/src/modules/{groups/groups.service.ts → plugins/plugins.service.ts} +43 -43
- package/src/modules/secrets-vault/__tests__/tool-owner-gate.route.test.ts +143 -143
- package/src/modules/settings/__tests__/setup.routes.test.ts +124 -3
- package/src/modules/settings/setup.routes.ts +112 -5
- package/src/modules/skills/__tests__/pending-skills.service.test.ts +14 -14
- package/src/modules/skills/__tests__/skills.service.test.ts +13 -13
- package/src/modules/skills/pending-skills.service.ts +7 -7
- package/src/modules/skills/skills.contract.ts +4 -4
- package/src/modules/skills/skills.service.ts +5 -5
- package/src/modules/tool-auth/llm-usage-meter.ts +19 -19
- package/src/modules/tool-manuals/__tests__/mcp-json-discovery.test.ts +198 -0
- package/src/modules/tool-manuals/__tests__/mcp-server-edit.service.test.ts +346 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.archive.route.test.ts +101 -0
- package/src/modules/tool-manuals/__tests__/tool-manuals.detail.route.test.ts +3 -3
- package/src/modules/tool-manuals/__tests__/tool-manuals.mcp-oauth.test.ts +2 -2
- package/src/modules/tool-manuals/__tests__/tool-manuals.service.test.ts +27 -27
- package/src/modules/tool-manuals/__tests__/tool-manuals.tools.test.ts +3 -3
- package/src/modules/tool-manuals/mcp-json-discovery.ts +328 -0
- package/src/modules/tool-manuals/mcp-server-edit.service.ts +434 -0
- package/src/modules/tool-manuals/tool-manuals.contract.ts +35 -12
- package/src/modules/tool-manuals/tool-manuals.routes.ts +222 -1
- package/src/modules/tool-manuals/tool-manuals.service.ts +82 -42
- package/src/modules/tool-manuals/tool-manuals.tools.ts +6 -3
- package/src/modules/workflow/__tests__/workflow.service.facade.test.ts +1 -1
- package/src/modules/workflow/git/__tests__/branch-name.test.ts +3 -3
- package/src/modules/workflow/git/__tests__/git.service.accessGating.test.ts +3 -3
- package/src/modules/workflow/git/__tests__/git.service.commitFile.test.ts +13 -8
- package/src/modules/workflow/git/__tests__/git.service.deleteBranch.test.ts +1 -1
- package/src/modules/workflow/git/__tests__/pull-request.service.test.ts +1 -1
- package/src/modules/workflow/git/git.service.ts +2 -2
- package/src/modules/workflow/review-workflow/__tests__/approval-states.test.ts +1 -1
- package/src/modules/workflow/review-workflow/__tests__/cancel-pr.test.ts +1 -1
- package/src/modules/workflow/workflow-hooks.ts +101 -101
- package/src/modules/workspace/__tests__/session-ontology.gate.test.ts +237 -237
- package/src/modules/workspace/__tests__/workspace.routes.create-grant.test.ts +236 -236
- package/src/modules/workspace/__tests__/workspace.routes.delete.test.ts +179 -179
- package/src/modules/workspace/__tests__/workspace.routes.download.test.ts +320 -320
- package/src/modules/workspace/__tests__/workspace.routes.read-gate.test.ts +337 -337
- package/src/modules/workspace/__tests__/workspace.service.test.ts +27 -0
- package/src/modules/workspace/bevel-ignore.ts +66 -66
- package/src/modules/workspace/session-sink.ts +25 -25
- package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +495 -0
- package/src/modules/workspace/startup/kb-git.ts +94 -0
- package/src/modules/workspace/startup/kb-startup-runner.ts +597 -0
- package/src/modules/workspace/startup/on-server-start.ts +97 -0
- package/src/modules/workspace/startup/steps/__tests__/steps.test.ts +636 -0
- package/src/modules/workspace/startup/steps/groups-to-plugins.step.ts +561 -0
- package/src/modules/workspace/startup/steps/roles-yaml.step.ts +71 -0
- package/src/modules/workspace/startup/steps/seed-tree.ts +115 -0
- package/src/modules/workspace/startup/steps/template-files.step.ts +360 -0
- package/src/modules/workspace/workspace.routes.ts +3 -3
- package/src/modules/workspace/workspace.service.ts +2 -35
- package/src/modules/workspace/workspace.tools.ts +922 -922
- package/src/shared/__tests__/join-request.test.ts +13 -13
- package/src/shared/__tests__/kb-layout.plugin.test.ts +45 -0
- package/src/shared/kb-layout.test.ts +3 -3
- package/src/shared/utcp-namespace.ts +10 -68
- package/src/shared/variable-refs.ts +64 -0
- package/src/modules/groups/__tests__/group-provision.service.test.ts +0 -247
- package/src/modules/groups/index.ts +0 -17
- package/src/modules/workspace/__tests__/kb-seed.service.test.ts +0 -444
- package/src/modules/workspace/kb-seed.interface.ts +0 -36
- package/src/modules/workspace/kb-seed.service.ts +0 -555
- package/src/shared/__tests__/kb-layout.group.test.ts +0 -45
- /package/kb-template/{Groups → Plugins}/.gitkeep +0 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { HEXIS_EXTENSION_NS, PLUGIN_MCP_FILE, PLUGIN_MANIFEST_FILE, PLUGINS_DIR, } from '@bevel-software/platform-shared';
|
|
2
|
+
import { assertSafeFetchUrl } from '../../shared/ssrf.js';
|
|
3
|
+
import { RESERVED_VARIABLE_NAMES, findReservedVariableRef } from '../../shared/variable-refs.js';
|
|
4
|
+
/**
|
|
5
|
+
* The same reserved-reference policy `.tool` parsing enforces, applied to the
|
|
6
|
+
* extension block: `API_URL`/`CONNECTION_KEY` (bare or namespaced) are seeded
|
|
7
|
+
* by the platform for its own manuals, and an extension header referencing one
|
|
8
|
+
* would be asking the substitutor to hand a third-party server the caller's
|
|
9
|
+
* bearer. One rule, both declaration surfaces — and one GRAMMAR deciding what
|
|
10
|
+
* a reference is (shared/variable-refs.ts), so nothing the migration or the
|
|
11
|
+
* editor classifies as a portable literal can be reserved here.
|
|
12
|
+
*/
|
|
13
|
+
const referencesReservedVariable = findReservedVariableRef;
|
|
14
|
+
function isRecord(v) {
|
|
15
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
16
|
+
}
|
|
17
|
+
/** The `mcpServers` extension map from a parsed plugin.json, or `{}`. */
|
|
18
|
+
function extensionServers(pluginJson) {
|
|
19
|
+
if (!isRecord(pluginJson))
|
|
20
|
+
return {};
|
|
21
|
+
const ext = pluginJson.extensions;
|
|
22
|
+
if (!isRecord(ext))
|
|
23
|
+
return {};
|
|
24
|
+
const ns = ext[HEXIS_EXTENSION_NS];
|
|
25
|
+
if (!isRecord(ns) || !isRecord(ns.mcpServers))
|
|
26
|
+
return {};
|
|
27
|
+
return ns.mcpServers;
|
|
28
|
+
}
|
|
29
|
+
/** A manual name must be usable as a UTCP namespace + route slug. Same shape `.tool` ids use. */
|
|
30
|
+
const SERVER_NAME_RE = /^[a-z0-9][a-z0-9_-]*$/;
|
|
31
|
+
/**
|
|
32
|
+
* Validate an extension entry's `variables` declarations, or `null` when any
|
|
33
|
+
* entry is malformed. The `.tool` parser THROWS on a bad entry so the whole
|
|
34
|
+
* file is skipped — a variable silently dropped or mis-read is not cosmetic:
|
|
35
|
+
* an undeclared reference defaults to the shared `admin` scope, so losing a
|
|
36
|
+
* `scope: user` declaration would hand one caller's slot to everyone. The
|
|
37
|
+
* same stake applies here, at this file's per-server grain: a bad entry
|
|
38
|
+
* invalidates the SERVER, never its siblings.
|
|
39
|
+
*
|
|
40
|
+
* Exported for the mcp-server editor: what it saves is what this scan reads
|
|
41
|
+
* on the next pass, so the two must judge a declaration with ONE function —
|
|
42
|
+
* a shape saveable there but undiscoverable here would be a server that
|
|
43
|
+
* silently vanishes from the catalog the moment its edit lands.
|
|
44
|
+
*/
|
|
45
|
+
export function validatedVariables(raw) {
|
|
46
|
+
if (raw === undefined)
|
|
47
|
+
return [];
|
|
48
|
+
if (!Array.isArray(raw))
|
|
49
|
+
return null;
|
|
50
|
+
const out = [];
|
|
51
|
+
const declared = new Set();
|
|
52
|
+
for (const entry of raw) {
|
|
53
|
+
if (!isRecord(entry))
|
|
54
|
+
return null;
|
|
55
|
+
if (typeof entry.name !== 'string' || !/^[A-Za-z0-9_]+$/.test(entry.name))
|
|
56
|
+
return null;
|
|
57
|
+
// The `.tool` parser's declaration rules, at this file's grain: a
|
|
58
|
+
// platform-seeded name may not be re-declared (it would shadow the
|
|
59
|
+
// seeding), and a duplicate would make later scope resolution depend on
|
|
60
|
+
// declaration order.
|
|
61
|
+
if (RESERVED_VARIABLE_NAMES.includes(entry.name) || declared.has(entry.name))
|
|
62
|
+
return null;
|
|
63
|
+
declared.add(entry.name);
|
|
64
|
+
const scope = entry.scope ?? 'admin';
|
|
65
|
+
if (scope !== 'admin' && scope !== 'user')
|
|
66
|
+
return null;
|
|
67
|
+
let oauth;
|
|
68
|
+
if (entry.oauth !== undefined) {
|
|
69
|
+
// OAuth is inherently per-caller (same rule the `.tool` parser
|
|
70
|
+
// enforces): an admin-shared OAuth token would leak one user's token
|
|
71
|
+
// to all callers. The provider config's required halves must be there
|
|
72
|
+
// — a sign-in wired to a missing URL is a declaration, not a feature.
|
|
73
|
+
if (!isRecord(entry.oauth) || scope !== 'user')
|
|
74
|
+
return null;
|
|
75
|
+
const o = entry.oauth;
|
|
76
|
+
// `clientId` is trimmed and must be non-empty, exactly as the `.tool`
|
|
77
|
+
// parser requires: a whitespace-only value would pass discovery and
|
|
78
|
+
// then fail the owner's client-secret setup with "clientId is
|
|
79
|
+
// required" — an error at the wrong surface, long after the save.
|
|
80
|
+
if (typeof o.authorizationUrl !== 'string' ||
|
|
81
|
+
typeof o.tokenUrl !== 'string' ||
|
|
82
|
+
typeof o.clientId !== 'string' ||
|
|
83
|
+
!o.clientId.trim()) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
// The same https + SSRF gate the `.tool` parser runs on these URLs: a
|
|
87
|
+
// sign-in or token exchange aimed at an internal host is a declaration
|
|
88
|
+
// this surface must refuse exactly like the other one does.
|
|
89
|
+
try {
|
|
90
|
+
assertSafeFetchUrl(o.authorizationUrl, { requireHttps: true, label: `${entry.name} oauth.authorizationUrl` });
|
|
91
|
+
assertSafeFetchUrl(o.tokenUrl, { requireHttps: true, label: `${entry.name} oauth.tokenUrl` });
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
// Forwarded verbatim as query params later — a non-string value here is
|
|
97
|
+
// a malformed declaration, not something to coerce.
|
|
98
|
+
if (o.authParams !== undefined) {
|
|
99
|
+
if (!isRecord(o.authParams) || !Object.values(o.authParams).every((v) => typeof v === 'string')) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
oauth = {
|
|
104
|
+
authorizationUrl: o.authorizationUrl,
|
|
105
|
+
tokenUrl: o.tokenUrl,
|
|
106
|
+
clientId: o.clientId.trim(),
|
|
107
|
+
...(Array.isArray(o.scopes) && o.scopes.every((s) => typeof s === 'string')
|
|
108
|
+
? { scopes: o.scopes }
|
|
109
|
+
: {}),
|
|
110
|
+
...(o.authParams !== undefined ? { authParams: o.authParams } : {}),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
out.push({
|
|
114
|
+
name: entry.name,
|
|
115
|
+
scope,
|
|
116
|
+
...(typeof entry.label === 'string' && entry.label.trim() ? { label: entry.label.trim() } : {}),
|
|
117
|
+
...(oauth ? { oauth } : {}),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Descriptors for one plugin's `mcp.json`. Malformed entries are skipped with
|
|
124
|
+
* a logged reason — one bad server must not take the plugin's others offline —
|
|
125
|
+
* and a missing/unparsable file yields `[]` (the caller decides whether that
|
|
126
|
+
* is worth a log line; an absent mcp.json is the common case, not an error).
|
|
127
|
+
*
|
|
128
|
+
* `stdio` entries are inherently LOCAL (`remote: false`): the hosted proxy can
|
|
129
|
+
* never spawn a subprocess out of knowledge-base content, so they are served
|
|
130
|
+
* only to local consumers (hexis-mcp), whose UTCP mcp plugin spawns them.
|
|
131
|
+
* `${PLUGIN_ROOT}`/`${PLUGIN_DATA}` placeholders are NOT expanded yet — local
|
|
132
|
+
* materialization is a later phase — so a stdio server relying on them will
|
|
133
|
+
* fail to spawn until then; bare-command servers (`npx …`) work today.
|
|
134
|
+
*/
|
|
135
|
+
export function descriptorsFromMcpJson(pluginFolder, mcpJsonText, pluginJsonText) {
|
|
136
|
+
let mcp;
|
|
137
|
+
try {
|
|
138
|
+
mcp = JSON.parse(mcpJsonText);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
console.warn(`[tool-manuals] ${PLUGINS_DIR}/${pluginFolder}/${PLUGIN_MCP_FILE} is not valid JSON — skipped.`);
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
if (!isRecord(mcp) || !isRecord(mcp.mcpServers))
|
|
145
|
+
return [];
|
|
146
|
+
let manifest = null;
|
|
147
|
+
if (pluginJsonText !== null) {
|
|
148
|
+
try {
|
|
149
|
+
manifest = JSON.parse(pluginJsonText);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// A broken manifest costs the extension data (auth wiring), not the
|
|
153
|
+
// servers themselves — they are still listed, as the spec's own
|
|
154
|
+
// "invalid components are skipped, valid ones load" posture suggests.
|
|
155
|
+
console.warn(`[tool-manuals] ${PLUGINS_DIR}/${pluginFolder}/${PLUGIN_MANIFEST_FILE} is not valid JSON — ` +
|
|
156
|
+
'its mcp-server auth/variable declarations are ignored.');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const extensions = extensionServers(manifest);
|
|
160
|
+
const mcpJsonPath = `${PLUGINS_DIR}/${pluginFolder}/${PLUGIN_MCP_FILE}`;
|
|
161
|
+
const out = [];
|
|
162
|
+
for (const [name, raw] of Object.entries(mcp.mcpServers)) {
|
|
163
|
+
if (!SERVER_NAME_RE.test(name)) {
|
|
164
|
+
console.warn(`[tool-manuals] skipping mcp server "${name}" in ${mcpJsonPath}: the name is the secret ` +
|
|
165
|
+
'namespace and route slug, so it must be lowercase alphanumeric with `_`/`-`.');
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (!isRecord(raw) || typeof raw.type !== 'string') {
|
|
169
|
+
console.warn(`[tool-manuals] skipping mcp server "${name}" in ${mcpJsonPath}: no transport type.`);
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// The extension entry is knowledge-base content too — same zero-trust
|
|
173
|
+
// parse as the rest: a non-object entry reads as "no extension data".
|
|
174
|
+
const ext = isRecord(extensions[name])
|
|
175
|
+
? extensions[name]
|
|
176
|
+
: {};
|
|
177
|
+
// The EFFECTIVE declaration, not just the extension block: a reserved
|
|
178
|
+
// reference in mcp.json's own url or literal headers would be expanded
|
|
179
|
+
// into outbound requests exactly the same way.
|
|
180
|
+
const reserved = referencesReservedVariable({ raw, ext });
|
|
181
|
+
if (reserved !== null) {
|
|
182
|
+
console.warn(`[tool-manuals] skipping mcp server "${name}" in ${mcpJsonPath}: its declaration (mcp.json ` +
|
|
183
|
+
`entry or plugin.json extension) references the reserved variable "${reserved}" — API_URL and ` +
|
|
184
|
+
'CONNECTION_KEY are platform-seeded and may not appear in server declarations.');
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const variables = validatedVariables(ext.variables);
|
|
188
|
+
if (variables === null) {
|
|
189
|
+
console.warn(`[tool-manuals] skipping mcp server "${name}" in ${mcpJsonPath}: its plugin.json \`variables\` ` +
|
|
190
|
+
'declaration is malformed — a dropped declaration would silently re-scope a credential, so ' +
|
|
191
|
+
'the server stays offline until the manifest is fixed.');
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const shared = {
|
|
195
|
+
slug: name,
|
|
196
|
+
name,
|
|
197
|
+
path: mcpJsonPath,
|
|
198
|
+
type: 'mcp',
|
|
199
|
+
...(typeof ext.description === 'string' ? { description: ext.description } : {}),
|
|
200
|
+
...(variables.length > 0 ? { variables } : {}),
|
|
201
|
+
};
|
|
202
|
+
if (raw.type === 'stdio') {
|
|
203
|
+
if (typeof raw.command !== 'string' || raw.command.length === 0) {
|
|
204
|
+
console.warn(`[tool-manuals] skipping stdio server "${name}" in ${mcpJsonPath}: no command.`);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
out.push({
|
|
208
|
+
...shared,
|
|
209
|
+
remote: false,
|
|
210
|
+
stdio: {
|
|
211
|
+
command: raw.command,
|
|
212
|
+
args: Array.isArray(raw.args) ? raw.args.map(String) : [],
|
|
213
|
+
env: isRecord(raw.env) ? raw.env : undefined,
|
|
214
|
+
cwd: typeof raw.cwd === 'string' ? raw.cwd : undefined,
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (raw.type === 'streamable-http' || raw.type === 'sse') {
|
|
220
|
+
if (typeof raw.url !== 'string' || raw.url.length === 0) {
|
|
221
|
+
console.warn(`[tool-manuals] skipping mcp server "${name}" in ${mcpJsonPath}: no url.`);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
// Remote-capable servers get the same SSRF gate `.tool` urls pass —
|
|
225
|
+
// otherwise mcp.json becomes the way to point the backend at loopback,
|
|
226
|
+
// private ranges, or the cloud metadata endpoint. A `local: true` entry
|
|
227
|
+
// is exempt because loopback is exactly what local MEANS, and only the
|
|
228
|
+
// user's own machine ever dials it.
|
|
229
|
+
// Scheme first, for EVERYONE: `local: true` exempts a server from the
|
|
230
|
+
// private-network reachability policy, not from being http(s) at all.
|
|
231
|
+
let schemeOk = false;
|
|
232
|
+
try {
|
|
233
|
+
const u = new URL(raw.url);
|
|
234
|
+
schemeOk = u.protocol === 'http:' || u.protocol === 'https:';
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
schemeOk = false;
|
|
238
|
+
}
|
|
239
|
+
if (!schemeOk) {
|
|
240
|
+
console.warn(`[tool-manuals] skipping mcp server "${name}" in ${mcpJsonPath}: url must be http(s).`);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (ext.local !== true) {
|
|
244
|
+
try {
|
|
245
|
+
assertSafeFetchUrl(raw.url, { label: `mcp server "${name}" url` });
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
console.warn(`[tool-manuals] skipping mcp server "${name}" in ${mcpJsonPath}: ` +
|
|
249
|
+
`${err instanceof Error ? err.message : String(err)} (declare it \`local: true\` if it is deliberately private).`);
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Extension headers (auth, `${VAR}` refs) win over mcp.json's literal
|
|
254
|
+
// ones on a key collision: the portable file cannot carry a credential,
|
|
255
|
+
// so when both name the same header the extension is the operative one.
|
|
256
|
+
// Both sides pass the isRecord gate — spreading a malformed non-object
|
|
257
|
+
// value (a string, say) would scatter its indices into header keys.
|
|
258
|
+
const headers = {
|
|
259
|
+
...(isRecord(raw.headers) ? raw.headers : {}),
|
|
260
|
+
...(isRecord(ext.headers) ? ext.headers : {}),
|
|
261
|
+
};
|
|
262
|
+
out.push({
|
|
263
|
+
...shared,
|
|
264
|
+
url: raw.url,
|
|
265
|
+
...(Object.keys(headers).length > 0 ? { headers } : {}),
|
|
266
|
+
...(ext.local === true ? { remote: false } : {}),
|
|
267
|
+
});
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
// Unknown transport: the spec says an unknown `type` invalidates the
|
|
271
|
+
// ENTRY, not the file — skip it, keep its siblings.
|
|
272
|
+
console.warn(`[tool-manuals] skipping mcp server "${name}" in ${mcpJsonPath}: unknown type "${raw.type}".`);
|
|
273
|
+
}
|
|
274
|
+
return out;
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=mcp-json-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-json-discovery.js","sourceRoot":"","sources":["../../../src/modules/tool-manuals/mcp-json-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { type AuthUser } from '@bevel-software/platform-shared';
|
|
2
|
+
import { type WorkspaceService } from '../workspace/workspace.service.js';
|
|
3
|
+
import type { IAccessControl } from '../access/access-control.interface.js';
|
|
4
|
+
import type { IToolManualService, ToolVariable } from './tool-manuals.contract.js';
|
|
5
|
+
/**
|
|
6
|
+
* Server-scoped editing of one MCP server — the form the tool page uses
|
|
7
|
+
* instead of dropping a writer into raw `mcp.json`.
|
|
8
|
+
*
|
|
9
|
+
* One server's truth spans TWO files (the spec's split, not ours): the
|
|
10
|
+
* portable half in `mcp.json` (transport, url, literal headers) and our half
|
|
11
|
+
* in `plugin.json`'s `extensions["software.bevel.hexis"].mcpServers[<name>]`
|
|
12
|
+
* (auth headers carrying `${VAR}` vault references, variable declarations,
|
|
13
|
+
* description, `local`). This service is the ONE writer that keeps the two in
|
|
14
|
+
* step: a save rewrites both entries and commits them together, because a
|
|
15
|
+
* server whose auth landed without its url — or the reverse — is a broken
|
|
16
|
+
* tool with no author to blame.
|
|
17
|
+
*
|
|
18
|
+
* RENAME IS DESTRUCTIVE BY DESIGN and the route says so: the `mcpServers` key
|
|
19
|
+
* is the namespace vault secrets bind to (`<name>_<VAR>`), so renaming a
|
|
20
|
+
* server orphans every configured secret and completed sign-in under the old
|
|
21
|
+
* key. The frontend counts what disconnects (it already holds per-variable
|
|
22
|
+
* status) and confirms; this service just refuses a rename onto a taken key.
|
|
23
|
+
*/
|
|
24
|
+
export type McpTransport = 'streamable-http' | 'sse' | 'stdio';
|
|
25
|
+
export interface McpServerView {
|
|
26
|
+
name: string;
|
|
27
|
+
transport: McpTransport;
|
|
28
|
+
url?: string;
|
|
29
|
+
command?: string;
|
|
30
|
+
args?: string[];
|
|
31
|
+
cwd?: string;
|
|
32
|
+
env?: Record<string, string>;
|
|
33
|
+
/** Portable headers, stored in mcp.json. Never carry a `${VAR}`. */
|
|
34
|
+
literalHeaders: Record<string, string>;
|
|
35
|
+
/** Auth headers with vault references, stored in the extensions block. */
|
|
36
|
+
authHeaders: Record<string, string>;
|
|
37
|
+
variables: ToolVariable[];
|
|
38
|
+
description?: string;
|
|
39
|
+
local: boolean;
|
|
40
|
+
canWrite: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* PATCH semantics, field by field: `undefined` means "the client did not
|
|
44
|
+
* surface this field" and the stored value survives; a present-but-empty
|
|
45
|
+
* value (`{}`, `[]`, `''`) is an explicit clear. A full-replace contract
|
|
46
|
+
* would make every client responsible for echoing back fields it does not
|
|
47
|
+
* edit — and the one that forgot would silently destroy the literal headers
|
|
48
|
+
* in mcp.json or the variable declarations behind `${VAR}` references.
|
|
49
|
+
*/
|
|
50
|
+
export interface McpServerWrite {
|
|
51
|
+
newName?: string;
|
|
52
|
+
transport: McpTransport;
|
|
53
|
+
url?: string;
|
|
54
|
+
command?: string;
|
|
55
|
+
args?: string[];
|
|
56
|
+
cwd?: string;
|
|
57
|
+
env?: Record<string, string>;
|
|
58
|
+
literalHeaders?: Record<string, string>;
|
|
59
|
+
authHeaders?: Record<string, string>;
|
|
60
|
+
variables?: ToolVariable[];
|
|
61
|
+
description?: string;
|
|
62
|
+
local?: boolean;
|
|
63
|
+
}
|
|
64
|
+
export declare class McpServerEditError extends Error {
|
|
65
|
+
readonly status: number;
|
|
66
|
+
constructor(message: string, status: number);
|
|
67
|
+
}
|
|
68
|
+
interface CommitDriver {
|
|
69
|
+
runPendingCommit(workspaceId: string, branch: string, targetPath: string, user: AuthUser, opts?: {
|
|
70
|
+
systemAuthorized?: boolean;
|
|
71
|
+
}): Promise<void>;
|
|
72
|
+
}
|
|
73
|
+
export declare class McpServerEditService {
|
|
74
|
+
private readonly workspaceService;
|
|
75
|
+
private readonly commits;
|
|
76
|
+
private readonly accessControl;
|
|
77
|
+
private readonly toolManuals;
|
|
78
|
+
private readonly kbDirName;
|
|
79
|
+
constructor(workspaceService: WorkspaceService, commits: CommitDriver, accessControl: IAccessControl, toolManuals: IToolManualService, kbDirName: string);
|
|
80
|
+
/** The merged view of one server, or null when unknown/unreadable (indistinguishable, fail closed). */
|
|
81
|
+
getServer(userEmail: string, slug: string): Promise<McpServerView | null>;
|
|
82
|
+
/** Rewrite one server across both files, in one commit. Returns the (possibly new) name. */
|
|
83
|
+
putServer(user: AuthUser, slug: string, write: McpServerWrite): Promise<{
|
|
84
|
+
name: string;
|
|
85
|
+
}>;
|
|
86
|
+
/** Resolve a slug to an mcp.json-backed server the caller can READ; null otherwise. */
|
|
87
|
+
private locate;
|
|
88
|
+
private readFiles;
|
|
89
|
+
private extensionEntry;
|
|
90
|
+
}
|
|
91
|
+
export {};
|
|
92
|
+
//# sourceMappingURL=mcp-server-edit.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server-edit.service.d.ts","sourceRoot":"","sources":["../../../src/modules/tool-manuals/mcp-server-edit.service.ts"],"names":[],"mappings":"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"}
|