Skip to content

Commit 806e347

Browse files
authored
Merge branch 'main' into hypeship/add-managed-auth-tools
2 parents ad0bf34 + 9cd7a3a commit 806e347

3 files changed

Lines changed: 350 additions & 180 deletions

File tree

src/lib/mcp/register.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { registerAPIKeyCapabilities } from "@/lib/mcp/tools/api-keys";
44
import { registerAppCapabilities } from "@/lib/mcp/tools/apps";
55
import { registerAuthConnectionTools } from "@/lib/mcp/tools/auth-connections";
66
import { registerBrowserPoolCapabilities } from "@/lib/mcp/tools/browser-pools";
7+
import { registerBrowserCurlTool } from "@/lib/mcp/tools/browser-curl";
78
import { registerBrowserCapabilities } from "@/lib/mcp/tools/browsers";
89
import { registerComputerActionTool } from "@/lib/mcp/tools/computer-action";
910
import { registerCredentialProviderTools } from "@/lib/mcp/tools/credential-providers";
@@ -25,6 +26,7 @@ const mcpToolRegistrations = [
2526
["projects", registerProjectCapabilities],
2627
["api_keys", registerAPIKeyCapabilities],
2728
["browser_pools", registerBrowserPoolCapabilities],
29+
["browser_curl", registerBrowserCurlTool],
2830
["proxies", registerProxyTools],
2931
["extensions", registerExtensionTools],
3032
["apps", registerAppCapabilities],

src/lib/mcp/tools/browser-curl.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2+
import { z } from "zod";
3+
import { createKernelClient, type KernelClient } from "@/lib/mcp/kernel-client";
4+
import { errorResponse, jsonResponse } from "@/lib/mcp/responses";
5+
6+
type BrowserCurlParams = Parameters<KernelClient["browsers"]["curl"]>[1];
7+
8+
function curlUrlValidationError(url: string) {
9+
const parsed = new URL(url);
10+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
11+
return "url must use http or https.";
12+
}
13+
}
14+
15+
export function registerBrowserCurlTool(server: McpServer) {
16+
server.tool(
17+
"browser_curl",
18+
"Send an HTTP request through an existing Kernel browser session's Chrome network stack.",
19+
{
20+
session_id: z.string().describe("Browser session ID."),
21+
url: z.string().url().describe("Target http or https URL."),
22+
method: z
23+
.enum(["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"])
24+
.describe("HTTP method. Defaults to GET.")
25+
.optional(),
26+
headers: z
27+
.record(z.string(), z.string())
28+
.describe("Custom headers merged with browser defaults.")
29+
.optional(),
30+
body: z
31+
.string()
32+
.describe("Request body for POST, PUT, or PATCH requests.")
33+
.optional(),
34+
response_encoding: z
35+
.enum(["utf8", "base64"])
36+
.describe("Response body encoding. Use base64 for binary content.")
37+
.optional(),
38+
timeout_ms: z
39+
.number()
40+
.int()
41+
.describe("Request timeout in milliseconds.")
42+
.optional(),
43+
},
44+
async (params, extra) => {
45+
if (!extra.authInfo) throw new Error("Authentication required");
46+
const client = createKernelClient(extra.authInfo.token);
47+
48+
try {
49+
const curlRequest: { session_id: string } & BrowserCurlParams = params;
50+
const { session_id, ...curlParams } = curlRequest;
51+
const urlError = curlUrlValidationError(curlParams.url);
52+
if (urlError) return errorResponse(`Error: ${urlError}`);
53+
54+
const response = await client.browsers.curl(session_id, curlParams);
55+
return jsonResponse(response);
56+
} catch (error) {
57+
return errorResponse(
58+
`Error in browser_curl: ${
59+
error instanceof Error ? error.message : String(error)
60+
}`,
61+
);
62+
}
63+
},
64+
);
65+
}

0 commit comments

Comments
 (0)