ScreenshotNeo

BlogAI agents

MCP Servers: Connecting AI Agents to Developer Tools

Learn how MCP servers connect AI agents to developer tools, choose a transport, secure tool calls, and build a reliable integration.

By the ScreenshotNeo team1 October 202610 min read

Model Context Protocol (MCP) is an open protocol that lets AI applications discover and invoke external tools and data sources through a consistent interface. An MCP server publishes named tools with structured input schemas. An AI host or client discovers those tools, validates model-requested calls, applies approval and security policy, sends the request to the server, and returns the structured result to the model.

This pattern lets an agent work with live repositories, issue trackers, CI systems, databases, cloud resources, documentation and business systems instead of relying only on information in its prompt. MCP is designed for context and action: servers can expose tools, resources, prompts and instructions. The official tools specification describes servers exposing tools that language models can invoke, while Anthropic’s original announcement describes connections to content repositories, business tools and development environments.

What an MCP server is

An MCP server is an adapter between an AI host and one or more developer systems. It defines a stable contract for operations such as search_issues, read_file, run_tests, query_database or capture_screenshot.

Part Responsibility
Host The application where the model runs, such as an IDE, desktop assistant or agent platform.
MCP client Maintains a connection to a server, discovers capabilities and sends protocol requests.
MCP server Publishes tools, resources, prompts and instructions, then executes approved calls.
Tool schema Names the operation and defines typed inputs and expected output structure.
Connected system The repository, API, database, browser, cloud account or other service the tool controls.

MCP standardizes the boundary. It does not decide which tools are safe, which users may invoke them, or whether a model should be trusted with production access. Those controls remain part of the host, server and deployment design.

How the connection works

  1. The host starts a local server process or opens a connection to a remote server.
  2. The client and server initialize and negotiate capabilities.
  3. The client asks what tools, resources, prompts and instructions are available.
  4. The host gives the model tool names, descriptions and JSON schemas.
  5. The model proposes a tool call when the user’s task requires external context or action.
  6. The host validates the arguments and applies approval rules.
  7. The client sends the call to the server.
  8. The server validates the request again, performs the operation, and returns structured content or an error.
  9. The host gives the result back to the model, which explains the outcome or continues with another call.

Tool descriptions and schemas are part of the reliability contract. A vague description can cause incorrect selection; an underspecified schema can allow invalid arguments. Validate every field on the server even when the host already validates it.

OpenAI documents support for public remote MCP servers and Secure MCP Tunnel for private or local servers. The OpenAI API documentation defines a remote MCP server as any public Internet server implementing the remote MCP protocol.

Transport choices: stdio, Streamable HTTP and hosted MCP

Transport Best fit Deployment boundary Authentication and operations
stdio A developer workstation, desktop agent or local development The host starts and supervises a local process Usually relies on local process and filesystem boundaries; keep secrets in the process environment or a secret manager
Streamable HTTP A shared or independently deployed service The server runs as a network service Use TLS, authentication, authorization, rate limits, request timeouts and centralized logs
Hosted MCP tool When an API platform manages the remote connection The platform owns more of the networking and credential flow Review data handling, approval behavior and third-party terms

Choose stdio when one user needs a local tool and process startup is acceptable. Choose Streamable HTTP when multiple agents or teams need a centrally governed service. A hosted integration can reduce networking work, but it moves trust and operational decisions to the provider.

Server-Sent Events (SSE) is identified as deprecated by the JavaScript SDK documentation for new MCP systems. Follow the current MCP transport guidance instead of starting a new SSE-only deployment.

A minimal MCP design for developer tools

Start with narrow, task-oriented tools. A server that exposes create_release_candidate is easier to secure and explain than one that exposes an unrestricted shell. Separate read operations from writes, keep destructive actions behind confirmation, and return enough structured context for the model to describe what happened.

Example tool contract

{
  "name": "find_failed_builds",
  "description": "Find failed CI builds for a repository in a time window.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "repository": { "type": "string", "description": "Owner and repository name" },
      "since": { "type": "string", "description": "RFC 3339 timestamp" },
      "limit": { "type": "integer", "minimum": 1, "maximum": 50 }
    },
    "required": ["repository", "since"]
  }
}

The server should reject an unknown repository, malformed timestamp or excessive limit. It should also enforce the caller’s authorization independently of the model’s requested arguments.

