Skip to content

MCP Tools

The API is defined in a single file using Effect’s HttpApi:

API definition View source →
import { HttpApi, HttpApiEndpoint, HttpApiGroup } from "@effect/platform";
import { Schema } from "effect";

const ScoutInput = Schema.Struct({
	url: Schema.String,
	task: Schema.String,
});

const ScoutResult = Schema.Struct({
	siteId: Schema.String,
	endpointCount: Schema.Number,
	pathId: Schema.String,
	openApiSpec: Schema.Unknown,
});

const WorkerInput = Schema.Struct({
	pathId: Schema.String,
	data: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Unknown })),
});

const WorkerResult = Schema.Struct({
	success: Schema.Boolean,
	response: Schema.optional(Schema.Unknown),
});

const HealInput = Schema.Struct({
	pathId: Schema.String,
	error: Schema.optional(Schema.String),
});

const HealResult = Schema.Struct({
	healed: Schema.Boolean,
	newPathId: Schema.optional(Schema.String),
});

const ToolsGroup = HttpApiGroup.make("Tools")
	.add(HttpApiEndpoint.post("scout", "/tools/scout").addSuccess(ScoutResult).setPayload(ScoutInput))
	.add(
		HttpApiEndpoint.post("worker", "/tools/worker")
			.addSuccess(WorkerResult)
			.setPayload(WorkerInput),
	)
	.add(HttpApiEndpoint.post("heal", "/tools/heal").addSuccess(HealResult).setPayload(HealInput));

export const UnsurfApi = HttpApi.make("unsurf").add(ToolsGroup);

Explore a website and capture its API endpoints.

FieldTypeRequiredDescription
urlstringTarget URL to scout
taskstringNatural language description of what to find
authobjectAuthentication config
auth.cookiesstringCookie header value
auth.headersRecord<string, string>Additional request headers
FieldTypeDescription
siteIdstringUnique identifier for the scouted site
endpointCountnumberNumber of unique endpoints captured
pathIdstringReplayable navigation path ID
openApiSpecobjectOpenAPI 3.1 specification
ErrorWhen
BrowserErrorBrowser container failed to launch or crashed
NetworkErrorTarget site unreachable
StoreErrorFailed to save results to D1/R2
{
"name": "scout",
"description": "Explore a website and capture its API endpoints",
"inputSchema": {
"type": "object",
"required": ["url", "task"],
"properties": {
"url": { "type": "string", "description": "Target URL to scout" },
"task": { "type": "string", "description": "What to find on the site" }
}
}
}

Execute a scouted path or replay a captured API endpoint.

FieldTypeRequiredDescription
pathIdstringID of the path to execute
dataRecord<string, unknown>Data to pass to the endpoint
FieldTypeDescription
successbooleanWhether execution succeeded
responseunknownResponse body from the target API
ErrorWhen
NotFoundErrorPath ID does not exist
PathBrokenErrorPath is broken — target site changed
NetworkErrorTarget API unreachable
BrowserErrorBrowser fallback failed
{
"name": "worker",
"description": "Execute a scouted path or replay a captured API endpoint",
"inputSchema": {
"type": "object",
"required": ["pathId"],
"properties": {
"pathId": { "type": "string", "description": "Path ID from a previous scout" },
"data": { "type": "object", "description": "Data to send to the endpoint" }
}
}
}

Re-scout and repair a broken path.

FieldTypeRequiredDescription
pathIdstringID of the broken path
errorstringDescription of what went wrong
FieldTypeDescription
healedbooleanWhether the path was successfully repaired
newPathIdstringID of the new path (if changed)
ErrorWhen
NotFoundErrorPath ID does not exist
BrowserErrorRe-scout browser failed
NetworkErrorTarget site unreachable
{
"name": "heal",
"description": "Re-scout and repair a broken path",
"inputSchema": {
"type": "object",
"required": ["pathId"],
"properties": {
"pathId": { "type": "string", "description": "ID of the broken path" },
"error": { "type": "string", "description": "What went wrong" }
}
}
}