McpSource.resourceTools
Java · package io.github.muthuishere:toolnexus · SPEC §2
// McpSourcepublic List<Tool> resourceTools() // [list_mcp_resources, read_mcp_resource]
// also reachable from a toolkit built with an MCP configpublic McpSource Toolkit.mcpSource()Two opt-in, read-only tools bound to the source’s connected servers:
list_mcp_resources {server?}— one line per resource:server uri — name (mimeType): description.read_mcp_resource {server, uri}— the resource’s text. An unknown server or uri is an error result, not a throw.
Both carry ToolHints.READ_ONLY and stop working when the source is closed. Nothing registers them
for you: add them to a toolkit with tk.register(...).
When to use it
Section titled “When to use it”Your MCP servers expose resources (docs, schemas, files, records) as well as tools, and the model should be able to browse and read them on its own during a run.
Why this and not the alternative
Section titled “Why this and not the alternative”Examples
Section titled “Examples”1. The smallest useful call — list, then read
Section titled “1. The smallest useful call — list, then read”import io.github.muthuishere.toolnexus.*;import java.util.List;import java.util.Map;
public class Example { public static void main(String[] args) { String cfg = "{\"mcpServers\":{\"progress\":{\"command\":[\"node\",\"examples/mcp-progress-server.mjs\"]}}}"; try (McpSource src = McpSource.load(cfg)) { List<Tool> tools = src.resourceTools(); ToolResult list = tools.get(0).execute(Map.of(), null); if (!list.output().contains("fixture://hello")) throw new AssertionError(list.output()); ToolResult read = tools.get(1).execute(Map.of("server", "progress", "uri", "fixture://hello"), null); if (!"hello resource".equals(read.output())) throw new AssertionError(read.output()); System.out.println("ok: " + list.output()); } }}2. The realistic case — register them on a toolkit
Section titled “2. The realistic case — register them on a toolkit”import io.github.muthuishere.toolnexus.*;
public class Example { public static void main(String[] args) { String cfg = "{\"mcpServers\":{\"progress\":{\"command\":[\"node\",\"examples/mcp-progress-server.mjs\"]}}}"; try (Toolkit tk = Toolkit.create(new Toolkit.Options().builtins(false).mcpConfig(cfg))) { tk.register(tk.mcpSource().resourceTools().toArray(new Tool[0])); Tool read = tk.get("read_mcp_resource"); if (read == null || !read.hints().readOnly()) throw new AssertionError("not registered read-only"); System.out.println("ok: " + tk.tools().stream().map(Tool::name).filter(n -> n.contains("resource")).toList()); } }}3. The full surface — errors are results
Section titled “3. The full surface — errors are results”import io.github.muthuishere.toolnexus.*;import java.util.Map;
public class Example { public static void main(String[] args) { String cfg = "{\"mcpServers\":{\"progress\":{\"command\":[\"node\",\"examples/mcp-progress-server.mjs\"]}}}"; try (McpSource src = McpSource.load(cfg)) { Tool read = src.resourceTools().get(1); ToolResult missing = read.execute(Map.of("server", "progress", "uri", "fixture://nope"), null); ToolResult unknown = read.execute(Map.of("server", "nope", "uri", "x"), null); if (!missing.isError() || !unknown.isError()) throw new AssertionError("expected error results"); System.out.println("ok: " + unknown.output()); } }}See also
Section titled “See also”McpSource.load— Read an mcp.json, connect every local stdio and remote streamable-HTTP server, expose each server tool as a Tool.McpSource.loadWith— The ctx-aware load: bound connection time and cancel a slow or hung server without leaking a child process.McpSource.listMcpTools— List what each configured server would expose, plus per-server status, without wiring it into a toolkit.McpSource.parseConfig— Parse and validate config without connecting — the fast fail for a malformed or misspelled server block.