From 94b5439442b1c244eb52e41194aa8eed6f1ecb06 Mon Sep 17 00:00:00 2001 From: Ryan Albert Date: Mon, 17 Mar 2025 10:49:54 -0600 Subject: [PATCH] feat: update --- .speakeasy/gen.lock | 11 +-- .speakeasy/workflow.lock | 9 +-- gen.yaml | 2 +- jsr.json | 2 +- package-lock.json | 4 +- package.json | 2 +- src/lib/config.ts | 6 +- src/mcp-server/extensions.ts | 4 + src/mcp-server/mcp-server.ts | 2 +- src/mcp-server/prompts.ts | 110 ++++++++++++++++++++++++++++ src/mcp-server/resources.ts | 1 + src/mcp-server/server.extensions.ts | 93 +++++++++++++++++++++++ src/mcp-server/server.ts | 10 ++- src/mcp-server/tools.ts | 1 + 14 files changed, 236 insertions(+), 21 deletions(-) create mode 100644 src/mcp-server/prompts.ts create mode 100644 src/mcp-server/server.extensions.ts diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 5969e8a5..ed840a4c 100755 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -3,10 +3,10 @@ id: f42cb8e6-e2ce-4565-b975-5a9f38b94d5a management: docChecksum: 2e7f129641ad96d49fcda2ceb173d43c docVersion: 1.0.81 - speakeasyVersion: 1.517.3 - generationVersion: 2.548.6 - releaseVersion: 0.22.0 - configChecksum: 0de256135a61cf1f1f4aa7e2b4cc8f93 + speakeasyVersion: 1.519.0 + generationVersion: 2.552.1 + releaseVersion: 0.23.0 + configChecksum: 86d5f752c6378b160f1e0a2fb1b0cea7 repoURL: https://github.com/Unstructured-IO/unstructured-js-client.git repoSubDirectory: . installationURL: https://github.com/Unstructured-IO/unstructured-js-client @@ -24,7 +24,7 @@ features: globalSecurity: 2.82.13 globalSecurityCallbacks: 0.1.0 globalServerURLs: 2.82.4 - mcpServer: 0.7.0 + mcpServer: 0.8.0 nameOverrides: 2.81.2 nullables: 0.1.1 openEnums: 0.1.1 @@ -88,6 +88,7 @@ generatedFiles: - src/mcp-server/console-logger.ts - src/mcp-server/extensions.ts - src/mcp-server/mcp-server.ts + - src/mcp-server/prompts.ts - src/mcp-server/resources.ts - src/mcp-server/scopes.ts - src/mcp-server/server.ts diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 3b0a1bfe..b157ab42 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,21 +1,20 @@ -speakeasyVersion: 1.517.3 +speakeasyVersion: 1.519.0 sources: my-source: sourceNamespace: my-source - sourceRevisionDigest: sha256:7b3ee52d5e5acc9bc97268e7996c203d4bec0181379eb5c95868c982fb820726 + sourceRevisionDigest: sha256:acb76c58ac398f0d1ea1f9eef8df422c40d5a237c7cf020522258b327792a68d sourceBlobDigest: sha256:822e38da0c61b9aeaa5446413a6cec058a464920a02d20d9ee7955c827446050 tags: - latest - - speakeasy-sdk-regen-1742057884 - 1.0.81 targets: unstructed-typescript: source: my-source sourceNamespace: my-source - sourceRevisionDigest: sha256:7b3ee52d5e5acc9bc97268e7996c203d4bec0181379eb5c95868c982fb820726 + sourceRevisionDigest: sha256:acb76c58ac398f0d1ea1f9eef8df422c40d5a237c7cf020522258b327792a68d sourceBlobDigest: sha256:822e38da0c61b9aeaa5446413a6cec058a464920a02d20d9ee7955c827446050 codeSamplesNamespace: my-source-typescript-code-samples - codeSamplesRevisionDigest: sha256:86e8bf47bf21198d030067fd18395449530c67061224d03d612d9f6de944baa4 + codeSamplesRevisionDigest: sha256:bc9b9485931a5f01bce3a872cdba2295e5aa3e155f52890568c3e8b18c9fd66d workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/gen.yaml b/gen.yaml index c27d9689..2e058e5a 100644 --- a/gen.yaml +++ b/gen.yaml @@ -12,7 +12,7 @@ generation: oAuth2ClientCredentialsEnabled: false oAuth2PasswordEnabled: false typescript: - version: 0.22.0 + version: 0.23.0 additionalDependencies: dependencies: async: ^3.2.5 diff --git a/jsr.json b/jsr.json index d4df6206..58f0eb21 100644 --- a/jsr.json +++ b/jsr.json @@ -2,7 +2,7 @@ { "name": "unstructured-client", - "version": "0.22.0", + "version": "0.23.0", "exports": { ".": "./src/index.ts", "./sdk/models/errors": "./src/sdk/models/errors/index.ts", diff --git a/package-lock.json b/package-lock.json index 48b08eed..478bc99b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "unstructured-client", - "version": "0.22.0", + "version": "0.23.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "unstructured-client", - "version": "0.22.0", + "version": "0.23.0", "dependencies": { "async": "^3.2.5", "pdf-lib": "^1.17.1" diff --git a/package.json b/package.json index e9d85c00..a9ab0b50 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "unstructured-client", - "version": "0.22.0", + "version": "0.23.0", "author": "Unstructured", "type": "module", "bin": { diff --git a/src/lib/config.ts b/src/lib/config.ts index 7530551f..1c13f7dd 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -69,8 +69,8 @@ export function serverURLFromOptions(options: SDKOptions): URL | null { export const SDK_METADATA = { language: "typescript", openapiDocVersion: "1.0.81", - sdkVersion: "0.22.0", - genVersion: "2.548.6", + sdkVersion: "0.23.0", + genVersion: "2.552.1", userAgent: - "speakeasy-sdk/typescript 0.22.0 2.548.6 1.0.81 unstructured-client", + "speakeasy-sdk/typescript 0.23.0 2.552.1 1.0.81 unstructured-client", } as const; diff --git a/src/mcp-server/extensions.ts b/src/mcp-server/extensions.ts index 02d6d97d..7aab2809 100644 --- a/src/mcp-server/extensions.ts +++ b/src/mcp-server/extensions.ts @@ -3,6 +3,7 @@ */ import { ZodRawShape } from "zod"; +import { PromptArgsRawShape, PromptDefinition } from "./prompts.js"; import { ResourceDefinition, ResourceTemplateDefinition } from "./resources.js"; import { ToolDefinition } from "./tools.js"; @@ -10,4 +11,7 @@ export type Register = { tool: (def: ToolDefinition) => void; resource: (def: ResourceDefinition) => void; resourceTemplate: (def: ResourceTemplateDefinition) => void; + prompt: ( + prompt: PromptDefinition, + ) => void; }; diff --git a/src/mcp-server/mcp-server.ts b/src/mcp-server/mcp-server.ts index 658a983d..d2236a4f 100644 --- a/src/mcp-server/mcp-server.ts +++ b/src/mcp-server/mcp-server.ts @@ -19,7 +19,7 @@ const routes = buildRouteMap({ export const app = buildApplication(routes, { name: "mcp", versionInfo: { - currentVersion: "0.22.0", + currentVersion: "0.23.0", }, }); diff --git a/src/mcp-server/prompts.ts b/src/mcp-server/prompts.ts new file mode 100644 index 00000000..138cc938 --- /dev/null +++ b/src/mcp-server/prompts.ts @@ -0,0 +1,110 @@ +/* + * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + */ + +import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; +import { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js"; +import { GetPromptResult } from "@modelcontextprotocol/sdk/types.js"; +import { + objectOutputType, + ZodOptional, + ZodType, + ZodTypeAny, + ZodTypeDef, +} from "zod"; +import { UnstructuredClientCore } from "../core.js"; +import { ConsoleLogger } from "./console-logger.js"; +import { MCPScope } from "./scopes.js"; + +// '@modelcontextprotocol/sdk' currently does not export this type +export type PromptArgsRawShape = { + [k: string]: + | ZodType + | ZodOptional>; +}; + +export type PromptDefinition< + Args extends undefined | PromptArgsRawShape = undefined, +> = Args extends PromptArgsRawShape ? { + name: string; + description?: string; + scopes?: MCPScope[]; + args: Args; + prompt: ( + client: UnstructuredClientCore, + args: objectOutputType, + extra: RequestHandlerExtra, + ) => GetPromptResult | Promise; + } + : { + name: string; + description?: string; + scopes?: MCPScope[]; + args?: undefined; + prompt: ( + client: UnstructuredClientCore, + extra: RequestHandlerExtra, + ) => GetPromptResult | Promise; + }; + +// Optional function to assist with formatting prompt results +export async function formatResult(value: string): Promise { + return { + messages: [ + { + role: "user", + content: { + type: "text", + text: value, + }, + }, + ], + }; +} + +export function createRegisterPrompt( + logger: ConsoleLogger, + server: McpServer, + sdk: UnstructuredClientCore, + allowedScopes: Set, +): ( + prompt: PromptDefinition, +) => void { + return ( + prompt: PromptDefinition, + ): void => { + const scopes = prompt.scopes ?? []; + if (!scopes.every((s: MCPScope) => allowedScopes.has(s))) { + return; + } + + if (prompt.args) { + if (prompt.description) { + server.prompt( + prompt.name, + prompt.description, + prompt.args, + async (args, ctx) => prompt.prompt(sdk, args, ctx), + ); + } else { + server.prompt( + prompt.name, + prompt.args, + async (args, ctx) => prompt.prompt(sdk, args, ctx), + ); + } + } else { + if (prompt.description) { + server.prompt( + prompt.name, + prompt.description, + async (ctx) => prompt.prompt(sdk, ctx), + ); + } else { + server.prompt(prompt.name, async (ctx) => prompt.prompt(sdk, ctx)); + } + } + + logger.debug("Registered prompt", { name: prompt.name }); + }; +} diff --git a/src/mcp-server/resources.ts b/src/mcp-server/resources.ts index 87fa4172..35bd5bdf 100644 --- a/src/mcp-server/resources.ts +++ b/src/mcp-server/resources.ts @@ -46,6 +46,7 @@ export type ResourceTemplateDefinition = { read: ReadResourceTemplateCallback; }; +// Optional function to assist with formatting resource results export async function formatResult( value: unknown, uri: URL, diff --git a/src/mcp-server/server.extensions.ts b/src/mcp-server/server.extensions.ts new file mode 100644 index 00000000..575a6140 --- /dev/null +++ b/src/mcp-server/server.extensions.ts @@ -0,0 +1,93 @@ +import { formatResult, ToolDefinition } from "./tools.js"; +import { Register } from "./extensions.js"; +import { generalPartition } from "../funcs/generalPartition.js"; +import fs from 'node:fs/promises'; +import { UnstructuredClientCore } from "../core.js"; +import { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol.js"; +import { z } from "zod"; +import { Strategy, Strategy$inboundSchema, StrategyOpen } from "../sdk/models/shared/partitionparameters.js"; + + +type FileRequest = { + strategy?: StrategyOpen | undefined; + file_content?: string | undefined; + file_path?: string | undefined; + file_name: string; +}; + +const FileRequest$inboundSchema: z.ZodType< +FileRequest, + z.ZodTypeDef, + unknown +> = z.object({ + file_content: z.string().optional(), + file_path: z.string().optional(), + file_name: z.string(), + strategy: Strategy$inboundSchema.default(Strategy.HiRes), +}); + +const customToolArg = { + request: FileRequest$inboundSchema +}; + + + +export const tool$generalPartitionCorrect: ToolDefinition = { + name: "correct_general-partition", + description: `use this tool to pass a file to unstructured. You must BASE64 ENCODE uploaded file content before passing to unstructured. Alternatively, if the user did not upload a file they can provide a full local file path. `, + args: customToolArg, + tool: async (client: UnstructuredClientCore, args, ctx: RequestHandlerExtra) => { + let data: Uint8Array; + if (args.request.file_content) { + try { + data = new Uint8Array(Buffer.from(args.request.file_content, 'base64')); + } catch (e) { + return { + content: [{ + type: "text", + text: `You must BASE64 encode this file content then pass it to the tool.`, + }], + isError: true, + }; + } + } else if (args.request.file_path) { + data = new Uint8Array(await fs.readFile(args.request.file_path)); + } else { + return { + content: [{ + type: "text", + text: `A full file path for file content must be provided`, + }], + isError: true, + }; + } + const [result, apiCall] = await generalPartition( + client, + { + partitionParameters: { + files: { + content: data, + fileName: args.request.file_name, + }, + strategy: args.request.strategy, + } + }, + { fetchOptions: { signal: ctx.signal } }, + ).$inspect(); + + if (!result.ok) { + return { + content: [{ type: "text", text: result.error.message }], + isError: true, + }; + } + + const value = result.value; + + return formatResult(value, apiCall); + }, +}; + +export function registerMCPExtensions(register: Register): void { + register.tool(tool$generalPartitionCorrect); +} \ No newline at end of file diff --git a/src/mcp-server/server.ts b/src/mcp-server/server.ts index f4370d00..00e43119 100644 --- a/src/mcp-server/server.ts +++ b/src/mcp-server/server.ts @@ -6,11 +6,14 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { UnstructuredClientCore } from "../core.js"; import { SDKOptions } from "../lib/config.js"; import type { ConsoleLogger } from "./console-logger.js"; +import { Register } from "./extensions.js"; +import { createRegisterPrompt } from "./prompts.js"; import { createRegisterResource, createRegisterResourceTemplate, } from "./resources.js"; import { MCPScope, mcpScopes } from "./scopes.js"; +import { registerMCPExtensions } from "./server.extensions.js"; import { createRegisterTool } from "./tools.js"; import { tool$generalPartition } from "./tools/generalPartition.js"; @@ -24,7 +27,7 @@ export function createMCPServer(deps: { }) { const server = new McpServer({ name: "UnstructuredClient", - version: "0.22.0", + version: "0.23.0", }); const client = new UnstructuredClientCore({ @@ -50,10 +53,13 @@ export function createMCPServer(deps: { client, scopes, ); - const register = { tool, resource, resourceTemplate }; + const prompt = createRegisterPrompt(deps.logger, server, client, scopes); + const register = { tool, resource, resourceTemplate, prompt }; void register; // suppress unused warnings tool(tool$generalPartition); + registerMCPExtensions(register satisfies Register); + return server; } diff --git a/src/mcp-server/tools.ts b/src/mcp-server/tools.ts index 563c683b..31ed6b86 100644 --- a/src/mcp-server/tools.ts +++ b/src/mcp-server/tools.ts @@ -34,6 +34,7 @@ export type ToolDefinition = ) => CallToolResult | Promise; }; +// Optional function to assist with formatting tool results export async function formatResult( value: unknown, init: { response?: Response | undefined },