Read an Octopus resource by URI
read_resourceFetch the full body of any 'octopus://' URI returned by other tools to access resource or task details.
Instructions
Universal fetch for any 'octopus://' URI returned by any other tool. Use this whenever you see fields like 'resourceUri' or 'taskResourceUri' in a response and need the full body.
How to use:
Pass the URI string verbatim. Examples: 'octopus://spaces/Default/releases/Releases-42', 'octopus://spaces/Default/tasks/ServerTasks-7', 'octopus://spaces/Default/tasks/ServerTasks-7/details'.
The response 'mimeType' tells you how to interpret 'text': 'application/json' → parse as JSON.
This tool is the backstop for clients that do not natively implement the MCP 'resources/read' primitive. Clients that DO support resources/read (Claude Code, MCP Inspector) can call it directly and skip this tool. Either path returns byte-identical bodies.
Tools that return resource URIs include: find_releases, get_deployment_from_url, get_task_from_url, and others. When in doubt, call read_resource on any 'octopus://' string you encounter.
Note: there is intentionally no octopus://...tasks/{id}/log resource. Call the grep_task_log tool to search task logs without inhaling the full body.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| uri | Yes | Any 'octopus://...' URI returned by another tool (e.g. in the resourceUri or taskResourceUri field). |
Implementation Reference
- src/tools/readResource.ts:8-52 (handler)The actual handler and registration of the 'read_resource' tool. It accepts an 'octopus://' URI string, calls dispatchOctopusUri to resolve and fetch the resource, and returns the payload with uri, mimeType, and text.
server.registerTool( "read_resource", { title: "Read an Octopus resource by URI", description: `Universal fetch for any 'octopus://' URI returned by any other tool. Use this whenever you see fields like 'resourceUri' or 'taskResourceUri' in a response and need the full body. How to use: - Pass the URI string verbatim. Examples: 'octopus://spaces/Default/releases/Releases-42', 'octopus://spaces/Default/tasks/ServerTasks-7', 'octopus://spaces/Default/tasks/ServerTasks-7/details'. - The response 'mimeType' tells you how to interpret 'text': 'application/json' → parse as JSON. This tool is the backstop for clients that do not natively implement the MCP 'resources/read' primitive. Clients that DO support resources/read (Claude Code, MCP Inspector) can call it directly and skip this tool. Either path returns byte-identical bodies. Tools that return resource URIs include: find_releases, get_deployment_from_url, get_task_from_url, and others. When in doubt, call read_resource on any 'octopus://' string you encounter. Note: there is intentionally no octopus://...tasks/{id}/log resource. Call the grep_task_log tool to search task logs without inhaling the full body.`, inputSchema: { uri: z .string() .describe( "Any 'octopus://...' URI returned by another tool (e.g. in the resourceUri or taskResourceUri field).", ), }, annotations: READ_ONLY_TOOL_ANNOTATIONS, }, async ({ uri }) => { const payload = await dispatchOctopusUri(uri); if (payload === null) { throw new Error(`Unrecognised resource URI '${uri}'.`); } return { content: [ { type: "text", text: JSON.stringify({ uri, mimeType: payload.mimeType, text: payload.text, }), }, ], }; }, ); - src/tools/readResource.ts:23-30 (schema)Input schema for the read_resource tool: a single required string parameter 'uri' described as an octopus:// URI.
inputSchema: { uri: z .string() .describe( "Any 'octopus://...' URI returned by another tool (e.g. in the resourceUri or taskResourceUri field).", ), }, annotations: READ_ONLY_TOOL_ANNOTATIONS, - src/tools/readResource.ts:55-59 (registration)Registration of read_resource in the tool registry. It belongs to the 'core' toolset and is read-only, ensuring it's always available regardless of toolset filtering.
registerToolDefinition({ toolName: "read_resource", config: { toolset: "core", readOnly: true }, registerFn: registerReadResourceTool, }); - src/tools/index.ts:88-95 (registration)Generic tool registration loop that registers all enabled tools (including read_resource) by iterating the TOOL_REGISTRY map.
export function registerTools(server: McpServer, config: ToolsetConfig = {}) { // Iterate through all registered tools and register those that are enabled for (const [, toolRegistration] of TOOL_REGISTRY) { if (isToolEnabled(toolRegistration, config)) { toolRegistration.registerFn(server); } } } - src/resources/dispatch.ts:80-97 (helper)The dispatch engine that resolves an octopus:// URI against the resource descriptor registry, respecting toolset filtering, and returns a ResourcePayload (mimeType + text) or null if not found.
export async function dispatchOctopusUri( uri: string, ): Promise<ResourcePayload | null> { if (!uri.startsWith("octopus://")) return null; const config = getActiveToolsetConfig(); for (const descriptor of RESOURCE_REGISTRY) { const variables = compiled(descriptor).match(uri); if (!variables) continue; // Even though the URI matches, the descriptor's toolset may be disabled // for this session. Skip and keep looking — but no other descriptor // should claim the same template, so this effectively returns null. if (!isToolsetEnabled(descriptor.toolset, config)) continue; return descriptor.read(flatten(variables)); } return null; }