Illustrative host flow in Python

import json

# The host receives this schema from an MCP server during discovery.
tool = {
    "name": "find_failed_builds",
    "inputSchema": {
        "type": "object",
        "properties": {
            "repository": {"type": "string"},
            "since": {"type": "string"},
            "limit": {"type": "integer", "minimum": 1, "maximum": 50}
        },
        "required": ["repository", "since"]
    }
}

# A real host obtains these arguments from the model, then validates them.
arguments = {
    "repository": "acme/payments",
    "since": "2026-01-01T00:00:00Z",
    "limit": 10
}

if not arguments["repository"] or not arguments["since"]:
    raise ValueError("repository and since are required")
if not 1 <= arguments.get("limit", 10) <= 50:
    raise ValueError("limit must be between 1 and 50")

request = {
    "jsonrpc": "2.0",
    "id": 7,
    "method": "tools/call",
    "params": {"name": tool["name"], "arguments": arguments}
}
print(json.dumps(request))

This snippet demonstrates the validation boundary and JSON-RPC call shape. Use an MCP SDK for production framing, initialization, transport handling and capability negotiation.

Building a local stdio server

  1. Define a small set of read-only tools first.
  2. Use the official SDK for your language to implement initialization, discovery and message framing.
  3. Read credentials from the environment or a secret manager, never from model-visible instructions.
  4. Validate paths, repository names, query limits and all other arguments on the server.
  5. Write protocol messages to stdout only; send diagnostics to stderr so the host does not receive corrupted messages.
  6. Run the server under a restricted operating-system user with only the required filesystem and network access.
# Example local process launch pattern
export GITHUB_TOKEN="replace-with-a-secret"
python server.py

Keep the process lifetime explicit. Handle cancellation, close network clients, and return bounded errors instead of dumping stack traces or secrets into tool results.

Building a remote Streamable HTTP server

A remote deployment needs the same tool contract plus network controls:

  • Terminate TLS before the MCP endpoint or use an internal service mesh with equivalent protection.
  • Authenticate every request and authorize each tool separately.
  • Apply request size limits, concurrency limits and per-user rate limits.
  • Set deadlines for upstream APIs and cancel work after the deadline.
  • Emit structured logs containing request ID, tool name, actor, outcome and duration, while redacting tokens and sensitive arguments.
  • Use OAuth-related discovery and resource indicators for protected servers where applicable. Bind tokens to their intended resource when supported.

Do not treat a network-reachable MCP endpoint as an internal-only utility. It is a privileged integration and should receive the same review as an API that can change production systems.

Security: prompt injection, permissions and approvals

Prompt injection is especially significant when connected content is user-provided or when tools can take action. A repository file, issue comment or web page can contain instructions aimed at the model. Treat retrieved content as untrusted data, not as policy.

  • Use least-privilege credentials scoped to the smallest repository, database schema or cloud account.
  • Keep access tokens in authorization headers, environment variables or server-side secret stores, not in URLs or prompts.
  • Separate read and write servers or tool namespaces when that makes policy easier to reason about.
  • Require explicit human approval for writes, payments, deletion, credential changes and production deployments.
  • Show users which tools are exposed and provide a clear indicator when a tool is invoked.
  • Validate arguments on the server, including paths, URLs, selectors, query filters and resource identifiers.
  • Prevent server-side request forgery by restricting outbound destinations and rejecting private-network targets unless required.
  • Rotate credentials independently of prompts and conversation history.
  • Return safe error messages that help the model recover without revealing secrets or internal topology.

Google Cloud identifies prompt injection, insecure tool chaining and naive error handling as common MCP risks. The MCP tools guidance recommends a human in the loop who can deny invocations.

Connecting an MCP server to screenshot automation

Browser screenshots are a useful MCP tool because an agent can inspect the current visual state of a page, compare a deployed route, or capture evidence for a report. A browser-capable server should constrain destination URLs, wait conditions, scripts and network access.

DIY browser flow

  1. Launch a browser context with a fixed viewport and optional device emulation.
  2. Navigate to an allowlisted URL with a timeout.
  3. Apply authentication headers or cookies from a protected server-side store.
  4. Wait for a selector, a delay or network idle, depending on the page.
  5. Optionally click an element, hide selectors or inject custom CSS.
  6. Capture one element or the full page and return an image or PDF result.
  7. Close the page and browser context even when the request fails.
