@openserp/mcp
Advanced tools
+2
-2
@@ -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":";;;AACA,SAAS,YAAAA,iBAAgB;;;ACDzB;AAAA,EACE;AAAA,OAGK;;;ACJA,IAAM,uBAAuB;AAC7B,IAAM,WAAW;AACjB,IAAM,aAAa;AAEnB,IAAM,eAAe,SAAS,QAAQ,cAAc,UAAU;AAC9D,IAAM,eAAe,mBAAmB,oBAAoB;;;ADEnE,IAAI,gBAAgB;AAQb,SAAS,WAAW,MAAyB,QAAQ,KAAmB;AAC7E,QAAM,SAAS,IAAI;AACnB,QAAM,UAAU,IAAI;AACpB,QAAM,UAAU,IAAI;AACpB,QAAM,YAAY,aAAa,IAAI,mBAAmB;AAEtD,MAAI,CAAC,UAAU,CAAC,WAAW,CAAC,eAAe;AACzC,YAAQ;AAAA,MACN;AAAA,IACF;AACA,YAAQ,MAAM,kBAAkB,YAAY,EAAE;AAC9C,YAAQ,MAAM,kBAAkB,YAAY,EAAE;AAC9C,oBAAgB;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,MACN,SAAS,EAAE,qBAAqB,MAAM;AAAA,MACtC,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,SAAS,EAAE,SAAS,aAAa,IAAI,CAAC;AAAA,MACnE,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACjD;AAAA,IACA,MAAM,IAAI,QAAQ;AAAA,IAClB,MAAM,aAAa,IAAI,IAAI,KAAK;AAAA,EAClC;AACF;AAEA,SAAS,aAAa,OAA+C;AACnE,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,UAAU,MAAM,IAAI,SAAS;AAC7C;;;AEjDA,SAAS,oBAA+D;AACxE,SAAS,0BAA0B;AACnC,SAAS,qCAAqC;AAE9C,SAAS,gBAAgB;;;ACJzB,SAAS,iBAAiB;AAE1B,SAAS,SAAS;;;ACOlB,eAAsB,SACpBC,SACA,MACAC,OACyB;AACzB,QAAM,QAAQ,aAAaA,KAAI;AAE/B,MAAI;AACF,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,sBAAc,OAAO,QAAQ;AAC7B,eAAO,WAAW,MAAMD,QAAO,OAAO,KAAY,CAAC;AAAA,MACrD,KAAK;AACH,eAAO,WAAW,MAAMA,QAAO,WAAW,KAAY,CAAC;AAAA,MACzD,KAAK;AACH,eAAO,WAAW,MAAMA,QAAO,WAAW,KAAY,CAAC;AAAA,MACzD,KAAK;AACH,eAAO,WAAW,MAAMA,QAAO,UAAU,KAAY,CAAC;AAAA,MACxD,KAAK;AACH,sBAAc,OAAO,QAAQ;AAC7B,eAAO,WAAW,MAAMA,QAAO,MAAM,KAAY,CAAC;AAAA,MACpD,KAAK;AACH,eAAO,WAAW,MAAMA,QAAO,UAAU,KAAY,CAAC;AAAA,MACxD,KAAK;AACH,sBAAc,OAAO,KAAK;AAC1B,eAAO,WAAW,MAAMA,QAAO,QAAQ,KAAY,CAAC;AAAA,MACtD,KAAK;AACH,eAAO,WAAW,MAAM,SAASA,OAAM,CAAC;AAAA,MAC1C,KAAK;AACH,eAAO,WAAW,MAAM,YAAYA,OAAM,CAAC;AAAA,MAC7C;AACE,cAAM,IAAI,MAAM,iBAAiB,IAAI,EAAE;AAAA,IAC3C;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,YAAY,GAAG,EAAE,CAAC;AAAA,IACpD;AAAA,EACF;AACF;AAEA,eAAe,SAASA,SAAoC;AAC1D,MAAIA,QAAO,YAAY,SAAS;AAC9B,UAAM,IAAI;AAAA,MACR,sGAAsG,oBAAoB;AAAA,IAC5H;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAASA,QAAO;AAAA,IAChB,SAASA,QAAO;AAAA,IAChB,SAAS,MAAMA,QAAO,GAAG;AAAA,IACzB,cAAc,sBAAsBA,OAAM;AAAA,EAC5C;AACF;AAEA,eAAe,YAAYA,SAAoC;AAC7D,MAAIA,QAAO,YAAY,SAAS;AAC9B,WAAO;AAAA,MACL,SAASA,QAAO;AAAA,MAChB,SAASA,QAAO;AAAA,MAChB,cAAc,MAAMA,QAAO,oBAAoB;AAAA,IACjD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAASA,QAAO;AAAA,IAChB,SAASA,QAAO;AAAA,IAChB,SAAS,MAAMA,QAAO,QAAQ;AAAA,EAChC;AACF;AAEA,SAAS,aAAa,OAAyC;AAC7D,MAAI,UAAU,UAAa,UAAU,MAAM;AACzC,WAAO,CAAC;AAAA,EACV;AACA,MAAI,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACrD,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AACA,SAAO;AACT;AAEA,SAAS,cAAc,OAAgC,KAAmB;AACxE,MAAI,OAAO,MAAM,GAAG,MAAM,YAAY,MAAM,GAAG,MAAM,IAAI;AACvD,UAAM,IAAI,MAAM,qCAAqC,GAAG,EAAE;AAAA,EAC5D;AACF;AAEA,SAAS,WAAW,OAAgC;AAClD,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,OAAO,MAAM,CAAC;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,YAAY,KAAsB;AACzC,MAAI,eAAe,OAAO;AACxB,WAAO,IAAI;AAAA,EACb;AACA,SAAO,OAAO,GAAG;AACnB;AAEA,SAAS,sBAAsBA,SAA2B;AACxD,QAAM,OAAOA,QAAO;AACpB,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,WAAW,KAAK;AAAA,IAChB,SAAS,KAAK;AAAA,IACd,YAAY,KAAK;AAAA,IACjB,cAAc,KAAK;AAAA,EACrB;AACF;;;AD3HA,IAAM,UAAU,CAAC,UAAU,QAAQ,UAAU,SAAS,QAAQ,cAAc,QAAQ;AACpF,IAAM,UAAU,CAAC,QAAQ,YAAY,QAAQ,QAAQ;AACrD,IAAM,YAAY,CAAC,YAAY,OAAO,MAAM;AAC5C,IAAM,eAAe,CAAC,QAAQ,QAAQ,UAAU;AAKhD,IAAM,UACJ,OAA+C,UAA2B;AAG5E,IAAM,qBAAqB;AAAA,EACzB,MAAM,EACH,OAAO,EACP,SAAS,EACT,SAAS,4EAA4E;AAAA,EACxF,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kCAAkC;AAAA,EACvE,QAAQ,EACL,OAAO,EACP,SAAS,EACT,SAAS,4EAA4E;AAAA,EACxF,MAAM,EACH,OAAO,EACP,MAAM,wBAAwB,EAC9B,SAAS,EACT,SAAS,6CAA6C;AAAA,EACzD,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qCAAqC;AAAA,EAC1E,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qCAAqC;AAAA,EAC1E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,uBAAuB;AAAA,EACnF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,oBAAoB;AAAA,EACvE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,6BAA6B;AAAA,EACrE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,uCAAuC;AAAA,EACjF,QAAQ,EAAE,KAAK,OAAO,EAAE,SAAS,EAAE,QAAQ,MAAM,EAAE,SAAS,kBAAkB;AAChF;AAIA,IAAM,mBAAmB;AAAA,EACvB,SAAS,EACN,MAAM,CAAC,EAAE,QAAQ,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EACnD,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,aAAa,EAAE,KAAK,YAAY,EAAE,SAAS,EAAE,SAAS,uCAAuC;AAAA,EAC7F,UAAU,EACP,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,SAAS,EACT,SAAS,sFAAsF;AACpG;AAEA,IAAM,kBAAkB;AAAA,EACtB,GAAG;AAAA,EACH,GAAG;AACL;AAEA,IAAM,mBAAmB;AAAA,EACvB,SAAS,EACN,MAAM,EAAE,KAAK,OAAO,CAAC,EACrB,SAAS,EACT,SAAS,sDAAsD;AAAA,EAClE,MAAM,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,QAAQ,UAAU,EAAE,SAAS,sBAAsB;AAAA,EACtF,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,gCAAgC;AAAA,EACxE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,kCAAkC;AAC3E;AAEA,IAAM,mBAAmB;AAAA,EACvB,GAAG;AAAA,EACH,GAAG;AACL;AAEA,IAAM,kBAAkB;AAAA,EACtB,GAAG;AAAA,EACH,GAAG;AACL;AAIA,IAAM,EAAE,MAAM,OAAO,GAAG,gBAAgB,IAAI;AAErC,SAAS,gBAAgBE,SAA6B;AAC3D,QAAM,SAAS,IAAI,UAAU;AAAA,IAC3B,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,QAAQ,EAAE,KAAK,OAAO,EAAE,SAAS,+BAA+B;AAAA,QAChE,GAAG;AAAA,MACL;AAAA,IACF;AAAA,IACA,CAACC,UAAS,SAASD,SAAQ,UAAUC,KAAI;AAAA,EAC3C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,CAACA,UAAS,SAASD,SAAQ,eAAeC,KAAI;AAAA,EAChD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,CAACA,UAAS,SAASD,SAAQ,eAAeC,KAAI;AAAA,EAChD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,CAACA,UAAS,SAASD,SAAQ,cAAcC,KAAI;AAAA,EAC/C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,QAAQ,EAAE,KAAK,OAAO,EAAE,SAAS,+BAA+B;AAAA,QAChE,GAAG;AAAA,MACL;AAAA,IACF;AAAA,IACA,CAACA,UAAS,SAASD,SAAQ,gBAAgBC,KAAI;AAAA,EACjD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA,CAACA,UAAS,SAASD,SAAQ,cAAcC,KAAI;AAAA,EAC/C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,CAAC;AAAA,IAChB;AAAA,IACA,MAAM,SAASD,SAAQ,aAAa,CAAC,CAAC;AAAA,EACxC;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa,CAAC;AAAA,IAChB;AAAA,IACA,MAAM,SAASA,SAAQ,gBAAgB,CAAC,CAAC;AAAA,EAC3C;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAa;AAAA,QACX,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,oCAAoC;AAAA,QACnE,MAAM,EAAE,KAAK,YAAY,EAAE,SAAS,EAAE,QAAQ,MAAM,EAAE,SAAS,sBAAsB;AAAA,QACrF,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gBAAgB;AAAA,QACrD,UAAU,EACP,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,SAAS,EACT,SAAS,sFAAsF;AAAA,QAClG,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,wCAAwC;AAAA,QAC/E,YAAY,EACT,QAAQ,EACR,SAAS,EACT,SAAS,oDAAoD;AAAA,QAChE,QAAQ,EAAE,KAAK,OAAO,EAAE,SAAS,EAAE,QAAQ,MAAM,EAAE,SAAS,kBAAkB;AAAA,MAChF;AAAA,IACF;AAAA,IACA,CAACC,UAAS,SAASD,SAAQ,WAAWC,KAAI;AAAA,EAC5C;AAEA,SAAO;AACT;;;ADtMO,SAAS,iBACd,cACA,SACM;AACN,QAAM,gBAAgB,oBAAI,IAAgC;AAE1D,QAAM,aAAa,aAAa,OAAO,SAAS,aAAa;AAC3D,QAAI;AACF,YAAM,MAAM,IAAI,IAAI,QAAQ,OAAO,KAAK,UAAU,QAAQ,QAAQ,QAAQ,WAAW,EAAE;AAEvF,UAAI,QAAQ,WAAW,WAAW;AAChC,kBAAU,UAAU,GAAG;AACvB;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW,SAAS,IAAI,aAAa,WAAW;AAC1D,iBAAS,UAAU,KAAK,EAAE,IAAI,KAAK,CAAC;AACpC;AAAA,MACF;AAEA,UAAI,IAAI,aAAa,QAAQ;AAC3B,cAAM,qBAAqB,cAAc,SAAS,QAAQ;AAC1D;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW,SAAS,IAAI,aAAa,QAAQ;AACvD,cAAM,YAAY,IAAI,mBAAmB,aAAa,QAAQ;AAC9D,sBAAc,IAAI,UAAU,WAAW,SAAS;AAChD,kBAAU,UAAU,MAAM;AACxB,wBAAc,OAAO,UAAU,SAAS;AAAA,QAC1C;AAEA,cAAM,gBAAgB,IAAI,SAAS,YAAY,CAAC,EAAE,QAAQ,SAAS;AACnE;AAAA,MACF;AAEA,UAAI,QAAQ,WAAW,UAAU,IAAI,aAAa,aAAa;AAC7D,cAAM,YAAY,IAAI,aAAa,IAAI,WAAW;AAClD,cAAM,YAAY,YAAY,cAAc,IAAI,SAAS,IAAI;AAC7D,YAAI,CAAC,WAAW;AACd,mBAAS,UAAU,KAAK,EAAE,OAAO,kBAAkB,CAAC;AACpD;AAAA,QACF;AACA,cAAM,UAAU,kBAAkB,SAAS,QAAQ;AACnD;AAAA,MACF;AAEA,eAAS,UAAU,KAAK,EAAE,OAAO,YAAY,CAAC;AAAA,IAChD,SAAS,KAAK;AACZ,eAAS,UAAU,KAAK,EAAE,OAAO,aAAa,GAAG,EAAE,CAAC;AAAA,IACtD;AAAA,EACF,CAAC;AAED,aAAW,OAAO,QAAQ,MAAM,QAAQ,MAAM,MAAM;AAClD,UAAM,UAAU,WAAW,QAAQ;AACnC,UAAM,OAAO,OAAO,YAAY,YAAY,UAAU,QAAQ,OAAO,QAAQ;AAC7E,YAAQ;AAAA,MACN,qDAAqD,QAAQ,IAAI,IAAI,IAAI,UAAU,YAAY;AAAA,IACjG;AAAA,EACF,CAAC;AACH;AAEA,eAAe,qBACb,cACA,SACA,UACe;AACf,QAAM,SAAS,gBAAgB,IAAI,SAAS,YAAY,CAAC;AACzD,QAAM,YAAY,IAAI,8BAA8B;AAAA,IAClD,oBAAoB;AAAA,EACtB,CAAQ;AAER,MAAI;AACF,UAAM,OAAO,QAAQ,SAAiC;AACtD,UAAM,UAAU,cAAc,SAAS,QAAQ;AAAA,EACjD,UAAE;AACA,aAAS,GAAG,SAAS,MAAM;AACzB,WAAK,UAAU,MAAM;AACrB,WAAK,OAAO,MAAM;AAAA,IACpB,CAAC;AAAA,EACH;AACF;AAEA,SAAS,SAAS,UAA0B,QAAgB,MAAqB;AAC/E,WAAS,UAAU,QAAQ;AAAA,IACzB,gBAAgB;AAAA,IAChB,+BAA+B;AAAA,IAC/B,gCAAgC;AAAA,IAChC,gCAAgC;AAAA,EAClC,CAAC;AACD,WAAS,IAAI,KAAK,UAAU,IAAI,CAAC;AACnC;AAEA,SAAS,UAAU,UAA0B,QAAsB;AACjE,WAAS,UAAU,QAAQ;AAAA,IACzB,+BAA+B;AAAA,IAC/B,gCAAgC;AAAA,IAChC,gCAAgC;AAAA,EAClC,CAAC;AACD,WAAS,IAAI;AACf;AAEA,SAAS,aAAa,KAAsB;AAC1C,MAAI,eAAe,OAAO;AACxB,WAAO,IAAI;AAAA,EACb;AACA,SAAO,OAAO,GAAG;AACnB;;;AGpHA,SAAS,4BAA4B;AAIrC,eAAsB,kBAAkB,QAAkC;AACxE,QAAM,OAAO,QAAQ,IAAI,qBAAqB,CAAC;AAC/C,UAAQ,MAAM,0CAA0C,YAAY,EAAE;AACxE;;;ANCA,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAEjC,IAAI,QAAQ,QAAQ,KAAK,QAAQ,IAAI,GAAG;AACtC,YAAU;AACV,UAAQ,KAAK,CAAC;AAChB;AAEA,IAAM,SAAS,WAAW;AAC1B,IAAM,SAAS,IAAIC,UAAS,OAAO,MAAM;AAEzC,IAAI,QAAQ,QAAQ,GAAG;AACrB,mBAAiB,OAAO,QAAQ;AAAA,IAC9B,MAAM,SAAS,QAAQ,KAAK,OAAO;AAAA,IACnC,MAAM,UAAU,SAAS,QAAQ,CAAC,KAAK,OAAO;AAAA,EAChD,CAAC;AACH,OAAO;AACL,QAAM,SAAS,gBAAgB,MAAM;AACrC,QAAM,kBAAkB,MAAM;AAChC;AAEA,SAAS,QAAQ,MAAuB;AACtC,SAAO,KAAK,SAAS,IAAI;AAC3B;AAEA,SAAS,SAAS,MAAkC;AAClD,QAAM,QAAQ,KAAK,QAAQ,IAAI;AAC/B,MAAI,QAAQ,GAAG;AACb,WAAO;AAAA,EACT;AACA,SAAO,KAAK,QAAQ,CAAC;AACvB;AAEA,SAAS,UAAU,OAA+C;AAChE,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,UAAU,MAAM,IAAI,SAAS;AAC7C;AAEA,SAAS,YAAkB;AACzB,UAAQ,OAAO,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6DAOsC,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAQvD,QAAQ;AAAA,0BACR,UAAU;AAAA,CACnC;AACD;","names":["OpenSERP","client","args","client","args","OpenSERP"]} |
+15
-15
| { | ||
| "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" | ||
| } | ||
| } | ||
| } |
+32
-2
| # @openserp/mcp | ||
| Model Context Protocol server for OpenSERP OSS and OpenSERP Cloud. | ||
| [](https://www.npmjs.com/package/@openserp/mcp) | ||
| [](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) |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
50097
1.02%132
29.41%Updated