@octopusdeploy/mcp-server 1.0.1 → 2.1.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.
Files changed (290) hide show
  1. package/README.md +237 -46
  2. package/dist/helpers/activeToolsetConfig.d.ts +4 -0
  3. package/dist/helpers/activeToolsetConfig.d.ts.map +1 -0
  4. package/dist/helpers/activeToolsetConfig.js +18 -0
  5. package/dist/helpers/activeToolsetConfig.js.map +1 -0
  6. package/dist/helpers/errorHandling.d.ts +38 -0
  7. package/dist/helpers/errorHandling.d.ts.map +1 -0
  8. package/dist/helpers/errorHandling.js +75 -0
  9. package/dist/helpers/errorHandling.js.map +1 -0
  10. package/dist/helpers/getClientConfigurationFromEnvironment.d.ts +2 -0
  11. package/dist/helpers/getClientConfigurationFromEnvironment.d.ts.map +1 -1
  12. package/dist/helpers/getClientConfigurationFromEnvironment.js +21 -5
  13. package/dist/helpers/getClientConfigurationFromEnvironment.js.map +1 -1
  14. package/dist/helpers/grepLines.d.ts +38 -0
  15. package/dist/helpers/grepLines.d.ts.map +1 -0
  16. package/dist/helpers/grepLines.js +65 -0
  17. package/dist/helpers/grepLines.js.map +1 -0
  18. package/dist/helpers/methodTier.d.ts +15 -0
  19. package/dist/helpers/methodTier.d.ts.map +1 -0
  20. package/dist/helpers/methodTier.js +25 -0
  21. package/dist/helpers/methodTier.js.map +1 -0
  22. package/dist/helpers/pathAllowlist.d.ts +27 -0
  23. package/dist/helpers/pathAllowlist.d.ts.map +1 -0
  24. package/dist/helpers/pathAllowlist.js +177 -0
  25. package/dist/helpers/pathAllowlist.js.map +1 -0
  26. package/dist/helpers/pathGlob.d.ts +15 -0
  27. package/dist/helpers/pathGlob.d.ts.map +1 -0
  28. package/dist/helpers/pathGlob.js +47 -0
  29. package/dist/helpers/pathGlob.js.map +1 -0
  30. package/dist/helpers/requireConfirmation.d.ts +119 -0
  31. package/dist/helpers/requireConfirmation.d.ts.map +1 -0
  32. package/dist/helpers/requireConfirmation.js +148 -0
  33. package/dist/helpers/requireConfirmation.js.map +1 -0
  34. package/dist/helpers/sensitivePathDenylist.d.ts +32 -0
  35. package/dist/helpers/sensitivePathDenylist.d.ts.map +1 -0
  36. package/dist/helpers/sensitivePathDenylist.js +49 -0
  37. package/dist/helpers/sensitivePathDenylist.js.map +1 -0
  38. package/dist/helpers/spaceResolver.d.ts +4 -0
  39. package/dist/helpers/spaceResolver.d.ts.map +1 -0
  40. package/dist/helpers/spaceResolver.js +18 -0
  41. package/dist/helpers/spaceResolver.js.map +1 -0
  42. package/dist/helpers/stripLinks.d.ts +15 -0
  43. package/dist/helpers/stripLinks.d.ts.map +1 -0
  44. package/dist/helpers/stripLinks.js +19 -0
  45. package/dist/helpers/stripLinks.js.map +1 -0
  46. package/dist/helpers/urlParser.d.ts +16 -0
  47. package/dist/helpers/urlParser.d.ts.map +1 -0
  48. package/dist/helpers/urlParser.js +83 -0
  49. package/dist/helpers/urlParser.js.map +1 -0
  50. package/dist/helpers/userCache.d.ts +14 -0
  51. package/dist/helpers/userCache.d.ts.map +1 -0
  52. package/dist/helpers/userCache.js +16 -0
  53. package/dist/helpers/userCache.js.map +1 -0
  54. package/dist/helpers/validateExecutePath.d.ts +29 -0
  55. package/dist/helpers/validateExecutePath.d.ts.map +1 -0
  56. package/dist/helpers/validateExecutePath.js +62 -0
  57. package/dist/helpers/validateExecutePath.js.map +1 -0
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +64 -15
  60. package/dist/index.js.map +1 -1
  61. package/dist/resources/catalog/capabilities.d.ts +36 -0
  62. package/dist/resources/catalog/capabilities.d.ts.map +1 -0
  63. package/dist/resources/catalog/capabilities.js +90 -0
  64. package/dist/resources/catalog/capabilities.js.map +1 -0
  65. package/dist/resources/catalog/llmsTxt.d.ts +8 -0
  66. package/dist/resources/catalog/llmsTxt.d.ts.map +1 -0
  67. package/dist/resources/catalog/llmsTxt.js +44 -0
  68. package/dist/resources/catalog/llmsTxt.js.map +1 -0
  69. package/dist/resources/dispatch.d.ts +30 -0
  70. package/dist/resources/dispatch.d.ts.map +1 -0
  71. package/dist/resources/dispatch.js +81 -0
  72. package/dist/resources/dispatch.js.map +1 -0
  73. package/dist/resources/featureToggle.d.ts +2 -0
  74. package/dist/resources/featureToggle.d.ts.map +1 -0
  75. package/dist/resources/featureToggle.js +34 -0
  76. package/dist/resources/featureToggle.js.map +1 -0
  77. package/dist/resources/index.d.ts +12 -0
  78. package/dist/resources/index.d.ts.map +1 -0
  79. package/dist/resources/index.js +44 -0
  80. package/dist/resources/index.js.map +1 -0
  81. package/dist/resources/interruption.d.ts +2 -0
  82. package/dist/resources/interruption.d.ts.map +1 -0
  83. package/dist/resources/interruption.js +34 -0
  84. package/dist/resources/interruption.js.map +1 -0
  85. package/dist/resources/release.d.ts +2 -0
  86. package/dist/resources/release.d.ts.map +1 -0
  87. package/dist/resources/release.js +33 -0
  88. package/dist/resources/release.js.map +1 -0
  89. package/dist/resources/rolloutGroup.d.ts +2 -0
  90. package/dist/resources/rolloutGroup.d.ts.map +1 -0
  91. package/dist/resources/rolloutGroup.js +35 -0
  92. package/dist/resources/rolloutGroup.js.map +1 -0
  93. package/dist/resources/runbook.d.ts +2 -0
  94. package/dist/resources/runbook.d.ts.map +1 -0
  95. package/dist/resources/runbook.js +34 -0
  96. package/dist/resources/runbook.js.map +1 -0
  97. package/dist/resources/task.d.ts +2 -0
  98. package/dist/resources/task.d.ts.map +1 -0
  99. package/dist/resources/task.js +68 -0
  100. package/dist/resources/task.js.map +1 -0
  101. package/dist/tools/createRelease.d.ts +3 -0
  102. package/dist/tools/createRelease.d.ts.map +1 -0
  103. package/dist/tools/createRelease.js +151 -0
  104. package/dist/tools/createRelease.js.map +1 -0
  105. package/dist/tools/deployRelease.d.ts +3 -0
  106. package/dist/tools/deployRelease.d.ts.map +1 -0
  107. package/dist/tools/deployRelease.js +227 -0
  108. package/dist/tools/deployRelease.js.map +1 -0
  109. package/dist/tools/execute.d.ts +3 -0
  110. package/dist/tools/execute.d.ts.map +1 -0
  111. package/dist/tools/execute.js +261 -0
  112. package/dist/tools/execute.js.map +1 -0
  113. package/dist/tools/findAccounts.d.ts +3 -0
  114. package/dist/tools/findAccounts.d.ts.map +1 -0
  115. package/dist/tools/findAccounts.js +90 -0
  116. package/dist/tools/findAccounts.js.map +1 -0
  117. package/dist/tools/findCertificates.d.ts +3 -0
  118. package/dist/tools/findCertificates.d.ts.map +1 -0
  119. package/dist/tools/findCertificates.js +98 -0
  120. package/dist/tools/findCertificates.js.map +1 -0
  121. package/dist/tools/findDeploymentTargets.d.ts +3 -0
  122. package/dist/tools/findDeploymentTargets.d.ts.map +1 -0
  123. package/dist/tools/findDeploymentTargets.js +161 -0
  124. package/dist/tools/findDeploymentTargets.js.map +1 -0
  125. package/dist/tools/findFeatureToggles.d.ts +37 -0
  126. package/dist/tools/findFeatureToggles.d.ts.map +1 -0
  127. package/dist/tools/findFeatureToggles.js +139 -0
  128. package/dist/tools/findFeatureToggles.js.map +1 -0
  129. package/dist/tools/findInterruptions.d.ts +79 -0
  130. package/dist/tools/findInterruptions.d.ts.map +1 -0
  131. package/dist/tools/findInterruptions.js +273 -0
  132. package/dist/tools/findInterruptions.js.map +1 -0
  133. package/dist/tools/findReleases.d.ts +3 -0
  134. package/dist/tools/findReleases.d.ts.map +1 -0
  135. package/dist/tools/findReleases.js +138 -0
  136. package/dist/tools/findReleases.js.map +1 -0
  137. package/dist/tools/findRunbooks.d.ts +3 -0
  138. package/dist/tools/findRunbooks.d.ts.map +1 -0
  139. package/dist/tools/findRunbooks.js +139 -0
  140. package/dist/tools/findRunbooks.js.map +1 -0
  141. package/dist/tools/findTenants.d.ts +19 -0
  142. package/dist/tools/findTenants.d.ts.map +1 -0
  143. package/dist/tools/findTenants.js +133 -0
  144. package/dist/tools/findTenants.js.map +1 -0
  145. package/dist/tools/getBranches.d.ts.map +1 -1
  146. package/dist/tools/getBranches.js +51 -33
  147. package/dist/tools/getBranches.js.map +1 -1
  148. package/dist/tools/getCurrentUser.d.ts.map +1 -1
  149. package/dist/tools/getCurrentUser.js +34 -25
  150. package/dist/tools/getCurrentUser.js.map +1 -1
  151. package/dist/tools/getDeploymentFromUrl.d.ts +57 -0
  152. package/dist/tools/getDeploymentFromUrl.d.ts.map +1 -0
  153. package/dist/tools/getDeploymentFromUrl.js +162 -0
  154. package/dist/tools/getDeploymentFromUrl.js.map +1 -0
  155. package/dist/tools/getDeploymentProcess.d.ts.map +1 -1
  156. package/dist/tools/getDeploymentProcess.js +57 -19
  157. package/dist/tools/getDeploymentProcess.js.map +1 -1
  158. package/dist/tools/getKubernetesLiveStatus.d.ts.map +1 -1
  159. package/dist/tools/getKubernetesLiveStatus.js +70 -48
  160. package/dist/tools/getKubernetesLiveStatus.js.map +1 -1
  161. package/dist/tools/getMissingTenantVariables.d.ts.map +1 -1
  162. package/dist/tools/getMissingTenantVariables.js +58 -26
  163. package/dist/tools/getMissingTenantVariables.js.map +1 -1
  164. package/dist/tools/getTaskFromUrl.d.ts +18 -0
  165. package/dist/tools/getTaskFromUrl.d.ts.map +1 -0
  166. package/dist/tools/getTaskFromUrl.js +90 -0
  167. package/dist/tools/getTaskFromUrl.js.map +1 -0
  168. package/dist/tools/getTenantVariables.d.ts.map +1 -1
  169. package/dist/tools/getTenantVariables.js +58 -38
  170. package/dist/tools/getTenantVariables.js.map +1 -1
  171. package/dist/tools/getVariables.d.ts.map +1 -1
  172. package/dist/tools/getVariables.js +12 -9
  173. package/dist/tools/getVariables.js.map +1 -1
  174. package/dist/tools/grepLlmsTxt.d.ts +13 -0
  175. package/dist/tools/grepLlmsTxt.d.ts.map +1 -0
  176. package/dist/tools/grepLlmsTxt.js +105 -0
  177. package/dist/tools/grepLlmsTxt.js.map +1 -0
  178. package/dist/tools/grepTaskLog.d.ts +30 -0
  179. package/dist/tools/grepTaskLog.d.ts.map +1 -0
  180. package/dist/tools/grepTaskLog.js +116 -0
  181. package/dist/tools/grepTaskLog.js.map +1 -0
  182. package/dist/tools/index.d.ts +22 -18
  183. package/dist/tools/index.d.ts.map +1 -1
  184. package/dist/tools/index.js +33 -21
  185. package/dist/tools/index.js.map +1 -1
  186. package/dist/tools/listDeployments.d.ts.map +1 -1
  187. package/dist/tools/listDeployments.js +77 -37
  188. package/dist/tools/listDeployments.js.map +1 -1
  189. package/dist/tools/listEnvironments.d.ts.map +1 -1
  190. package/dist/tools/listEnvironments.js +63 -37
  191. package/dist/tools/listEnvironments.js.map +1 -1
  192. package/dist/tools/listProjects.d.ts.map +1 -1
  193. package/dist/tools/listProjects.js +64 -38
  194. package/dist/tools/listProjects.js.map +1 -1
  195. package/dist/tools/listSpaces.d.ts.map +1 -1
  196. package/dist/tools/listSpaces.js +56 -30
  197. package/dist/tools/listSpaces.js.map +1 -1
  198. package/dist/tools/readResource.d.ts +3 -0
  199. package/dist/tools/readResource.d.ts.map +1 -0
  200. package/dist/tools/readResource.js +50 -0
  201. package/dist/tools/readResource.js.map +1 -0
  202. package/dist/tools/runRunbook.d.ts +3 -0
  203. package/dist/tools/runRunbook.d.ts.map +1 -0
  204. package/dist/tools/runRunbook.js +174 -0
  205. package/dist/tools/runRunbook.js.map +1 -0
  206. package/dist/tools/updateFeatureToggle.d.ts +94 -0
  207. package/dist/tools/updateFeatureToggle.d.ts.map +1 -0
  208. package/dist/tools/updateFeatureToggle.js +308 -0
  209. package/dist/tools/updateFeatureToggle.js.map +1 -0
  210. package/dist/types/featureToggleTypes.d.ts +47 -0
  211. package/dist/types/featureToggleTypes.d.ts.map +1 -0
  212. package/dist/types/featureToggleTypes.js +10 -0
  213. package/dist/types/featureToggleTypes.js.map +1 -0
  214. package/dist/types/resourceConfig.d.ts +17 -0
  215. package/dist/types/resourceConfig.d.ts.map +1 -0
  216. package/dist/types/resourceConfig.js +6 -0
  217. package/dist/types/resourceConfig.js.map +1 -0
  218. package/dist/types/toolAnnotations.d.ts +8 -0
  219. package/dist/types/toolAnnotations.d.ts.map +1 -0
  220. package/dist/types/toolAnnotations.js +28 -0
  221. package/dist/types/toolAnnotations.js.map +1 -0
  222. package/dist/types/toolConfig.d.ts +7 -1
  223. package/dist/types/toolConfig.d.ts.map +1 -1
  224. package/dist/types/toolConfig.js +4 -1
  225. package/dist/types/toolConfig.js.map +1 -1
  226. package/dist/utils/parseConfig.d.ts +1 -1
  227. package/dist/utils/parseConfig.d.ts.map +1 -1
  228. package/dist/utils/parseConfig.js +3 -2
  229. package/dist/utils/parseConfig.js.map +1 -1
  230. package/dist/utils/version.d.ts +2 -0
  231. package/dist/utils/version.d.ts.map +1 -0
  232. package/dist/utils/version.js +3 -0
  233. package/dist/utils/version.js.map +1 -0
  234. package/package.json +9 -3
  235. package/dist/tools/getAccount.d.ts +0 -3
  236. package/dist/tools/getAccount.d.ts.map +0 -1
  237. package/dist/tools/getAccount.js +0 -40
  238. package/dist/tools/getAccount.js.map +0 -1
  239. package/dist/tools/getCertificate.d.ts +0 -3
  240. package/dist/tools/getCertificate.d.ts.map +0 -1
  241. package/dist/tools/getCertificate.js +0 -40
  242. package/dist/tools/getCertificate.js.map +0 -1
  243. package/dist/tools/getDeploymentTarget.d.ts +0 -3
  244. package/dist/tools/getDeploymentTarget.d.ts.map +0 -1
  245. package/dist/tools/getDeploymentTarget.js +0 -66
  246. package/dist/tools/getDeploymentTarget.js.map +0 -1
  247. package/dist/tools/getReleaseById.d.ts +0 -3
  248. package/dist/tools/getReleaseById.d.ts.map +0 -1
  249. package/dist/tools/getReleaseById.js +0 -45
  250. package/dist/tools/getReleaseById.js.map +0 -1
  251. package/dist/tools/getTaskById.d.ts +0 -9
  252. package/dist/tools/getTaskById.d.ts.map +0 -1
  253. package/dist/tools/getTaskById.js +0 -44
  254. package/dist/tools/getTaskById.js.map +0 -1
  255. package/dist/tools/getTaskDetails.d.ts +0 -9
  256. package/dist/tools/getTaskDetails.d.ts.map +0 -1
  257. package/dist/tools/getTaskDetails.js +0 -44
  258. package/dist/tools/getTaskDetails.js.map +0 -1
  259. package/dist/tools/getTaskRaw.d.ts +0 -9
  260. package/dist/tools/getTaskRaw.d.ts.map +0 -1
  261. package/dist/tools/getTaskRaw.js +0 -43
  262. package/dist/tools/getTaskRaw.js.map +0 -1
  263. package/dist/tools/getTenantById.d.ts +0 -3
  264. package/dist/tools/getTenantById.d.ts.map +0 -1
  265. package/dist/tools/getTenantById.js +0 -50
  266. package/dist/tools/getTenantById.js.map +0 -1
  267. package/dist/tools/listAccounts.d.ts +0 -3
  268. package/dist/tools/listAccounts.d.ts.map +0 -1
  269. package/dist/tools/listAccounts.js +0 -54
  270. package/dist/tools/listAccounts.js.map +0 -1
  271. package/dist/tools/listCertificates.d.ts +0 -3
  272. package/dist/tools/listCertificates.d.ts.map +0 -1
  273. package/dist/tools/listCertificates.js +0 -62
  274. package/dist/tools/listCertificates.js.map +0 -1
  275. package/dist/tools/listDeploymentTargets.d.ts +0 -3
  276. package/dist/tools/listDeploymentTargets.d.ts.map +0 -1
  277. package/dist/tools/listDeploymentTargets.js +0 -98
  278. package/dist/tools/listDeploymentTargets.js.map +0 -1
  279. package/dist/tools/listReleases.d.ts +0 -3
  280. package/dist/tools/listReleases.d.ts.map +0 -1
  281. package/dist/tools/listReleases.js +0 -54
  282. package/dist/tools/listReleases.js.map +0 -1
  283. package/dist/tools/listReleasesForProject.d.ts +0 -3
  284. package/dist/tools/listReleasesForProject.d.ts.map +0 -1
  285. package/dist/tools/listReleasesForProject.js +0 -60
  286. package/dist/tools/listReleasesForProject.js.map +0 -1
  287. package/dist/tools/listTenants.d.ts +0 -3
  288. package/dist/tools/listTenants.d.ts.map +0 -1
  289. package/dist/tools/listTenants.js +0 -69
  290. package/dist/tools/listTenants.js.map +0 -1
