UNPKG

@tanstack/ai-mcp

Version:

Host-side Model Context Protocol client for TanStack AI: discover and run MCP server tools, resources, and prompts in any adapter's chat() loop, with generated end-to-end types.

86 lines (85 loc) • 2.64 kB
//#region src/server/definitions.ts /** * Builds a resource definition for the MCP server. * * `config` takes `name`, `mimeType`, and one of `uri` or `uriTemplate`. * If `uri` and `uriTemplate` are both missing, this function throws a TypeError. * Only a template can take `list(ctx)`. It returns the concrete resources * for `resources/list`. * Call `.read` with a function that returns the resource contents. * It gets the requested `uri`, the template `variables`, and `ctx`. * `ctx.context` holds the values from `handle(request, { context })` and * the verified `authInfo`. A tool gets the same values on its `ctx.context`. * * @param config - The resource `name`, `mimeType`, `uri` or `uriTemplate`, and `list`. * @throws {TypeError} When `uri` and `uriTemplate` are both missing. * * @example * ```ts * const readme = resourceDefinition({ * uri: 'file:///readme.md', * name: 'readme', * mimeType: 'text/markdown', * }).read(async () => ({ text: '# Hello' })) * * const summary = resourceDefinition({ * uriTemplate: 'myapp://items/{itemId}/summary', * name: 'item-summary', * mimeType: 'text/plain', * }).read(async (_uri, { itemId }) => ({ text: `Summary of ${String(itemId)}` })) * ``` */ function resourceDefinition(config) { const hasUri = config.uri !== void 0; const hasUriTemplate = config.uriTemplate !== void 0; if (!hasUri && !hasUriTemplate) throw new TypeError("This resource has no uri and no uriTemplate. Pass a uri or a uriTemplate."); return { ...config, read(readContents) { return { ...config, read: readContents }; } }; } /** * Builds a prompt definition for the MCP server. * * `config` takes `name`, `description`, and `argsSchema`. * `argsSchema.parse` runs before the render function receives the arguments. * Call `.render` with a function that returns an array of messages. * Each message has `role` and `content`. * * @param config - The prompt `name`, `description`, and `argsSchema`. * * @example * ```ts * const summarize = promptDefinition({ * name: 'summarize', * description: 'Summarize a topic', * argsSchema: z.object({ topic: z.string() }), * }).render(async (args) => [{ role: 'user', content: args.topic }]) * ``` */ function promptDefinition(config) { const definition = { name: config.name, description: config.description, argsSchema: config.argsSchema }; return { ...definition, render(renderPrompt) { return { ...definition, async render(input) { return renderPrompt(config.argsSchema.parse(input)); } }; } }; } //#endregion export { promptDefinition, resourceDefinition }; //# sourceMappingURL=definitions.js.map