MCP server/ai-tools

dot-do MCP Server

A framework that provides search, fetch, and do primitives for AI agents.

dot-do/mcp ↗by dot-doupdated
1

Add it to Claude Code

claude mcp add dot-do-mcp -- npx -y mcp
2

Make your agent remember this setup

dot-do-mcp's config, env vars, and the gotchas you hit — recalled in every future Claude Code, Cursor, and Codex session.

npx conare@latest

Free · one command · indexes the sessions already on disk. Set up in the browser instead →

What it does

  • Sandboxed TypeScript code execution in a V8 isolate
  • Capability-based security with zero ambient access
  • Reduces multiple sequential tool calls into a single inference round-trip
  • Composable orchestration using search, fetch, and do primitives
  • Significant reduction in token usage for complex workflows

Tools 3

searchQuery a corpus, discover resources, or match patterns.
fetchRetrieve a specific resource by identifier.
doExecute sandboxed code with access to provided bindings for composable orchestration.

Try it

Use the do tool to search for recent AI research papers and extract their titles and abstracts.
Fetch the configuration file at /etc/nginx/nginx.conf and summarize its contents.
Search for users who signed up last week and fetch their profile data using the provided bindings.
Execute a script to filter premium users by verifying their profile status.
Original README from dot-do/mcp

MCP

Three primitives. Infinite capabilities.

Build AI agents that can search, fetch, and do — with any backend, any scale, complete safety.

import { createMCPServer } from 'mcp'

const server = createMCPServer({
  search: webSearch(),
  fetch: httpFetch(),
  do: evaluate()
})

The Problem

AI agents are trapped in a fragmented world.

Every capability requires a separate tool. Every tool requires a round-trip to the model. Every round-trip costs tokens, time, and reliability.

An agent that needs to search the web, fetch a document, extract data, and save results might make 5-10 sequential tool calls — each one requiring the model to:

  1. Receive the previous result
  2. Decide what to do next
  3. Format a new tool call
  4. Wait for execution
  5. Repeat

This pattern has three fatal flaws:

Token explosion. Context windows fill with intermediate results. A workflow that should cost 2,000 tokens balloons to 150,000.

Latency multiplication. Each tool call requires a full model inference. Ten tools means ten inference round-trips.

Fragile orchestration. The model must correctly sequence every step. One wrong decision cascades into failure.

There's a better way.


The Insight

LLMs are better programmers than they are tool-callers.

They've been trained on billions of lines of code. They understand TypeScript interfaces, async/await patterns, error handling, loops, and conditionals.

But structured tool-call syntax? That's artificial. It was never in their training data. Every tool call is the model working against its strengths.

The solution: let the model write code.

Instead of N sequential tool calls, give the model ONE tool that accepts code. That code can call functions, handle errors, loop over results, and compose operations — all in a single execution.

// Before: 5 tool calls, 5 round-trips, 150K tokens
tool_call: search({ query: "latest AI research" })
tool_call: fetch({ url: results[0].url })
tool_call: extract({ content: page, fields: ["title", "abstract"] })
tool_call: search({ query: extracted.abstract })
tool_call: save({ data: relatedPapers })

// After: 1 tool call, 1 round-trip, 2K tokens
tool_call: do({
  code: `
    const results = await search("latest AI research")
    const page = await fetch(results[0].url)
    const { title, abstract } = extractFields(page, ["title", "abstract"])
    const related = await search(abstract)
    return { title, abstract, related }
  `
})

Same capability. 98% fewer tokens. One inference instead of five.


Three Primitives

Every AI agent capability reduces to three operations:

`search` — Find information

Query a corpus. Discover resources. Match patterns.

search("users who signed up last week")
search("*.config.json")
search("SELECT * FROM orders WHERE status = 'pending'")

`fetch` — Retrieve resources

Get a specific thing by identifier.

fetch("https://api.example.com/users/123")
fetch("/etc/nginx/nginx.conf")
fetch("order:ord_abc123")

`do` — Execute operations

Run code with access to search and fetch (and any other bindings you provide).

do(`
  const users = await search("premium users")
  const enriched = await Promise.all(
    users.map(async u => ({
      ...u,
      profile: await fetch(u.profileUrl)
    }))
  )
  return enriched.filter(u => u.profile.verified)
`)

The do primitive is where the magic happens. It's not just code execution — it's composable orchestration.


Safe by Design

Arbitrary code execution sounds dangerous. It isn't — when designed correctly.

The execution environment is a V8 isolate with zero ambient capabilities:

  • No filesystem access
  • No network access
  • No environment variables
  • No system calls

The ONLY way code can interact with the outside world is through explicitly provided bindings.

do({
  code: `
    // These work because they're provided bindings
    const results = await search("query")
    const doc = await fetch("doc:123")

    // These fail because they're not provided
    await fetch("https://evil.com")      // Error: not a valid resource
    require('fs').readFileSync('/etc/passwd')  // Error: require is not defined
    process.env.API_KEY                   // Error: process is not defined
  `,
  bindings: {
    search: scopedSearch,  // Your implementation
    fetch: scopedFetch     // Your implementation
  }
})

This is capability-based security. Code can only do what you explicitly allow. Credentials never enter the sandbox. The attack surface is exactly the surface you define.


Configurable Scope

The power of this pattern comes from configurable scope. The same three primitives adapt to any domain:

Web Research Agent

createMCPServer({
  search: braveSearch({ apiKey }),
  fetch: httpFetch({ allowedDomains: ['*.gov', '*.edu'] }),
  do: {
    bindings: { search, fetch },

Frequently Asked Questions

What are the key features of dot-do MCP?

Sandboxed TypeScript code execution in a V8 isolate. Capability-based security with zero ambient access. Reduces multiple sequential tool calls into a single inference round-trip. Composable orchestration using search, fetch, and do primitives. Significant reduction in token usage for complex workflows.

What can I use dot-do MCP for?

Building web research agents that perform multi-step data extraction. Automating complex data retrieval and processing tasks across multiple APIs. Creating secure, sandboxed environments for AI agents to interact with local or remote resources. Optimizing agent workflows to reduce latency and token costs.

How do I install dot-do MCP?

Install dot-do MCP by running: npx -y mcp

What MCP clients work with dot-do MCP?

dot-do MCP works with any MCP-compatible client including Claude Desktop, Claude Code, Cursor, and other editors with MCP support.

Conare · memory for coding agents

Turn this server into reusable context

Keep dot-do MCP docs, env vars, and workflow notes in Conare so your agent carries them across sessions.

Set up free$npx conare@latest