The best MCP servers for Claude Code, tested
Updated 1 Oct 2026 · Tested on 1 Oct 2026
For web access in Claude Code: Playwright MCP to drive a browser, Fetch for the odd page, Firecrawl or Skryp for pages as compact Markdown, and Context7 or DeepWiki for documentation. We started seven servers as Claude Code does and ran each on the tasks it is for; below are the results, the size of each server's tool definitions, setup commands and costs. Skryp is ours.
Seven servers, run on the tasks they are for
We started each server with the command Claude Code uses and called it through the official MCP client on three tasks: read a documentation page, read a page built by JavaScript, and answer a question about a library. Page readers ran the first two; documentation servers the third. We also counted how many tokens each server's tool definitions take up once they are loaded. The script and what it printed on 1 October 2026:
# Seven MCP servers you might add to Claude Code, started the way Claude Code starts them and run on the tasks
# each is for: (A) read a documentation page, (B) read a page built by JavaScript, (C) answer a library question.
# Also measured: how many tokens each server's tool definitions add to every request Claude Code makes.
# pip install mcp tiktoken export SKRYP_API_KEY=... FIRECRAWL_API_KEY=... (needs Node.js and uv)
# timeout: 900
import asyncio
import json
import os
import re
import time
from contextlib import AsyncExitStack
import tiktoken
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp.client.streamable_http import create_mcp_http_client, streamable_http_client
API = os.environ.get("SKRYP_API_URL", "https://api.skryp.dev")
ENC = tiktoken.get_encoding("cl100k_base")
DOCS = "https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/404"
JS = "https://quotes.toscrape.com/js/"
CHECK = { # text that must be in the reply for the task to count as done
"A": ["cannot find the requested resource"],
"B": ["The world as we have created it", "It is our choices, Harry", "only two ways to live your life"],
"C": ["cleanup"],
}
def text_of(result) -> str:
return "\n".join(getattr(c, "text", "") for c in result.content)
async def page_reader(s, tool, args): # one call that returns the page
return text_of(await s.call_tool(tool, args))
async def playwright(s, url):
await s.call_tool("browser_navigate", {"url": url})
await asyncio.sleep(1)
return text_of(await s.call_tool("browser_snapshot", {}))
async def devtools(s, url):
pages = text_of(await s.call_tool("new_page", {"url": url})) # "2: Quotes to Scrape (https://…) [selected]"
page_id = int(re.search(r"(\d+):[^\n]*\[selected\]", pages).group(1))
return text_of(await s.call_tool("take_snapshot", {"pageId": page_id}))
async def context7(s, _):
found = text_of(await s.call_tool("resolve-library-id", {"libraryName": "react", "query": "useEffect cleanup"}))
lib = re.search(r"(/[\w.-]+/[\w.-]+)", found).group(1)
return text_of(await s.call_tool("query-docs", {"libraryId": lib, "query": "What does the useEffect cleanup function do?"}))
async def deepwiki(s, _):
return text_of(await s.call_tool("ask_wiki_question", {"repoName": "facebook/react",
"question": "What does the cleanup function returned from useEffect do?"}))
def stdio(cmd, *args, env=None):
return StdioServerParameters(command=cmd, args=list(args), env={**os.environ, **(env or {})})
# name: (how to start it, {task: how to run it})
SERVERS = {
"Playwright MCP": (stdio("npx", "-y", "@playwright/mcp@latest", "--headless"), {"A": playwright, "B": playwright}),
"Chrome DevTools MCP": (stdio("npx", "-y", "chrome-devtools-mcp@latest", "--headless", "--isolated"), {"A": devtools, "B": devtools}),
"Fetch": (stdio("uvx", "mcp-server-fetch"), {t: (lambda s, u: page_reader(s, "fetch", {"url": u, "max_length": 20000})) for t in "AB"}),
"Firecrawl": (stdio("npx", "-y", "firecrawl-mcp", env={"FIRECRAWL_API_KEY": os.environ.get("FIRECRAWL_API_KEY", "")}),
{t: (lambda s, u: page_reader(s, "firecrawl_scrape", {"url": u, "formats": ["markdown"]})) for t in "AB"}),
"Skryp (ours)": (("http", f"{API}/mcp", {"Authorization": f"Bearer {os.environ.get('SKRYP_API_KEY', '')}"}),
{t: (lambda s, u: page_reader(s, "scrape", {"url": u})) for t in "AB"}),
"Context7": (stdio("npx", "-y", "@upstash/context7-mcp"), {"C": context7}),
"DeepWiki": (("http", "https://mcp.deepwiki.com/mcp", {}), {"C": deepwiki}),
}
async def run(name):
how, tasks = SERVERS[name]
row = {"name": name}
async with AsyncExitStack() as stack:
if isinstance(how, tuple): # ("http", url, headers)
client = await stack.enter_async_context(create_mcp_http_client(headers=how[2]))
r, w = await stack.enter_async_context(streamable_http_client(how[1], http_client=client))
else:
r, w = await stack.enter_async_context(stdio_client(how, errlog=open(os.devnull, "w")))
async with ClientSession(r, w) as s:
await s.initialize()
tools = (await s.list_tools()).tools
defs = [{"name": t.name, "description": t.description, "input_schema": t.input_schema} for t in tools]
row["tools"], row["def_tokens"] = len(tools), len(ENC.encode(json.dumps(defs), disallowed_special=()))
for task, url in (("A", DOCS), ("B", JS), ("C", None)):
if task not in tasks:
continue
t0 = time.monotonic()
try:
out = await tasks[task](s, url)
except Exception as e:
out = f"error: {type(e).__name__}"
ok = all(c.lower() in out.lower() for c in CHECK[task])
row[task] = (ok, time.monotonic() - t0, len(ENC.encode(out, disallowed_special=())))
return row
async def main():
rows = [await run(n) for n in SERVERS]
print(f"{'server':<22}{'tools':>6}{'definition tokens':>19} {'A: docs page':<20}{'B: JavaScript page':<20}{'C: library question':<20}")
for r in rows:
cells = []
for t, width in (("A", 20), ("B", 20), ("C", 20)):
if t in r:
ok, secs, tok = r[t]
cells.append(f"{'done' if ok else 'missed'} {secs:.0f}s {tok:,}t".ljust(width))
else:
cells.append("-".ljust(width))
print(f"{r['name']:<22}{r['tools']:>6}{r['def_tokens']:>19,} {''.join(cells)}")
print("\nper task: done or missed, seconds, tokens in the reply (t)")
asyncio.run(main())server tools definition tokens A: docs page B: JavaScript page C: library question
Playwright MCP 25 4,445 done 1s 9,843t done 2s 1,123t -
Chrome DevTools MCP 30 6,505 done 3s 8,986t done 4s 1,507t -
Fetch 1 290 done 2s 781t missed 2s 28t -
Firecrawl 27 14,511 done 1s 1,997t done 0s 564t -
Skryp (ours) 17 6,319 done 0s 1,377t done 0s 419t -
Context7 2 1,036 - - done 4s 1,413t
DeepWiki 3 286 - - done 43s 534t
per task: done or missed, seconds, tokens in the reply (t)What the run shows[1 Oct 2026]:
- Browsers return big pages. Playwright MCP and Chrome DevTools MCP read the documentation page as an accessibility snapshot of about 9,000 to 10,000 tokens; Firecrawl and Skryp returned it as 1,400 to 2,000 tokens of Markdown. Claude Code warns when an MCP result passes 10,000 tokens and cuts it at 25,000 by default[1 Oct 2026].
- Fetch does not run JavaScript. It read the documentation page but not the quotes, which a script adds after the page loads.
- Tool definitions differ fifty-fold. Firecrawl's 27 tools come to 14,511 tokens; Fetch's one tool to 290. Skryp's 17 tools are 6,319 tokens, more than Playwright MCP's 25.
- Documentation servers answer from the source. Context7 and DeepWiki both answered the React question; DeepWiki took 43 seconds.
Claude Code defers MCP tool definitions by default and loads a server's tools when Claude looks for them[1 Oct 2026], so a large server costs context mainly when it is used. With tool search off, or in clients that load every tool up front, each server's definitions go with every request.
The servers
Playwright MCP: a browser Claude drives
claude mcp add playwright -- npx @playwright/mcp@latestA local browser that Claude navigates, clicks and types in, step by step. Free; needs Node.js. Best for testing your own app and multi-step flows; its page snapshots are large for reading. See Claude Code web access for Claude Code sessions with it.
Chrome DevTools MCP: debugging and performance
claude mcp add chrome-devtools -- npx chrome-devtools-mcp@latestDrives Chrome through its DevTools, with tools for console messages, network requests, performance traces and Lighthouse audits. Free; needs Node.js and Chrome. Best for debugging pages you are building rather than reading other sites.
Fetch: the smallest page reader
claude mcp add fetch -- uvx mcp-server-fetchOne tool that fetches a URL and returns it as Markdown. Free; needs uv. It reads what the server sends, without JavaScript, from your own connection.
Firecrawl: pages, crawls and search through an API
claude mcp add firecrawl -e FIRECRAWL_API_KEY=your-key -- npx -y firecrawl-mcpScrape, crawl, map, search and more through Firecrawl's API. Needs an account: 1,000 free credits a month, plans from $16 a month billed annually[1 Oct 2026]. Its tool definitions are the largest here. See Skryp vs Firecrawl.
Skryp: pages and data from the country you choose (ours)
claude mcp add --transport http skryp https://api.skryp.dev/mcp \
--header "Authorization: Bearer $SKRYP_API_KEY"Reads pages as Markdown or checked JSON, searches, crawls, keeps datasets and monitors, and drives a live browser, with the exit country verified and the cost on every result. Needs an account: 1,000 free credits a month, plans from $9[1 Oct 2026]. See AI web scraping.
Context7: current library documentation
claude mcp add context7 -- npx -y @upstash/context7-mcpLooks up a library and returns passages and code examples from its documentation for your question. Two small tools.
DeepWiki: questions about a GitHub repository
claude mcp add --transport http deepwiki https://mcp.deepwiki.com/mcpAnswers questions about a public GitHub repository from a generated wiki of it. No install; three small tools. It was the slowest to answer in our run.
Which to add
| For | Add |
|---|---|
| Testing your own app in a browser | Playwright MCP |
| Debugging and profiling pages | Chrome DevTools MCP |
| Reading the odd public page, at no cost | Fetch |
| Reading pages, including JavaScript-built and blocked ones, as compact Markdown | Firecrawl or Skryp |
| Pages as seen from a country, with the exit verified | Skryp |
| Up-to-date documentation for the libraries you use | Context7 |
| Questions about a GitHub codebase | DeepWiki |
Add servers to the projects that need them (claude mcp add --scope project) and check what is connected with /mcp.
Questions
- What are the best MCP servers for Claude Code?
- It depends on the job: Playwright MCP to drive a browser, Chrome DevTools MCP to debug pages, Fetch for the odd public page, Firecrawl or Skryp to read pages as compact Markdown, and Context7 or DeepWiki for documentation.
- Do MCP servers use up Claude Code's context?
- Their tool definitions do once loaded: from 286 tokens for DeepWiki to 14,511 for Firecrawl in our run. Claude Code defers MCP tool definitions by default and loads a server's tools when Claude looks for them; their results count too, and Claude Code warns above 10,000 tokens.
- Which servers are free?
- Playwright MCP, Chrome DevTools MCP and Fetch run on your machine at no cost; Context7 and DeepWiki answered our questions without an account. Firecrawl and Skryp need accounts, each with 1,000 free credits a month.
- How do I add an MCP server to Claude Code?
- With claude mcp add, for example claude mcp add fetch -- uvx mcp-server-fetch, or with --transport http for a hosted server. Add --scope project to keep it to one project, and check connections with /mcp.
Evidence
Started as Claude Code starts them and run on 1 October 2026, the tool definitions of Firecrawl's MCP server (27 tools) came to 14,511 tokens, Chrome DevTools MCP (30 tools) 6,505, Skryp (17) 6,319, Playwright MCP (25) 4,445, Context7 (2) 1,036, Fetch (1) 290 and DeepWiki (3) 286. Playwright MCP, Chrome DevTools MCP, Firecrawl and Skryp read both a documentation page and a page built by JavaScript; Fetch read only the documentation page. Reading the documentation page, Playwright MCP's and Chrome DevTools MCP's page snapshots were 9,843 and 8,986 tokens, against Firecrawl's 1,997 and Skryp's 1,377 tokens of Markdown. Context7 and DeepWiki both answered a React question; DeepWiki took 43 seconds.
observed test · checked 1 Oct 2026 · Seven servers, each run once on the tasks it is for: an MDN reference page, quotes.toscrape.com/js, and a question about React's useEffect.
Limits: One run, one location, simple tasks. Skryp's and Firecrawl's quick times include results they had cached from earlier runs. Claude Code itself did not drive these calls; its own choices between servers are recorded in the Claude Code web access guide.
Claude Code's MCP documentation says tool search is on by default from version 2.1.221: MCP tool definitions are deferred until Claude searches for or calls a tool. It is off with ENABLE_TOOL_SEARCH=false or a custom ANTHROPIC_BASE_URL. MCP tool output is limited to 25,000 tokens by default, with a warning above 10,000.
provider docs · checked 1 Oct 2026 · Claude Code, as documented.
Limits: Defaults change between Claude Code versions.
Firecrawl's pricing page (prices effective 4 September 2026) lists Free (1,000 credits a month), Hobby ($19 a month, or $16 billed annually, 5,000 credits), Standard ($83 a month billed annually, 100,000 credits), Growth ($333, 500,000) and Scale ($599, 1,000,000). One credit is one page on a basic scrape, crawl or map; a page that responds with an error status such as 403 or 404 costs 1 credit, and a scrape that returns no result is not charged.
provider docs · checked 1 Oct 2026 · firecrawl.dev/pricing
Limits: Prices change; re-read on the day a page citing them is published.
Skryp's plans from 1 October 2026: Free (1,000 credits a month), Hobby ($9 a month for 20,000 credits), Standard ($49 for 150,000), Growth ($149 for 600,000) and Scale ($399 for 2,000,000); unused plan credits expire at the end of each month, and top-ups, which never expire (also after a plan is cancelled), cost $10 for 20,000 credits on Free and the plan's rate on a plan. A page costs 1 credit through Skryp's own network, 5 through a residential or mobile proxy (10 with JavaScript rendering) and 25 for advanced unblocking, only when it succeeds; model extraction adds 5; failed, blocked and cached results cost 0, and a missing page (404 or 410) costs at most 1.
observed test · checked 1 Oct 2026 · Skryp's own prices (the service's rate card).
Limits: Prices in US dollars, charged in rand through Paystack at R17 to the US dollar (Chad, 2 Oct 2026).