🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@openserp/mcp

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@openserp/mcp - npm Package Compare versions

Comparing version
0.1.5
to
0.1.6
+2
-2
dist/index.js

@@ -14,3 +14,3 @@ #!/usr/bin/env node

var DOCS_URL = "https://openserp.org/docs";
var ISSUES_URL = "https://github.com/karust/openserp/issues";
var ISSUES_URL = "https://github.com/openserpapi/mcp/issues";
var SUPPORT_LINE = `Docs: ${DOCS_URL} | Issues: ${ISSUES_URL}`;

@@ -176,3 +176,3 @@ var API_KEY_LINE = `Get an API key: ${DASHBOARD_STATUS_URL}`;

var extractModes = ["auto", "fast", "rendered"];
var VERSION = true ? "0.1.5" : "dev";
var VERSION = true ? "0.1.6" : "dev";
var commonSearchSchema = {

@@ -179,0 +179,0 @@ text: z.string().optional().describe("Search query text. At least one of text, site, or file should be provided."),

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/messages.ts","../src/http.ts","../src/mcp-server.ts","../src/tools.ts","../src/stdio.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { OpenSERP } from \"@openserp/sdk\";\nimport { loadConfig } from \"./config\";\nimport { runHttpTransport } from \"./http\";\nimport { DASHBOARD_STATUS_URL, DOCS_URL, ISSUES_URL } from \"./messages\";\nimport { createMcpServer } from \"./mcp-server\";\nimport { runStdioTransport } from \"./stdio\";\n\nconst args = process.argv.slice(2);\n\nif (hasFlag(\"--help\") || hasFlag(\"-h\")) {\n printHelp();\n process.exit(0);\n}\n\nconst config = loadConfig();\nconst client = new OpenSERP(config.client);\n\nif (hasFlag(\"--http\")) {\n runHttpTransport(config.client, {\n host: valueFor(\"--host\") ?? config.host,\n port: parsePort(valueFor(\"--port\")) ?? config.port,\n });\n} else {\n const server = createMcpServer(client);\n await runStdioTransport(server);\n}\n\nfunction hasFlag(flag: string): boolean {\n return args.includes(flag);\n}\n\nfunction valueFor(flag: string): string | undefined {\n const index = args.indexOf(flag);\n if (index < 0) {\n return undefined;\n }\n return args[index + 1];\n}\n\nfunction parsePort(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isInteger(parsed) ? parsed : undefined;\n}\n\nfunction printHelp(): void {\n process.stdout.write(`OpenSERP MCP server\n\nUsage:\n openserp-mcp --stdio\n openserp-mcp --http [--host 127.0.0.1] [--port 3333]\n\nEnvironment:\n OPENSERP_API_KEY Use OpenSERP Cloud when set. Keys: ${DASHBOARD_STATUS_URL}\n OPENSERP_BASE_URL Override API base URL, for example http://localhost:7000.\n OPENSERP_BACKEND Optional backend hint: oss or cloud.\n OPENSERP_TIMEOUT_MS Request timeout in milliseconds.\n HOST HTTP host, default 127.0.0.1.\n PORT HTTP port, default 3333.\n\nResources:\n Docs ${DOCS_URL}\n GitHub / Issues ${ISSUES_URL}\n`);\n}\n","import {\n OSS_BASE_URL,\n type Backend,\n type OpenSERPConfig,\n} from \"@openserp/sdk\";\nimport { API_KEY_LINE, SUPPORT_LINE } from \"./messages\";\n\nlet loggedOssMode = false;\n\nexport interface ServerConfig {\n client: OpenSERPConfig;\n host: string;\n port: number;\n}\n\nexport function loadConfig(env: NodeJS.ProcessEnv = process.env): ServerConfig {\n const apiKey = env.OPENSERP_API_KEY;\n const baseUrl = env.OPENSERP_BASE_URL;\n const backend = env.OPENSERP_BACKEND as Backend | undefined;\n const timeoutMs = parseInteger(env.OPENSERP_TIMEOUT_MS);\n\n if (!apiKey && !baseUrl && !loggedOssMode) {\n console.error(\n \"[openserp-mcp] No OPENSERP_API_KEY set - using OSS mode at http://localhost:7000.\",\n );\n console.error(`[openserp-mcp] ${API_KEY_LINE}`);\n console.error(`[openserp-mcp] ${SUPPORT_LINE}`);\n loggedOssMode = true;\n }\n\n return {\n client: {\n headers: { \"X-OpenSERP-Client\": \"mcp\" },\n ...(apiKey ? { apiKey } : {}),\n ...(baseUrl ? { baseUrl } : !apiKey ? { baseUrl: OSS_BASE_URL } : {}),\n ...(backend ? { backend } : {}),\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n },\n host: env.HOST ?? \"127.0.0.1\",\n port: parseInteger(env.PORT) ?? 3333,\n };\n}\n\nfunction parseInteger(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isInteger(parsed) ? parsed : undefined;\n}\n","export const DASHBOARD_STATUS_URL = \"https://openserp.org/dashboard/keys\";\nexport const DOCS_URL = \"https://openserp.org/docs\";\nexport const ISSUES_URL = \"https://github.com/karust/openserp/issues\";\n\nexport const SUPPORT_LINE = `Docs: ${DOCS_URL} | Issues: ${ISSUES_URL}`;\nexport const API_KEY_LINE = `Get an API key: ${DASHBOARD_STATUS_URL}`;\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { OpenSERP } from \"@openserp/sdk\";\nimport type { OpenSERPConfig } from \"@openserp/sdk\";\nimport { SUPPORT_LINE } from \"./messages\";\nimport { createMcpServer } from \"./mcp-server\";\n\nexport function runHttpTransport(\n clientConfig: OpenSERPConfig,\n options: { host: string; port: number },\n): void {\n const sseTransports = new Map<string, SSEServerTransport>();\n\n const httpServer = createServer(async (request, response) => {\n try {\n const url = new URL(request.url ?? \"/\", `http://${request.headers.host ?? \"localhost\"}`);\n\n if (request.method === \"OPTIONS\") {\n sendEmpty(response, 204);\n return;\n }\n\n if (request.method === \"GET\" && url.pathname === \"/health\") {\n sendJson(response, 200, { ok: true });\n return;\n }\n\n if (url.pathname === \"/mcp\") {\n await handleStreamableHttp(clientConfig, request, response);\n return;\n }\n\n if (request.method === \"GET\" && url.pathname === \"/sse\") {\n const transport = new SSEServerTransport(\"/messages\", response);\n sseTransports.set(transport.sessionId, transport);\n transport.onclose = () => {\n sseTransports.delete(transport.sessionId);\n };\n\n await createMcpServer(new OpenSERP(clientConfig)).connect(transport);\n return;\n }\n\n if (request.method === \"POST\" && url.pathname === \"/messages\") {\n const sessionId = url.searchParams.get(\"sessionId\");\n const transport = sessionId ? sseTransports.get(sessionId) : undefined;\n if (!transport) {\n sendJson(response, 404, { error: \"unknown_session\" });\n return;\n }\n await transport.handlePostMessage(request, response);\n return;\n }\n\n sendJson(response, 404, { error: \"not_found\" });\n } catch (err) {\n sendJson(response, 500, { error: errorMessage(err) });\n }\n });\n\n httpServer.listen(options.port, options.host, () => {\n const address = httpServer.address();\n const port = typeof address === \"object\" && address ? address.port : options.port;\n console.error(\n `[openserp-mcp] HTTP transport listening at http://${options.host}:${port}/mcp | ${SUPPORT_LINE}`,\n );\n });\n}\n\nasync function handleStreamableHttp(\n clientConfig: OpenSERPConfig,\n request: IncomingMessage,\n response: ServerResponse,\n): Promise<void> {\n const server = createMcpServer(new OpenSERP(clientConfig));\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n } as any);\n\n try {\n await server.connect(transport as unknown as Transport);\n await transport.handleRequest(request, response);\n } finally {\n response.on(\"close\", () => {\n void transport.close();\n void server.close();\n });\n }\n}\n\nfunction sendJson(response: ServerResponse, status: number, body: unknown): void {\n response.writeHead(status, {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Headers\": \"content-type, authorization, mcp-session-id\",\n \"Access-Control-Allow-Methods\": \"GET, POST, DELETE, OPTIONS\",\n });\n response.end(JSON.stringify(body));\n}\n\nfunction sendEmpty(response: ServerResponse, status: number): void {\n response.writeHead(status, {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Headers\": \"content-type, authorization, mcp-session-id\",\n \"Access-Control-Allow-Methods\": \"GET, POST, DELETE, OPTIONS\",\n });\n response.end();\n}\n\nfunction errorMessage(err: unknown): string {\n if (err instanceof Error) {\n return err.message;\n }\n return String(err);\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\r\nimport { OpenSERP } from \"@openserp/sdk\";\r\nimport { z } from \"zod\";\r\nimport { callTool } from \"./tools\";\r\n\r\nconst engines = [\"google\", \"bing\", \"yandex\", \"baidu\", \"duck\", \"duckduckgo\", \"ecosia\"] as const;\r\nconst formats = [\"json\", \"markdown\", \"text\", \"ndjson\"] as const;\r\nconst megaModes = [\"balanced\", \"any\", \"fast\"] as const;\r\nconst extractModes = [\"auto\", \"fast\", \"rendered\"] as const;\r\n\r\n// Replaced at build time with the package.json version (see tsup.config.ts).\r\n// Falls back to \"dev\" when run from source without the define in place.\r\ndeclare const __OPENSERP_MCP_VERSION__: string;\r\nconst VERSION =\r\n typeof __OPENSERP_MCP_VERSION__ === \"string\" ? __OPENSERP_MCP_VERSION__ : \"dev\";\r\n\r\n// Fields shared by every search-style tool, web and image alike.\r\nconst commonSearchSchema = {\r\n text: z\r\n .string()\r\n .optional()\r\n .describe(\"Search query text. At least one of text, site, or file should be provided.\"),\r\n lang: z.string().optional().describe(\"Language code, such as EN or de.\"),\r\n region: z\r\n .string()\r\n .optional()\r\n .describe(\"Market or location hint, such as US, DE, en-GB, Berlin, or a Yandex lr id.\"),\r\n date: z\r\n .string()\r\n .regex(/^[0-9]{8}\\.\\.[0-9]{8}$/)\r\n .optional()\r\n .describe(\"Date interval in YYYYMMDD..YYYYMMDD format.\"),\r\n file: z.string().optional().describe(\"File extension filter, such as PDF.\"),\r\n site: z.string().optional().describe(\"Domain filter, such as example.com.\"),\r\n limit: z.number().int().min(1).max(100).optional().describe(\"Maximum result count.\"),\r\n start: z.number().int().min(0).optional().describe(\"Pagination offset.\"),\r\n filter: z.boolean().optional().describe(\"Enable duplicate filtering.\"),\r\n features: z.boolean().optional().describe(\"Include supported rich SERP features.\"),\r\n format: z.enum(formats).optional().default(\"json\").describe(\"Response format.\"),\r\n};\r\n\r\n// Page-content extraction only applies to web results, so these are kept off\r\n// the image tools (the image endpoints ignore them).\r\nconst webExtractSchema = {\r\n extract: z\r\n .union([z.boolean(), z.number().int().min(0).max(5)])\r\n .optional()\r\n .describe(\r\n \"Enrich the top web results with cleaned page content. Boolean or integer depth: false/0 off, true/1 top result, N top N (1-5).\",\r\n ),\r\n extractMode: z.enum(extractModes).optional().describe(\"Extraction strategy for target pages.\"),\r\n minRunes: z\r\n .number()\r\n .int()\r\n .min(0)\r\n .optional()\r\n .describe(\"Minimum content length (in runes) before auto mode escalates to rendered extraction.\"),\r\n};\r\n\r\nconst webSearchSchema = {\r\n ...commonSearchSchema,\r\n ...webExtractSchema,\r\n};\r\n\r\nconst megaEngineSchema = {\r\n engines: z\r\n .array(z.enum(engines))\r\n .optional()\r\n .describe(\"Engines to query. Omit to use all available engines.\"),\r\n mode: z.enum(megaModes).optional().default(\"balanced\").describe(\"Mega execution mode.\"),\r\n dedupe: z.boolean().optional().describe(\"Deduplicate by normalized URL.\"),\r\n merge: z.boolean().optional().describe(\"Merge successful engine results.\"),\r\n};\r\n\r\nconst megaSearchSchema = {\r\n ...webSearchSchema,\r\n ...megaEngineSchema,\r\n};\r\n\r\nconst megaImageSchema = {\r\n ...commonSearchSchema,\r\n ...megaEngineSchema,\r\n};\r\n\r\n// fast_search / any_search are mega_search with a fixed mode, so they take the\r\n// same inputs minus the mode selector.\r\nconst { mode: _mode, ...fastOrAnySchema } = megaSearchSchema;\r\n\r\nexport function createMcpServer(client: OpenSERP): McpServer {\r\n const server = new McpServer({\r\n name: \"@openserp/mcp\",\r\n version: VERSION,\r\n });\r\n\r\n server.registerTool(\r\n \"search\",\r\n {\r\n title: \"Search\",\r\n description: \"Search web results with a specific OpenSERP engine.\",\r\n inputSchema: {\r\n engine: z.enum(engines).describe(\"Search engine endpoint alias.\"),\r\n ...webSearchSchema,\r\n },\r\n },\r\n (args) => callTool(client, \"search\", args),\r\n );\r\n\r\n server.registerTool(\r\n \"mega_search\",\r\n {\r\n title: \"Mega Search\",\r\n description: \"Search across multiple engines with balanced, any, or fast execution.\",\r\n inputSchema: megaSearchSchema,\r\n },\r\n (args) => callTool(client, \"mega_search\", args),\r\n );\r\n\r\n server.registerTool(\r\n \"fast_search\",\r\n {\r\n title: \"Fast Search\",\r\n description: \"Search using the fastest currently healthy engine.\",\r\n inputSchema: fastOrAnySchema,\r\n },\r\n (args) => callTool(client, \"fast_search\", args),\r\n );\r\n\r\n server.registerTool(\r\n \"any_search\",\r\n {\r\n title: \"Any Search\",\r\n description: \"Try engines in order and return the first successful web result set.\",\r\n inputSchema: fastOrAnySchema,\r\n },\r\n (args) => callTool(client, \"any_search\", args),\r\n );\r\n\r\n server.registerTool(\r\n \"image_search\",\r\n {\r\n title: \"Image Search\",\r\n description: \"Search image results with a specific OpenSERP engine.\",\r\n inputSchema: {\r\n engine: z.enum(engines).describe(\"Search engine endpoint alias.\"),\r\n ...commonSearchSchema,\r\n },\r\n },\r\n (args) => callTool(client, \"image_search\", args),\r\n );\r\n\r\n server.registerTool(\r\n \"mega_image\",\r\n {\r\n title: \"Mega Image Search\",\r\n description: \"Search images across multiple engines.\",\r\n inputSchema: megaImageSchema,\r\n },\r\n (args) => callTool(client, \"mega_image\", args),\r\n );\r\n\r\n server.registerTool(\r\n \"get_usage\",\r\n {\r\n title: \"Get Usage\",\r\n description: \"Return OpenSERP Cloud account and credit information.\",\r\n inputSchema: {},\r\n },\r\n () => callTool(client, \"get_usage\", {}),\r\n );\r\n\r\n server.registerTool(\r\n \"list_engines\",\r\n {\r\n title: \"List Engines\",\r\n description: \"List available engines on OSS or Cloud engine capabilities on Cloud.\",\r\n inputSchema: {},\r\n },\r\n () => callTool(client, \"list_engines\", {}),\r\n );\r\n\r\n server.registerTool(\r\n \"extract\",\r\n {\r\n title: \"Extract URL\",\r\n description: \"Extract LLM-ready content from a URL.\",\r\n inputSchema: {\r\n url: z.string().url().describe(\"Absolute URL to fetch and extract.\"),\r\n mode: z.enum(extractModes).optional().default(\"auto\").describe(\"Extraction strategy.\"),\r\n lang: z.string().optional().describe(\"Language hint.\"),\r\n minRunes: z\r\n .number()\r\n .int()\r\n .min(0)\r\n .optional()\r\n .describe(\"Minimum content length (in runes) before auto mode escalates to rendered extraction.\"),\r\n clean: z.boolean().optional().describe(\"Use article-only extraction when true.\"),\r\n useLlmsTxt: z\r\n .boolean()\r\n .optional()\r\n .describe(\"Prefer /llms-full.txt or /llms.txt for site roots.\"),\r\n format: z.enum(formats).optional().default(\"json\").describe(\"Response format.\"),\r\n },\r\n },\r\n (args) => callTool(client, \"extract\", args),\r\n );\r\n\r\n return server;\r\n}\r\n","import { OpenSERP } from \"@openserp/sdk\";\nimport { DASHBOARD_STATUS_URL } from \"./messages\";\n\nexport interface ToolCallResult {\n [key: string]: unknown;\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n}\n\nexport async function callTool(\n client: OpenSERP,\n name: string,\n args: unknown,\n): Promise<ToolCallResult> {\n const input = assertObject(args);\n\n try {\n switch (name) {\n case \"search\":\n requireString(input, \"engine\");\n return toolResult(await client.search(input as any));\n case \"mega_search\":\n return toolResult(await client.megaSearch(input as any));\n case \"fast_search\":\n return toolResult(await client.fastSearch(input as any));\n case \"any_search\":\n return toolResult(await client.anySearch(input as any));\n case \"image_search\":\n requireString(input, \"engine\");\n return toolResult(await client.image(input as any));\n case \"mega_image\":\n return toolResult(await client.megaImage(input as any));\n case \"extract\":\n requireString(input, \"url\");\n return toolResult(await client.extract(input as any));\n case \"get_usage\":\n return toolResult(await getUsage(client));\n case \"list_engines\":\n return toolResult(await listEngines(client));\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n } catch (err) {\n return {\n isError: true,\n content: [{ type: \"text\", text: formatError(err) }],\n };\n }\n}\n\nasync function getUsage(client: OpenSERP): Promise<unknown> {\n if (client.backend !== \"cloud\") {\n throw new Error(\n `get_usage requires OpenSERP Cloud. Set OPENSERP_API_KEY or OPENSERP_BACKEND=cloud. Get an API key: ${DASHBOARD_STATUS_URL}`,\n );\n }\n\n return {\n backend: client.backend,\n baseUrl: client.baseUrl,\n account: await client.me(),\n lastResponse: summarizeLastResponse(client),\n };\n}\n\nasync function listEngines(client: OpenSERP): Promise<unknown> {\n if (client.backend === \"cloud\") {\n return {\n backend: client.backend,\n baseUrl: client.baseUrl,\n capabilities: await client.enginesCapabilities(),\n };\n }\n\n return {\n backend: client.backend,\n baseUrl: client.baseUrl,\n engines: await client.engines(),\n };\n}\n\nfunction assertObject(value: unknown): Record<string, unknown> {\n if (value === undefined || value === null) {\n return {};\n }\n if (typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\"Tool arguments must be an object.\");\n }\n return value as Record<string, unknown>;\n}\n\nfunction requireString(input: Record<string, unknown>, key: string): void {\n if (typeof input[key] !== \"string\" || input[key] === \"\") {\n throw new Error(`Missing required string argument: ${key}`);\n }\n}\n\nfunction toolResult(value: unknown): ToolCallResult {\n return {\n content: [\n {\n type: \"text\",\n text: typeof value === \"string\" ? value : JSON.stringify(value, null, 2),\n },\n ],\n };\n}\n\nfunction formatError(err: unknown): string {\n if (err instanceof Error) {\n return err.message;\n }\n return String(err);\n}\n\nfunction summarizeLastResponse(client: OpenSERP): unknown {\n const last = client.lastResponse;\n if (!last) {\n return undefined;\n }\n\n return {\n status: last.status,\n requestId: last.requestId,\n credits: last.credits,\n engineUsed: last.engineUsed,\n networkBytes: last.networkBytes,\n };\n}\n","import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { SUPPORT_LINE } from \"./messages\";\n\nexport async function runStdioTransport(server: McpServer): Promise<void> {\n await server.connect(new StdioServerTransport());\n console.error(`[openserp-mcp] stdio transport ready | ${SUPPORT_LINE}`);\n}\n"],"mappings":"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","names":["OpenSERP","client","args","client","args","OpenSERP"]}
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/messages.ts","../src/http.ts","../src/mcp-server.ts","../src/tools.ts","../src/stdio.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { OpenSERP } from \"@openserp/sdk\";\nimport { loadConfig } from \"./config\";\nimport { runHttpTransport } from \"./http\";\nimport { DASHBOARD_STATUS_URL, DOCS_URL, ISSUES_URL } from \"./messages\";\nimport { createMcpServer } from \"./mcp-server\";\nimport { runStdioTransport } from \"./stdio\";\n\nconst args = process.argv.slice(2);\n\nif (hasFlag(\"--help\") || hasFlag(\"-h\")) {\n printHelp();\n process.exit(0);\n}\n\nconst config = loadConfig();\nconst client = new OpenSERP(config.client);\n\nif (hasFlag(\"--http\")) {\n runHttpTransport(config.client, {\n host: valueFor(\"--host\") ?? config.host,\n port: parsePort(valueFor(\"--port\")) ?? config.port,\n });\n} else {\n const server = createMcpServer(client);\n await runStdioTransport(server);\n}\n\nfunction hasFlag(flag: string): boolean {\n return args.includes(flag);\n}\n\nfunction valueFor(flag: string): string | undefined {\n const index = args.indexOf(flag);\n if (index < 0) {\n return undefined;\n }\n return args[index + 1];\n}\n\nfunction parsePort(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isInteger(parsed) ? parsed : undefined;\n}\n\nfunction printHelp(): void {\n process.stdout.write(`OpenSERP MCP server\n\nUsage:\n openserp-mcp --stdio\n openserp-mcp --http [--host 127.0.0.1] [--port 3333]\n\nEnvironment:\n OPENSERP_API_KEY Use OpenSERP Cloud when set. Keys: ${DASHBOARD_STATUS_URL}\n OPENSERP_BASE_URL Override API base URL, for example http://localhost:7000.\n OPENSERP_BACKEND Optional backend hint: oss or cloud.\n OPENSERP_TIMEOUT_MS Request timeout in milliseconds.\n HOST HTTP host, default 127.0.0.1.\n PORT HTTP port, default 3333.\n\nResources:\n Docs ${DOCS_URL}\n GitHub / Issues ${ISSUES_URL}\n`);\n}\n","import {\n OSS_BASE_URL,\n type Backend,\n type OpenSERPConfig,\n} from \"@openserp/sdk\";\nimport { API_KEY_LINE, SUPPORT_LINE } from \"./messages\";\n\nlet loggedOssMode = false;\n\nexport interface ServerConfig {\n client: OpenSERPConfig;\n host: string;\n port: number;\n}\n\nexport function loadConfig(env: NodeJS.ProcessEnv = process.env): ServerConfig {\n const apiKey = env.OPENSERP_API_KEY;\n const baseUrl = env.OPENSERP_BASE_URL;\n const backend = env.OPENSERP_BACKEND as Backend | undefined;\n const timeoutMs = parseInteger(env.OPENSERP_TIMEOUT_MS);\n\n if (!apiKey && !baseUrl && !loggedOssMode) {\n console.error(\n \"[openserp-mcp] No OPENSERP_API_KEY set - using OSS mode at http://localhost:7000.\",\n );\n console.error(`[openserp-mcp] ${API_KEY_LINE}`);\n console.error(`[openserp-mcp] ${SUPPORT_LINE}`);\n loggedOssMode = true;\n }\n\n return {\n client: {\n headers: { \"X-OpenSERP-Client\": \"mcp\" },\n ...(apiKey ? { apiKey } : {}),\n ...(baseUrl ? { baseUrl } : !apiKey ? { baseUrl: OSS_BASE_URL } : {}),\n ...(backend ? { backend } : {}),\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n },\n host: env.HOST ?? \"127.0.0.1\",\n port: parseInteger(env.PORT) ?? 3333,\n };\n}\n\nfunction parseInteger(value: string | undefined): number | undefined {\n if (!value) {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isInteger(parsed) ? parsed : undefined;\n}\n","export const DASHBOARD_STATUS_URL = \"https://openserp.org/dashboard/keys\";\nexport const DOCS_URL = \"https://openserp.org/docs\";\nexport const ISSUES_URL = \"https://github.com/openserpapi/mcp/issues\";\n\nexport const SUPPORT_LINE = `Docs: ${DOCS_URL} | Issues: ${ISSUES_URL}`;\nexport const API_KEY_LINE = `Get an API key: ${DASHBOARD_STATUS_URL}`;\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { OpenSERP } from \"@openserp/sdk\";\nimport type { OpenSERPConfig } from \"@openserp/sdk\";\nimport { SUPPORT_LINE } from \"./messages\";\nimport { createMcpServer } from \"./mcp-server\";\n\nexport function runHttpTransport(\n clientConfig: OpenSERPConfig,\n options: { host: string; port: number },\n): void {\n const sseTransports = new Map<string, SSEServerTransport>();\n\n const httpServer = createServer(async (request, response) => {\n try {\n const url = new URL(request.url ?? \"/\", `http://${request.headers.host ?? \"localhost\"}`);\n\n if (request.method === \"OPTIONS\") {\n sendEmpty(response, 204);\n return;\n }\n\n if (request.method === \"GET\" && url.pathname === \"/health\") {\n sendJson(response, 200, { ok: true });\n return;\n }\n\n if (url.pathname === \"/mcp\") {\n await handleStreamableHttp(clientConfig, request, response);\n return;\n }\n\n if (request.method === \"GET\" && url.pathname === \"/sse\") {\n const transport = new SSEServerTransport(\"/messages\", response);\n sseTransports.set(transport.sessionId, transport);\n transport.onclose = () => {\n sseTransports.delete(transport.sessionId);\n };\n\n await createMcpServer(new OpenSERP(clientConfig)).connect(transport);\n return;\n }\n\n if (request.method === \"POST\" && url.pathname === \"/messages\") {\n const sessionId = url.searchParams.get(\"sessionId\");\n const transport = sessionId ? sseTransports.get(sessionId) : undefined;\n if (!transport) {\n sendJson(response, 404, { error: \"unknown_session\" });\n return;\n }\n await transport.handlePostMessage(request, response);\n return;\n }\n\n sendJson(response, 404, { error: \"not_found\" });\n } catch (err) {\n sendJson(response, 500, { error: errorMessage(err) });\n }\n });\n\n httpServer.listen(options.port, options.host, () => {\n const address = httpServer.address();\n const port = typeof address === \"object\" && address ? address.port : options.port;\n console.error(\n `[openserp-mcp] HTTP transport listening at http://${options.host}:${port}/mcp | ${SUPPORT_LINE}`,\n );\n });\n}\n\nasync function handleStreamableHttp(\n clientConfig: OpenSERPConfig,\n request: IncomingMessage,\n response: ServerResponse,\n): Promise<void> {\n const server = createMcpServer(new OpenSERP(clientConfig));\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n } as any);\n\n try {\n await server.connect(transport as unknown as Transport);\n await transport.handleRequest(request, response);\n } finally {\n response.on(\"close\", () => {\n void transport.close();\n void server.close();\n });\n }\n}\n\nfunction sendJson(response: ServerResponse, status: number, body: unknown): void {\n response.writeHead(status, {\n \"Content-Type\": \"application/json; charset=utf-8\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Headers\": \"content-type, authorization, mcp-session-id\",\n \"Access-Control-Allow-Methods\": \"GET, POST, DELETE, OPTIONS\",\n });\n response.end(JSON.stringify(body));\n}\n\nfunction sendEmpty(response: ServerResponse, status: number): void {\n response.writeHead(status, {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Headers\": \"content-type, authorization, mcp-session-id\",\n \"Access-Control-Allow-Methods\": \"GET, POST, DELETE, OPTIONS\",\n });\n response.end();\n}\n\nfunction errorMessage(err: unknown): string {\n if (err instanceof Error) {\n return err.message;\n }\n return String(err);\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { OpenSERP } from \"@openserp/sdk\";\nimport { z } from \"zod\";\nimport { callTool } from \"./tools\";\n\nconst engines = [\"google\", \"bing\", \"yandex\", \"baidu\", \"duck\", \"duckduckgo\", \"ecosia\"] as const;\nconst formats = [\"json\", \"markdown\", \"text\", \"ndjson\"] as const;\nconst megaModes = [\"balanced\", \"any\", \"fast\"] as const;\nconst extractModes = [\"auto\", \"fast\", \"rendered\"] as const;\n\n// Replaced at build time with the package.json version (see tsup.config.ts).\n// Falls back to \"dev\" when run from source without the define in place.\ndeclare const __OPENSERP_MCP_VERSION__: string;\nconst VERSION =\n typeof __OPENSERP_MCP_VERSION__ === \"string\" ? __OPENSERP_MCP_VERSION__ : \"dev\";\n\n// Fields shared by every search-style tool, web and image alike.\nconst commonSearchSchema = {\n text: z\n .string()\n .optional()\n .describe(\"Search query text. At least one of text, site, or file should be provided.\"),\n lang: z.string().optional().describe(\"Language code, such as EN or de.\"),\n region: z\n .string()\n .optional()\n .describe(\"Market or location hint, such as US, DE, en-GB, Berlin, or a Yandex lr id.\"),\n date: z\n .string()\n .regex(/^[0-9]{8}\\.\\.[0-9]{8}$/)\n .optional()\n .describe(\"Date interval in YYYYMMDD..YYYYMMDD format.\"),\n file: z.string().optional().describe(\"File extension filter, such as PDF.\"),\n site: z.string().optional().describe(\"Domain filter, such as example.com.\"),\n limit: z.number().int().min(1).max(100).optional().describe(\"Maximum result count.\"),\n start: z.number().int().min(0).optional().describe(\"Pagination offset.\"),\n filter: z.boolean().optional().describe(\"Enable duplicate filtering.\"),\n features: z.boolean().optional().describe(\"Include supported rich SERP features.\"),\n format: z.enum(formats).optional().default(\"json\").describe(\"Response format.\"),\n};\n\n// Page-content extraction only applies to web results, so these are kept off\n// the image tools (the image endpoints ignore them).\nconst webExtractSchema = {\n extract: z\n .union([z.boolean(), z.number().int().min(0).max(5)])\n .optional()\n .describe(\n \"Enrich the top web results with cleaned page content. Boolean or integer depth: false/0 off, true/1 top result, N top N (1-5).\",\n ),\n extractMode: z.enum(extractModes).optional().describe(\"Extraction strategy for target pages.\"),\n minRunes: z\n .number()\n .int()\n .min(0)\n .optional()\n .describe(\"Minimum content length (in runes) before auto mode escalates to rendered extraction.\"),\n};\n\nconst webSearchSchema = {\n ...commonSearchSchema,\n ...webExtractSchema,\n};\n\nconst megaEngineSchema = {\n engines: z\n .array(z.enum(engines))\n .optional()\n .describe(\"Engines to query. Omit to use all available engines.\"),\n mode: z.enum(megaModes).optional().default(\"balanced\").describe(\"Mega execution mode.\"),\n dedupe: z.boolean().optional().describe(\"Deduplicate by normalized URL.\"),\n merge: z.boolean().optional().describe(\"Merge successful engine results.\"),\n};\n\nconst megaSearchSchema = {\n ...webSearchSchema,\n ...megaEngineSchema,\n};\n\nconst megaImageSchema = {\n ...commonSearchSchema,\n ...megaEngineSchema,\n};\n\n// fast_search / any_search are mega_search with a fixed mode, so they take the\n// same inputs minus the mode selector.\nconst { mode: _mode, ...fastOrAnySchema } = megaSearchSchema;\n\nexport function createMcpServer(client: OpenSERP): McpServer {\n const server = new McpServer({\n name: \"@openserp/mcp\",\n version: VERSION,\n });\n\n server.registerTool(\n \"search\",\n {\n title: \"Search\",\n description: \"Search web results with a specific OpenSERP engine.\",\n inputSchema: {\n engine: z.enum(engines).describe(\"Search engine endpoint alias.\"),\n ...webSearchSchema,\n },\n },\n (args) => callTool(client, \"search\", args),\n );\n\n server.registerTool(\n \"mega_search\",\n {\n title: \"Mega Search\",\n description: \"Search across multiple engines with balanced, any, or fast execution.\",\n inputSchema: megaSearchSchema,\n },\n (args) => callTool(client, \"mega_search\", args),\n );\n\n server.registerTool(\n \"fast_search\",\n {\n title: \"Fast Search\",\n description: \"Search using the fastest currently healthy engine.\",\n inputSchema: fastOrAnySchema,\n },\n (args) => callTool(client, \"fast_search\", args),\n );\n\n server.registerTool(\n \"any_search\",\n {\n title: \"Any Search\",\n description: \"Try engines in order and return the first successful web result set.\",\n inputSchema: fastOrAnySchema,\n },\n (args) => callTool(client, \"any_search\", args),\n );\n\n server.registerTool(\n \"image_search\",\n {\n title: \"Image Search\",\n description: \"Search image results with a specific OpenSERP engine.\",\n inputSchema: {\n engine: z.enum(engines).describe(\"Search engine endpoint alias.\"),\n ...commonSearchSchema,\n },\n },\n (args) => callTool(client, \"image_search\", args),\n );\n\n server.registerTool(\n \"mega_image\",\n {\n title: \"Mega Image Search\",\n description: \"Search images across multiple engines.\",\n inputSchema: megaImageSchema,\n },\n (args) => callTool(client, \"mega_image\", args),\n );\n\n server.registerTool(\n \"get_usage\",\n {\n title: \"Get Usage\",\n description: \"Return OpenSERP Cloud account and credit information.\",\n inputSchema: {},\n },\n () => callTool(client, \"get_usage\", {}),\n );\n\n server.registerTool(\n \"list_engines\",\n {\n title: \"List Engines\",\n description: \"List available engines on OSS or Cloud engine capabilities on Cloud.\",\n inputSchema: {},\n },\n () => callTool(client, \"list_engines\", {}),\n );\n\n server.registerTool(\n \"extract\",\n {\n title: \"Extract URL\",\n description: \"Extract LLM-ready content from a URL.\",\n inputSchema: {\n url: z.string().url().describe(\"Absolute URL to fetch and extract.\"),\n mode: z.enum(extractModes).optional().default(\"auto\").describe(\"Extraction strategy.\"),\n lang: z.string().optional().describe(\"Language hint.\"),\n minRunes: z\n .number()\n .int()\n .min(0)\n .optional()\n .describe(\"Minimum content length (in runes) before auto mode escalates to rendered extraction.\"),\n clean: z.boolean().optional().describe(\"Use article-only extraction when true.\"),\n useLlmsTxt: z\n .boolean()\n .optional()\n .describe(\"Prefer /llms-full.txt or /llms.txt for site roots.\"),\n format: z.enum(formats).optional().default(\"json\").describe(\"Response format.\"),\n },\n },\n (args) => callTool(client, \"extract\", args),\n );\n\n return server;\n}\n","import { OpenSERP } from \"@openserp/sdk\";\nimport { DASHBOARD_STATUS_URL } from \"./messages\";\n\nexport interface ToolCallResult {\n [key: string]: unknown;\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n}\n\nexport async function callTool(\n client: OpenSERP,\n name: string,\n args: unknown,\n): Promise<ToolCallResult> {\n const input = assertObject(args);\n\n try {\n switch (name) {\n case \"search\":\n requireString(input, \"engine\");\n return toolResult(await client.search(input as any));\n case \"mega_search\":\n return toolResult(await client.megaSearch(input as any));\n case \"fast_search\":\n return toolResult(await client.fastSearch(input as any));\n case \"any_search\":\n return toolResult(await client.anySearch(input as any));\n case \"image_search\":\n requireString(input, \"engine\");\n return toolResult(await client.image(input as any));\n case \"mega_image\":\n return toolResult(await client.megaImage(input as any));\n case \"extract\":\n requireString(input, \"url\");\n return toolResult(await client.extract(input as any));\n case \"get_usage\":\n return toolResult(await getUsage(client));\n case \"list_engines\":\n return toolResult(await listEngines(client));\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n } catch (err) {\n return {\n isError: true,\n content: [{ type: \"text\", text: formatError(err) }],\n };\n }\n}\n\nasync function getUsage(client: OpenSERP): Promise<unknown> {\n if (client.backend !== \"cloud\") {\n throw new Error(\n `get_usage requires OpenSERP Cloud. Set OPENSERP_API_KEY or OPENSERP_BACKEND=cloud. Get an API key: ${DASHBOARD_STATUS_URL}`,\n );\n }\n\n return {\n backend: client.backend,\n baseUrl: client.baseUrl,\n account: await client.me(),\n lastResponse: summarizeLastResponse(client),\n };\n}\n\nasync function listEngines(client: OpenSERP): Promise<unknown> {\n if (client.backend === \"cloud\") {\n return {\n backend: client.backend,\n baseUrl: client.baseUrl,\n capabilities: await client.enginesCapabilities(),\n };\n }\n\n return {\n backend: client.backend,\n baseUrl: client.baseUrl,\n engines: await client.engines(),\n };\n}\n\nfunction assertObject(value: unknown): Record<string, unknown> {\n if (value === undefined || value === null) {\n return {};\n }\n if (typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\"Tool arguments must be an object.\");\n }\n return value as Record<string, unknown>;\n}\n\nfunction requireString(input: Record<string, unknown>, key: string): void {\n if (typeof input[key] !== \"string\" || input[key] === \"\") {\n throw new Error(`Missing required string argument: ${key}`);\n }\n}\n\nfunction toolResult(value: unknown): ToolCallResult {\n return {\n content: [\n {\n type: \"text\",\n text: typeof value === \"string\" ? value : JSON.stringify(value, null, 2),\n },\n ],\n };\n}\n\nfunction formatError(err: unknown): string {\n if (err instanceof Error) {\n return err.message;\n }\n return String(err);\n}\n\nfunction summarizeLastResponse(client: OpenSERP): unknown {\n const last = client.lastResponse;\n if (!last) {\n return undefined;\n }\n\n return {\n status: last.status,\n requestId: last.requestId,\n credits: last.credits,\n engineUsed: last.engineUsed,\n networkBytes: last.networkBytes,\n };\n}\n","import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { SUPPORT_LINE } from \"./messages\";\n\nexport async function runStdioTransport(server: McpServer): Promise<void> {\n await server.connect(new StdioServerTransport());\n console.error(`[openserp-mcp] stdio transport ready | ${SUPPORT_LINE}`);\n}\n"],"mappings":"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","names":["OpenSERP","client","args","client","args","OpenSERP"]}
{
"name": "@openserp/mcp",
"version": "0.1.5",
"version": "0.1.6",
"description": "Model Context Protocol server for OpenSERP OSS and OpenSERP Cloud.",

@@ -11,6 +11,6 @@ "type": "module",

"type": "git",
"url": "git+https://github.com/karust/openserp.git"
"url": "git+https://github.com/openserpapi/mcp.git"
},
"bugs": {
"url": "https://github.com/karust/openserp/issues"
"url": "https://github.com/openserpapi/mcp/issues"
},

