Skip to content

[MCP] Verb tools for table-less programmatic Resources are listed only to super-users #1940

Description

@kylebernhardy

Follow-up from the docs pass for #1923 (documentation#605), which surfaced this while verifying what #1921 actually delivers.

Problem

makeVisibleTo gates tools/list visibility on the Resource having a backing database and table:

// components/mcp/tools/application.ts:716
if (!databaseName || !tableName) return false;

A purely programmatic Resource — a Resource subclass that overrides get/post/put/delete, or aggregates across tables — has neither, so every non-super user sees none of its verb tools in tools/list. The tools are still invocable by name via tools/call; they are just undiscoverable.

The surrounding comment frames this as a conservative default ("non-table Resources have no static permission gate — runtime allow* predicates enforce"), which is a reasonable starting posture. But it now collides with #1920/#1921: we just did the work to give exactly these Resources rich inputSchema / outputSchema output, and for any non-super user that work is invisible.

Why it matters

The realistic MCP deployment is an LLM host connecting as an application user, not as super_user. In that configuration a component author who follows the static properties authoring guide gets a correct, well-described tool that their agent can never discover.

Options

  1. List it when the Resource opts in — e.g. honor static mcp = { listPublicly: true } or reuse the existing exportTypes.mcp signal, so the author takes explicit responsibility for the runtime allow* predicates.
  2. List it whenever the class declares allowRead/allowUpdate/etc. — presence of a predicate is the author asserting they enforce access.
  3. List it to any authenticated user by default and rely on the runtime predicates, matching how the custom mcpTools surface already behaves (those have no per-user listing filter beyond authentication).
  4. Keep as-is and document it — the docs PR currently does this, so this issue is not blocking.

Option 3 is the most consistent with mcpTools, which already lists to any authenticated caller and delegates enforcement to the method. Worth a deliberate decision either way rather than leaving the asymmetry implicit.

Whatever we choose, the note in reference/resources/resource-api.md and the troubleshooting line in learn/developers/mcp-and-openapi-metadata.mdx need a follow-up edit.

Issue generated by kAIle (Claude Opus 4.8).

Metadata

Metadata

Assignees

Labels

area:mcpModel Context Protocol (MCP) server: protocol, profiles, stdio CLI

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions