Grep the Octopus API catalog (llms.txt)
grep_llms_txtSearch the Octopus API catalog using grep-style pattern matching to locate endpoints, resource families, or deployment step types. Supports regex and literal strings with context lines.
Instructions
Search the Octopus API catalog at octopus://api/llms.txt with grep-style semantics. The catalog is large (~300+ KB) — call this rather than reading the resource body directly.
llms.txt is structured as:
Authentication and Space Selection sections (top of file)
Endpoints section: one '### {Category}' heading per resource family (Accounts, ActionTemplates, Channels, Releases, …) and one bullet per endpoint of the form
- \METHOD /path` - description | Prefixes (pick one): /{spaceId}, /spaces/{spaceIdentifier} | ?queryParams → ReturnType`Steps section: deployment step types (Octopus.* ActionType) and their configurable property keys.
Useful patterns:
'POST /releases' — find write endpoints under a resource family
'DELETE ' — enumerate delete endpoints
'### Channels' — jump to a section heading
'Body: Create.*Command' — find endpoints that take a Create command body
Parameter conventions mirror GNU grep:
pattern (regex by default; set fixedString:true for literal text)
caseInsensitive (-i)
invertMatch (-v)
fixedString (-F)
beforeContext (-B)
afterContext (-A)
maxCount (-m)
Response: totalMatches (true count across the whole file), totalLines, the matched lines with 1-indexed lineNumber, optional before/after context arrays, and catalogResourceUri for the structured fall-through.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| pattern | Yes | Regex (default) or literal substring (when fixedString=true). Tested against each line of llms.txt independently — same model as `grep`. | |
| caseInsensitive | No | Equivalent to grep -i. Default false. | |
| invertMatch | No | Equivalent to grep -v: return lines that do NOT match. Default false. | |
| fixedString | No | Equivalent to grep -F: treat pattern as a literal substring, not a regex. Use this when grepping for text containing regex metacharacters. Default false. | |
| beforeContext | No | Equivalent to grep -B: lines of preceding context to include with each match. Capped at 50. | |
| afterContext | No | Equivalent to grep -A: lines of trailing context to include with each match. Capped at 50. | |
| maxCount | No | Equivalent to grep -m: stop returning matches after this many. totalMatches in the response still reflects the true count across the whole file. Hard cap 500. |
Implementation Reference
- src/tools/grepLlmsTxt.ts:108-134 (handler)The async handler function that executes the grep_llms_txt tool. It fetches the llms.txt via fetchLlmsTxt(), runs grepLines() over the body, and returns JSON-serialized results including matches, counts, and truncation status.
async (args) => { const params = args as GrepLinesParams; const body = await fetchLlmsTxt(); const { totalLines, totalMatches, matches } = grepLines(body, params); const result: GrepLlmsTxtResult = { pattern: params.pattern, totalLines, totalMatches, returnedMatches: matches.length, truncated: totalMatches > matches.length, matches, catalogResourceUri: "octopus://api/llms.txt", }; return { content: [ { type: "text", text: JSON.stringify(result), }, ], }; }, ); } - src/tools/grepLlmsTxt.ts:24-74 (schema)Zod input schema for the tool: pattern (regex or literal), caseInsensitive, invertMatch, fixedString, beforeContext (cap 50), afterContext (cap 50), maxCount (cap 500).
const inputSchema = { pattern: z .string() .min(1) .describe( "Regex (default) or literal substring (when fixedString=true). Tested against each line of llms.txt independently — same model as `grep`.", ), caseInsensitive: z .boolean() .default(false) .describe("Equivalent to grep -i. Default false."), invertMatch: z .boolean() .default(false) .describe( "Equivalent to grep -v: return lines that do NOT match. Default false.", ), fixedString: z .boolean() .default(false) .describe( "Equivalent to grep -F: treat pattern as a literal substring, not a regex. Use this when grepping for text containing regex metacharacters. Default false.", ), beforeContext: z .number() .int() .min(0) .max(MAX_CONTEXT) .default(0) .describe( `Equivalent to grep -B: lines of preceding context to include with each match. Capped at ${MAX_CONTEXT}.`, ), afterContext: z .number() .int() .min(0) .max(MAX_CONTEXT) .default(0) .describe( `Equivalent to grep -A: lines of trailing context to include with each match. Capped at ${MAX_CONTEXT}.`, ), maxCount: z .number() .int() .min(1) .max(MAX_COUNT_HARD_CAP) .default(100) .describe( `Equivalent to grep -m: stop returning matches after this many. totalMatches in the response still reflects the true count across the whole file. Hard cap ${MAX_COUNT_HARD_CAP}.`, ), }; - src/tools/grepLlmsTxt.ts:14-22 (schema)Result interface GrepLlmsTxtResult: pattern, totalLines, totalMatches, returnedMatches, truncated flag, matches array, and catalog resource URI.
export interface GrepLlmsTxtResult { pattern: string; totalLines: number; totalMatches: number; returnedMatches: number; truncated: boolean; matches: GrepMatch[]; catalogResourceUri: string; } - src/tools/grepLlmsTxt.ts:136-142 (registration)Tool registration via registerToolDefinition: toolName 'grep_llms_txt', toolset 'core', readOnly:true, minimumOctopusVersion '2026.2.3916'. The registerGrepLlmsTxtTool function at line 76 calls server.registerTool().
registerToolDefinition({ toolName: "grep_llms_txt", config: { toolset: "core", readOnly: true }, registerFn: registerGrepLlmsTxtTool, // The /api/experimental/llms.txt endpoint shipped in Octopus 2026.2.3916. minimumOctopusVersion: "2026.2.3916", }); - fetchLlmsTxt() helper: fetches the Octopus API catalog from ~/api/experimental/llms.txt with a 5-minute TTL cache, used by the grep_llms_txt handler.
export async function fetchLlmsTxt(): Promise<string> { const configuration = getClientConfigurationFromEnvironment(); const cacheKey = configuration.instanceURL ?? "(unknown)"; const now = Date.now(); const hit = cache.get(cacheKey); if (hit && now - hit.fetchedAt < CACHE_TTL_MS) { return hit.body; } const client = await Client.create(configuration); const body = await client.getRaw(LLMS_TXT_PATH); cache.set(cacheKey, { body, fetchedAt: now }); return body; } - src/tools/index.ts:47-47 (registration)Import of the grepLlmsTxt.ts module in the tools index, triggering self-registration on import.
import "./grepLlmsTxt.js";