Integrations

How do I give a CrewAI agent web access with UpRock?

Connect UpRock's MCP server with MCPServerAdapter from crewai-tools, using the streamable-http transport and your API key in an Authorization header, and pass the tools it returns to your Agent. The newer mcps field works with the same header, but it stops every tool call after 30 seconds, and a fresh fetch can take longer.

Updated · Read as markdown

What your crew gets

UpRock's MCP server runs over streamable HTTP at https://mcp.uprock.ai/mcp, with your API key in an Authorization: Bearer header. MCPServerAdapter turns each of its tools into a CrewAI tool with the same name, and takes a list of names to load only some of them:

ToolWhat it doesLoad it?
crawl_fetchLoads a page in a real browser on a desktop or mobile device in the country you pass; returns a summary and links to the stored markdown and HTMLYes
resource_fetchReads a stored result in full, such as that markdownYes, with crawl_fetch
verifyLoads one URL from several regions with status, timings and screenshotsWhen the crew checks websites
video_searchFinds moments in public video by meaningWhen answers may be in video
video_momentReads the time-stamped moments of one videoUse with care: it returned 502 "temporarily unavailable" when we tested on 25 Oct 2026
web_researchSearches several engines from chosen countriesUse with care: on 25 Oct 2026, 4 of the 8 results for a query about the MCP spec were unrelated Wikipedia pages

Get a key at uprock.ai/app/api-keys and set it as UPROCK_API_KEY.

MCPServerAdapter or the mcps field

CrewAI's docs recommend the mcps field on Agent for most MCP servers. It works with UpRock as long as the key goes in a header, but MCPServerAdapter is still the better fit. This is what each setup gave us:

