{"version":3,"sources":["../../src/util/prompts.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport type { Prompt } from '@modelcontextprotocol/sdk/types.js';\nimport {\n  GenkitError,\n  z,\n  type ExecutablePrompt,\n  type GenerateOptions,\n  type GenerateResponse,\n  type GenerateStreamResponse,\n  type Genkit,\n  type JSONSchema,\n  type PromptGenerateOptions,\n  type ToolAction,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { fromMcpPromptMessage } from './message.mjs';\n\nfunction toSchema(args: Prompt['arguments']) {\n  if (!args) return {};\n  const schema: JSONSchema = { type: 'object', properties: {}, required: [] };\n  for (const arg of args) {\n    schema.properties[arg.name] = {\n      type: 'string',\n      description: arg.description,\n    };\n    if (arg.required) schema.required.push(arg.name);\n  }\n  return schema;\n}\n\n/**\n * Registers a single MCP prompt as a Genkit prompt.\n * It defines a new Genkit prompt action that, when called, will\n * interact with the MCP client to fetch and render the corresponding MCP prompt.\n *\n * @param ai The Genkit instance to define the prompt on.\n * @param client The MCP client instance used to interact with the MCP server.\n * @param prompt The MCP Prompt object to register.\n * @param params Contains the Genkit client name and the MCP server name for namespacing and logging.\n */\nfunction registerPrompt(\n  ai: Genkit,\n  client: Client,\n  prompt: Prompt,\n  params: { name: string; serverName: string }\n) {\n  logger.debug(`[MCP] Registering MCP prompt ${params.name}/${prompt.name}`);\n  ai.definePrompt({\n    name: prompt.name,\n    description: prompt.description || '',\n    input: { jsonSchema: toSchema(prompt.arguments) },\n    output: { format: 'text' },\n    metadata: { mcp: { _meta: prompt._meta || {} } },\n    messages: async (args, { context }) => {\n      logger.debug(\n        `[MCP] Calling MCP prompt ${params.name}/${prompt.name} with arguments`,\n        JSON.stringify(args)\n      );\n      const result = await client.getPrompt({\n        name: prompt.name,\n        arguments: args,\n        _meta: context?.mcp?._meta,\n      });\n      return result.messages.map(fromMcpPromptMessage);\n    },\n  });\n}\n\nfunction createExecutablePrompt<\n  I extends z.ZodTypeAny = z.ZodTypeAny,\n  O extends z.ZodTypeAny = z.ZodTypeAny,\n  CustomOptions extends z.ZodTypeAny = z.ZodTypeAny,\n>(\n  client: Client,\n  prompt: Prompt,\n  params: {\n    ai: Genkit;\n    name: string;\n    serverName: string;\n    promptName: string;\n    options?: PromptGenerateOptions<any, any>;\n  }\n): ExecutablePrompt<z.infer<I>, O, CustomOptions> {\n  const callPrompt = (async (\n    input?: z.infer<I>,\n    opts?: PromptGenerateOptions<O, CustomOptions>\n  ): Promise<GenerateResponse<z.infer<O>>> => {\n    logger.debug(`[MCP] Calling MCP prompt ${params.name}/${prompt.name}`);\n    return params.ai.generate(callPrompt.render(input, opts));\n  }) as ExecutablePrompt<z.infer<I>, O, CustomOptions>;\n\n  callPrompt.ref = {\n    name: prompt.name,\n    metadata: {\n      description: prompt.description,\n      arguments: prompt.arguments,\n      mcp: { _meta: prompt._meta || {} },\n    },\n  };\n\n  callPrompt.stream = (\n    input?: z.infer<I>,\n    opts?: PromptGenerateOptions<O, CustomOptions>\n  ): GenerateStreamResponse<z.infer<O>> => {\n    logger.debug(`[MCP] Streaming MCP prompt ${params.name}/${prompt.name}`);\n    return params.ai.generateStream(callPrompt.render(input, opts));\n  };\n\n  callPrompt.render = async (\n    input?: I,\n    opts?: PromptGenerateOptions<O, CustomOptions>\n  ): Promise<GenerateOptions<O, CustomOptions>> => {\n    logger.debug(`[MCP] Rendering MCP prompt ${params.name}/${prompt.name}`);\n    const result = await client.getPrompt({\n      name: prompt.name,\n      arguments: input as any,\n      _meta: opts?.context?.mcp?._meta,\n    });\n    const messages = result.messages.map(fromMcpPromptMessage);\n    return {\n      ...params.options,\n      ...opts,\n      messages,\n    };\n  };\n\n  callPrompt.asTool = async (): Promise<ToolAction> => {\n    throw new GenkitError({\n      status: 'UNIMPLEMENTED',\n      message: `[MCP] prompt.asTool not supported with MCP`,\n    });\n  };\n\n  return callPrompt;\n}\n\n/**\n * Lookup all prompts available in the server and register each as a Genkit\n * prompt.\n */\nexport async function registerAllPrompts(\n  ai: Genkit,\n  client: Client,\n  params: { name: string; serverName: string }\n): Promise<void> {\n  let cursor: string | undefined;\n  while (true) {\n    const { nextCursor, prompts } = await client.listPrompts({ cursor });\n    prompts.forEach((p) => registerPrompt(ai, client, p, params));\n    cursor = nextCursor;\n    if (!cursor) break;\n  }\n}\n\n/**\n * Lookup a specified prompt from the server and return as an ExecutablePrompt.\n */\nexport async function getExecutablePrompt(\n  client: Client,\n  params: {\n    name: string;\n    serverName: string;\n    promptName: string;\n    ai: Genkit;\n    options?: PromptGenerateOptions;\n  }\n): Promise<ExecutablePrompt | undefined> {\n  let cursor: string | undefined;\n\n  while (true) {\n    const { nextCursor, prompts } = await client.listPrompts({ cursor });\n    const maybePrompt = prompts.find(\n      (p: Prompt) => p.name === params.promptName\n    );\n    if (maybePrompt) {\n      return createExecutablePrompt(client, maybePrompt, params);\n    }\n    cursor = nextCursor;\n    if (!cursor) break;\n  }\n  return undefined;\n}\n\nexport async function fetchAllPrompts(\n  client: Client,\n  params: {\n    name: string;\n    serverName: string;\n    ai: Genkit;\n    options?: PromptGenerateOptions;\n  }\n): Promise<ExecutablePrompt[]> {\n  let cursor: string | undefined;\n  const out: ExecutablePrompt[] = [];\n\n  while (true) {\n    const { nextCursor, prompts } = await client.listPrompts({ cursor });\n    for (const p of prompts) {\n      out.push(\n        createExecutablePrompt(client, p, { ...params, promptName: p.name })\n      );\n    }\n    cursor = nextCursor;\n    if (!cursor) break;\n  }\n  return out;\n}\n"],"mappings":"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","names":[]}