Agentic Research

Read these first

This article assumes the following earlier in its learning path.

MCP (Model Context Protocol) Ecosystem Explained: The Three Core Primitives of Tool, Resource, and Prompt

2026/05/1010 min readBryan Chan閱讀中文原文
TopicsMCPClaude Code

What Is MCP?

MCP's three primitives: Tools, Resources, PromptsAn MCP server exposes three kinds of thing, and the most useful axis for distinguishing them is not what they are but who decides to use them. Tools are called at the MODEL's decision; they can do things rather than merely return data, and are the only one of the three that changes the outside world, so they carry the highest risk and are why gates and permission settings exist. Resources are read at the APPLICATION's decision; they are data rather than actions, and their risk lies in content — what is read shapes the model's judgement, so the source must be trusted. Prompts are chosen by the USER; they are templates supplied by the server and surfaced in a menu, lowest risk but easiest to overlook, because they are prompts written by the server's author and you should know what they say. How to read a server's primitive list: a server exposing only Resources cannot act on your behalf, it can only supply data, while one exposing Tools can — and that single difference should change how carefully you read its access notes. The list also does not tell you two things: how many of each (a server with one tool and one with forty both show "tools"), and what they touch — which is why every entry in this site's MCP catalog requires access and risk fields.Three primitives, distinguished by who decides to use themThat axis matters more than what they are, because it maps straight onto permission and riskHost (your AI app)connects to serversMCP serverexposes the threestdio / Streamable HTTPToolsThe model decides to call itIt can DO things, not just return data.The only one that changes the world.e.g. query a database, send a message,file an issue, run codeResourcesThe application decides to read itIt is DATA, not an action.The host app picks what enters context.e.g. file contents, a database schema,document excerptsPromptsThe user chooses itIt is a TEMPLATE, usually in a menu.You pick it; the model never invents it.e.g. "review this code","turn these notes into tasks"Tools · riskHighest risk, so it needs a gate. The model decides whether to use it — which is why permissions exist.Two things a primitive list does not tell you· How many of each. A server with one tool and one with forty tools both show "tools".· What they touch. That is why every entry in this site's catalog carries access and risk fields.1
1/4Tools: the model decides
The only one that changes the world
Step 1 of 4 Tools: the model decides
Diagram: MCP's three primitives — tools, resources and prompts. Who initiates, who responds, and which way the data flows.

MCP (Model Context Protocol) is an open-source protocol introduced by Anthropic that defines a standard interface between LLMs and external tools/data sources. It enables AI clients such as Claude Code to securely access external resources such as local files, databases, and APIs.

Core Concepts

┌──────────────┐     MCP Protocol     ┌──────────────┐
│  MCP Client  │ ◄──────────────────► │  MCP Server  │
│ (Claude Code)│    JSON-RPC 2.0      │ (tool/data)  │
└──────────────┘                      └──────────────┘

Three Major Primitives

PrimitivePurposeExample
ToolAllows the LLM to perform operationsQuery databases, send HTTP requests
ResourceExposes data to the LLMFile contents, API responses
PromptPredefined prompt templatesCode review templates, translation templates

Tool

Tool enables LLMs to perform actions, not just generate text.

Built-in Commonly Used MCP Servers

# File System Access
npx @anthropic-ai/mcp-server-filesystem /path/to/allowed/dir

# GitHub Integration
npx @anthropic-ai/mcp-server-github

# PostgreSQL Queries
npx @anthropic-ai/mcp-server-postgres

# Brave Search
npx @anthropic-ai/mcp-server-brave-search

# Puppeteer Browser
npx @anthropic-ai/mcp-server-puppeteer

Configure Claude Code to Use MCP

Edit ~/.claude.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["@anthropic-ai/mcp-server-filesystem", "/Users/me/projects"],
      "env": {}
    },
    "github": {
      "command": "npx",
      "args": ["@anthropic-ai/mcp-server-github"],
      "env": {
        "GITHUB_TOKEN": "ghp_xxx"
      }
    }
  }
}

After configuring, restart Claude Code and enter /mcp to view connected servers.


Resource

Resource allows LLMs to read structured data without users pasting content.

Typical Scenarios

  • Database Schema: Let the LLM understand the table structure and automatically generate SQL
  • API Documentation: Automatically read the OpenAPI spec and generate correct API calls
  • Project Structure: Expose the project file tree so the LLM can understand the codebase layout
{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["@anthropic-ai/mcp-server-postgres", "postgresql://localhost/mydb"]
    }
  }
}

Prompt (Prompt Templates)

Prompt provides reusable prompt templates to ensure consistency.

{
  "mcpServers": {
    "review-templates": {
      "command": "npx",
      "args": ["@anthropic-ai/mcp-server-prompt", "--dir", "~/.claude/prompts"]
    }
  }
}

Place .md files under ~/.claude/prompts/ and they can be invoked through MCP.


Hands-On: Building a Custom MCP Server

# my_mcp_server.py
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationCapabilities
import mcp.server.stdio
import mcp.types as types

server = Server("my-tools")

@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
    return [
        types.Tool(
            name="get_weather",
description="Get the weather for a specified city",
            inputSchema={
                "type": "object",
                "properties": {
"city": {"type": "string", "description": "City name"}
                },
                "required": ["city"]
            }
        )
    ]

@server.call_tool()
async def handle_call_tool(name: str, arguments: dict):
    if name == "get_weather":
        city = arguments["city"]
# Actually call the weather API
        return [types.TextContent(type="text", text=f"{city} Weather: Sunny 25°C")]

async def run():
    async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream,
            InitializationCapabilities(
                sampling={},
                experimental={},
            ))

if __name__ == "__main__":
    import asyncio
    asyncio.run(run())

Register it in ~/.claude.json:

{
  "mcpServers": {
    "my-tools": {
      "command": "python",
      "args": ["/path/to/my_mcp_server.py"]
    }
  }
}

Security Considerations

MCP Server can access the file system and network, so caution is required:

  1. Principle of least privilege: the filesystem server should expose only the necessary directories
  2. Environment variable isolation: pass sensitive credentials via env, and do not write them to configuration files
  3. Audit logs: regularly review MCP Server access records
  4. Do not expose the / root directory: limit the filesystem server's access scope

Recommended Reading

Next on this path