0

MCP Concepts

awesome-llm-appsfoundations

Core primitives you'll use to build MCP servers with mcp-use.

Sign in to save downloads to your library and vote.

Preview

MCP Concepts

Core primitives you'll use to build MCP servers with mcp-use.

The Four Primitives

1. Tool

A backend action the AI can call. Takes input, returns output.

Use for: Actions, operations, mutations, API calls

server.tool({ name, description, schema }, async (input) => {
  // Your logic here
  return text("result");
});

→ Detailed guide: ../server/tools.md

2. Resource

Read-only data that clients can fetch. No input parameters (use resource templates for that).

Use for: Configuration, static data, listings

server.resource({ uri, name, mimeType }, async () => {
  return object({ data });
});

→ Detailed guide: ../server/resources.md

3. Prompt

A reusable message template with parameters.

Use for: Common prompts, instruction templates

server.prompt({ name, description, schema }, async (input) => {
  return text(`Your prompt template with ${input.param}`);
});

→ Detailed guide: ../server/prompts.md

4. Widget (Tool + UI)

A tool that returns visual UI. Same as a tool but renders a React component.

Use for: Browsing data, interactive selection, visual feedback

server.tool({ name, schema, widget: { name: "widget-name" } }, async (input) =>
  widget({ props: { data }, output: text("...") }),
);

→ Detailed guide: ../widgets/basics.md


Decision Matrix

NeedUseExample
Backend actionToolsend-email, create-user, fetch-data
Read-only dataResourceconfig, user-profile, api-docs
Prompt templatePromptcode-review, summarize, translate
Visual UIWidget Toolsearch-results, calendar, dashboard

Tool vs Widget?

Use a tool (no widget) when:

  • Output is simple text or data
  • No visual representation helps
  • Quick conversational response

Use a widget when:

  • Browsing/comparing multiple items
  • Visual data improves understanding (charts, images)
  • Interactive selection is easier visually

When in doubt: Use a widget. It makes the experience better.


Key Patterns

1. One tool = one capability

❌ manage-users (too broad) ✅ create-user, delete-user, list-users

2. Don't lazy-load

Tool calls are expensive. Return all needed data upfront.

❌ list-products + get-product-details (two calls) ✅ list-products returns full data including details

3. Widget handles its own state

UI state (selections, filters) lives in the widget via useState or setState.

❌ select-item tool, set-filter tool ✅ Widget manages internally

4. exposeAsTool defaults to false

Widgets are not auto-registered as tools by default. When defining a custom tool with widget: { name }, omitting exposeAsTool (or leaving it false) is correct — the custom tool handles registration:

export const widgetMetadata: WidgetMetadata = {
  description: "...",
  props: z.object({...}),
  // exposeAsTool defaults to false — correct for custom-tool pattern
};

Next Steps

Ingestion metadata

Source catalog
awesome-llm-apps
File path
generative_ui_agents/ai-mcp-app-builder/apps/mcp-use-server/.agent/skills/mcp-apps-builder/references/foundations/concepts.md
Last refreshed
10/24/2026, 3:00:14 AM (5h ago)
Refresh schedule
Daily · 03:00 UTC
Dedupe status
Unique · deduped by (source, url)