package/dist/index.js CHANGED
@@ -2,16 +2,17 @@
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";
8
- import { DEFAULT_TOOLSETS, printToolVersionAnalysis } from "./types/toolConfig.js";
9
+ import { DEFAULT_TOOLSETS, printToolVersionAnalysis, } from "./types/toolConfig.js";
9
10
  import { getClientConfigurationFromEnvironment } from "./helpers/getClientConfigurationFromEnvironment.js";
10
11
  import { setClientInfo } from "./utils/clientInfo.js";
11
12
  import { logger } from "./utils/logger.js";
12
13
  import packageJson from "../package.json" with { type: "json" };
13
14
  import { fileURLToPath } from "url";
14
- import { dirname, join, isAbsolute } from "path";
15
+ import { dirname, join } from "path";
15
16
  export const SEMVER_VERSION = packageJson.version;
16
17
  // Set entry directory for logger (ESM equivalent of __dirname)
17
18
  const __filename = fileURLToPath(import.meta.url);
@@ -24,28 +25,81 @@ 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("--read-only", "Enable read-only mode (default: enabled)", true)
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. Has no effect when --read-only is set. Default false.")
30
31
  .option("--log-level <level>", "Minimum log level (info, error)", "info")
31
- .option("--log-file <path>", 'Log file path or filename. If not specified, logs are written to console only.')
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 (core, releases, deployments, tasks, tenants, kubernetes, machines, certificates, accounts, interruptions, featureToggles) 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);
46
100
  }
47
101
  if (options.logFile) {
48
- if (dirname(options.logFile) === '.') {
102
+ if (dirname(options.logFile) === ".") {
49
103
  logger.setLogFilePath(join(__dirname, options.logFile));
50
104
  }
51
105
  else {
@@ -54,14 +108,7 @@ if (options.logFile) {
54
108
  }
55
109
  logger.setLogLevel(logger.parseLogLevel(options.logLevel));
56
110
  logger.setQuietMode(options.quiet);
57
- if (options.serverUrl) {
58
- process.env.CLI_SERVER_URL = options.serverUrl;
59
- }
60
- if (options.apiKey) {
61
- process.env.CLI_API_KEY = options.apiKey;
62
- }
63
- // Test configuration
64
- getClientConfigurationFromEnvironment();
111
+ // CLI_SERVER_URL is set earlier so the MCP instructions string can reference it.
65
112
  // Set up initialization callback to capture client info
66
113
  server.server.oninitialized = () => {
67
114
  const clientInfo = server.server.getClientVersion();
@@ -76,6 +123,8 @@ server.server.oninitialized = () => {
76
123
  logger.info(`Starting Octopus Deploy MCP server (version: ${SEMVER_VERSION})`);
77
124
  // Start server
78
125
  async function runServer() {
126
+ // Test configuration
127
+ getClientConfigurationFromEnvironment();
79
128
  const transport = new StdioServerTransport();
80
129
  await server.connect(transport);
81
130
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
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;AAE9D,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,CAgE/D"}
@@ -0,0 +1,90 @@
1
+ import { Client } from "@octopusdeploy/api-client";
2
+ import { registerResourceDescriptor } from "../../types/resourceConfig.js";
3
+ import { getClientConfigurationFromEnvironment } from "../../helpers/getClientConfigurationFromEnvironment.js";
4
+ import { TOOL_REGISTRY, DEFAULT_TOOLSETS, } from "../../types/toolConfig.js";
5
+ import { getActiveToolsetConfig } from "../../helpers/activeToolsetConfig.js";
6
+ import {} from "../../helpers/methodTier.js";
7
+ function resolveEnabledToolsets() {
8
+ const config = getActiveToolsetConfig();
9
+ if (config.enabledToolsets === "all" || config.enabledToolsets == null) {
10
+ return DEFAULT_TOOLSETS;
11
+ }
12
+ return config.enabledToolsets;
13
+ }
14
+ export async function buildCapabilities() {
15
+ const client = await Client.create(getClientConfigurationFromEnvironment());
16
+ const serverInfo = await client.getServerInformation();
17
+ const activeConfig = getActiveToolsetConfig();
18
+ const enabledToolsets = resolveEnabledToolsets();
19
+ const readOnlyMode = activeConfig.readOnlyMode ?? false;
20
+ const allowDeletes = activeConfig.allowDeletes ?? false;
21
+ const enabledSet = new Set(enabledToolsets);
22
+ enabledSet.add("core");
23
+ const tools = [];
24
+ for (const [name, registration] of TOOL_REGISTRY) {
25
+ if (!enabledSet.has(registration.config.toolset))
26
+ continue;
27
+ if (readOnlyMode && !registration.config.readOnly)
28
+ continue;
29
+ const entry = {
30
+ name,
31
+ toolset: registration.config.toolset,
32
+ readOnly: registration.config.readOnly,
33
+ minimumOctopusVersion: registration.minimumOctopusVersion,
34
+ };
35
+ // The execute tool registers as readOnly:true (so it survives the
36
+ // registration filter in read-only mode for its GET branch) but its
37
+ // actual behaviour is method-gated. Surface that explicitly so callers
38
+ // don't conclude execute is fully read-only.
39
+ if (name === "execute") {
40
+ entry.methodGated = true;
41
+ const tiers = ["read"];
42
+ if (!readOnlyMode)
43
+ tiers.push("write");
44
+ if (!readOnlyMode && allowDeletes)
45
+ tiers.push("delete");
46
+ entry.tiersAvailable = tiers;
47
+ }
48
+ tools.push(entry);
49
+ }
50
+ tools.sort((a, b) => a.name.localeCompare(b.name));
51
+ let featureFlags;
52
+ try {
53
+ featureFlags = await client.get("~/api/serverstatus/extensions");
54
+ }
55
+ catch {
56
+ // The serverstatus/extensions endpoint isn't universally available across
57
+ // older Octopus versions. Omit feature flags rather than failing the whole
58
+ // capabilities read — server version is the high-value field.
59
+ featureFlags = undefined;
60
+ }
61
+ const capabilities = {
62
+ server: {
63
+ version: serverInfo.version,
64
+ installationId: serverInfo.installationId,
65
+ },
66
+ session: {
67
+ enabledToolsets: Array.from(enabledSet).sort(),
68
+ readOnlyMode,
69
+ allowDeletes,
70
+ },
71
+ tools,
72
+ };
73
+ if (featureFlags !== undefined) {
74
+ capabilities.featureFlags = featureFlags;
75
+ }
76
+ return capabilities;
77
+ }
78
+ registerResourceDescriptor({
79
+ name: "catalog-capabilities",
80
+ uriTemplate: "octopus://api/capabilities",
81
+ toolset: "core",
82
+ title: "Octopus MCP capabilities",
83
+ description: "Server version, enabled toolsets, available tools, and Octopus feature flags for this MCP session. Use this to discover what's reachable before calling other tools.",
84
+ mimeType: "application/json",
85
+ read: async () => ({
86
+ mimeType: "application/json",
87
+ text: JSON.stringify(await buildCapabilities()),
88
+ }),
89
+ });
90
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../../src/resources/catalog/capabilities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Fetch llms.txt for the configured Octopus server, with a 5-minute TTL cache.
3
+ * Exposed so grep_llms_txt can share the same cache.
4
+ */
5
+ export declare function fetchLlmsTxt(): Promise<string>;
6
+ /** Test seam: clear the cache between tests. */
7
+ export declare function clearLlmsTxtCache(): void;
8
+ //# sourceMappingURL=llmsTxt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llmsTxt.d.ts","sourceRoot":"","sources":["../../../src/resources/catalog/llmsTxt.ts"],"names":[],"mappings":"AAkBA;;;GAGG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAcpD;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -0,0 +1,44 @@
1
+ import { Client } from "@octopusdeploy/api-client";
2
+ import { registerResourceDescriptor } from "../../types/resourceConfig.js";
3
+ import { getClientConfigurationFromEnvironment } from "../../helpers/getClientConfigurationFromEnvironment.js";
4
+ const LLMS_TXT_PATH = "~/api/experimental/llms.txt";
5
+ const CACHE_TTL_MS = 5 * 60 * 1000;
6
+ // Module-scoped cache keyed on the configured Octopus server URL. llms.txt
7
+ // only changes when Octopus itself ships a new version; refetching on every
8
+ // resource read or every grep call would burn ~360 KB of bandwidth and add
9
+ // latency to every catalog query.
10
+ const cache = new Map();
11
+ /**
12
+ * Fetch llms.txt for the configured Octopus server, with a 5-minute TTL cache.
13
+ * Exposed so grep_llms_txt can share the same cache.
14
+ */
15
+ export async function fetchLlmsTxt() {
16
+ const configuration = getClientConfigurationFromEnvironment();
17
+ const cacheKey = configuration.instanceURL ?? "(unknown)";
18
+ const now = Date.now();
19
+ const hit = cache.get(cacheKey);
20
+ if (hit && now - hit.fetchedAt < CACHE_TTL_MS) {
21
+ return hit.body;
22
+ }
23
+ const client = await Client.create(configuration);
24
+ const body = await client.getRaw(LLMS_TXT_PATH);
25
+ cache.set(cacheKey, { body, fetchedAt: now });
26
+ return body;
27
+ }
28
+ /** Test seam: clear the cache between tests. */
29
+ export function clearLlmsTxtCache() {
30
+ cache.clear();
31
+ }
32
+ registerResourceDescriptor({
33
+ name: "catalog-llms-txt",
34
+ uriTemplate: "octopus://api/llms.txt",
35
+ toolset: "core",
36
+ title: "Octopus API catalog (llms.txt)",
37
+ description: "Markdown catalog of every Octopus REST endpoint, including HTTP method, path, query params, and request/response types. Large (~300+ KB) — prefer the grep_llms_txt tool to search it instead of reading the whole body. Requires Octopus Server 2026.2.3916 or later (the /api/experimental/llms.txt endpoint shipped in that release).",
38
+ mimeType: "text/markdown",
39
+ read: async () => ({
40
+ mimeType: "text/markdown",
41
+ text: await fetchLlmsTxt(),
42
+ }),
43
+ });
44
+ //# sourceMappingURL=llmsTxt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llmsTxt.js","sourceRoot":"","sources":["../../../src/resources/catalog/llmsTxt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EAAE,qCAAqC,EAAE,MAAM,wDAAwD,CAAC;AAE/G,MAAM,aAAa,GAAG,6BAA6B,CAAC;AACpD,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAOnC,2EAA2E;AAC3E,4EAA4E;AAC5E,2EAA2E;AAC3E,kCAAkC;AAClC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;AAE5C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,aAAa,GAAG,qCAAqC,EAAE,CAAC;IAC9D,MAAM,QAAQ,GAAG,aAAa,CAAC,WAAW,IAAI,WAAW,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEvB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,CAAC,SAAS,GAAG,YAAY,EAAE,CAAC;QAC9C,OAAO,GAAG,CAAC,IAAI,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAChD,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,iBAAiB;IAC/B,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC;AAED,0BAA0B,CAAC;IACzB,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,wBAAwB;IACrC,OAAO,EAAE,MAAM;IACf,KAAK,EAAE,gCAAgC;IACvC,WAAW,EACT,0UAA0U;IAC5U,QAAQ,EAAE,eAAe;IACzB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QACjB,QAAQ,EAAE,eAAe;QACzB,IAAI,EAAE,MAAM,YAAY,EAAE;KAC3B,CAAC;CACH,CAAC,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Registry-driven dispatch for octopus:// resource URIs.
3
+ *
4
+ * Both the Resource Template registrations (src/resources/index.ts) and the
5
+ * `read_resource` Tool backstop (src/tools/readResource.ts) flow through the
6
+ * same descriptor registry, so resource-aware clients (which call resources/read)
7
+ * and resource-less clients (which call the Tool wrapper) hit identical logic.
8
+ *
9
+ * Toolset filtering is enforced at dispatch time. Native MCP clients only
10
+ * see resources whose toolset is enabled because registerResources skips
11
+ * disabled descriptors at registration. The `read_resource` backstop, by
12
+ * contrast, is registered under `core` and is always available — so without
13
+ * filtering here a caller could guess a URI for a descriptor whose toolset
14
+ * is disabled and still fetch the body. The filter below closes that gap.
15
+ */
16
+ import { type ResourcePayload } from "../types/resourceConfig.js";
17
+ /**
18
+ * Pick the first value for each variable and URL-decode it.
19
+ *
20
+ * The SDK's UriTemplate.match captures regex groups as raw strings (no decoding),
21
+ * so an input URI like `octopus://spaces/AI%20Foundations/releases/Releases-1`
22
+ * yields `spaceName = "AI%20Foundations"` here. Decoding makes the variables
23
+ * usable directly against the Octopus API, which expects the literal `AI Foundations`.
24
+ *
25
+ * Falls back to the raw value if a string contains an invalid percent-escape so
26
+ * a malformed input surfaces as a clearer downstream error rather than a URIError.
27
+ */
28
+ export declare function flatten(variables: Record<string, string | string[]>): Record<string, string>;
29
+ export declare function dispatchOctopusUri(uri: string): Promise<ResourcePayload | null>;
30
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/resources/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,4BAA4B,CAAC;AAmBpC;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,GAC3C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAmBD,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAejC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Registry-driven dispatch for octopus:// resource URIs.
3
+ *
4
+ * Both the Resource Template registrations (src/resources/index.ts) and the
5
+ * `read_resource` Tool backstop (src/tools/readResource.ts) flow through the
6
+ * same descriptor registry, so resource-aware clients (which call resources/read)
7
+ * and resource-less clients (which call the Tool wrapper) hit identical logic.
8
+ *
9
+ * Toolset filtering is enforced at dispatch time. Native MCP clients only
10
+ * see resources whose toolset is enabled because registerResources skips
11
+ * disabled descriptors at registration. The `read_resource` backstop, by
12
+ * contrast, is registered under `core` and is always available — so without
13
+ * filtering here a caller could guess a URI for a descriptor whose toolset
14
+ * is disabled and still fetch the body. The filter below closes that gap.
15
+ */
16
+ import { UriTemplate } from "@modelcontextprotocol/sdk/shared/uriTemplate.js";
17
+ import { RESOURCE_REGISTRY, } from "../types/resourceConfig.js";
18
+ import { DEFAULT_TOOLSETS, } from "../types/toolConfig.js";
19
+ import { getActiveToolsetConfig } from "../helpers/activeToolsetConfig.js";
20
+ const COMPILED = new WeakMap();
21
+ function compiled(descriptor) {
22
+ let template = COMPILED.get(descriptor);
23
+ if (!template) {
24
+ template = new UriTemplate(descriptor.uriTemplate);
25
+ COMPILED.set(descriptor, template);
26
+ }
27
+ return template;
28
+ }
29
+ /**
30
+ * Pick the first value for each variable and URL-decode it.
31
+ *
32
+ * The SDK's UriTemplate.match captures regex groups as raw strings (no decoding),
33
+ * so an input URI like `octopus://spaces/AI%20Foundations/releases/Releases-1`
34
+ * yields `spaceName = "AI%20Foundations"` here. Decoding makes the variables
35
+ * usable directly against the Octopus API, which expects the literal `AI Foundations`.
36
+ *
37
+ * Falls back to the raw value if a string contains an invalid percent-escape so
38
+ * a malformed input surfaces as a clearer downstream error rather than a URIError.
39
+ */
40
+ export function flatten(variables) {
41
+ const out = {};
42
+ for (const [key, value] of Object.entries(variables)) {
43
+ const first = Array.isArray(value) ? (value[0] ?? "") : value;
44
+ out[key] = safeDecode(first);
45
+ }
46
+ return out;
47
+ }
48
+ function safeDecode(value) {
49
+ try {
50
+ return decodeURIComponent(value);
51
+ }
52
+ catch {
53
+ return value;
54
+ }
55
+ }
56
+ function isToolsetEnabled(toolset, config) {
57
+ if (toolset === "core")
58
+ return true;
59
+ const enabled = config.enabledToolsets === "all"
60
+ ? DEFAULT_TOOLSETS
61
+ : config.enabledToolsets || DEFAULT_TOOLSETS;
62
+ return enabled.includes(toolset);
63
+ }
64
+ export async function dispatchOctopusUri(uri) {
65
+ if (!uri.startsWith("octopus://"))
66
+ return null;
67
+ const config = getActiveToolsetConfig();
68
+ for (const descriptor of RESOURCE_REGISTRY) {
69
+ const variables = compiled(descriptor).match(uri);
70
+ if (!variables)
71
+ continue;
72
+ // Even though the URI matches, the descriptor's toolset may be disabled
73
+ // for this session. Skip and keep looking — but no other descriptor
74
+ // should claim the same template, so this effectively returns null.
75
+ if (!isToolsetEnabled(descriptor.toolset, config))
76
+ continue;
77
+ return descriptor.read(flatten(variables));
78
+ }
79
+ return null;
80
+ }
81
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/resources/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iDAAiD,CAAC;AAC9E,OAAO,EACL,iBAAiB,GAGlB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,gBAAgB,GAGjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAE3E,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAmC,CAAC;AAEhE,SAAS,QAAQ,CAAC,UAA8B;IAC9C,IAAI,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,IAAI,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QACnD,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,OAAO,CACrB,SAA4C;IAE5C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC9D,GAAG,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAgB,EAAE,MAAqB;IAC/D,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,OAAO,GACX,MAAM,CAAC,eAAe,KAAK,KAAK;QAC9B,CAAC,CAAC,gBAAgB;QAClB,CAAC,CAAC,MAAM,CAAC,eAAe,IAAI,gBAAgB,CAAC;IACjD,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAW;IAEX,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAE/C,MAAM,MAAM,GAAG,sBAAsB,EAAE,CAAC;IACxC,KAAK,MAAM,UAAU,IAAI,iBAAiB,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAClD,IAAI,CAAC,SAAS;YAAE,SAAS;QACzB,wEAAwE;QACxE,oEAAoE;QACpE,oEAAoE;QACpE,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC;YAAE,SAAS;QAC5D,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=featureToggle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"featureToggle.d.ts","sourceRoot":"","sources":["../../src/resources/featureToggle.ts"],"names":[],"mappings":""}
@@ -0,0 +1,34 @@
1
+ import { Client, resolveSpaceId } from "@octopusdeploy/api-client";
2
+ import { registerResourceDescriptor } from "../types/resourceConfig.js";
3
+ import { getClientConfigurationFromEnvironment } from "../helpers/getClientConfigurationFromEnvironment.js";
4
+ import { handleOctopusApiError } from "../helpers/errorHandling.js";
5
+ import { stripLinks } from "../helpers/stripLinks.js";
6
+ import {} from "../types/featureToggleTypes.js";
7
+ registerResourceDescriptor({
8
+ name: "featureToggle",
9
+ uriTemplate: "octopus://spaces/{spaceName}/projects/{projectId}/featuretoggles/{slug}",
10
+ toolset: "featureToggles",
11
+ title: "Octopus feature toggle",
12
+ description: "Full customer feature toggle body for a given slug in a project. Includes per-environment configuration (tenants, segments, minimum versions) that the find_feature_toggles slim summary omits.",
13
+ mimeType: "application/json",
14
+ read: async ({ spaceName, projectId, slug }) => {
15
+ try {
16
+ const client = await Client.create(getClientConfigurationFromEnvironment());
17
+ const spaceId = await resolveSpaceId(client, spaceName);
18
+ const toggle = await client.get("~/api/{spaceId}/projects/{projectId}/featuretoggles/{slug}", { spaceId, projectId, slug });
19
+ return {
20
+ mimeType: "application/json",
21
+ text: JSON.stringify(stripLinks(toggle)),
22
+ };
23
+ }
24
+ catch (error) {
25
+ handleOctopusApiError(error, {
26
+ entityType: "feature toggle",
27
+ entityId: slug,
28
+ spaceName,
29
+ helpText: "Use find_feature_toggles to list valid slugs. If 404 persists across all toggles, the customer feature toggles capability may be disabled on the Octopus instance.",
30
+ });
31
+ }
32
+ },
33
+ });
34
+ //# sourceMappingURL=featureToggle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"featureToggle.js","sourceRoot":"","sources":["../../src/resources/featureToggle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,qCAAqC,EAAE,MAAM,qDAAqD,CAAC;AAC5G,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAA8B,MAAM,gCAAgC,CAAC;AAE5E,0BAA0B,CAAC;IACzB,IAAI,EAAE,eAAe;IACrB,WAAW,EACT,yEAAyE;IAC3E,OAAO,EAAE,gBAAgB;IACzB,KAAK,EAAE,wBAAwB;IAC/B,WAAW,EACT,iMAAiM;IACnM,QAAQ,EAAE,kBAAkB;IAC5B,IAAI,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE;QAC7C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAChC,qCAAqC,EAAE,CACxC,CAAC;YACF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YACxD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAC7B,4DAA4D,EAC5D,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAC7B,CAAC;YAEF,OAAO;gBACL,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;aACzC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,qBAAqB,CAAC,KAAK,EAAE;gBAC3B,UAAU,EAAE,gBAAgB;gBAC5B,QAAQ,EAAE,IAAI;gBACd,SAAS;gBACT,QAAQ,EACN,oKAAoK;aACvK,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { type McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type ToolsetConfig } from "../types/toolConfig.js";
3
+ import "./release.js";
4
+ import "./runbook.js";
5
+ import "./task.js";
6
+ import "./interruption.js";
7
+ import "./featureToggle.js";
8
+ import "./rolloutGroup.js";
9
+ import "./catalog/llmsTxt.js";
10
+ import "./catalog/capabilities.js";
11
+ export declare function registerResources(server: McpServer, config?: ToolsetConfig): void;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,yCAAyC,CAAC;AAC3F,OAAO,EACL,KAAK,aAAa,EAGnB,MAAM,wBAAwB,CAAC;AAMhC,OAAO,cAAc,CAAC;AACtB,OAAO,cAAc,CAAC;AACtB,OAAO,WAAW,CAAC;AACnB,OAAO,mBAAmB,CAAC;AAC3B,OAAO,oBAAoB,CAAC;AAC5B,OAAO,mBAAmB,CAAC;AAC3B,OAAO,sBAAsB,CAAC;AAC9B,OAAO,2BAA2B,CAAC;AAWnC,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,GAAE,aAAkB,GAAG,IAAI,CA2BrF"}
@@ -0,0 +1,44 @@
1
+ import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { DEFAULT_TOOLSETS, } from "../types/toolConfig.js";
3
+ import { RESOURCE_REGISTRY } from "../types/resourceConfig.js";
4
+ import { flatten } from "./dispatch.js";
5
+ import { setActiveToolsetConfig } from "../helpers/activeToolsetConfig.js";
6
+ // Side-effect imports populate RESOURCE_REGISTRY.
7
+ import "./release.js";
8
+ import "./runbook.js";
9
+ import "./task.js";
10
+ import "./interruption.js";
11
+ import "./featureToggle.js";
12
+ import "./rolloutGroup.js";
13
+ import "./catalog/llmsTxt.js";
14
+ import "./catalog/capabilities.js";
15
+ function isToolsetEnabled(toolset, config) {
16
+ const enabled = config.enabledToolsets === "all"
17
+ ? DEFAULT_TOOLSETS
18
+ : config.enabledToolsets || DEFAULT_TOOLSETS;
19
+ return toolset === "core" || enabled.includes(toolset);
20
+ }
21
+ export function registerResources(server, config = {}) {
22
+ setActiveToolsetConfig(config);
23
+ for (const descriptor of RESOURCE_REGISTRY) {
24
+ if (!isToolsetEnabled(descriptor.toolset, config))
25
+ continue;
26
+ server.registerResource(descriptor.name, new ResourceTemplate(descriptor.uriTemplate, { list: undefined }), {
27
+ title: descriptor.title,
28
+ description: descriptor.description,
29
+ mimeType: descriptor.mimeType,
30
+ }, async (uri, variables) => {
31
+ const payload = await descriptor.read(flatten(variables));
32
+ return {
33
+ contents: [
34
+ {
35
+ uri: uri.href,
36
+ mimeType: payload.mimeType,
37
+ text: payload.text,
38
+ },
39
+ ],
40
+ };
41
+ });
42
+ }
43
+ }
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,gBAAgB,EAAE,MAAM,yCAAyC,CAAC;AAC3F,OAAO,EAGL,gBAAgB,GACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAE3E,kDAAkD;AAClD,OAAO,cAAc,CAAC;AACtB,OAAO,cAAc,CAAC;AACtB,OAAO,WAAW,CAAC;AACnB,OAAO,mBAAmB,CAAC;AAC3B,OAAO,oBAAoB,CAAC;AAC5B,OAAO,mBAAmB,CAAC;AAC3B,OAAO,sBAAsB,CAAC;AAC9B,OAAO,2BAA2B,CAAC;AAEnC,SAAS,gBAAgB,CAAC,OAAgB,EAAE,MAAqB;IAC/D,MAAM,OAAO,GACX,MAAM,CAAC,eAAe,KAAK,KAAK;QAC9B,CAAC,CAAC,gBAAgB;QAClB,CAAC,CAAC,MAAM,CAAC,eAAe,IAAI,gBAAgB,CAAC;IAEjD,OAAO,OAAO,KAAK,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAiB,EAAE,SAAwB,EAAE;IAC7E,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,KAAK,MAAM,UAAU,IAAI,iBAAiB,EAAE,CAAC;QAC3C,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC;YAAE,SAAS;QAE5D,MAAM,CAAC,gBAAgB,CACrB,UAAU,CAAC,IAAI,EACf,IAAI,gBAAgB,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EACjE;YACE,KAAK,EAAE,UAAU,CAAC,KAAK;YACvB,WAAW,EAAE,UAAU,CAAC,WAAW;YACnC,QAAQ,EAAE,UAAU,CAAC,QAAQ;SAC9B,EACD,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE;YACvB,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;YAC1D,OAAO;gBACL,QAAQ,EAAE;oBACR;wBACE,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,QAAQ,EAAE,OAAO,CAAC,QAAQ;wBAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;qBACnB;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=interruption.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interruption.d.ts","sourceRoot":"","sources":["../../src/resources/interruption.ts"],"names":[],"mappings":""}