ScreenshotNeo

BlogAI agents

Types of MCP Servers: Tools, Resources, Prompts, Local and Remote

Learn how MCP servers differ by capability, deployment, transport, trust boundary and use case, with runnable examples and selection guidance.

By the ScreenshotNeo team1 October 20269 min read

There are two useful ways to classify MCP servers: by what they expose (tools, resources and prompts) and by where and how they run (usually local over stdio or remote over Streamable HTTP). These dimensions overlap: a local server can expose all three primitives, and a remote server can expose only a tool or a combination of tools, resources and prompts.

An MCP server is a program that provides context and capabilities to an MCP client. The host application coordinates one client connection per server. The official architecture describes local filesystem and database servers as well as a remote service example. See the MCP architecture documentation.

1. Types by capability

Tools, resources and prompts are capabilities, not mutually exclusive product categories. A server advertises whichever primitives it implements.

Primitive What it provides Typical examples Model interaction
Tools Executable functions Run a query, create a ticket, call an API, modify a file The model can request an action with structured arguments
Resources Context identified by a URI Files, database records, API responses, schemas The client reads or subscribes to context
Prompts Reusable message templates Code-review template, incident summary, SQL investigation workflow The client retrieves a structured prompt for a model interaction

Tool servers

A tool server exposes operations that a client can discover and call. Use tools when the model needs to perform an action or retrieve data through a controlled function. Define input schemas, validate every argument, and return useful error messages.

Resource servers

A resource server exposes read-oriented context. Resources can represent files, records or generated API responses. A database server might publish a schema resource while keeping query execution behind a separate tool.

Prompt servers

A prompt server provides named templates with arguments. Prompts are useful when an organization wants repeatable instructions without hard-coding them into every client application.

Servers with multiple primitives

A single server can combine capabilities. For example, a database server can expose a query tool, a schema resource and an example prompt. Combining primitives keeps related policy and authentication in one integration while preserving clear boundaries between actions and context.

2. Types by deployment and transport

Deployment Common transport Where it runs Best fit
Local stdio On the user’s machine or inside the host environment Private files, local tools, development databases and offline workflows
Remote Streamable HTTP On service infrastructure reachable by the client Shared services, hosted data and integrations used by many users or agents

These are common pairings rather than protocol definitions. The TypeScript SDK documents stdio for local process-spawned integrations and Streamable HTTP for remote servers; it also supports HTTP plus SSE for backwards compatibility. See the official TypeScript SDK documentation.

Local stdio servers

With stdio, the host starts the server as a child process and exchanges JSON-RPC messages over standard input and output. There is no public listening port, which simplifies development and keeps local data on the machine. The host must still restrict filesystem access, environment variables and executable commands.

Remote Streamable HTTP servers

A remote server exposes an HTTP endpoint. Streamable HTTP supports request and response traffic over HTTP and is the recommended modern transport in the TypeScript SDK. A remote endpoint needs authentication, authorization, TLS, request limits and careful handling of tenant data.

Private remote servers and tunnels

A service can remain private while an approved client reaches it through a secure tunnel. OpenAI’s MCP guidance distinguishes remote public Internet servers from local or private servers reachable through Secure MCP Tunnel, and recommends using a provider’s hosted server when one is available. Treat the connection method as part of your trust model: the host decides which server may receive data and which operations it may perform.

3. A practical classification matrix

When evaluating a server, record these five properties:

  1. Capability: tools, resources, prompts or a combination.
  2. Deployment: local process, provider-hosted service or private service.
  3. Transport: stdio, Streamable HTTP or legacy HTTP plus SSE.
  4. Connection and trust: what credentials, files and network access the host grants it.
  5. Use case: which data source or service it connects to and what it can change.
Example Capabilities Deployment Transport Primary concern
Local filesystem helper Tools and resources Local stdio Path and command restrictions
Hosted issue tracker Tools, resources and prompts Remote Streamable HTTP OAuth scopes and tenant isolation
Private analytics gateway Tools and schema resources Private remote Streamable HTTP through a tunnel Network and data residency controls

4. Runnable local server example (Python)

The official Python SDK can expose tools, resources and prompts. Install it with:

pip install "mcp[cli]"

Save this as server.py. It runs over stdio, registers one tool, one resource and one prompt, and keeps diagnostics off stdout so the JSON-RPC stream is not corrupted.

from mcp.server.fastmcp import FastMCP

mcp = FastMCP('catalog-server')

@mcp.tool()
def lookup_product(sku: str) -> str:
    """Return a small product record for a SKU."""
    products = {
        'A-100': {'name': 'Notebook', 'stock': 42},
        'B-200': {'name': 'Pen', 'stock': 180},
    }
    product = products.get(sku)
    if product is None:
        raise ValueError(f'Unknown SKU: {sku}')
    return str(product)

@mcp.resource('catalog://schema')
def catalog_schema() -> str:
    return '{"sku": "string", "name": "string", "stock": "integer"}'

@mcp.prompt()
def stock_check(sku: str) -> str:
    return f'Check the stock for SKU {sku} and explain whether it needs replenishment.'

if __name__ == '__main__':
    mcp.run(transport='stdio')

Start it from an MCP host or inspector that supports stdio. Do not print logs with print(); write diagnostics to stderr instead.

5. Runnable remote server example (Node.js)

Install the TypeScript SDK and a runner:

npm install @modelcontextprotocol/sdk zod
npm install --save-dev tsx typescript

This minimal server exposes a tool over Streamable HTTP. Save it as server.ts and run npx tsx server.ts.

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { createServer } from 'node:http';
import { z } from 'zod';

const mcp = new McpServer({ name: 'catalog-http', version: '1.0.0' });

