# MCP Protocol Specification for Tools and Resources: A Complete Implementation Guide

> Explore the MCP protocol specification, a JSON-RPC contract for LLM clients to discover invoke and stream data from server tools and resources. Learn implementation details.

- Repository: [Model Context Protocol/servers](https://github.com/modelcontextprotocol/servers)
- Tags: api-reference
- Published: 2026-03-01

---

**The Model Context Protocol (MCP) specification defines a JSON-RPC based contract that allows LLM-powered clients to discover, invoke, and stream data from server-exposed tools and resources through standardized registration methods and capability negotiation.**

The MCP protocol specification for tools and resources is implemented in the `modelcontextprotocol/servers` repository, which serves as the official reference implementation. This protocol enables secure, discoverable interactions between AI clients and external data sources or computational capabilities.

## Core Concepts of the MCP Protocol Specification

The specification establishes distinct abstractions for capabilities exposed by an MCP server:

| Concept | Specification Definition | Implementation in Repository |
|---------|-------------------------|------------------------------|
| **Tool** | A callable operation returning a `CallToolResult` containing messages, resources, or errors. Discovered via the `tools/list` endpoint and invoked through `tools/call`. | TypeScript modules under `src/everything/tools/` (e.g., [`get-sum.ts`](https://github.com/modelcontextprotocol/servers/blob/main/get-sum.ts), [`get-tiny-image.ts`](https://github.com/modelcontextprotocol/servers/blob/main/get-tiny-image.ts)) register via `server.registerTool()` in [`src/everything/tools/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/index.ts). |
| **Resource** | Addressable content items (static files or dynamically generated blobs) accessible via URI. Advertised through `resources/list` and fetched via `resources/read`, with optional subscription support. | Modules under `src/everything/resources/` (e.g., [`templates.ts`](https://github.com/modelcontextprotocol/servers/blob/main/templates.ts), [`session.ts`](https://github.com/modelcontextprotocol/servers/blob/main/session.ts)) use `server.registerResource()` exported from [`src/everything/resources/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/resources/index.ts). |
| **ToolAnnotations** | Optional metadata indicating tool behavior: `idempotentHint`, `destructiveHint`, and `readOnlyHint`. Used by clients to determine auto-invocation safety. | Referenced in [`src/filesystem/README.md`](https://github.com/modelcontextprotocol/servers/blob/main/src/filesystem/README.md) (line 180) and implemented in tool config objects passed to `registerTool`. |
| **Capability Negotiation** | Handshake protocol where client and server agree on supported features (tools, resources, logging, experimental tasks). | [`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts) constructs `McpServer` with capabilities derived from configuration flags. |

## How Tools Are Registered in MCP

### Tool Registration Flow

The specification requires tools to be registered through a centralized server instance. In [`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts), the server factory creates an `McpServer` instance and triggers registration:

1. **Server instantiation** with capability flags
2. **Tool module loading** via [`src/everything/tools/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/index.ts)
3. **Individual registration** using `server.registerTool(name, config, handler)`

### Tool Configuration Schema

According to the MCP specification (2025-03-26), the configuration object passed to `registerTool` must conform to:

```typescript
{
  description: string;
  input_schema: JSONSchema7;      // Required argument validation
  output_schema?: JSONSchema7;    // Optional result validation
  annotations?: {
    idempotentHint?: boolean;     // Safe to retry
    destructiveHint?: boolean;    // Modifies state destructively
    readOnlyHint?: boolean;       // No side effects
  };
}

```

### Example: Registering a Simple Tool

The following implementation from [`src/everything/tools/get-sum.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/get-sum.ts) demonstrates a pure, idempotent tool with proper annotations:

```typescript
import { CallToolResult } from "modelcontextprotocol/types";

export const registerTool = (server: McpServer) => {
  const name = "get-sum";
  const config = {
    description: "Returns the sum of two numbers",
    input_schema: {
      type: "object",
      properties: {
        a: { type: "number" },
        b: { type: "number" },
      },
      required: ["a", "b"],
    },
    // MCP ToolAnnotations – this tool is pure (no side‑effects)
    annotations: { idempotentHint: true, readOnlyHint: true },
  };

  server.registerTool(name, config, async (args): Promise<CallToolResult> => {
    const { a, b } = args as { a: number; b: number };
    return { messages: [{ role: "assistant", content: `${a} + ${b} = ${a + b}` }] };
  });
};

```

## How Resources Are Registered in MCP

### Static and Dynamic Resources

The MCP specification distinguishes between static resources (fixed files) and dynamic resources (generated content). Both are registered via `server.registerResource(name, uri, config, handler)` in [`src/everything/resources/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/resources/index.ts).

Dynamic resources, such as the session blob example from [`src/everything/resources/session.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/resources/session.ts), generate content on demand:

```typescript
export const registerSessionResource = (server: McpServer) => {
  const name = "session-blob";
  const uri = "demo://resource/session/blob";
  const config = {
    description: "Per‑session gzipped data blob",
    mimeType: "application/gzip",
    // MCP ResourceAnnotations (optional)
    annotations: { readOnlyHint: true },
  };

  server.registerResource(name, uri, config, async () => {
    // Generate a gzipped Buffer on demand
    const payload = Buffer.from("session‑specific‑data");
    const gzipped = await gzipAsync(payload);
    return { data: gzipped };
  });
};

```

Resources are advertised through the `resources/list` endpoint and accessed via `resources/read` or real-time subscriptions if the server supports them.

## Advanced MCP Features: Task-Based Tools and Annotations

### ToolAnnotations for Safety

The MCP specification (2025-03-26) defines **ToolAnnotations** as critical metadata for client-side safety decisions. As noted in [`src/filesystem/README.md`](https://github.com/modelcontextprotocol/servers/blob/main/src/filesystem/README.md) (line 180), these annotations inform the client whether a tool can be automatically invoked or requires user confirmation:

- **`readOnlyHint`**: Indicates the tool does not modify server state (safe for automatic invocation)
- **`idempotentHint`**: Indicates repeated invocations with the same arguments produce the same result (safe to retry)
- **`destructiveHint`**: Warns that the tool performs destructive operations (requires explicit confirmation)

### Long-Running Task Tools

For operations that exceed typical request timeouts, the MCP specification supports task-based tools via `server.experimental.tasks.registerToolTask`. This pattern, implemented in [`src/everything/tools/simulate-research-query.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/simulate-research-query.ts), allows servers to:

1. Accept a tool call and return a `taskId` immediately
2. Stream progress updates through the `progress` callback
3. Complete asynchronously while the client polls or listens for completion

```typescript
// src/everything/tools/simulate-research-query.ts
export const registerSimulatedTask = (server: McpServer) => {
  const name = "simulate-research-query";
  const config = {
    description: "Runs a multi‑stage simulated research task",
    input_schema: {
      type: "object",
      properties: {
        topic: { type: "string" },
        ambiguous: { type: "boolean" },
      },
      required: ["topic"],
    },
  };

  server.experimental.tasks.registerToolTask(name, config, async (args, progress) => {
    // Emit staged progress updates
    await progress({ status: "searching", detail: "Gathering sources…" });
    await sleep(1000);
    await progress({ status: "reading", detail: "Reading abstracts…" });
    await sleep(1000);
    // Final result
    return { messages: [{ role: "assistant", content: `Research on ${args.topic} completed.` }] };
  });
};

```

## Key Implementation Files in the Reference Server

The `modelcontextprotocol/servers` repository implements the MCP protocol specification through the following critical paths:

- **[`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts)** – Creates the `McpServer` instance, configures capabilities, and orchestrates registration of all tools, resources, prompts, and instructions.

- **[`src/everything/tools/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/index.ts)** – Central export that iterates over tool modules and invokes their `registerTool` functions with the server instance.

- **[`src/everything/resources/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/resources/index.ts)** – Exports `registerResources` and `registerResourceTemplates` to bind static and dynamic resources to the server.

- **[`src/everything/tools/get-sum.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/get-sum.ts)** – Reference implementation of a pure, idempotent tool with complete `ToolAnnotations`.

- **[`src/everything/resources/templates.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/resources/templates.ts)** – Demonstrates static file resources and MIME type handling.

- **[`src/filesystem/README.md`](https://github.com/modelcontextprotocol/servers/blob/main/src/filesystem/README.md)** – Documents real-world usage of `ToolAnnotations` for safety hints (line 180).

- **[`src/everything/__tests__/registrations.test.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/__tests__/registrations.test.ts)** – Validates that the server registers the expected number of tools and resources, ensuring spec compliance.

## Summary

- The **MCP protocol specification for tools and resources** defines a JSON-RPC interface for LLM clients to discover and invoke server capabilities.

- **Tools** are registered via `server.registerTool()` with JSON Schema validation and optional `ToolAnnotations` (`idempotentHint`, `destructiveHint`, `readOnlyHint`) that govern client-side safety decisions.

- **Resources** are registered via `server.registerResource()` and can be static files or dynamically generated content streams, identified by unique URIs.

- **Task-based tools** support long-running operations through `server.experimental.tasks.registerToolTask`, enabling asynchronous execution with progress streaming.

- The reference implementation in `modelcontextprotocol/servers` enforces the specification through TypeScript types in [`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts), runtime validation, and comprehensive test coverage in [`src/everything/__tests__/registrations.test.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/__tests__/registrations.test.ts).

## Frequently Asked Questions

### What is the difference between tools and resources in the MCP protocol specification?

**Tools** are executable functions that perform operations and return structured results (text, images, or errors) to the LLM client. They are invoked on-demand via the `tools/call` endpoint and can accept parameters validated against JSON Schema. **Resources** are addressable content items (files, blobs, or generated data) accessed via URI through the `resources/read` endpoint. Unlike tools, resources are typically read-only streams of data that clients can subscribe to for updates, rather than executable logic. In the reference server, tools live in `src/everything/tools/` while resources are defined in `src/everything/resources/`.

### How does MCP handle tool safety and permissions?

The MCP protocol specification defines **ToolAnnotations** that servers attach to tool registrations to communicate safety characteristics to clients. These boolean hints include `readOnlyHint` (indicating no state modification), `idempotentHint` (safe to retry), and `destructiveHint` (irreversible changes). According to the implementation in [`src/filesystem/README.md`](https://github.com/modelcontextprotocol/servers/blob/main/src/filesystem/README.md) (line 180), clients like VS Code use these annotations to decide whether to auto-invoke a tool or require explicit user confirmation. The TypeScript SDK enforces these types at compile time, while runtime validation ensures tools behave according to their declared annotations.

### What is the registration flow for adding new tools to an MCP server?

Adding a tool requires implementing the three-phase registration pattern used in [`src/everything/server/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/server/index.ts). First, create a TypeScript module in `src/everything/tools/` that exports a `registerTool` function accepting an `McpServer` instance. Second, define the tool's configuration object containing `description`, `input_schema` (JSON Schema 7), and optional `annotations`. Third, invoke `server.registerTool(name, config, handler)` where the handler implements the business logic and returns a `CallToolResult`. Finally, export the module from [`src/everything/tools/index.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/index.ts) to include it in the server's capability advertisement during client handshake.

### How do task-based tools work in the MCP protocol?

Task-based tools extend the standard tool interface to support long-running operations that exceed typical HTTP timeouts. Implemented via `server.experimental.tasks.registerToolTask` as shown in [`src/everything/tools/simulate-research-query.ts`](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/tools/simulate-research-query.ts), these tools accept a `progress` callback alongside arguments. When invoked, the server immediately returns a `taskId` while continuing execution asynchronously. The handler emits progress updates through the callback (e.g., `{status: "searching", detail: "Gathering sources…"}`), which the client receives via polling or server-sent events. This pattern is essential for operations like research queries, file indexing, or data processing that require minutes rather than seconds to complete.