// Browser automation outline; use your chosen browser SDK for the concrete calls.
async function capture(url, browser) {
  const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
  try {
    await page.goto(url, { waitUntil: 'networkidle', timeout: 30000 });
    await page.screenshot({ path: 'page.png', fullPage: true });
  } finally {
    await page.close();
  }
}

In an MCP server, expose this as a narrow tool with an allowlist and bounded options rather than passing arbitrary browser commands from the model.

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP or PDF. Before capture, it accepts cookie and consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and each response identifies the result with X-Page-Verdict and X-Billed headers.

Use the same service directly from code or connect its MCP tools to an AI host. The available tools include take_screenshot, get_page_info and capture_pdf.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

See the ScreenshotNeo API documentation for the full option set, including full-page capture with lazy images loaded, CSS selector capture, dark mode, device presets, arbitrary viewports, retina scale, PDF paper size and margins, custom CSS and JavaScript, clicks, waits, blocking rules, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous jobs with signed webhooks, bulk capture and usage reporting.

ScreenshotNeo has 1,000 free shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan. Create a free ScreenshotNeo account.

Reliability and performance checklist

  • Set an end-to-end deadline shorter than the host’s own request timeout.
  • Use idempotency keys or deterministic job identifiers for retried writes.
  • Retry only transient transport and upstream failures, with exponential backoff and a cap.
  • Do not retry validation failures, authorization failures or destructive calls automatically.
  • Bound tool output size and paginate large query results.
  • Cache immutable reads and document cache freshness to the model.
  • Record latency separately for queueing, upstream calls and tool execution.
  • Return a stable error code plus a human-readable explanation.
  • For screenshots, wait on a meaningful selector when possible instead of using a long fixed delay.

For cost control, limit concurrency, avoid repeated calls within one agent turn, cache safe reads and expose bulk operations where the downstream service supports them. For screenshot workloads, cache hits and unsuccessful page verdicts in ScreenshotNeo are not billed; inspect the response headers when accounting for usage.

Troubleshooting MCP connections

Symptom Likely cause Fix
Server never appears in the host Incorrect command, endpoint or transport configuration Run the local process directly, inspect stderr, verify the remote URL and confirm the host supports the selected transport.
Tools are discovered but never called Description is vague, schema is invalid or host policy blocks the tool Use task-specific descriptions, validate the schema and inspect approval or allowlist settings.
Invalid-argument errors Model supplied a value outside the server’s constraints Add JSON Schema limits and return a precise correction; keep server-side validation authoritative.
Unauthorized Missing, expired or wrongly scoped credential Refresh the credential, check its audience/resource and verify per-tool authorization.
Requests hang No timeout, stalled upstream or unbounded browser wait Set deadlines at every layer, cancel upstream work and use bounded selector or network-idle waits.
Protocol parse errors over stdio Logs were written to stdout Write diagnostics to stderr and reserve stdout for protocol messages.
Remote connection drops TLS, proxy, load balancer or keepalive mismatch Check proxy timeouts, TLS configuration and current Streamable HTTP guidance.
Screenshot is blank or blocked Bot check, consent overlay, failed load or premature capture Inspect page verdict headers, configure waits or headers, and use a service that handles consent and reports failed loads clearly.

When MCP is the right fit

MCP fits an agent that needs live repository data, issue trackers, CI systems, databases, cloud resources, documentation or business tools. It adds little value to a self-contained prompt that needs no external context or action. Start with one narrow workflow, measure failure modes, then add tools only when the policy and operational cost are clear.

FAQ

Is MCP an AI model?

No. MCP is a protocol for connecting AI applications to tools and context. The model and host remain separate components.

Can one host use several MCP servers?

Yes. A host can maintain multiple client connections and present their discovered tools to the model, subject to its own naming, approval and security policies.

Should a production MCP server expose a shell?

Usually not. Prefer narrow tools with explicit inputs, bounded outputs and separate approval for sensitive operations.

How should secrets reach a server?

Keep them server-side in environment variables, authorization headers or a secret manager. Do not place them in prompts, tool descriptions or URLs.

What should I monitor?

Monitor tool calls, actor identity, authorization decisions, latency, timeout rate, upstream errors, retries and redacted outcome codes. Track sensitive operations separately so approvals and failures are auditable.

Primary references