@nextclaw/server 0.18.3 → 0.19.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/dist/index.d.ts +21 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +264 -9
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -8,10 +8,10 @@ import { lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat, writ
|
|
|
8
8
|
import { basename, dirname, extname, isAbsolute, join, parse, relative, resolve, sep } from "node:path";
|
|
9
9
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
10
10
|
import * as NextclawCore from "@nextclaw/core";
|
|
11
|
-
import { ConfigSchema, DEFAULT_WORKSPACE_PATH, ProviderModelDiscoveryHttpError, buildConfigSchema, createAgentProfile, expandHome, findEffectiveAgentProfile, getDataDir, getPackageVersion, getProviderName, hasSecretRef, isSensitiveConfigPath, loadConfig, mergeExtensionConfigView, normalizeModelThinkingCapability, normalizeProviderModelConfig, probeFeishu, readAgentAvatarContent, removeAgentProfile, resolveEffectiveAgentProfiles, saveConfig, toExtensionConfigView, updateAgentProfile } from "@nextclaw/core";
|
|
11
|
+
import { ConfigSchema, DEFAULT_WORKSPACE_PATH, McpServerDefinitionSchema, ProviderModelDiscoveryHttpError, buildConfigSchema, createAgentProfile, expandHome, findEffectiveAgentProfile, getDataDir, getPackageVersion, getProviderName, hasSecretRef, isSensitiveConfigPath, loadConfig, mergeExtensionConfigView, normalizeModelThinkingCapability, normalizeProviderModelConfig, probeFeishu, readAgentAvatarContent, removeAgentProfile, resolveEffectiveAgentProfiles, saveConfig, toExtensionConfigView, updateAgentProfile } from "@nextclaw/core";
|
|
12
12
|
import { homedir, platform } from "node:os";
|
|
13
13
|
import { findBuiltinProviderByName, listBuiltinProviders } from "@nextclaw/runtime";
|
|
14
|
-
import { McpInstalledViewService } from "@nextclaw/mcp";
|
|
14
|
+
import { McpInstalledViewService, McpMutationService, McpRegistryService, normalizeMcpServerName } from "@nextclaw/mcp";
|
|
15
15
|
import { serveStatic } from "hono/serve-static";
|
|
16
16
|
//#region src/features/auth/utils/auth-bridge.utils.ts
|
|
17
17
|
const REMOTE_BRIDGE_DIR = join(getDataDir(), "remote");
|
|
@@ -67,7 +67,7 @@ async function readJson(req) {
|
|
|
67
67
|
function isRecord$3(value) {
|
|
68
68
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
69
69
|
}
|
|
70
|
-
function readErrorMessage(value, fallback) {
|
|
70
|
+
function readErrorMessage$1(value, fallback) {
|
|
71
71
|
if (!isRecord$3(value)) return fallback;
|
|
72
72
|
const maybeError = value.error;
|
|
73
73
|
if (!isRecord$3(maybeError)) return fallback;
|
|
@@ -390,7 +390,7 @@ function readNcpEventChannel(event) {
|
|
|
390
390
|
return readString(metadata.channelId) ?? readString(metadata.channel) ?? parseAgentSessionChannel(readString(message.sessionId) ?? readString(payload.sessionId));
|
|
391
391
|
}
|
|
392
392
|
function canStreamAppEventToPrincipal(principal, event) {
|
|
393
|
-
if (event.type === "extension.request") {
|
|
393
|
+
if (event.type === "extension.request" || event.type === "extension.host.desktop.event") {
|
|
394
394
|
const target = readExtensionRequestTarget(event);
|
|
395
395
|
return hasGrant(principal, "event-stream:extension-requests") && hasScopeValue(principal, "extensionIds", target.extensionId) && hasScopeValue(principal, "extensionGenerations", target.extensionId && target.generation ? `${target.extensionId}:${target.generation}` : null);
|
|
396
396
|
}
|
|
@@ -478,7 +478,8 @@ const ingressKeys = {
|
|
|
478
478
|
channelCommandExecute: createTypedKey("extension.channel.command.execute"),
|
|
479
479
|
runtimeReady: createTypedKey("extension.runtime.ready"),
|
|
480
480
|
response: createTypedKey("extension.response"),
|
|
481
|
-
observationEvent: createTypedKey("extension.observation.event")
|
|
481
|
+
observationEvent: createTypedKey("extension.observation.event"),
|
|
482
|
+
desktopHostInvoke: createTypedKey("extension.host.desktop.invoke")
|
|
482
483
|
},
|
|
483
484
|
agentRun: {
|
|
484
485
|
send: createTypedKey("agent-run.send"),
|
|
@@ -1964,6 +1965,131 @@ var AppRoutesController = class {
|
|
|
1964
1965
|
extensionCatalog = (c) => c.json(ok(buildExtensionsView(this.options)));
|
|
1965
1966
|
};
|
|
1966
1967
|
//#endregion
|
|
1968
|
+
//#region src/app/controllers/capability-access.controller.ts
|
|
1969
|
+
var CapabilityAccessRoutesController = class {
|
|
1970
|
+
constructor(options) {
|
|
1971
|
+
this.options = options;
|
|
1972
|
+
}
|
|
1973
|
+
listGrants = async (c) => this.listDesktopGrants(c);
|
|
1974
|
+
grant = async (c) => {
|
|
1975
|
+
const body = await readJson(c.req.raw);
|
|
1976
|
+
const request = body.ok ? readGrantRequest(body.data) : null;
|
|
1977
|
+
if (!request) return c.json(err("INVALID_CAPABILITY_GRANT", "A valid capability grant request is required."), 400);
|
|
1978
|
+
try {
|
|
1979
|
+
if (request.resource.type !== "desktop.application") return c.json(err("INVALID_CAPABILITY_GRANT", "Generic capability grants must use their resource-specific authorization endpoint."), 400);
|
|
1980
|
+
return c.json(ok(await this.options.getDesktopHost().grantAccess(request)), 201);
|
|
1981
|
+
} catch (error) {
|
|
1982
|
+
return c.json(err("INVALID_CAPABILITY_GRANT", readErrorMessage(error)), 400);
|
|
1983
|
+
}
|
|
1984
|
+
};
|
|
1985
|
+
revoke = async (c) => {
|
|
1986
|
+
const body = await readJson(c.req.raw);
|
|
1987
|
+
const filter = body.ok ? readGrantFilter(body.data) : null;
|
|
1988
|
+
if (!filter || !isExactGrantSelector(filter) || filter.resourceType !== "desktop.application") return c.json(err("INVALID_CAPABILITY_GRANT_FILTER", "An exact Desktop subject, resource type, and target selector is required."), 400);
|
|
1989
|
+
return c.json(ok({ revoked: await this.options.capabilityGrantManager.revoke(filter) }));
|
|
1990
|
+
};
|
|
1991
|
+
getDesktopStatus = async (c) => c.json(ok(await this.options.getDesktopHost().status()));
|
|
1992
|
+
getDesktopPermissions = async (c) => c.json(ok(await this.options.getDesktopHost().getPermissions()));
|
|
1993
|
+
requestDesktopPermissions = async (c) => c.json(ok(await this.options.getDesktopHost().requestPermissions()));
|
|
1994
|
+
openDesktopPermissionSettings = async (c) => c.json(ok(await this.options.getDesktopHost().openPermissionSettings()));
|
|
1995
|
+
listDesktopGrants = async (c) => {
|
|
1996
|
+
const filter = readGrantFilterFromQuery(c);
|
|
1997
|
+
if (filter.resourceType !== void 0 && filter.resourceType !== "desktop.application") return c.json(err("INVALID_CAPABILITY_GRANT_FILTER", "Only Desktop capability grants can be listed from this endpoint."), 400);
|
|
1998
|
+
if (filter.subject && (!filter.subject.type || !filter.subject.id)) return c.json(err("INVALID_CAPABILITY_GRANT_FILTER", "Desktop grant subject filters must include both type and id."), 400);
|
|
1999
|
+
return c.json(ok(await this.options.capabilityGrantManager.list({
|
|
2000
|
+
...filter,
|
|
2001
|
+
resourceType: "desktop.application"
|
|
2002
|
+
})));
|
|
2003
|
+
};
|
|
2004
|
+
};
|
|
2005
|
+
function isExactGrantSelector(filter) {
|
|
2006
|
+
return Boolean(filter.subject?.type && filter.subject.id && filter.resourceType && filter.access?.length && Object.hasOwn(filter, "target") && filter.target !== void 0);
|
|
2007
|
+
}
|
|
2008
|
+
function readGrantFilterFromQuery(c) {
|
|
2009
|
+
const subjectType = readOptionalString(c.req.query("subjectType"));
|
|
2010
|
+
const subjectId = readOptionalString(c.req.query("subjectId"));
|
|
2011
|
+
const resourceType = readOptionalString(c.req.query("resourceType"));
|
|
2012
|
+
return {
|
|
2013
|
+
...subjectType || subjectId ? { subject: {
|
|
2014
|
+
...subjectType ? { type: subjectType } : {},
|
|
2015
|
+
...subjectId ? { id: subjectId } : {}
|
|
2016
|
+
} } : {},
|
|
2017
|
+
...resourceType ? { resourceType } : {}
|
|
2018
|
+
};
|
|
2019
|
+
}
|
|
2020
|
+
function readGrantRequest(value) {
|
|
2021
|
+
if (!isRecord$3(value) || !hasExactKeys(value, [
|
|
2022
|
+
"access",
|
|
2023
|
+
"declarationFingerprint",
|
|
2024
|
+
"resource",
|
|
2025
|
+
"subject"
|
|
2026
|
+
])) return null;
|
|
2027
|
+
const subject = readSubject(value.subject, false);
|
|
2028
|
+
const resource = isRecord$3(value.resource) && hasExactKeys(value.resource, ["target", "type"]) ? value.resource : null;
|
|
2029
|
+
if (!subject || !resource || !readOptionalString(resource.type) || !Array.isArray(value.access) || value.access.length === 0 || !value.access.every((entry) => Boolean(readOptionalString(entry))) || !readOptionalString(value.declarationFingerprint)) return null;
|
|
2030
|
+
return {
|
|
2031
|
+
subject: {
|
|
2032
|
+
type: subject.type,
|
|
2033
|
+
id: subject.id
|
|
2034
|
+
},
|
|
2035
|
+
resource: {
|
|
2036
|
+
type: String(resource.type).trim(),
|
|
2037
|
+
target: resource.target
|
|
2038
|
+
},
|
|
2039
|
+
access: value.access.map((entry) => String(entry).trim()),
|
|
2040
|
+
declarationFingerprint: String(value.declarationFingerprint).trim()
|
|
2041
|
+
};
|
|
2042
|
+
}
|
|
2043
|
+
function readGrantFilter(value) {
|
|
2044
|
+
if (!isRecord$3(value) || !hasExactKeys(value, [
|
|
2045
|
+
"access",
|
|
2046
|
+
"resourceType",
|
|
2047
|
+
"subject",
|
|
2048
|
+
"target"
|
|
2049
|
+
], true)) return null;
|
|
2050
|
+
const subject = value.subject === void 0 ? void 0 : readSubject(value.subject, true);
|
|
2051
|
+
if (value.subject !== void 0 && !subject) return null;
|
|
2052
|
+
const resourceType = value.resourceType === void 0 ? void 0 : readOptionalString(value.resourceType);
|
|
2053
|
+
if (value.resourceType !== void 0 && !resourceType) return null;
|
|
2054
|
+
const access = value.access === void 0 ? void 0 : Array.isArray(value.access) && value.access.length > 0 && value.access.every((entry) => Boolean(readOptionalString(entry))) ? value.access.map((entry) => String(entry).trim()) : null;
|
|
2055
|
+
if (access === null) return null;
|
|
2056
|
+
return {
|
|
2057
|
+
...subject ? { subject } : {},
|
|
2058
|
+
...resourceType ? { resourceType } : {},
|
|
2059
|
+
...Object.hasOwn(value, "target") ? { target: value.target } : {},
|
|
2060
|
+
...access ? { access } : {}
|
|
2061
|
+
};
|
|
2062
|
+
}
|
|
2063
|
+
function readSubject(value, partial) {
|
|
2064
|
+
if (!isRecord$3(value) || !hasExactKeys(value, ["id", "type"], partial)) return null;
|
|
2065
|
+
const type = value.type === void 0 ? void 0 : readOptionalString(value.type);
|
|
2066
|
+
const id = value.id === void 0 ? void 0 : readOptionalString(value.id);
|
|
2067
|
+
if (!partial && (!type || !id) || value.type !== void 0 && !type || value.id !== void 0 && !id) return null;
|
|
2068
|
+
return {
|
|
2069
|
+
...type ? { type } : {},
|
|
2070
|
+
...id ? { id } : {}
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
function hasExactKeys(value, allowed, allowMissing = false) {
|
|
2074
|
+
const keys = Object.keys(value);
|
|
2075
|
+
return keys.every((key) => allowed.includes(key)) && (allowMissing || keys.length === allowed.length);
|
|
2076
|
+
}
|
|
2077
|
+
function readOptionalString(value) {
|
|
2078
|
+
if (typeof value !== "string") return void 0;
|
|
2079
|
+
return value.trim() || void 0;
|
|
2080
|
+
}
|
|
2081
|
+
function readErrorMessage(error) {
|
|
2082
|
+
return error instanceof Error ? error.message : String(error);
|
|
2083
|
+
}
|
|
2084
|
+
//#endregion
|
|
2085
|
+
//#region src/features/feature-controls/controllers/feature-controls.controller.ts
|
|
2086
|
+
var FeatureControlsRoutesController = class {
|
|
2087
|
+
constructor(featureControls) {
|
|
2088
|
+
this.featureControls = featureControls;
|
|
2089
|
+
}
|
|
2090
|
+
get = async (c) => c.json(ok(await this.featureControls.get()));
|
|
2091
|
+
};
|
|
2092
|
+
//#endregion
|
|
1967
2093
|
//#region src/features/app-packages/controllers/app-packages.controller.ts
|
|
1968
2094
|
var AppPackagesRoutesController = class {
|
|
1969
2095
|
constructor(manager) {
|
|
@@ -4846,7 +4972,7 @@ async function fetchMarketplaceDataFromBase(params) {
|
|
|
4846
4972
|
if (!response.ok) return {
|
|
4847
4973
|
ok: false,
|
|
4848
4974
|
status: response.status,
|
|
4849
|
-
message: readErrorMessage(payload, `marketplace request failed (${response.status})`)
|
|
4975
|
+
message: readErrorMessage$1(payload, `marketplace request failed (${response.status})`)
|
|
4850
4976
|
};
|
|
4851
4977
|
if (!payload || typeof payload !== "object" || !("ok" in payload)) return {
|
|
4852
4978
|
ok: false,
|
|
@@ -4857,7 +4983,7 @@ async function fetchMarketplaceDataFromBase(params) {
|
|
|
4857
4983
|
if (!typed.ok) return {
|
|
4858
4984
|
ok: false,
|
|
4859
4985
|
status: 502,
|
|
4860
|
-
message: readErrorMessage(payload, "marketplace response returned error")
|
|
4986
|
+
message: readErrorMessage$1(payload, "marketplace response returned error")
|
|
4861
4987
|
};
|
|
4862
4988
|
return {
|
|
4863
4989
|
ok: true,
|
|
@@ -6038,6 +6164,88 @@ var NcpSessionRoutesController = class {
|
|
|
6038
6164
|
};
|
|
6039
6165
|
};
|
|
6040
6166
|
//#endregion
|
|
6167
|
+
//#region src/features/mcp/controllers/mcp.controller.ts
|
|
6168
|
+
var McpRoutesController = class {
|
|
6169
|
+
constructor(options) {
|
|
6170
|
+
this.options = options;
|
|
6171
|
+
}
|
|
6172
|
+
testConnection = async (c) => {
|
|
6173
|
+
const parsed = await this.readConnectionRequest(c);
|
|
6174
|
+
if (!parsed.ok) return parsed.response;
|
|
6175
|
+
const config = structuredClone(loadConfig(this.options.configPath));
|
|
6176
|
+
const result = new McpMutationService({
|
|
6177
|
+
getConfig: () => config,
|
|
6178
|
+
saveConfig: () => void 0
|
|
6179
|
+
}).addServer(parsed.value.name, parsed.value.definition);
|
|
6180
|
+
if (!result.changed) return c.json(err("MCP_CONNECTION_INVALID", result.message), 400);
|
|
6181
|
+
const registry = new McpRegistryService({ getConfig: () => config });
|
|
6182
|
+
try {
|
|
6183
|
+
const warm = await registry.warmServer(result.name);
|
|
6184
|
+
return c.json(ok({
|
|
6185
|
+
name: warm.name,
|
|
6186
|
+
transport: parsed.value.definition.transport.type,
|
|
6187
|
+
accessible: warm.ok,
|
|
6188
|
+
toolCount: warm.toolCount,
|
|
6189
|
+
...warm.error ? { error: warm.error } : {}
|
|
6190
|
+
}));
|
|
6191
|
+
} finally {
|
|
6192
|
+
await registry.close();
|
|
6193
|
+
}
|
|
6194
|
+
};
|
|
6195
|
+
createConnection = async (c) => {
|
|
6196
|
+
const parsed = await this.readConnectionRequest(c);
|
|
6197
|
+
if (!parsed.ok) return parsed.response;
|
|
6198
|
+
const result = new McpMutationService({
|
|
6199
|
+
getConfig: () => loadConfig(this.options.configPath),
|
|
6200
|
+
saveConfig: (config) => saveConfig(config, this.options.configPath)
|
|
6201
|
+
}).addServer(parsed.value.name, parsed.value.definition);
|
|
6202
|
+
if (!result.changed || !result.definition) return c.json(err("MCP_CONNECTION_INVALID", result.message), 400);
|
|
6203
|
+
emitConfigUpdated(this.options, "mcp");
|
|
6204
|
+
await this.options.applyLiveConfigReload?.();
|
|
6205
|
+
return c.json(ok({
|
|
6206
|
+
name: result.name,
|
|
6207
|
+
transport: result.definition.transport.type,
|
|
6208
|
+
message: result.message
|
|
6209
|
+
}));
|
|
6210
|
+
};
|
|
6211
|
+
readConnectionRequest = async (c) => {
|
|
6212
|
+
const body = await readJson(c.req.raw);
|
|
6213
|
+
if (!body.ok || !body.data || typeof body.data !== "object") return {
|
|
6214
|
+
ok: false,
|
|
6215
|
+
response: c.json(err("INVALID_BODY", "invalid json body"), 400)
|
|
6216
|
+
};
|
|
6217
|
+
try {
|
|
6218
|
+
const name = normalizeMcpServerName(body.data.name ?? "");
|
|
6219
|
+
const definition = McpServerDefinitionSchema.parse(body.data.definition);
|
|
6220
|
+
return {
|
|
6221
|
+
ok: true,
|
|
6222
|
+
value: {
|
|
6223
|
+
name,
|
|
6224
|
+
definition: {
|
|
6225
|
+
...definition,
|
|
6226
|
+
metadata: {
|
|
6227
|
+
...definition.metadata,
|
|
6228
|
+
source: "manual",
|
|
6229
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6230
|
+
}
|
|
6231
|
+
}
|
|
6232
|
+
}
|
|
6233
|
+
};
|
|
6234
|
+
} catch (error) {
|
|
6235
|
+
return {
|
|
6236
|
+
ok: false,
|
|
6237
|
+
response: c.json(err("MCP_CONNECTION_INVALID", error instanceof Error ? error.message : String(error)), 400)
|
|
6238
|
+
};
|
|
6239
|
+
}
|
|
6240
|
+
};
|
|
6241
|
+
};
|
|
6242
|
+
//#endregion
|
|
6243
|
+
//#region src/features/mcp/routes/mcp.route.ts
|
|
6244
|
+
function mountMcpRoutes(app, controller) {
|
|
6245
|
+
app.post("/api/mcp/servers/test", controller.testConnection);
|
|
6246
|
+
app.post("/api/mcp/servers", controller.createConnection);
|
|
6247
|
+
}
|
|
6248
|
+
//#endregion
|
|
6041
6249
|
//#region src/features/remote-access/controllers/remote.controller.ts
|
|
6042
6250
|
const REMOTE_SERVICE_ACTIONS = new Set([
|
|
6043
6251
|
"start",
|
|
@@ -6748,6 +6956,11 @@ function createUiRouteControllers(options, authService, marketplaceBaseUrls, ser
|
|
|
6748
6956
|
const { kernel, panelAppClientSdkScript, remoteAccess, runtimeControl, runtimeUpdate } = options;
|
|
6749
6957
|
return {
|
|
6750
6958
|
app: new AppRoutesController(options),
|
|
6959
|
+
capabilityAccess: new CapabilityAccessRoutesController({
|
|
6960
|
+
capabilityGrantManager: kernel.capabilityGrants,
|
|
6961
|
+
getDesktopHost: () => kernel.extensions.getDesktopHost()
|
|
6962
|
+
}),
|
|
6963
|
+
featureControls: new FeatureControlsRoutesController(kernel.featureControls),
|
|
6751
6964
|
appPackages: new AppPackagesRoutesController(kernel.appPackageManager),
|
|
6752
6965
|
appData: new AppDataRoutesController(kernel.appDataManager),
|
|
6753
6966
|
agents: new AgentsRoutesController(options),
|
|
@@ -6770,7 +6983,8 @@ function createUiRouteControllers(options, authService, marketplaceBaseUrls, ser
|
|
|
6770
6983
|
runtimeControl: runtimeControl ? new RuntimeControlRoutesController(runtimeControl) : null,
|
|
6771
6984
|
runtimeUpdate: runtimeUpdate ? new RuntimeUpdateRoutesController(runtimeUpdate) : null,
|
|
6772
6985
|
skillMarketplace: new SkillMarketplaceController(options, marketplaceBaseUrls),
|
|
6773
|
-
mcpMarketplace: new McpMarketplaceController(options, marketplaceBaseUrls)
|
|
6986
|
+
mcpMarketplace: new McpMarketplaceController(options, marketplaceBaseUrls),
|
|
6987
|
+
mcp: new McpRoutesController(options)
|
|
6774
6988
|
};
|
|
6775
6989
|
}
|
|
6776
6990
|
function isRecord(value) {
|
|
@@ -6874,7 +7088,7 @@ var UiRouteRegistry = class {
|
|
|
6874
7088
|
]]);
|
|
6875
7089
|
};
|
|
6876
7090
|
mountResourceRoutes = () => {
|
|
6877
|
-
const { appData, appPackages, ncpSession, inboxDeliveries, panelApps, preferences, projects, serviceApps, serverPath, systemObjectReferences } = this.controllers;
|
|
7091
|
+
const { appData, appPackages, capabilityAccess, featureControls, ncpSession, inboxDeliveries, panelApps, preferences, projects, serviceApps, serverPath, systemObjectReferences } = this.controllers;
|
|
6878
7092
|
this.mountRoutes([
|
|
6879
7093
|
[
|
|
6880
7094
|
"get",
|
|
@@ -6981,6 +7195,46 @@ var UiRouteRegistry = class {
|
|
|
6981
7195
|
"/api/system-object-references/resolve",
|
|
6982
7196
|
systemObjectReferences.resolve
|
|
6983
7197
|
],
|
|
7198
|
+
[
|
|
7199
|
+
"get",
|
|
7200
|
+
"/api/capability-grants",
|
|
7201
|
+
capabilityAccess.listGrants
|
|
7202
|
+
],
|
|
7203
|
+
[
|
|
7204
|
+
"post",
|
|
7205
|
+
"/api/capability-grants",
|
|
7206
|
+
capabilityAccess.grant
|
|
7207
|
+
],
|
|
7208
|
+
[
|
|
7209
|
+
"delete",
|
|
7210
|
+
"/api/capability-grants",
|
|
7211
|
+
capabilityAccess.revoke
|
|
7212
|
+
],
|
|
7213
|
+
[
|
|
7214
|
+
"get",
|
|
7215
|
+
"/api/feature-controls",
|
|
7216
|
+
featureControls.get
|
|
7217
|
+
],
|
|
7218
|
+
[
|
|
7219
|
+
"get",
|
|
7220
|
+
"/api/desktop-host/status",
|
|
7221
|
+
capabilityAccess.getDesktopStatus
|
|
7222
|
+
],
|
|
7223
|
+
[
|
|
7224
|
+
"get",
|
|
7225
|
+
"/api/desktop-host/permissions",
|
|
7226
|
+
capabilityAccess.getDesktopPermissions
|
|
7227
|
+
],
|
|
7228
|
+
[
|
|
7229
|
+
"post",
|
|
7230
|
+
"/api/desktop-host/permissions/request",
|
|
7231
|
+
capabilityAccess.requestDesktopPermissions
|
|
7232
|
+
],
|
|
7233
|
+
[
|
|
7234
|
+
"post",
|
|
7235
|
+
"/api/desktop-host/permissions/open-settings",
|
|
7236
|
+
capabilityAccess.openDesktopPermissionSettings
|
|
7237
|
+
],
|
|
6984
7238
|
[
|
|
6985
7239
|
"get",
|
|
6986
7240
|
"/api/app-packages",
|
|
@@ -7650,6 +7904,7 @@ var UiRouteRegistry = class {
|
|
|
7650
7904
|
skill: this.controllers.skillMarketplace,
|
|
7651
7905
|
mcp: this.controllers.mcpMarketplace
|
|
7652
7906
|
});
|
|
7907
|
+
mountMcpRoutes(this.app, this.controllers.mcp);
|
|
7653
7908
|
};
|
|
7654
7909
|
};
|
|
7655
7910
|
function createUiRouter(options, authServiceOverride, internal) {
|