@ai-sdk/mcp 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,7 +1,10 @@
1
1
  // src/tool/mcp-client.ts
2
2
  import {
3
+ asSchema,
3
4
  dynamicTool,
4
5
  jsonSchema,
6
+ safeParseJSON,
7
+ safeValidateTypes,
5
8
  tool
6
9
  } from "@ai-sdk/provider-utils";
7
10
 
@@ -103,6 +106,10 @@ var ToolSchema = z.object({
103
106
  type: z.literal("object"),
104
107
  properties: z.optional(z.object({}).loose())
105
108
  }).loose(),
109
+ /**
110
+ * @see https://modelcontextprotocol.io/specification/2025-06-18/server/tools#output-schema
111
+ */
112
+ outputSchema: z.optional(z.object({}).loose()),
106
113
  annotations: z.optional(
107
114
  z.object({
108
115
  title: z.optional(z.string())
@@ -165,6 +172,10 @@ var CallToolResultSchema = ResultSchema.extend({
165
172
  content: z.array(
166
173
  z.union([TextContentSchema, ImageContentSchema, EmbeddedResourceSchema])
167
174
  ),
175
+ /**
176
+ * @see https://modelcontextprotocol.io/specification/2025-06-18/server/tools#structured-content
177
+ */
178
+ structuredContent: z.optional(z.unknown()),
168
179
  isError: z.boolean().default(false).optional()
169
180
  }).or(
170
181
  ResultSchema.extend({
@@ -1833,7 +1844,7 @@ var DefaultMCPClient = class {
1833
1844
  async tools({
1834
1845
  schemas = "automatic"
1835
1846
  } = {}) {
1836
- var _a3;
1847
+ var _a3, _b3;
1837
1848
  const tools = {};
1838
1849
  try {
1839
1850
  const listToolsResult = await this.listTools();
@@ -1849,17 +1860,22 @@ var DefaultMCPClient = class {
1849
1860
  continue;
1850
1861
  }
1851
1862
  const self = this;
1863
+ const outputSchema = schemas !== "automatic" ? (_a3 = schemas[name3]) == null ? void 0 : _a3.outputSchema : void 0;
1852
1864
  const execute = async (args, options) => {
1853
1865
  var _a4;
1854
1866
  (_a4 = options == null ? void 0 : options.abortSignal) == null ? void 0 : _a4.throwIfAborted();
1855
- return self.callTool({ name: name3, args, options });
1867
+ const result = await self.callTool({ name: name3, args, options });
1868
+ if (outputSchema != null) {
1869
+ return self.extractStructuredContent(result, outputSchema, name3);
1870
+ }
1871
+ return result;
1856
1872
  };
1857
1873
  const toolWithExecute = schemas === "automatic" ? dynamicTool({
1858
1874
  description,
1859
1875
  title,
1860
1876
  inputSchema: jsonSchema({
1861
1877
  ...inputSchema,
1862
- properties: (_a3 = inputSchema.properties) != null ? _a3 : {},
1878
+ properties: (_b3 = inputSchema.properties) != null ? _b3 : {},
1863
1879
  additionalProperties: false
1864
1880
  }),
1865
1881
  execute
@@ -1867,6 +1883,7 @@ var DefaultMCPClient = class {
1867
1883
  description,
1868
1884
  title,
1869
1885
  inputSchema: schemas[name3].inputSchema,
1886
+ ...outputSchema != null ? { outputSchema } : {},
1870
1887
  execute
1871
1888
  });
1872
1889
  tools[name3] = { ...toolWithExecute, _meta };
@@ -1876,6 +1893,43 @@ var DefaultMCPClient = class {
1876
1893
  throw error;
1877
1894
  }
1878
1895
  }
1896
+ /**
1897
+ * Extracts and validates structuredContent from a tool result.
1898
+ */
1899
+ async extractStructuredContent(result, outputSchema, toolName) {
1900
+ if ("structuredContent" in result && result.structuredContent != null) {
1901
+ const validationResult = await safeValidateTypes({
1902
+ value: result.structuredContent,
1903
+ schema: asSchema(outputSchema)
1904
+ });
1905
+ if (!validationResult.success) {
1906
+ throw new MCPClientError({
1907
+ message: `Tool "${toolName}" returned structuredContent that does not match the expected outputSchema`,
1908
+ cause: validationResult.error
1909
+ });
1910
+ }
1911
+ return validationResult.value;
1912
+ }
1913
+ if ("content" in result && Array.isArray(result.content)) {
1914
+ const textContent = result.content.find((c) => c.type === "text");
1915
+ if (textContent && "text" in textContent) {
1916
+ const parseResult = await safeParseJSON({
1917
+ text: textContent.text,
1918
+ schema: outputSchema
1919
+ });
1920
+ if (!parseResult.success) {
1921
+ throw new MCPClientError({
1922
+ message: `Tool "${toolName}" returned content that does not match the expected outputSchema`,
1923
+ cause: parseResult.error
1924
+ });
1925
+ }
1926
+ return parseResult.value;
1927
+ }
1928
+ }
1929
+ throw new MCPClientError({
1930
+ message: `Tool "${toolName}" did not return structuredContent or parseable text content`
1931
+ });
1932
+ }
1879
1933
  listResources({
1880
1934
  params,
1881
1935
  options