@octopusdeploy/mcp-server 1.1.0 → 2.1.1
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/README.md +202 -47
- package/dist/helpers/activeToolsetConfig.d.ts +4 -0
- package/dist/helpers/activeToolsetConfig.d.ts.map +1 -0
- package/dist/helpers/activeToolsetConfig.js +18 -0
- package/dist/helpers/activeToolsetConfig.js.map +1 -0
- package/dist/helpers/errorHandling.d.ts +3 -0
- package/dist/helpers/errorHandling.d.ts.map +1 -1
- package/dist/helpers/errorHandling.js +4 -1
- package/dist/helpers/errorHandling.js.map +1 -1
- package/dist/helpers/getClientConfigurationFromEnvironment.d.ts +2 -0
- package/dist/helpers/getClientConfigurationFromEnvironment.d.ts.map +1 -1
- package/dist/helpers/getClientConfigurationFromEnvironment.js +20 -4
- package/dist/helpers/getClientConfigurationFromEnvironment.js.map +1 -1
- package/dist/helpers/grepLines.d.ts +38 -0
- package/dist/helpers/grepLines.d.ts.map +1 -0
- package/dist/helpers/grepLines.js +65 -0
- package/dist/helpers/grepLines.js.map +1 -0
- package/dist/helpers/methodTier.d.ts +15 -0
- package/dist/helpers/methodTier.d.ts.map +1 -0
- package/dist/helpers/methodTier.js +25 -0
- package/dist/helpers/methodTier.js.map +1 -0
- package/dist/helpers/pathAllowlist.d.ts +27 -0
- package/dist/helpers/pathAllowlist.d.ts.map +1 -0
- package/dist/helpers/pathAllowlist.js +177 -0
- package/dist/helpers/pathAllowlist.js.map +1 -0
- package/dist/helpers/pathGlob.d.ts +15 -0
- package/dist/helpers/pathGlob.d.ts.map +1 -0
- package/dist/helpers/pathGlob.js +47 -0
- package/dist/helpers/pathGlob.js.map +1 -0
- package/dist/helpers/requireConfirmation.d.ts +119 -0
- package/dist/helpers/requireConfirmation.d.ts.map +1 -0
- package/dist/helpers/requireConfirmation.js +148 -0
- package/dist/helpers/requireConfirmation.js.map +1 -0
- package/dist/helpers/sensitivePathDenylist.d.ts +32 -0
- package/dist/helpers/sensitivePathDenylist.d.ts.map +1 -0
- package/dist/helpers/sensitivePathDenylist.js +49 -0
- package/dist/helpers/sensitivePathDenylist.js.map +1 -0
- package/dist/helpers/stripLinks.d.ts +15 -0
- package/dist/helpers/stripLinks.d.ts.map +1 -0
- package/dist/helpers/stripLinks.js +19 -0
- package/dist/helpers/stripLinks.js.map +1 -0
- package/dist/helpers/userCache.d.ts +14 -0
- package/dist/helpers/userCache.d.ts.map +1 -0
- package/dist/helpers/userCache.js +16 -0
- package/dist/helpers/userCache.js.map +1 -0
- package/dist/helpers/validateExecutePath.d.ts +29 -0
- package/dist/helpers/validateExecutePath.d.ts.map +1 -0
- package/dist/helpers/validateExecutePath.js +62 -0
- package/dist/helpers/validateExecutePath.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -9
- package/dist/index.js.map +1 -1
- package/dist/resources/catalog/capabilities.d.ts +36 -0
- package/dist/resources/catalog/capabilities.d.ts.map +1 -0
- package/dist/resources/catalog/capabilities.js +89 -0
- package/dist/resources/catalog/capabilities.js.map +1 -0
- package/dist/resources/catalog/llmsTxt.d.ts +8 -0
- package/dist/resources/catalog/llmsTxt.d.ts.map +1 -0
- package/dist/resources/catalog/llmsTxt.js +44 -0
- package/dist/resources/catalog/llmsTxt.js.map +1 -0
- package/dist/resources/dispatch.d.ts +30 -0
- package/dist/resources/dispatch.d.ts.map +1 -0
- package/dist/resources/dispatch.js +81 -0
- package/dist/resources/dispatch.js.map +1 -0
- package/dist/resources/featureToggle.d.ts +2 -0
- package/dist/resources/featureToggle.d.ts.map +1 -0
- package/dist/resources/featureToggle.js +34 -0
- package/dist/resources/featureToggle.js.map +1 -0
- package/dist/resources/index.d.ts +12 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +44 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/interruption.d.ts +2 -0
- package/dist/resources/interruption.d.ts.map +1 -0
- package/dist/resources/interruption.js +34 -0
- package/dist/resources/interruption.js.map +1 -0
- package/dist/resources/release.d.ts +2 -0
- package/dist/resources/release.d.ts.map +1 -0
- package/dist/resources/release.js +33 -0
- package/dist/resources/release.js.map +1 -0
- package/dist/resources/rolloutGroup.d.ts +2 -0
- package/dist/resources/rolloutGroup.d.ts.map +1 -0
- package/dist/resources/rolloutGroup.js +35 -0
- package/dist/resources/rolloutGroup.js.map +1 -0
- package/dist/resources/runbook.d.ts +2 -0
- package/dist/resources/runbook.d.ts.map +1 -0
- package/dist/resources/runbook.js +34 -0
- package/dist/resources/runbook.js.map +1 -0
- package/dist/resources/task.d.ts +2 -0
- package/dist/resources/task.d.ts.map +1 -0
- package/dist/resources/task.js +68 -0
- package/dist/resources/task.js.map +1 -0
- package/dist/tools/createRelease.d.ts.map +1 -1
- package/dist/tools/createRelease.js +93 -50
- package/dist/tools/createRelease.js.map +1 -1
- package/dist/tools/deployRelease.d.ts.map +1 -1
- package/dist/tools/deployRelease.js +117 -97
- package/dist/tools/deployRelease.js.map +1 -1
- package/dist/tools/execute.d.ts +3 -0
- package/dist/tools/execute.d.ts.map +1 -0
- package/dist/tools/execute.js +262 -0
- package/dist/tools/execute.js.map +1 -0
- package/dist/tools/findAccounts.d.ts.map +1 -1
- package/dist/tools/findAccounts.js +15 -12
- package/dist/tools/findAccounts.js.map +1 -1
- package/dist/tools/findCertificates.d.ts.map +1 -1
- package/dist/tools/findCertificates.js +19 -16
- package/dist/tools/findCertificates.js.map +1 -1
- package/dist/tools/findDeploymentTargets.d.ts.map +1 -1
- package/dist/tools/findDeploymentTargets.js +26 -23
- package/dist/tools/findDeploymentTargets.js.map +1 -1
- package/dist/tools/findFeatureToggles.d.ts +37 -0
- package/dist/tools/findFeatureToggles.d.ts.map +1 -0
- package/dist/tools/findFeatureToggles.js +139 -0
- package/dist/tools/findFeatureToggles.js.map +1 -0
- package/dist/tools/findInterruptions.d.ts +79 -0
- package/dist/tools/findInterruptions.d.ts.map +1 -0
- package/dist/tools/findInterruptions.js +273 -0
- package/dist/tools/findInterruptions.js.map +1 -0
- package/dist/tools/findReleases.d.ts.map +1 -1
- package/dist/tools/findReleases.js +90 -48
- package/dist/tools/findReleases.js.map +1 -1
- package/dist/tools/findRunbooks.d.ts +3 -0
- package/dist/tools/findRunbooks.d.ts.map +1 -0
- package/dist/tools/findRunbooks.js +139 -0
- package/dist/tools/findRunbooks.js.map +1 -0
- package/dist/tools/findTenants.d.ts.map +1 -1
- package/dist/tools/findTenants.js +28 -25
- package/dist/tools/findTenants.js.map +1 -1
- package/dist/tools/getBranches.d.ts.map +1 -1
- package/dist/tools/getBranches.js +13 -10
- package/dist/tools/getBranches.js.map +1 -1
- package/dist/tools/getCurrentUser.d.ts.map +1 -1
- package/dist/tools/getCurrentUser.js +7 -4
- package/dist/tools/getCurrentUser.js.map +1 -1
- package/dist/tools/getDeploymentFromUrl.d.ts +8 -3
- package/dist/tools/getDeploymentFromUrl.d.ts.map +1 -1
- package/dist/tools/getDeploymentFromUrl.js +46 -18
- package/dist/tools/getDeploymentFromUrl.js.map +1 -1
- package/dist/tools/getDeploymentProcess.d.ts.map +1 -1
- package/dist/tools/getDeploymentProcess.js +26 -23
- package/dist/tools/getDeploymentProcess.js.map +1 -1
- package/dist/tools/getKubernetesLiveStatus.d.ts.map +1 -1
- package/dist/tools/getKubernetesLiveStatus.js +13 -10
- package/dist/tools/getKubernetesLiveStatus.js.map +1 -1
- package/dist/tools/getMissingTenantVariables.d.ts.map +1 -1
- package/dist/tools/getMissingTenantVariables.js +13 -10
- package/dist/tools/getMissingTenantVariables.js.map +1 -1
- package/dist/tools/getTaskFromUrl.d.ts +2 -3
- package/dist/tools/getTaskFromUrl.d.ts.map +1 -1
- package/dist/tools/getTaskFromUrl.js +33 -33
- package/dist/tools/getTaskFromUrl.js.map +1 -1
- package/dist/tools/getTenantVariables.d.ts.map +1 -1
- package/dist/tools/getTenantVariables.js +13 -10
- package/dist/tools/getTenantVariables.js.map +1 -1
- package/dist/tools/getVariables.d.ts.map +1 -1
- package/dist/tools/getVariables.js +12 -9
- package/dist/tools/getVariables.js.map +1 -1
- package/dist/tools/grepLlmsTxt.d.ts +13 -0
- package/dist/tools/grepLlmsTxt.d.ts.map +1 -0
- package/dist/tools/grepLlmsTxt.js +105 -0
- package/dist/tools/grepLlmsTxt.js.map +1 -0
- package/dist/tools/grepTaskLog.d.ts +30 -0
- package/dist/tools/grepTaskLog.d.ts.map +1 -0
- package/dist/tools/grepTaskLog.js +116 -0
- package/dist/tools/grepTaskLog.js.map +1 -0
- package/dist/tools/index.d.ts +11 -5
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +21 -7
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/listDeployments.d.ts.map +1 -1
- package/dist/tools/listDeployments.js +22 -13
- package/dist/tools/listDeployments.js.map +1 -1
- package/dist/tools/listEnvironments.d.ts.map +1 -1
- package/dist/tools/listEnvironments.js +12 -9
- package/dist/tools/listEnvironments.js.map +1 -1
- package/dist/tools/listProjects.d.ts.map +1 -1
- package/dist/tools/listProjects.js +10 -7
- package/dist/tools/listProjects.js.map +1 -1
- package/dist/tools/listSpaces.d.ts.map +1 -1
- package/dist/tools/listSpaces.js +9 -6
- package/dist/tools/listSpaces.js.map +1 -1
- package/dist/tools/readResource.d.ts +3 -0
- package/dist/tools/readResource.d.ts.map +1 -0
- package/dist/tools/readResource.js +50 -0
- package/dist/tools/readResource.js.map +1 -0
- package/dist/tools/runRunbook.d.ts +3 -0
- package/dist/tools/runRunbook.d.ts.map +1 -0
- package/dist/tools/runRunbook.js +174 -0
- package/dist/tools/runRunbook.js.map +1 -0
- package/dist/tools/updateFeatureToggle.d.ts +94 -0
- package/dist/tools/updateFeatureToggle.d.ts.map +1 -0
- package/dist/tools/updateFeatureToggle.js +308 -0
- package/dist/tools/updateFeatureToggle.js.map +1 -0
- package/dist/types/featureToggleTypes.d.ts +47 -0
- package/dist/types/featureToggleTypes.d.ts.map +1 -0
- package/dist/types/featureToggleTypes.js +10 -0
- package/dist/types/featureToggleTypes.js.map +1 -0
- package/dist/types/resourceConfig.d.ts +17 -0
- package/dist/types/resourceConfig.d.ts.map +1 -0
- package/dist/types/resourceConfig.js +6 -0
- package/dist/types/resourceConfig.js.map +1 -0
- package/dist/types/toolAnnotations.d.ts +8 -0
- package/dist/types/toolAnnotations.d.ts.map +1 -0
- package/dist/types/toolAnnotations.js +28 -0
- package/dist/types/toolAnnotations.js.map +1 -0
- package/dist/types/toolConfig.d.ts +15 -1
- package/dist/types/toolConfig.d.ts.map +1 -1
- package/dist/types/toolConfig.js +4 -1
- package/dist/types/toolConfig.js.map +1 -1
- package/dist/utils/parseConfig.d.ts +1 -1
- package/dist/utils/parseConfig.d.ts.map +1 -1
- package/dist/utils/parseConfig.js +3 -2
- package/dist/utils/parseConfig.js.map +1 -1
- package/package.json +4 -4
- package/dist/tools/getTaskById.d.ts +0 -9
- package/dist/tools/getTaskById.d.ts.map +0 -1
- package/dist/tools/getTaskById.js +0 -51
- package/dist/tools/getTaskById.js.map +0 -1
- package/dist/tools/getTaskDetails.d.ts +0 -9
- package/dist/tools/getTaskDetails.d.ts.map +0 -1
- package/dist/tools/getTaskDetails.js +0 -65
- package/dist/tools/getTaskDetails.js.map +0 -1
- package/dist/tools/getTaskRaw.d.ts +0 -9
- package/dist/tools/getTaskRaw.d.ts.map +0 -1
- package/dist/tools/getTaskRaw.js +0 -50
- package/dist/tools/getTaskRaw.js.map +0 -1
- package/dist/tools/listReleasesForProject.d.ts +0 -3
- package/dist/tools/listReleasesForProject.d.ts.map +0 -1
- package/dist/tools/listReleasesForProject.js +0 -60
- package/dist/tools/listReleasesForProject.js.map +0 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import {} from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { env } from "process";
|
|
3
|
+
function renderChange(change) {
|
|
4
|
+
// Preserve source order first, then append target-only keys, so related
|
|
5
|
+
// fields stay together rather than getting alphabetised apart.
|
|
6
|
+
const seen = new Set();
|
|
7
|
+
const keys = [];
|
|
8
|
+
for (const k of Object.keys(change.source)) {
|
|
9
|
+
keys.push(k);
|
|
10
|
+
seen.add(k);
|
|
11
|
+
}
|
|
12
|
+
for (const k of Object.keys(change.target)) {
|
|
13
|
+
if (!seen.has(k))
|
|
14
|
+
keys.push(k);
|
|
15
|
+
}
|
|
16
|
+
const entries = [];
|
|
17
|
+
const buildEntry = (marker, key, value) => {
|
|
18
|
+
const valueLines = JSON.stringify(value, null, 2).split("\n");
|
|
19
|
+
const lines = [` ${JSON.stringify(key)}: ${valueLines[0]}`];
|
|
20
|
+
for (let i = 1; i < valueLines.length; i++) {
|
|
21
|
+
lines.push(` ${valueLines[i]}`);
|
|
22
|
+
}
|
|
23
|
+
return { marker, lines };
|
|
24
|
+
};
|
|
25
|
+
for (const key of keys) {
|
|
26
|
+
const inSource = key in change.source;
|
|
27
|
+
const inTarget = key in change.target;
|
|
28
|
+
const sourceJson = inSource
|
|
29
|
+
? JSON.stringify(change.source[key], null, 2)
|
|
30
|
+
: undefined;
|
|
31
|
+
const targetJson = inTarget
|
|
32
|
+
? JSON.stringify(change.target[key], null, 2)
|
|
33
|
+
: undefined;
|
|
34
|
+
if (sourceJson === targetJson)
|
|
35
|
+
continue;
|
|
36
|
+
if (inSource)
|
|
37
|
+
entries.push(buildEntry("-", key, change.source[key]));
|
|
38
|
+
if (inTarget)
|
|
39
|
+
entries.push(buildEntry("+", key, change.target[key]));
|
|
40
|
+
}
|
|
41
|
+
if (entries.length === 0)
|
|
42
|
+
return "{}";
|
|
43
|
+
const out = ["{"];
|
|
44
|
+
entries.forEach((entry, idx) => {
|
|
45
|
+
const isLastEntry = idx === entries.length - 1;
|
|
46
|
+
entry.lines.forEach((line, lineIdx) => {
|
|
47
|
+
const isLastLineOfEntry = lineIdx === entry.lines.length - 1;
|
|
48
|
+
const suffix = isLastLineOfEntry && !isLastEntry ? "," : "";
|
|
49
|
+
out.push(`${entry.marker}${line}${suffix}`);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
out.push("}");
|
|
53
|
+
return out.join("\n");
|
|
54
|
+
}
|
|
55
|
+
function buildConfirmationMessage(message, change) {
|
|
56
|
+
return change ? `${message}\n\n${renderChange(change)}` : message;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Gate a write/destructive tool call on explicit user confirmation.
|
|
60
|
+
*
|
|
61
|
+
* Resolution order:
|
|
62
|
+
* 1. `OCTOPUS_SKIP_ELICITATION=true` env var → bypass (automation/CI).
|
|
63
|
+
* 2. Client advertises elicitation capability → SDK emits `elicitation/create`
|
|
64
|
+
* and we map `result.action` to accepted/declined/cancelled.
|
|
65
|
+
* 3. Client does not advertise elicitation → fall back to the `confirm` arg
|
|
66
|
+
* the tool surfaced in its own input schema. Distinguishes between
|
|
67
|
+
* explicit `false` (declined) and missing (confirmationRequired) so the
|
|
68
|
+
* caller can surface the latter as a hard error.
|
|
69
|
+
*/
|
|
70
|
+
export async function requireConfirmation(server, opts) {
|
|
71
|
+
if (env["OCTOPUS_SKIP_ELICITATION"] === "true") {
|
|
72
|
+
return { confirmed: true, reason: "envSkip" };
|
|
73
|
+
}
|
|
74
|
+
const capabilities = server.server.getClientCapabilities();
|
|
75
|
+
if (capabilities?.elicitation) {
|
|
76
|
+
const result = await server.server.elicitInput({
|
|
77
|
+
mode: "form",
|
|
78
|
+
message: buildConfirmationMessage(opts.message, opts.change),
|
|
79
|
+
// Empty properties → most clients render as a plain Accept/Decline prompt.
|
|
80
|
+
requestedSchema: { type: "object", properties: {} },
|
|
81
|
+
});
|
|
82
|
+
switch (result.action) {
|
|
83
|
+
case "accept":
|
|
84
|
+
return { confirmed: true, reason: "accepted" };
|
|
85
|
+
case "decline":
|
|
86
|
+
return { confirmed: false, reason: "declined" };
|
|
87
|
+
case "cancel":
|
|
88
|
+
default:
|
|
89
|
+
return { confirmed: false, reason: "cancelled" };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (opts.fallbackConfirm === true) {
|
|
93
|
+
return { confirmed: true, reason: "fallbackConfirm" };
|
|
94
|
+
}
|
|
95
|
+
if (opts.fallbackConfirm === false) {
|
|
96
|
+
return { confirmed: false, reason: "declined" };
|
|
97
|
+
}
|
|
98
|
+
return { confirmed: false, reason: "confirmationRequired" };
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Build the standard tool response for a non-confirmed gate result.
|
|
102
|
+
*
|
|
103
|
+
* - `confirmationRequired` → `isError: true` with directive prose telling the
|
|
104
|
+
* LLM to ask the user before retrying with `confirm: true`. This is the
|
|
105
|
+
* "user was never asked" branch — distinct from a real cancellation, and
|
|
106
|
+
* marked as an error so the LLM doesn't paper over it.
|
|
107
|
+
* - `declined` / `cancelled` → soft cancellation shape with the original
|
|
108
|
+
* reason preserved for telemetry.
|
|
109
|
+
*
|
|
110
|
+
* Centralized here so every gated tool produces identical responses; the only
|
|
111
|
+
* thing a caller varies is the `action` noun. Return type is inferred so it
|
|
112
|
+
* stays compatible with the SDK's tool-handler return shape (which carries an
|
|
113
|
+
* `[key: string]: unknown` index signature we don't want to redeclare).
|
|
114
|
+
*/
|
|
115
|
+
export function unconfirmedResponse(result, opts) {
|
|
116
|
+
if (result.reason === "confirmationRequired") {
|
|
117
|
+
return {
|
|
118
|
+
content: [
|
|
119
|
+
{
|
|
120
|
+
type: "text",
|
|
121
|
+
text: JSON.stringify({
|
|
122
|
+
success: false,
|
|
123
|
+
confirmationRequired: true,
|
|
124
|
+
message: `This MCP client does not support elicitation, so the server cannot prompt the user to confirm this ${opts.action} directly. ` +
|
|
125
|
+
`The user has NOT been asked. Stop and ask the user explicitly whether to proceed; if they approve, retry the call with confirm: true. ` +
|
|
126
|
+
`Do not pass confirm: true without their explicit approval.`,
|
|
127
|
+
}, null, 2),
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
isError: true,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const capitalized = opts.action.charAt(0).toUpperCase() + opts.action.slice(1);
|
|
134
|
+
return {
|
|
135
|
+
content: [
|
|
136
|
+
{
|
|
137
|
+
type: "text",
|
|
138
|
+
text: JSON.stringify({
|
|
139
|
+
success: false,
|
|
140
|
+
cancelled: true,
|
|
141
|
+
reason: result.reason,
|
|
142
|
+
message: `${capitalized} cancelled by user.`,
|
|
143
|
+
}, null, 2),
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=requireConfirmation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requireConfirmation.js","sourceRoot":"","sources":["../../src/helpers/requireConfirmation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hard denylist for `execute` paths that must never be reachable, regardless
|
|
3
|
+
* of toolsets or mode flags. These are entries the user cannot opt into via
|
|
4
|
+
* --allow-deletes, and remain blocked even when --read-only is not set.
|
|
5
|
+
*
|
|
6
|
+
* Two categories live here:
|
|
7
|
+
* 1. API-key management — creating or modifying API keys via the MCP server
|
|
8
|
+
* is structurally out of scope (the agent uses a key already; minting more
|
|
9
|
+
* from inside the agent is a privilege escalation pattern).
|
|
10
|
+
* 2. Catastrophic deletes — paths whose DELETE removes a top-level container
|
|
11
|
+
* (a Space, a User) and is operationally irreversible. Allowing the agent
|
|
12
|
+
* to issue these from a single tool call is too sharp an edge.
|
|
13
|
+
*
|
|
14
|
+
* Pattern syntax is the shared `compilePathGlob` engine: `*` matches one
|
|
15
|
+
* segment, `**` matches across segments, and every other character is literal.
|
|
16
|
+
*/
|
|
17
|
+
import { type HttpMethod } from "./methodTier.js";
|
|
18
|
+
export interface DenyEntry {
|
|
19
|
+
/** Optional method filter; absent = all methods. */
|
|
20
|
+
method?: HttpMethod;
|
|
21
|
+
/** Glob pattern. `*` = one segment, `**` = any number of segments. */
|
|
22
|
+
pattern: string;
|
|
23
|
+
/** Short reason surfaced in the error response. */
|
|
24
|
+
reason: string;
|
|
25
|
+
}
|
|
26
|
+
export declare const SENSITIVE_PATHS: readonly DenyEntry[];
|
|
27
|
+
export interface SensitiveCheckResult {
|
|
28
|
+
blocked: boolean;
|
|
29
|
+
reason?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare function isSensitive(method: HttpMethod, path: string, entries?: readonly DenyEntry[]): SensitiveCheckResult;
|
|
32
|
+
//# sourceMappingURL=sensitivePathDenylist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sensitivePathDenylist.d.ts","sourceRoot":"","sources":["../../src/helpers/sensitivePathDenylist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,SAAS,EAuB/C,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,SAAS,SAAS,EAAoB,GAC9C,oBAAoB,CAQtB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hard denylist for `execute` paths that must never be reachable, regardless
|
|
3
|
+
* of toolsets or mode flags. These are entries the user cannot opt into via
|
|
4
|
+
* --allow-deletes, and remain blocked even when --read-only is not set.
|
|
5
|
+
*
|
|
6
|
+
* Two categories live here:
|
|
7
|
+
* 1. API-key management — creating or modifying API keys via the MCP server
|
|
8
|
+
* is structurally out of scope (the agent uses a key already; minting more
|
|
9
|
+
* from inside the agent is a privilege escalation pattern).
|
|
10
|
+
* 2. Catastrophic deletes — paths whose DELETE removes a top-level container
|
|
11
|
+
* (a Space, a User) and is operationally irreversible. Allowing the agent
|
|
12
|
+
* to issue these from a single tool call is too sharp an edge.
|
|
13
|
+
*
|
|
14
|
+
* Pattern syntax is the shared `compilePathGlob` engine: `*` matches one
|
|
15
|
+
* segment, `**` matches across segments, and every other character is literal.
|
|
16
|
+
*/
|
|
17
|
+
import {} from "./methodTier.js";
|
|
18
|
+
import { pathMatchesGlob } from "./pathGlob.js";
|
|
19
|
+
export const SENSITIVE_PATHS = [
|
|
20
|
+
{
|
|
21
|
+
pattern: "/api/users/*/apikeys",
|
|
22
|
+
reason: "API key management is out of scope for the MCP server. Use the Octopus web portal.",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
pattern: "/api/users/*/apikeys/**",
|
|
26
|
+
reason: "API key management is out of scope for the MCP server. Use the Octopus web portal.",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
method: "DELETE",
|
|
30
|
+
pattern: "/api/users/*",
|
|
31
|
+
reason: "Deleting a user is irreversible and out of scope for the MCP server.",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
method: "DELETE",
|
|
35
|
+
pattern: "/api/spaces/*",
|
|
36
|
+
reason: "Deleting a Space is catastrophic and out of scope for the MCP server.",
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
export function isSensitive(method, path, entries = SENSITIVE_PATHS) {
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
if (entry.method && entry.method !== method)
|
|
42
|
+
continue;
|
|
43
|
+
if (pathMatchesGlob(path, entry.pattern)) {
|
|
44
|
+
return { blocked: true, reason: entry.reason };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { blocked: false };
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=sensitivePathDenylist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sensitivePathDenylist.js","sourceRoot":"","sources":["../../src/helpers/sensitivePathDenylist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAmB,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAWhD,MAAM,CAAC,MAAM,eAAe,GAAyB;IACnD;QACE,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EACJ,oFAAoF;KACvF;IACD;QACE,OAAO,EAAE,yBAAyB;QAClC,MAAM,EACJ,oFAAoF;KACvF;IACD;QACE,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,cAAc;QACvB,MAAM,EACJ,sEAAsE;KACzE;IACD;QACE,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,eAAe;QACxB,MAAM,EACJ,uEAAuE;KAC1E;CACF,CAAC;AAOF,MAAM,UAAU,WAAW,CACzB,MAAkB,EAClB,IAAY,EACZ,UAAgC,eAAe;IAE/C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM;YAAE,SAAS;QACtD,IAAI,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip the HATEOAS `Links` bag from an Octopus API response object.
|
|
3
|
+
*
|
|
4
|
+
* Octopus REST responses include a `Links` map of hypermedia URLs (self, related
|
|
5
|
+
* collections, etc.) that an LLM consumer doesn't need and that bloats the payload.
|
|
6
|
+
* Every resource handler that returns an api-client object as JSON should pass it
|
|
7
|
+
* through this helper first.
|
|
8
|
+
*
|
|
9
|
+
* The api-client typings often don't include `Links` on their response interfaces
|
|
10
|
+
* (the runtime payload has it; the typings don't always declare it), which is why
|
|
11
|
+
* the input is widened to `Record<string, unknown>` rather than typed against a
|
|
12
|
+
* specific resource interface.
|
|
13
|
+
*/
|
|
14
|
+
export declare function stripLinks(resource: object): Record<string, unknown>;
|
|
15
|
+
//# sourceMappingURL=stripLinks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripLinks.d.ts","sourceRoot":"","sources":["../../src/helpers/stripLinks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIpE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip the HATEOAS `Links` bag from an Octopus API response object.
|
|
3
|
+
*
|
|
4
|
+
* Octopus REST responses include a `Links` map of hypermedia URLs (self, related
|
|
5
|
+
* collections, etc.) that an LLM consumer doesn't need and that bloats the payload.
|
|
6
|
+
* Every resource handler that returns an api-client object as JSON should pass it
|
|
7
|
+
* through this helper first.
|
|
8
|
+
*
|
|
9
|
+
* The api-client typings often don't include `Links` on their response interfaces
|
|
10
|
+
* (the runtime payload has it; the typings don't always declare it), which is why
|
|
11
|
+
* the input is widened to `Record<string, unknown>` rather than typed against a
|
|
12
|
+
* specific resource interface.
|
|
13
|
+
*/
|
|
14
|
+
export function stripLinks(resource) {
|
|
15
|
+
const copy = { ...resource };
|
|
16
|
+
delete copy.Links;
|
|
17
|
+
return copy;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=stripLinks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stripLinks.js","sourceRoot":"","sources":["../../src/helpers/stripLinks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,IAAI,GAA4B,EAAE,GAAG,QAAQ,EAA6B,CAAC;IACjF,OAAO,IAAI,CAAC,KAAK,CAAC;IAClB,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type Client } from "@octopusdeploy/api-client";
|
|
2
|
+
export interface CurrentUser {
|
|
3
|
+
Id: string;
|
|
4
|
+
Username: string;
|
|
5
|
+
DisplayName: string;
|
|
6
|
+
IsActive: boolean;
|
|
7
|
+
IsService: boolean;
|
|
8
|
+
EmailAddress: string;
|
|
9
|
+
CanPasswordBeEdited: boolean;
|
|
10
|
+
IsRequestor: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function getCurrentUserCached(client: Client): Promise<CurrentUser>;
|
|
13
|
+
export declare function clearUserCache(): void;
|
|
14
|
+
//# sourceMappingURL=userCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userCache.d.ts","sourceRoot":"","sources":["../../src/helpers/userCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;CACtB;AAMD,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAS/E;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {} from "@octopusdeploy/api-client";
|
|
2
|
+
const CACHE_TTL = 3600000;
|
|
3
|
+
let cached;
|
|
4
|
+
export async function getCurrentUserCached(client) {
|
|
5
|
+
const now = Date.now();
|
|
6
|
+
if (cached && now - cached.timestamp < CACHE_TTL) {
|
|
7
|
+
return cached.user;
|
|
8
|
+
}
|
|
9
|
+
const user = await client.get("~/api/users/me");
|
|
10
|
+
cached = { user, timestamp: now };
|
|
11
|
+
return user;
|
|
12
|
+
}
|
|
13
|
+
export function clearUserCache() {
|
|
14
|
+
cached = undefined;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=userCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userCache.js","sourceRoot":"","sources":["../../src/helpers/userCache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,MAAM,2BAA2B,CAAC;AAaxD,MAAM,SAAS,GAAG,OAAO,CAAC;AAE1B,IAAI,MAA4D,CAAC;AAEjE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,MAAc;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;QACjD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAc,gBAAgB,CAAC,CAAC;IAC7D,MAAM,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;IAClC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,SAAS,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reject `execute` paths whose canonical form differs from what the allowlist
|
|
3
|
+
* and denylist would see, so a path like
|
|
4
|
+
*
|
|
5
|
+
* /api/spaces/Spaces-1/../../users/me/apikeys
|
|
6
|
+
*
|
|
7
|
+
* cannot pass the `/api/spaces/**` allowlist while resolving to
|
|
8
|
+
* `/api/users/me/apikeys` on the server.
|
|
9
|
+
*
|
|
10
|
+
* The validator is deliberately conservative: anything that introduces
|
|
11
|
+
* ambiguity between the literal path string and what the HTTP client / Octopus
|
|
12
|
+
* routing will see — `..` segments, encoded slashes, backslashes, query
|
|
13
|
+
* strings, fragments, double slashes — is rejected outright. We do NOT try to
|
|
14
|
+
* normalise the path; rejecting unambiguously is safer than guessing the
|
|
15
|
+
* caller's intent.
|
|
16
|
+
*
|
|
17
|
+
* Query parameters belong in the `query` argument of the execute tool, not
|
|
18
|
+
* inside the `path` string — surfacing that as a reject prompts the agent to
|
|
19
|
+
* use the right field.
|
|
20
|
+
*/
|
|
21
|
+
export type PathValidation = {
|
|
22
|
+
ok: true;
|
|
23
|
+
path: string;
|
|
24
|
+
} | {
|
|
25
|
+
ok: false;
|
|
26
|
+
reason: string;
|
|
27
|
+
};
|
|
28
|
+
export declare function validateExecutePath(raw: string): PathValidation;
|
|
29
|
+
//# sourceMappingURL=validateExecutePath.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateExecutePath.d.ts","sourceRoot":"","sources":["../../src/helpers/validateExecutePath.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC1B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CA2C/D"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reject `execute` paths whose canonical form differs from what the allowlist
|
|
3
|
+
* and denylist would see, so a path like
|
|
4
|
+
*
|
|
5
|
+
* /api/spaces/Spaces-1/../../users/me/apikeys
|
|
6
|
+
*
|
|
7
|
+
* cannot pass the `/api/spaces/**` allowlist while resolving to
|
|
8
|
+
* `/api/users/me/apikeys` on the server.
|
|
9
|
+
*
|
|
10
|
+
* The validator is deliberately conservative: anything that introduces
|
|
11
|
+
* ambiguity between the literal path string and what the HTTP client / Octopus
|
|
12
|
+
* routing will see — `..` segments, encoded slashes, backslashes, query
|
|
13
|
+
* strings, fragments, double slashes — is rejected outright. We do NOT try to
|
|
14
|
+
* normalise the path; rejecting unambiguously is safer than guessing the
|
|
15
|
+
* caller's intent.
|
|
16
|
+
*
|
|
17
|
+
* Query parameters belong in the `query` argument of the execute tool, not
|
|
18
|
+
* inside the `path` string — surfacing that as a reject prompts the agent to
|
|
19
|
+
* use the right field.
|
|
20
|
+
*/
|
|
21
|
+
export function validateExecutePath(raw) {
|
|
22
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
23
|
+
return { ok: false, reason: "Path must be a non-empty string." };
|
|
24
|
+
}
|
|
25
|
+
if (!raw.startsWith("/")) {
|
|
26
|
+
return { ok: false, reason: "Path must start with '/'." };
|
|
27
|
+
}
|
|
28
|
+
if (raw.includes("\\")) {
|
|
29
|
+
return { ok: false, reason: "Path must not contain backslashes." };
|
|
30
|
+
}
|
|
31
|
+
if (raw.includes("?")) {
|
|
32
|
+
return {
|
|
33
|
+
ok: false,
|
|
34
|
+
reason: "Path must not contain a query string. Pass query parameters via the `query` argument instead.",
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (raw.includes("#")) {
|
|
38
|
+
return { ok: false, reason: "Path must not contain a fragment ('#')." };
|
|
39
|
+
}
|
|
40
|
+
if (raw.includes("//")) {
|
|
41
|
+
return { ok: false, reason: "Path must not contain '//'." };
|
|
42
|
+
}
|
|
43
|
+
if (/%2f|%5c/i.test(raw)) {
|
|
44
|
+
return {
|
|
45
|
+
ok: false,
|
|
46
|
+
reason: "Path must not contain percent-encoded slashes ('%2F') or backslashes ('%5C').",
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
// Reject any `..` segment — exact, leading, trailing, or surrounded by
|
|
50
|
+
// slashes. We do not attempt to resolve them.
|
|
51
|
+
const segments = raw.split("/");
|
|
52
|
+
for (const segment of segments) {
|
|
53
|
+
if (segment === "..") {
|
|
54
|
+
return {
|
|
55
|
+
ok: false,
|
|
56
|
+
reason: "Path must not contain '..' segments. Provide the canonical path explicitly.",
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { ok: true, path: raw };
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=validateExecutePath.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateExecutePath.js","sourceRoot":"","sources":["../../src/helpers/validateExecutePath.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kCAAkC,EAAE,CAAC;IACnE,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC;IAC5D,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC;IACrE,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EACJ,+FAA+F;SAClG,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,yCAAyC,EAAE,CAAC;IAC1E,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,6BAA6B,EAAE,CAAC;IAC9D,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EACJ,+EAA+E;SAClF,CAAC;IACJ,CAAC;IACD,uEAAuE;IACvE,8CAA8C;IAC9C,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EACJ,6EAA6E;aAChF,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AACjC,CAAC"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAoBA,eAAO,MAAM,cAAc,QAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { registerTools } from "./tools/index.js";
|
|
5
|
+
import { registerResources } from "./resources/index.js";
|
|
5
6
|
import { Command } from "commander";
|
|
6
7
|
import dotenv from "dotenv";
|
|
7
8
|
import { createToolsetConfig } from "./utils/parseConfig.js";
|
|
@@ -24,22 +25,75 @@ program
|
|
|
24
25
|
.description("Octopus Deploy MCP Server")
|
|
25
26
|
.version(SEMVER_VERSION)
|
|
26
27
|
.option("-s, --server-url <url>", "Octopus server URL")
|
|
27
|
-
.option("-k, --api-key <key>", "Octopus API key")
|
|
28
28
|
.option("--toolsets <toolsets>", `Comma-separated list of toolsets to enable, or "all" (default: all). Available toolsets: ${DEFAULT_TOOLSETS.join(", ")}`)
|
|
29
|
-
.option("--
|
|
29
|
+
.option("--read-only", "Enable read-only mode: disable all write tools and block POST/PUT/PATCH/DELETE through the execute tool (default: write tools enabled)")
|
|
30
|
+
.option("--allow-deletes", "Permit DELETE-method requests through the execute tool. Ignored (with a startup warning) when --read-only is set. Default false.")
|
|
30
31
|
.option("--log-level <level>", "Minimum log level (info, error)", "info")
|
|
31
32
|
.option("--log-file <path>", "Log file path or filename. If not specified, logs are written to console only.")
|
|
32
33
|
.option("-q, --quiet", "Disable file logging, only log errors to console", false)
|
|
33
34
|
.option("--list-tools-by-version", "List all registered tools by their supported Octopus Server version and exit")
|
|
34
35
|
.parse();
|
|
35
36
|
const options = program.opts();
|
|
37
|
+
// Resolve the Octopus server URL up front so the MCP `instructions` string
|
|
38
|
+
// can advertise which instance the client is connected to. Mirrors the
|
|
39
|
+
// precedence used by getClientConfigurationFromEnvironment (CLI flag wins
|
|
40
|
+
// over OCTOPUS_SERVER_URL env var).
|
|
41
|
+
if (options.serverUrl) {
|
|
42
|
+
process.env.CLI_SERVER_URL = options.serverUrl;
|
|
43
|
+
}
|
|
44
|
+
const configuredServerUrl = process.env.CLI_SERVER_URL ||
|
|
45
|
+
process.env.OCTOPUS_SERVER_URL ||
|
|
46
|
+
"(not configured — set OCTOPUS_SERVER_URL or pass --server-url)";
|
|
47
|
+
const SERVER_INSTRUCTIONS = `
|
|
48
|
+
The official Octopus Deploy MCP server, currently connected to: ${configuredServerUrl}
|
|
49
|
+
|
|
50
|
+
Tools are grouped into toolsets (${DEFAULT_TOOLSETS.join(", ")}) and you can filter them via --toolsets. Writes are on by default; pass --read-only to gate them off.
|
|
51
|
+
|
|
52
|
+
Resource URIs and how to dereference them:
|
|
53
|
+
- Many tools return slim summaries plus an 'octopus://...' URI in fields like 'resourceUri' or 'taskResourceUri' instead of inlining heavy payloads (release notes, packaged versions, structured task activity trees, etc.). To fetch the full body, dereference the URI.
|
|
54
|
+
- Resource-aware clients (Claude Code, MCP Inspector): call the standard 'resources/read' primitive with the URI.
|
|
55
|
+
- Clients without native resources/read (Claude.ai web, several IDE integrations): call the 'read_resource' tool with { uri }. It returns the same body as resources/read. Always available, regardless of toolset filter.
|
|
56
|
+
- The 'read_resource' tool is the universal bridge from any URI returned by any tool — if you see an 'octopus://' string in a response and don't know what to do with it, call read_resource with it.
|
|
57
|
+
|
|
58
|
+
Currently exposed resource families:
|
|
59
|
+
- releases: 'octopus://spaces/{spaceName}/releases/{releaseId}'
|
|
60
|
+
- tasks: 'octopus://spaces/{spaceName}/tasks/{taskId}' (metadata) and '/details' (structured ActivityLogs tree)
|
|
61
|
+
- interruptions: 'octopus://spaces/{spaceName}/interruptions/{interruptionId}' (full Form definition with control types, Markdown instructions, button options like Abort/Proceed, and any submitted Form.Values). The find_interruptions tool returns slim summaries that point at this URI; dereference it to drill into a specific interruption.
|
|
62
|
+
- feature toggles: 'octopus://spaces/{spaceName}/projects/{projectId}/featuretoggles/{slug}' (full toggle body — per-environment configuration including tenant lists, segments, minimum versions). The find_feature_toggles slim summaries omit those fields and point at this URI.
|
|
63
|
+
- rollout groups: 'octopus://spaces/{spaceName}/projects/{projectId}/rolloutgroups/{rolloutGroupId}' (read-only — this server doesn't expose rollout group writes; use the Octopus UI for those).
|
|
64
|
+
- catalog: 'octopus://api/llms.txt' is the markdown catalog of every Octopus REST endpoint (~300+ KB). 'octopus://api/capabilities' is the runtime introspection blob (server version, enabled toolsets, available tools, feature flags).
|
|
65
|
+
|
|
66
|
+
There is intentionally NO 'octopus://.../tasks/{id}/log' resource. Activity logs can be multi-megabyte; an addressable resource would tempt you to fetch the entire body when you almost always want only the matching lines. To search a task log, call the 'grep_task_log' tool — its parameters mirror GNU grep (pattern, caseInsensitive, invertMatch, fixedString, beforeContext, afterContext, maxCount) and it returns matching lines with totalMatches count and optional context windows. For step hierarchy / categories / timing, fetch the /details resource instead.
|
|
67
|
+
|
|
68
|
+
The same pattern applies to the API catalog: do NOT read 'octopus://api/llms.txt' directly because the body is large. Use the 'grep_llms_txt' tool — same GNU-grep parameter shape — to find the endpoints, methods, and request/response shapes you need.
|
|
69
|
+
|
|
70
|
+
The 'execute' tool reaches Octopus REST endpoints not covered by curated tools. **Method gating is hard-coded server-side**, three tiers:
|
|
71
|
+
- GET → read tier: always allowed (subject to toolset allowlist + sensitive denylist).
|
|
72
|
+
- POST / PUT / PATCH → write tier: blocked when --read-only is set; requires user confirmation via elicitation otherwise.
|
|
73
|
+
- DELETE → delete tier: requires --allow-deletes (and is blocked when --read-only is set) AND a stronger confirmation.
|
|
74
|
+
|
|
75
|
+
The HTTP method enum IS the read/write/delete classifier — the runtime classifies based on the actual method, never on a flag the agent sets. Use grep_llms_txt to discover the right path + method before calling execute.
|
|
76
|
+
|
|
77
|
+
More resource families will be added over time.
|
|
78
|
+
`.trim();
|
|
36
79
|
const server = new McpServer({
|
|
37
80
|
name: "Octopus Deploy",
|
|
38
81
|
description: "Official Octopus Deploy MCP server.",
|
|
39
82
|
version: SEMVER_VERSION,
|
|
83
|
+
}, {
|
|
84
|
+
instructions: SERVER_INSTRUCTIONS,
|
|
40
85
|
});
|
|
41
|
-
const toolsetConfig = createToolsetConfig(options.toolsets, options.readOnly);
|
|
86
|
+
const toolsetConfig = createToolsetConfig(options.toolsets, options.readOnly, options.allowDeletes);
|
|
87
|
+
// `--allow-deletes` only takes effect when writes are enabled. Surface this
|
|
88
|
+
// on stderr at startup so an operator who set both --read-only and
|
|
89
|
+
// --allow-deletes doesn't silently end up with DELETE requests blocked.
|
|
90
|
+
if (toolsetConfig.allowDeletes && toolsetConfig.readOnlyMode) {
|
|
91
|
+
process.stderr.write("WARNING: --allow-deletes was provided, but --read-only is also set. " +
|
|
92
|
+
"DELETE requests through the execute tool remain blocked. Remove " +
|
|
93
|
+
"--read-only to enable DELETE.\n");
|
|
94
|
+
}
|
|
42
95
|
registerTools(server, toolsetConfig);
|
|
96
|
+
registerResources(server, toolsetConfig);
|
|
43
97
|
if (options.listToolsByVersion) {
|
|
44
98
|
printToolVersionAnalysis();
|
|
45
99
|
process.exit(0);
|
|
@@ -54,12 +108,7 @@ if (options.logFile) {
|
|
|
54
108
|
}
|
|
55
109
|
logger.setLogLevel(logger.parseLogLevel(options.logLevel));
|
|
56
110
|
logger.setQuietMode(options.quiet);
|
|
57
|
-
|
|
58
|
-
process.env.CLI_SERVER_URL = options.serverUrl;
|
|
59
|
-
}
|
|
60
|
-
if (options.apiKey) {
|
|
61
|
-
process.env.CLI_API_KEY = options.apiKey;
|
|
62
|
-
}
|
|
111
|
+
// CLI_SERVER_URL is set earlier so the MCP instructions string can reference it.
|
|
63
112
|
// Set up initialization callback to capture client info
|
|
64
113
|
server.server.oninitialized = () => {
|
|
65
114
|
const clientInfo = server.server.getClientVersion();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EACL,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,qCAAqC,EAAE,MAAM,oDAAoD,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,WAAW,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAErC,MAAM,CAAC,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,CAAC;AAElD,+DAA+D;AAC/D,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAE/B,+BAA+B;AAC/B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,oBAAoB,CAAC;KAC1B,WAAW,CAAC,2BAA2B,CAAC;KACxC,OAAO,CAAC,cAAc,CAAC;KACvB,MAAM,CAAC,wBAAwB,EAAE,oBAAoB,CAAC;KACtD,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type Toolset } from "../../types/toolConfig.js";
|
|
2
|
+
import { type MethodTier } from "../../helpers/methodTier.js";
|
|
3
|
+
interface CapabilityToolEntry {
|
|
4
|
+
name: string;
|
|
5
|
+
toolset: Toolset;
|
|
6
|
+
readOnly: boolean;
|
|
7
|
+
minimumOctopusVersion?: string;
|
|
8
|
+
/**
|
|
9
|
+
* True for tools whose actual read/write/delete behaviour depends on
|
|
10
|
+
* arguments rather than a static tool-level flag. Currently set only on
|
|
11
|
+
* `execute`, where the HTTP method is the runtime classifier.
|
|
12
|
+
*/
|
|
13
|
+
methodGated?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Effective method tiers reachable through this tool in the *current*
|
|
16
|
+
* session. For `execute` this reflects --read-only and --allow-deletes;
|
|
17
|
+
* for static tools it is undefined (the `readOnly` flag is sufficient).
|
|
18
|
+
*/
|
|
19
|
+
tiersAvailable?: MethodTier[];
|
|
20
|
+
}
|
|
21
|
+
interface Capabilities {
|
|
22
|
+
server: {
|
|
23
|
+
version: string;
|
|
24
|
+
installationId: string;
|
|
25
|
+
};
|
|
26
|
+
session: {
|
|
27
|
+
enabledToolsets: Toolset[];
|
|
28
|
+
readOnlyMode: boolean;
|
|
29
|
+
allowDeletes: boolean;
|
|
30
|
+
};
|
|
31
|
+
tools: CapabilityToolEntry[];
|
|
32
|
+
featureFlags?: unknown;
|
|
33
|
+
}
|
|
34
|
+
export declare function buildCapabilities(): Promise<Capabilities>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=capabilities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/resources/catalog/capabilities.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,OAAO,EACb,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,cAAc,CAAC,EAAE,UAAU,EAAE,CAAC;CAC/B;AAED,UAAU,YAAY;IACpB,MAAM,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,OAAO,EAAE;QACP,eAAe,EAAE,OAAO,EAAE,CAAC;QAC3B,YAAY,EAAE,OAAO,CAAC;QACtB,YAAY,EAAE,OAAO,CAAC;KACvB,CAAC;IACF,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAUD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,YAAY,CAAC,CA+D/D"}
|