mcp.tool('lookup_product', { sku: z.string() }, async ({ sku }) => ({
  content: [{ type: 'text', text: JSON.stringify({ sku, stock: 42 }) }]
}));

const httpServer = createServer(async (req, res) => {
  if (req.url !== '/mcp') {
    res.writeHead(404).end('Not found');
    return;
  }
  const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
  res.on('close', () => transport.close());
  await mcp.connect(transport);
  await transport.handleRequest(req, res);
});

httpServer.listen(3000, '127.0.0.1', () => {
  console.error('MCP server listening on http://127.0.0.1:3000/mcp');
});

For production, put the endpoint behind TLS and authentication, validate the origin, apply per-user authorization and use a session strategy appropriate for your client. The SDK’s server and client guides show stateful, stateless and JSON-response variations.

6. Calling a remote MCP endpoint with cURL

MCP uses JSON-RPC messages, so the exact request envelope depends on the operation and protocol version. A typical initialization request looks like this:

curl -i https://example.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-06-18",
      "capabilities": {},
      "clientInfo": {"name": "curl-client", "version": "1.0.0"}
    }
  }'

After initialization, send the session identifier returned by the server and call a discovered tool. Always inspect tools/list, resources/list and prompts/list instead of assuming names or arguments.

7. Choosing the right type

  • Choose local stdio when data must stay on a workstation, setup is controlled by one host, or the integration needs local files and executables.
  • Choose remote Streamable HTTP when many clients need the same service, credentials belong on a server, or the data source already has an HTTPS API.
  • Expose a tool for a bounded action, a resource for addressable context, and a prompt for a reusable interaction pattern.
  • Combine primitives when they share authentication and policy, but keep read operations and state-changing actions separately named and authorized.
  • Use a private endpoint or tunnel when the service cannot be exposed publicly; document which host is trusted to connect.

8. Security and reliability checklist

  • Grant the minimum filesystem, network and API permissions.
  • Validate tool arguments on the server; never rely on the model to enforce policy.
  • Require authentication for remote endpoints and authorize every tool call per user or tenant.
  • Use TLS, request size limits, timeouts, concurrency limits and idempotency for write operations.
  • Redact secrets from tool results and logs.
  • Return structured, actionable errors and preserve correlation IDs.
  • Pin SDK versions and protocol versions where your host requires it.
  • Test disconnects, duplicate requests, malformed JSON, expired credentials and partial upstream failures.
  • Keep stdout reserved for stdio protocol messages; send logs to stderr.

9. Common errors and fixes

Symptom Likely cause Fix
Client cannot parse a local server Logs or banners were written to stdout Write diagnostics to stderr and emit only JSON-RPC on stdout.
HTTP client receives 404 Wrong path or reverse-proxy route Use the server’s configured MCP path and forward POST, GET and required headers.
Tool is missing The server was not initialized or the client cached an old list Complete initialization, call tools/list again and verify registration.
Invalid tool arguments Client sent a shape that does not match the input schema Read the advertised schema and validate before calling.
Requests hang Upstream timeout, blocked stream or missing response handling Set bounded timeouts, inspect proxy buffering and close transports on disconnect.
Unauthorized response Missing, expired or insufficient credentials Refresh credentials and check per-tool scopes.
Data appears in the wrong tenant Authorization was applied only at connection time Authorize every request using the authenticated identity and tenant context.

10. Performance, reliability and cost

stdio avoids network hops but still pays process startup and serialization costs. Keep a local server process alive when the host supports it. Remote servers can serve many clients, but latency includes DNS, TLS, authentication and upstream calls; use connection reuse, bounded concurrency and caching for safe reads.

Resources can be cheaper than repeatedly embedding large documents in prompts, while tools should return only the fields an agent needs. Streamable HTTP is useful for long responses and notifications, but proxies must preserve streaming behavior. Measure end-to-end latency, error rate, timeout rate and upstream quota usage for each tool.

MCP itself does not set a universal price. Your cost comes from compute, hosting, network traffic, upstream APIs and model tokens. Record tool calls and resource reads by user and tenant so expensive operations are visible before they become a reliability problem.

11. ScreenshotNeo as an MCP server for webpage captures

ScreenshotNeo is a website screenshot API and MCP server. Its MCP tools include take_screenshot, get_page_info and capture_pdf, so Claude, Cursor and other MCP clients can request page images or PDFs as agent actions. It is a remote, provider-hosted service: the agent connects to the service rather than spawning a local browser process.

If you need a screenshot without configuring Playwright or Chromium, call its HTTP API. The ScreenshotNeo API documentation has the full option list.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get('https://api.screenshotneo.com/v1/shot', params={'access_key': 'YOUR_API_KEY', 'url': 'https://stripe.com'}, timeout=90)
open('shot.webp', 'wb').write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Or skip the browser setup

ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed; response headers identify the page verdict and whether it was billed. You can also use its MCP server from AI agents, and every plan includes the features listed in the product documentation. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.

Create a free ScreenshotNeo account and start with 1,000 screenshots per month without a card.

12. FAQ

Are tools, resources and prompts separate MCP server types?

No. They are primitives a server may expose individually or together.

Is every remote MCP server hosted by a vendor?

No. A remote server can run on your infrastructure, a private network or a provider’s service.

Can a local server use HTTP?

Yes. Local and remote describe deployment; stdio and Streamable HTTP describe common transports. The pairing is a convention, not a restriction.

Should a read operation be a tool or a resource?

Use a resource for addressable context that clients can read. Use a tool when the operation needs arguments, computation, side effects or explicit authorization.

Do clients support every primitive?

No. Check the host and client capability negotiation, then handle unavailable tools, resources or prompts gracefully.