How UpRock is addedTool names the model seesLimit per tool call
MCPServerAdapter(...), or get_mcp_tools() in a @CrewBase crewcrawl_fetch, resource_fetchNone
mcps=[MCPServerHTTP(url="https://mcp.uprock.ai/mcp", headers=...)]mcp_uprock_ai_mcp_crawl_fetch, mcp_uprock_ai_mcp_resource_fetch, ...30 seconds, fixed
mcps with the key in the URL (https://mcp.uprock.ai/<API_KEY>/mcp)mcp_uprock_ai_<your key>_mcp_887879dd: the key, with the tool's own name cut off to fit 64 characters30 seconds, fixed

A fresh UpRock fetch takes 10 to 40 seconds, so through mcps some will be cut off. The last row is why the key never goes in the URL with CrewAI: CrewAI builds tool names from the URL, path included, so the key would go to your model provider with every request, show up in verbose logs and in CrewAI's "MCP Connected" panel, and the model couldn't tell the tools apart.

The code

The example makes a direct call first, which needs no model, then gives the same two tools to an agent in a crew:

# pip install "crewai[anthropic]" "crewai-tools[mcp]"   env: UPROCK_API_KEY, ANTHROPIC_API_KEYimport astimport jsonimport os​from crewai import LLM, Agent, Crew, Taskfrom crewai_tools import MCPServerAdapter​UPROCK = {    "url": "https://mcp.uprock.ai/mcp",    "transport": "streamable-http",    "headers": {"Authorization": f"Bearer {os.environ['UPROCK_API_KEY']}"},}MODEL = "anthropic/claude-sonnet-5-5"  # any model CrewAI supports​​def summary(output: str) -> dict:    """crawl_fetch returns a JSON summary and two resource links. The adapter keeps the    text and returns str() of a list when there's more than one block."""    text = ast.literal_eval(output)[0] if output.startswith("[") else output    try:        page = json.loads(text)    except ValueError:        page = {}    if page.get("status") != "success":        raise RuntimeError(f"UpRock: {text}")    return page​​with MCPServerAdapter(    UPROCK, "crawl_fetch", "resource_fetch", connect_timeout=60) as tools:    crawl_fetch, resource_fetch = tools["crawl_fetch"], tools["resource_fetch"]​    # 1. A direct call, no model involved: load a page on a device in Germany.    page = summary(crawl_fetch.run(url="https://example.com", country="DE"))    markdown = resource_fetch.run(uri=page["content"]["markdown"]["resource"])    print(page["meta"]["title"], len(markdown), "chars of markdown")​    # 2. The same tools in a crew.    reader = Agent(        role="Web reader",        goal="Read web pages as they look in the country the user names",        backstory=(            "When you need a page from a specific country, or another fetch failed, "            "call crawl_fetch with the url and country, then resource_fetch on the "            "markdown resource it returns."        ),        tools=tools,        llm=LLM(model=MODEL),    )    task = Task(        description="What does https://example.com say when opened from Germany?",        expected_output="The page title and one sentence on what the page says.",        agent=reader,    )    print(Crew(agents=[reader], tasks=[task]).kickoff())

Keep the crew inside the with block: the adapter closes the connection when the block ends.

In a crew made with crewai create

Projects scaffolded with crewai create crew use a @CrewBase class. Give it the server once and pick tools per agent:

import os​from crewai import Agentfrom crewai.project import CrewBase, agent​​@CrewBaseclass ResearchCrew:    mcp_server_params = {        "url": "https://mcp.uprock.ai/mcp",        "transport": "streamable-http",        "headers": {"Authorization": f"Bearer {os.environ['UPROCK_API_KEY']}"},    }    mcp_connect_timeout = 60​    @agent    def reader(self) -> Agent:        return Agent(            config=self.agents_config["reader"],            tools=self.get_mcp_tools("crawl_fetch", "resource_fetch"),        )

Add your @task and @crew methods as usual. CrewBase opens one adapter for the whole crew and closes it after kickoff().

What comes back

The first call above printed Example Domain 958 chars of markdown. Here's what each tool hands back through the adapter:

ToolWhat you getHow to read it
crawl_fetchstr() of a one-item list holding the JSON summary (status, title, and the crawl:// addresses of the markdown and HTML); the two resource links are droppedast.literal_eval(output)[0], then json.loads
resource_fetchThe page as markdown, as a plain stringUse it as is
Any tool that failsThe error text as a plain string, such as all 3 attempts failed; last error: ... Invalid API key; the adapter doesn't raise. A wrong key took 14 seconds to fail, because UpRock tried three timesCheck before parsing, as summary() does

Inside a crew the agent sees the same strings, and the backstory tells it to follow up with resource_fetch. Two more things: meta.status_code isn't reliable (when we fetched a page that answers 403, status said success and status_code was missing), and a fresh fetch takes 10 to 40 seconds (19 in this test), against under half a second for a page fetched recently.

On 29 Oct 2026 we re-ran the direct calls in both examples with the key in the header, using crewai and crewai-tools 1.15.33 and mcp 1.30.0 on Python 3.12, and called crawl_fetch through the mcps field with the header; the 30-second limit is MCP_TOOL_EXECUTION_TIMEOUT in that version's source. Before that, on 25 Oct with 1.15.30 and the key in the URL, we ran both examples against the live UpRock server. The direct calls returned example.com's title and markdown. For the crew we swapped LLM(model=MODEL) for a scripted test model with no API key: it called crawl_fetch and then resource_fetch through UpRock and finished with the page title. The @CrewBase class ran the same way with a minimal agents.yaml. The key-in-URL mcps names come from that version, with a made-up key and a model that recorded what it was sent.

FAQ

Can I use the mcps field on Agent instead?

Yes, with MCPServerHTTP(url="https://mcp.uprock.ai/mcp", headers={"Authorization": f"Bearer {key}"}); the tools are then named mcp_uprock_ai_mcp_crawl_fetch and so on. It stops every tool call after 30 seconds (a fixed limit in crewai 1.15.33), and a fresh fetch can take 10 to 40, so MCPServerAdapter is the safer choice. Never give mcps the older address with the key in the URL: CrewAI builds tool names from the URL, so the key reached the model in every tool name when we tried it.

Why does crawl_fetch return a string that starts with a square bracket?

crawl_fetch answers with a JSON summary plus two resource links. MCPServerAdapter keeps only text blocks, and when a tool returns more than one block it returns str() of a list of them. Read it with ast.literal_eval and take the first item, as the example's summary() does.

Does MCPServerAdapter time out on slow fetches?

connect_timeout (30 seconds by default) only covers connecting. In crewai-tools 1.15.30 and 1.15.33 the tool calls themselves had no time limit, and a fresh fetch that took 19 seconds went through. The mcps field is different: it stops each tool call after 30 seconds.

Can I use it in a crew made with crewai create?

Yes. Set mcp_server_params on the @CrewBase class and call self.get_mcp_tools("crawl_fetch", "resource_fetch") in the agent method. CrewBase uses MCPServerAdapter underneath, so the tool names stay plain, and it closes the connection after kickoff.

What does it cost?

One credit per page fetched, $0.50 per 1,000 pages by card or USDC and $0.40 with UPT, prepaid. Video search is $1 per 1,000 searches.

Other use cases to explore

References

Get started

Add UpRock in one paste.

Paste this into Claude Code, Codex, Cursor or any agent with a terminal. It reads our docs, sets up the MCP server or CLI, and tells you the cost before it spends anything.

Set up UpRock for me: read https://uprock.ai/agents.md, connect the UpRock MCP server, and run one test crawl. Tell me what it costs before you spend anything.

How do I give a CrewAI agent web access with UpRock? | UpRock AI