index.ts•6.37 kB
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListResourcesRequestSchema,
ListToolsRequestSchema,
ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
// Get API configuration from environment variables
const API_KEY = process.env.AUTOPILOT_API_KEY;
if (!API_KEY) {
console.error("Error: AUTOPILOT_API_KEY environment variable is required");
process.exit(1);
}
// Autopilot Browser API Client
class AutopilotAPIClient {
private apiKey: string;
private baseUrl = 'https://api.autopilotbrowser.com';
constructor(apiKey: string) {
this.apiKey = apiKey;
}
async searchWorkflows(searchTerm?: string) {
const url = new URL(`${this.baseUrl}/wf/search`);
if (searchTerm) {
url.searchParams.append('searchTerm', searchTerm);
}
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
'x-api-key': this.apiKey,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error(`API Error: ${response.status} ${response.statusText}`);
}
return await response.json();
}
async runWorkflow(workflowName: string, workflowInputs: Record<string, any>) {
const response = await fetch(`${this.baseUrl}/wf/run`, {
method: 'POST',
headers: {
'x-api-key': this.apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({
workflowName,
workflowInputs,
}),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`API Error: ${response.status} ${response.statusText} - ${errorText}`);
}
return await response.json();
}
}
const apiClient = new AutopilotAPIClient(API_KEY);
// Create MCP Server
const server = new Server(
{
name: "autopilot-browser-server",
version: "1.0.0",
},
{
capabilities: {
resources: {},
tools: {},
},
}
);
// List Resources
server.setRequestHandler(ListResourcesRequestSchema, async () => {
return {
resources: [
{
uri: "autopilot://workflows",
name: "Available Workflows",
description: "List of all available Autopilot Browser workflows that can be executed",
mimeType: "application/json",
},
],
};
});
// Read Resource
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
if (request.params.uri === "autopilot://workflows") {
try {
const workflows = await apiClient.searchWorkflows();
return {
contents: [
{
uri: request.params.uri,
mimeType: "application/json",
text: JSON.stringify(workflows, null, 2),
},
],
};
} catch (error) {
throw new Error(`Failed to fetch workflows: ${error instanceof Error ? error.message : String(error)}`);
}
}
throw new Error(`Unknown resource: ${request.params.uri}`);
});
// List Tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "search_workflows",
description: "Search for available Autopilot Browser workflows by keyword. Returns a list of workflows that match the search term. If no search term is provided, returns all workflows.",
inputSchema: {
type: "object",
properties: {
searchTerm: {
type: "string",
description: "Optional keyword to search for specific workflows (e.g., 'scraping', 'automation', 'data extraction')",
},
},
},
},
{
name: "run_workflow",
description: "Execute a specific Autopilot Browser workflow with the provided inputs. Use search_workflows first to find available workflows and their required inputs.",
inputSchema: {
type: "object",
properties: {
workflowName: {
type: "string",
description: "The name of the workflow to execute",
},
workflowInputs: {
type: "object",
description: "Key-value pairs of inputs required by the workflow. The required inputs depend on the specific workflow being executed.",
additionalProperties: true,
},
},
required: ["workflowName", "workflowInputs"],
},
},
],
};
});
// Call Tool
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "search_workflows") {
const { searchTerm } = request.params.arguments as {
searchTerm?: string;
};
try {
const workflows = await apiClient.searchWorkflows(searchTerm);
return {
content: [
{
type: "text",
text: JSON.stringify(workflows, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error searching workflows: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
}
if (request.params.name === "run_workflow") {
const { workflowName, workflowInputs } = request.params.arguments as {
workflowName: string;
workflowInputs: Record<string, any>;
};
try {
const result = await apiClient.runWorkflow(workflowName, workflowInputs);
return {
content: [
{
type: "text",
text: JSON.stringify(result, null, 2),
},
],
};
} catch (error) {
return {
content: [
{
type: "text",
text: `Error executing workflow: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
}
throw new Error(`Unknown tool: ${request.params.name}`);
});
// Start Server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Autopilot Browser MCP Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error:", error);
process.exit(1);
});