@@ -39,6 +39,15 @@ "keywords": [

],
"scripts": {
"build": "tsup",
"clean": "rimraf dist",
"dev:stdio": "tsx src/index.ts --stdio",
"dev:http": "tsx src/index.ts --http --port 3333",
"start:stdio": "node dist/index.js --stdio",
"start:http": "node dist/index.js --http --port 3333",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.29.0",
"zod": "^4.1.13",
"@openserp/sdk": "^0.2.0"
"@openserp/sdk": "^0.2.4",
"zod": "^4.1.13"
},

@@ -57,12 +66,3 @@ "devDependencies": {

"access": "public"
},
"scripts": {
"build": "tsup",
"clean": "rimraf dist",
"dev:stdio": "tsx src/index.ts --stdio",
"dev:http": "tsx src/index.ts --http --port 3333",
"start:stdio": "node dist/index.js --stdio",
"start:http": "node dist/index.js --http --port 3333",
"typecheck": "tsc --noEmit"
}
}
}
# @openserp/mcp
Model Context Protocol server for OpenSERP OSS and OpenSERP Cloud.
[![npm version](https://img.shields.io/npm/v/@openserp/mcp.svg)](https://www.npmjs.com/package/@openserp/mcp)
[![license](https://img.shields.io/npm/l/@openserp/mcp.svg)](https://github.com/openserpapi/mcp/blob/main/LICENSE.md)
Model Context Protocol server for OpenSERP OSS and OpenSERP Cloud. It gives MCP clients search, image search, URL extraction, usage, and engine metadata tools.
When `OPENSERP_API_KEY` is not set, the server uses OSS mode at `http://localhost:7000` and writes:

@@ -10,3 +13,3 @@

[openserp-mcp] Get an API key: https://openserp.org/dashboard/keys
[openserp-mcp] Docs: https://openserp.org/docs | Issues: https://github.com/karust/openserp/issues
[openserp-mcp] Docs: https://openserp.org/docs | Issues: https://github.com/openserpapi/mcp/issues
```

@@ -16,2 +19,14 @@

## Install
```bash
npm install -g @openserp/mcp
```
You can also run it without installing:
```bash
npx -y @openserp/mcp --stdio
```
## Tools

@@ -29,2 +44,11 @@

## Quick Examples
Ask your MCP client to:
- Search Google for current docs and return the top 5 URLs.
- Compare Google and Bing results for an SEO keyword.
- Extract clean Markdown from a URL before passing it to an LLM.
- Check remaining Cloud credits with `get_usage`.
## Claude Desktop

@@ -105,1 +129,7 @@

- `PORT`: HTTP port, default `3333`.
## Resources
- [OpenSERP Cloud docs](https://openserp.org/docs/cloud)
- [MCP server source](https://github.com/openserpapi/mcp)
- [JavaScript SDK](https://github.com/openserpapi/sdk-js)