create-mcp-use-app 2.0.0-beta.1 → 2.0.0-beta.3

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.
Files changed (55) hide show
  1. package/README.md +3 -3
  2. package/dist/index.js +38 -66
  3. package/dist/templates/blank/package.json +14 -7
  4. package/dist/templates/blank/tsconfig.json +13 -10
  5. package/dist/templates/mcp-apps/index.ts +119 -15
  6. package/dist/templates/mcp-apps/{tools.d.ts → mcp-env.d.ts} +3 -1
  7. package/dist/templates/mcp-apps/package.json +16 -14
  8. package/dist/templates/mcp-apps/public/fruits/apple.webp +0 -0
  9. package/dist/templates/mcp-apps/public/fruits/apricot.webp +0 -0
  10. package/dist/templates/mcp-apps/public/fruits/avocado.webp +0 -0
  11. package/dist/templates/mcp-apps/public/fruits/banana.webp +0 -0
  12. package/dist/templates/mcp-apps/public/fruits/blueberry.webp +0 -0
  13. package/dist/templates/mcp-apps/public/fruits/cherries.webp +0 -0
  14. package/dist/templates/mcp-apps/public/fruits/coconut.webp +0 -0
  15. package/dist/templates/mcp-apps/public/fruits/grapes.webp +0 -0
  16. package/dist/templates/mcp-apps/public/fruits/lemon.webp +0 -0
  17. package/dist/templates/mcp-apps/public/fruits/mango.webp +0 -0
  18. package/dist/templates/mcp-apps/public/fruits/orange.webp +0 -0
  19. package/dist/templates/mcp-apps/public/fruits/pear.webp +0 -0
  20. package/dist/templates/mcp-apps/public/fruits/pineapple.webp +0 -0
  21. package/dist/templates/mcp-apps/public/fruits/plum.webp +0 -0
  22. package/dist/templates/mcp-apps/public/fruits/strawberry.webp +0 -0
  23. package/dist/templates/mcp-apps/public/fruits/watermelon.webp +0 -0
  24. package/dist/templates/mcp-apps/tsconfig.json +9 -4
  25. package/dist/templates/mcp-apps/views/product-search-result/components/Accordion.tsx +35 -0
  26. package/dist/templates/mcp-apps/views/product-search-result/components/AccordionItem.tsx +35 -0
  27. package/dist/templates/mcp-apps/views/product-search-result/components/Carousel.tsx +52 -0
  28. package/dist/templates/mcp-apps/views/product-search-result/components/CarouselItem.tsx +91 -0
  29. package/dist/templates/mcp-apps/views/product-search-result/components/CarouselSkeleton.tsx +18 -0
  30. package/dist/templates/mcp-apps/views/product-search-result/hooks/useCarouselAnimation.ts +72 -0
  31. package/dist/templates/mcp-apps/views/product-search-result/view.css +81 -0
  32. package/dist/templates/mcp-apps/views/product-search-result/view.tsx +371 -0
  33. package/dist/templates/starter/package.json +14 -10
  34. package/dist/templates/starter/tsconfig.json +13 -10
  35. package/package.json +2 -2
  36. package/dist/templates/blank/public/favicon.ico +0 -0
  37. package/dist/templates/mcp-apps/public/favicon.ico +0 -0
  38. package/dist/templates/mcp-apps/public/fruits/apple.png +0 -0
  39. package/dist/templates/mcp-apps/public/fruits/apricot.png +0 -0
  40. package/dist/templates/mcp-apps/public/fruits/avocado.png +0 -0
  41. package/dist/templates/mcp-apps/public/fruits/banana.png +0 -0
  42. package/dist/templates/mcp-apps/public/fruits/blueberry.png +0 -0
  43. package/dist/templates/mcp-apps/public/fruits/cherries.png +0 -0
  44. package/dist/templates/mcp-apps/public/fruits/coconut.png +0 -0
  45. package/dist/templates/mcp-apps/public/fruits/grapes.png +0 -0
  46. package/dist/templates/mcp-apps/public/fruits/lemon.png +0 -0
  47. package/dist/templates/mcp-apps/public/fruits/mango.png +0 -0
  48. package/dist/templates/mcp-apps/public/fruits/orange.png +0 -0
  49. package/dist/templates/mcp-apps/public/fruits/pear.png +0 -0
  50. package/dist/templates/mcp-apps/public/fruits/pineapple.png +0 -0
  51. package/dist/templates/mcp-apps/public/fruits/plum.png +0 -0
  52. package/dist/templates/mcp-apps/public/fruits/strawberry.png +0 -0
  53. package/dist/templates/mcp-apps/public/fruits/watermelon.png +0 -0
  54. package/dist/templates/mcp-apps/resources/product-search-result/view.tsx +0 -25
  55. package/dist/templates/starter/public/favicon.ico +0 -0
package/README.md CHANGED
@@ -156,8 +156,8 @@ Perfect for getting started with all available features or building full-feature
156
156
  The mcp-apps template includes:
157
157
 
158
158
  - MCP server setup focused on OpenAI Apps SDK integration
159
- - OpenAI Apps SDK compatible widgets
160
- - Example display-weather widget
159
+ - OpenAI Apps SDK compatible views under `views/<name>/view.tsx`
160
+ - Example `product-search-result` view with carousel UI
161
161
  - Optimized for OpenAI assistant integration
162
162
 
163
163
  Ideal for building MCP servers that integrate with OpenAI's Apps SDK.
@@ -433,7 +433,7 @@ server.prompt("code_review", {
433
433
  **Command not found:**
434
434
 
435
435
  ```bash
436
- # Make sure you have Node.js 20.19+ installed
436
+ # Make sure you have Node.js 22.22.2+ installed
437
437
  node --version
438
438
 
439
439
  # Try with npx
package/dist/index.js CHANGED
@@ -1321,7 +1321,7 @@ function updatePackageJson(projectPath, projectName) {
1321
1321
  const packageJsonPath = join2(projectPath, "package.json");
1322
1322
  const packageJsonContent = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
1323
1323
  packageJsonContent.name = projectName;
1324
- packageJsonContent.description = `MCP server: ${projectName}`;
1324
+ packageJsonContent.description = `${projectName}: an mcp-use server`;
1325
1325
  writeFileSync(packageJsonPath, JSON.stringify(packageJsonContent, null, 2));
1326
1326
  }
1327
1327
  function updateIndexTs(projectPath, projectName) {
@@ -1346,7 +1346,7 @@ function parseCli(argv) {
1346
1346
  install: { type: "boolean" },
1347
1347
  skills: { type: "boolean" },
1348
1348
  dev: { type: "boolean" },
1349
- canary: { type: "boolean" },
1349
+ "sdk-version": { type: "string" },
1350
1350
  yarn: { type: "boolean" },
1351
1351
  npm: { type: "boolean" },
1352
1352
  pnpm: { type: "boolean" },
@@ -1366,7 +1366,7 @@ function parseCli(argv) {
1366
1366
  install,
1367
1367
  skills,
1368
1368
  dev: values.dev,
1369
- canary: values.canary,
1369
+ sdkVersion: values["sdk-version"],
1370
1370
  yarn: values.yarn,
1371
1371
  npm: values.npm,
1372
1372
  pnpm: values.pnpm
@@ -1539,32 +1539,13 @@ function renderLogo() {
1539
1539
  var packageJson = JSON.parse(
1540
1540
  readFileSync2(join3(__dirname, "../package.json"), "utf-8")
1541
1541
  );
1542
- function getCurrentPackageVersions(isDevelopment = false, useCanary = false) {
1543
- const versions = {};
1544
- try {
1545
- if (isDevelopment) {
1546
- versions["mcp-use"] = "workspace:*";
1547
- } else if (useCanary) {
1548
- versions["mcp-use"] = "canary";
1549
- } else {
1550
- versions["mcp-use"] = "latest";
1551
- }
1552
- } catch (error) {
1553
- if (process.env.NODE_ENV === "development") {
1554
- console.warn(
1555
- "\u26A0\uFE0F Could not read workspace package versions, using defaults"
1556
- );
1557
- console.warn(
1558
- ` Error: ${error instanceof Error ? error.message : String(error)}`
1559
- );
1560
- if (error instanceof Error && error.stack) {
1561
- console.warn(` Stack: ${error.stack}`);
1562
- }
1563
- }
1542
+ function getCurrentPackageVersions(isDevelopment = false, sdkVersion) {
1543
+ if (isDevelopment) {
1544
+ return { "mcp-use": "workspace:*" };
1564
1545
  }
1565
- return versions;
1546
+ return { "mcp-use": sdkVersion ?? "latest" };
1566
1547
  }
1567
- function processTemplateFile(filePath, versions, isDevelopment = false, useCanary = false) {
1548
+ function processTemplateFile(filePath, versions, isDevelopment = false) {
1568
1549
  const content = readFileSync2(filePath, "utf-8");
1569
1550
  let processedContent = content;
1570
1551
  for (const [packageName, version] of Object.entries(versions)) {
@@ -1574,24 +1555,20 @@ function processTemplateFile(filePath, versions, isDevelopment = false, useCanar
1574
1555
  version
1575
1556
  );
1576
1557
  }
1558
+ const mcpUseVersion = isDevelopment ? "workspace:*" : versions["mcp-use"] || "latest";
1577
1559
  if (isDevelopment) {
1578
1560
  processedContent = processedContent.replace(
1579
1561
  /"mcp-use": "\^[^"]+"/,
1580
1562
  '"mcp-use": "workspace:*"'
1581
1563
  );
1582
- } else if (useCanary) {
1564
+ } else {
1583
1565
  processedContent = processedContent.replace(
1584
1566
  /"mcp-use": "workspace:\*"/,
1585
- `"mcp-use": "canary"`
1567
+ `"mcp-use": "${mcpUseVersion}"`
1586
1568
  );
1587
1569
  processedContent = processedContent.replace(
1588
1570
  /"mcp-use": "\^[^"]+"/,
1589
- `"mcp-use": "canary"`
1590
- );
1591
- } else {
1592
- processedContent = processedContent.replace(
1593
- /"mcp-use": "workspace:\*"/,
1594
- `"mcp-use": "${versions["mcp-use"] || "latest"}"`
1571
+ `"mcp-use": "${mcpUseVersion}"`
1595
1572
  );
1596
1573
  }
1597
1574
  return processedContent;
@@ -1779,7 +1756,7 @@ function validateTemplateName(template) {
1779
1756
  }
1780
1757
  return resolvedTemplate;
1781
1758
  }
1782
- async function copyTemplate(projectPath, template, versions, isDevelopment = false, useCanary = false) {
1759
+ async function copyTemplate(projectPath, template, versions, isDevelopment = false) {
1783
1760
  const repoInfo = parseGitHubRepoUrl(template);
1784
1761
  if (repoInfo) {
1785
1762
  const tempDir = mkdtempSync(join3(tmpdir(), "create-mcp-use-app-"));
@@ -1789,8 +1766,7 @@ async function copyTemplate(projectPath, template, versions, isDevelopment = fal
1789
1766
  tempDir,
1790
1767
  projectPath,
1791
1768
  versions,
1792
- isDevelopment,
1793
- useCanary
1769
+ isDevelopment
1794
1770
  );
1795
1771
  } finally {
1796
1772
  try {
@@ -1832,11 +1808,10 @@ async function copyTemplate(projectPath, template, versions, isDevelopment = fal
1832
1808
  templatePath,
1833
1809
  projectPath,
1834
1810
  versions,
1835
- isDevelopment,
1836
- useCanary
1811
+ isDevelopment
1837
1812
  );
1838
1813
  }
1839
- function copyDirectoryWithProcessing(src, dest, versions, isDevelopment, useCanary = false) {
1814
+ function copyDirectoryWithProcessing(src, dest, versions, isDevelopment) {
1840
1815
  const entries = readdirSync3(src, { withFileTypes: true });
1841
1816
  for (const entry of entries) {
1842
1817
  if (entry.name === ".git") {
@@ -1847,19 +1822,12 @@ function copyDirectoryWithProcessing(src, dest, versions, isDevelopment, useCana
1847
1822
  const destPath = join3(dest, destName);
1848
1823
  if (entry.isDirectory()) {
1849
1824
  mkdirSync(destPath, { recursive: true });
1850
- copyDirectoryWithProcessing(
1851
- srcPath,
1852
- destPath,
1853
- versions,
1854
- isDevelopment,
1855
- useCanary
1856
- );
1825
+ copyDirectoryWithProcessing(srcPath, destPath, versions, isDevelopment);
1857
1826
  } else if (entry.name === "package.json" || entry.name.endsWith(".json")) {
1858
1827
  const processedContent = processTemplateFile(
1859
1828
  srcPath,
1860
1829
  versions,
1861
- isDevelopment,
1862
- useCanary
1830
+ isDevelopment
1863
1831
  );
1864
1832
  writeFileSync2(destPath, processedContent);
1865
1833
  } else {
@@ -1946,7 +1914,7 @@ Options:
1946
1914
  --no-skills Skip installing skills
1947
1915
  --no-git Skip initializing a git repository
1948
1916
  --dev Use workspace dependencies for development
1949
- --canary Use canary versions of packages
1917
+ --sdk-version <version> Pin mcp-use to an npm version or dist-tag (e.g. canary, 1.34.0)
1950
1918
  --yarn Use yarn as package manager
1951
1919
  --npm Use npm as package manager
1952
1920
  --pnpm Use pnpm as package manager
@@ -1968,11 +1936,15 @@ async function main() {
1968
1936
  listTemplates();
1969
1937
  return;
1970
1938
  }
1971
- if (options.dev && options.canary) {
1972
- console.error(red("\u274C Cannot use --dev and --canary together"));
1939
+ if (options.dev && options.sdkVersion) {
1940
+ console.error(red("\u274C Cannot use --dev and --sdk-version together"));
1973
1941
  console.error(yellow(" Please choose only one dependency mode"));
1974
1942
  process.exit(1);
1975
1943
  }
1944
+ if (options.sdkVersion !== void 0 && !options.sdkVersion.trim()) {
1945
+ console.error(red("\u274C --sdk-version requires a non-empty value"));
1946
+ process.exit(1);
1947
+ }
1976
1948
  let projectName = initialProjectName;
1977
1949
  let selectedTemplate = options.template;
1978
1950
  const interactive = isInteractive();
@@ -2059,14 +2031,8 @@ async function main() {
2059
2031
  }
2060
2032
  console.log(cyan(`\u{1F680} Creating MCP server "${displayName}"...`));
2061
2033
  const validatedTemplate = validateTemplateName(selectedTemplate);
2062
- const versions = getCurrentPackageVersions(options.dev, options.canary);
2063
- await copyTemplate(
2064
- projectPath,
2065
- validatedTemplate,
2066
- versions,
2067
- options.dev,
2068
- options.canary
2069
- );
2034
+ const versions = getCurrentPackageVersions(options.dev, options.sdkVersion);
2035
+ await copyTemplate(projectPath, validatedTemplate, versions, options.dev);
2070
2036
  updatePackageJson(projectPath, packageName);
2071
2037
  updateIndexTs(projectPath, packageName);
2072
2038
  let install = options.install;
@@ -2168,8 +2134,8 @@ async function main() {
2168
2134
  console.log(
2169
2135
  yellow("\u{1F527} Development mode: Using workspace dependencies")
2170
2136
  );
2171
- } else if (options.canary) {
2172
- console.log(cyan("\u{1F680} Canary mode: Using canary versions of packages"));
2137
+ } else if (options.sdkVersion) {
2138
+ console.log(cyan(`\u{1F4CC} Using mcp-use@${options.sdkVersion}`));
2173
2139
  }
2174
2140
  console.log("");
2175
2141
  console.log(bold("\u{1F4C1} Project structure:"));
@@ -2186,10 +2152,16 @@ async function main() {
2186
2152
  console.log(" \u251C\u2500\u2500 tsconfig.json");
2187
2153
  console.log(" \u2514\u2500\u2500 README.md");
2188
2154
  } else if (validatedTemplate === "mcp-apps") {
2189
- console.log(" \u251C\u2500\u2500 resources/");
2155
+ console.log(" \u251C\u2500\u2500 public/");
2156
+ console.log(" \u2502 \u251C\u2500\u2500 icon.svg");
2157
+ console.log(" \u2502 \u2514\u2500\u2500 fruits/ (16 WebP assets)");
2158
+ console.log(" \u251C\u2500\u2500 views/");
2190
2159
  console.log(" \u2502 \u2514\u2500\u2500 product-search-result/");
2191
- console.log(" \u2502 \u2514\u2500\u2500 view.tsx");
2192
- console.log(" \u251C\u2500\u2500 tools.d.ts");
2160
+ console.log(" \u2502 \u251C\u2500\u2500 view.tsx");
2161
+ console.log(" \u2502 \u251C\u2500\u2500 view.css");
2162
+ console.log(" \u2502 \u251C\u2500\u2500 components/");
2163
+ console.log(" \u2502 \u2514\u2500\u2500 hooks/");
2164
+ console.log(" \u251C\u2500\u2500 mcp-env.d.ts");
2193
2165
  console.log(" \u251C\u2500\u2500 index.ts (server entry point)");
2194
2166
  console.log(" \u251C\u2500\u2500 package.json");
2195
2167
  console.log(" \u251C\u2500\u2500 tsconfig.json");
@@ -1,15 +1,22 @@
1
1
  {
2
2
  "name": "mcp-use server",
3
3
  "type": "module",
4
+ "engines": {
5
+ "node": ">=22.22.2"
6
+ },
4
7
  "version": "1.0.0",
5
- "description": "Blank mcp-use server",
6
- "author": "",
8
+ "description": "an mcp-use server",
9
+ "author": "mcp-use",
7
10
  "license": "MIT",
11
+ "homepage": "https://github.com/mcp-use/mcp-use",
8
12
  "keywords": [
9
13
  "mcp",
10
- "server",
11
- "blank",
12
- "mcp-use"
14
+ "mcp-server",
15
+ "chatgpt plugins",
16
+ "claude connector",
17
+ "mcp-app",
18
+ "mcp-use",
19
+ "manufact"
13
20
  ],
14
21
  "main": "dist/index.js",
15
22
  "scripts": {
@@ -23,7 +30,7 @@
23
30
  "mcp-use": "workspace:*"
24
31
  },
25
32
  "devDependencies": {
26
- "@types/node": "^24.13.2",
27
- "typescript": "7.0.1-rc"
33
+ "@types/node": "^22.20.0",
34
+ "typescript": "^7.0.2"
28
35
  }
29
36
  }
@@ -1,20 +1,23 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "ES2022",
3
+ "target": "ES2024",
4
4
  "jsx": "react-jsx",
5
- "module": "ESNext",
6
- "moduleResolution": "bundler",
7
- "allowJs": true,
5
+ "module": "NodeNext",
6
+ "moduleResolution": "NodeNext",
7
+ "lib": ["ES2024", "DOM", "DOM.Iterable"],
8
8
  "strict": true,
9
- "outDir": "./dist",
10
- "sourceMap": true,
11
- "allowSyntheticDefaultImports": true,
12
9
  "esModuleInterop": true,
13
10
  "forceConsistentCasingInFileNames": true,
14
11
  "skipLibCheck": true,
15
- "incremental": true,
16
- "tsBuildInfoFile": "./dist/.tsbuildinfo"
12
+ "noEmit": true
17
13
  },
18
- "include": ["index.ts", "src/**/*", "resources/**/*", "server.ts", ".mcp-use/**/*.d.ts"],
14
+ "include": [
15
+ "index.ts",
16
+ "mcp-env.d.ts",
17
+ "src/**/*",
18
+ "views/**/*",
19
+ "server.ts",
20
+ ".mcp-use/**/*.d.ts"
21
+ ],
19
22
  "exclude": ["node_modules", "dist"]
20
23
  }
@@ -1,43 +1,147 @@
1
1
  import { MCPServer } from "mcp-use";
2
2
  import { z } from "zod";
3
3
 
4
- const fruits = ["apple", "banana", "mango", "orange", "strawberry"];
4
+ const fruits = [
5
+ { fruit: "mango", color: "bg-[#FBF1E1] dark:bg-[#FBF1E1]/10" },
6
+ { fruit: "pineapple", color: "bg-[#f8f0d9] dark:bg-[#f8f0d9]/10" },
7
+ { fruit: "cherries", color: "bg-[#E2EDDC] dark:bg-[#E2EDDC]/10" },
8
+ { fruit: "coconut", color: "bg-[#fbedd3] dark:bg-[#fbedd3]/10" },
9
+ { fruit: "apricot", color: "bg-[#fee6ca] dark:bg-[#fee6ca]/10" },
10
+ { fruit: "blueberry", color: "bg-[#e0e6e6] dark:bg-[#e0e6e6]/10" },
11
+ { fruit: "grapes", color: "bg-[#f4ebe2] dark:bg-[#f4ebe2]/10" },
12
+ { fruit: "watermelon", color: "bg-[#e6eddb] dark:bg-[#e6eddb]/10" },
13
+ { fruit: "orange", color: "bg-[#fdebdf] dark:bg-[#fdebdf]/10" },
14
+ { fruit: "avocado", color: "bg-[#ecefda] dark:bg-[#ecefda]/10" },
15
+ { fruit: "apple", color: "bg-[#F9E7E4] dark:bg-[#F9E7E4]/10" },
16
+ { fruit: "pear", color: "bg-[#f1f1cf] dark:bg-[#f1f1cf]/10" },
17
+ { fruit: "plum", color: "bg-[#ece5ec] dark:bg-[#ece5ec]/10" },
18
+ { fruit: "banana", color: "bg-[#fdf0dd] dark:bg-[#fdf0dd]/10" },
19
+ { fruit: "strawberry", color: "bg-[#f7e6df] dark:bg-[#f7e6df]/10" },
20
+ { fruit: "lemon", color: "bg-[#feeecd] dark:bg-[#feeecd]/10" },
21
+ ];
5
22
 
6
- const outputSchema = z.object({
23
+ const fruitRowSchema = z.object({
24
+ fruit: z.string(),
25
+ color: z.string(),
26
+ });
27
+
28
+ const searchOutputSchema = z.object({
7
29
  query: z.string(),
8
- items: z.array(z.object({ id: z.string(), name: z.string() })),
30
+ results: z.array(fruitRowSchema),
9
31
  });
10
32
 
33
+ const detailsOutputSchema = z.object({
34
+ fruit: z.string(),
35
+ color: z.string(),
36
+ facts: z.array(z.string()),
37
+ });
38
+
39
+ function renderAsMarkdownTable(
40
+ results: Array<{ fruit: string; color: string }>
41
+ ): string {
42
+ const header = "| Fruit | Color |\n| --- | --- |";
43
+ const rows = results.map((r) => `| ${r.fruit} | ${r.color} |`).join("\n");
44
+ return `${header}\n${rows}`;
45
+ }
46
+
11
47
  const server = new MCPServer({
12
48
  name: "{{PROJECT_NAME}}",
13
49
  title: "{{PROJECT_NAME}}",
14
50
  version: "1.0.0",
15
- description: "An MCP Apps server built with mcp-use",
51
+ description: "MCP Apps server with a fruit shop view",
52
+ instructions:
53
+ "Use search-fruits to find fruit matches before calling get-fruit-details. Prefer the view result when the user wants to browse or compare options visually.",
54
+ websiteUrl: "https://mcp-use.com",
55
+ icons: [
56
+ {
57
+ src: "icon.svg",
58
+ mimeType: "image/svg+xml",
59
+ sizes: ["512x512"],
60
+ },
61
+ ],
16
62
  });
17
63
 
18
64
  export const searchFruits = server.tool(
19
65
  {
20
66
  name: "search-fruits",
21
- description: "Search the fruit catalog",
22
- inputSchema: z.object({ query: z.string().optional() }),
23
- outputSchema,
67
+ title: "Search fruits",
68
+ description: "Search for fruits and display the results in a view",
69
+ inputSchema: z.object({
70
+ query: z.string().optional().describe("Search query to filter fruits"),
71
+ }),
72
+ outputSchema: searchOutputSchema,
24
73
  view: {
25
74
  name: "product-search-result",
26
- description: "Fruit search results",
75
+ description: "Product search results with carousel and details",
27
76
  prefersBorder: true,
28
77
  },
29
- annotations: { readOnlyHint: true, openWorldHint: false },
78
+ annotations: {
79
+ readOnlyHint: true,
80
+ destructiveHint: false,
81
+ openWorldHint: false,
82
+ },
30
83
  },
31
- async ({ query = "" }) => {
32
- const items = fruits
33
- .filter((fruit) => fruit.includes(query.toLowerCase()))
34
- .map((fruit) => ({ id: fruit, name: fruit }));
35
- const data = { query, items };
84
+ async ({ query = "" }, ctx) => {
85
+ const results = fruits.filter(
86
+ (f) => query === "" || f.fruit.toLowerCase().includes(query.toLowerCase())
87
+ );
88
+
89
+ // Emulate a delay to show the loading state in the view
90
+ await new Promise((resolve) => setTimeout(resolve, 2000));
91
+
92
+ const data = { query, results };
93
+
94
+ if (!ctx.client.supportsViews()) {
95
+ return {
96
+ content: [{ type: "text", text: renderAsMarkdownTable(results) }],
97
+ structuredContent: data,
98
+ };
99
+ }
100
+
36
101
  return {
37
- content: [{ type: "text", text: `Found ${items.length} fruits.` }],
102
+ content: [
103
+ {
104
+ type: "text",
105
+ text: `Found ${results.length} fruits matching "${query || "all"}"`,
106
+ },
107
+ ],
38
108
  structuredContent: data,
39
109
  };
40
110
  }
41
111
  );
42
112
 
113
+ export const getFruitDetails = server.tool(
114
+ {
115
+ name: "get-fruit-details",
116
+ title: "Get fruit details",
117
+ description: "Get detailed information about a specific fruit",
118
+ inputSchema: z.object({
119
+ fruit: z.string().describe("The fruit name"),
120
+ }),
121
+ outputSchema: detailsOutputSchema,
122
+ annotations: {
123
+ readOnlyHint: true,
124
+ destructiveHint: false,
125
+ openWorldHint: false,
126
+ },
127
+ },
128
+ async ({ fruit }) => {
129
+ const found = fruits.find(
130
+ (f) => f.fruit.toLowerCase() === fruit.toLowerCase()
131
+ );
132
+ const details = {
133
+ fruit: found?.fruit ?? fruit,
134
+ color: found?.color ?? "unknown",
135
+ facts: [
136
+ `${fruit} is a delicious fruit`,
137
+ `Color: ${found?.color ?? "unknown"}`,
138
+ ],
139
+ };
140
+ return {
141
+ content: [{ type: "text", text: JSON.stringify(details) }],
142
+ structuredContent: details,
143
+ };
144
+ }
145
+ );
146
+
43
147
  export default server;
@@ -1,4 +1,6 @@
1
- // Created by mcp-use when missing. Existing files are never overwritten.
1
+ // mcp-use typing shim — dev/build recreate this file if missing.
2
+ declare module "*.css";
3
+
2
4
  declare module "mcp-use/react" {
3
5
  interface Register {
4
6
  tools: typeof import("./index.js");
@@ -1,20 +1,22 @@
1
1
  {
2
2
  "name": "mcp-use server",
3
3
  "type": "module",
4
+ "engines": {
5
+ "node": ">=22.22.2"
6
+ },
4
7
  "version": "1.0.0",
5
- "description": "MCP server with a standard MCP Apps view",
6
- "author": "",
8
+ "description": "an mcp-use server",
9
+ "author": "mcp-use",
7
10
  "license": "MIT",
11
+ "homepage": "https://github.com/mcp-use/mcp-use",
8
12
  "keywords": [
9
13
  "mcp",
10
- "server",
11
- "starter",
12
- "tools",
13
- "resources",
14
- "prompts",
15
- "ui",
16
- "react",
17
- "mcp-apps"
14
+ "mcp-server",
15
+ "chatgpt plugins",
16
+ "claude connector",
17
+ "mcp-app",
18
+ "mcp-use",
19
+ "manufact"
18
20
  ],
19
21
  "main": "dist/index.js",
20
22
  "scripts": {
@@ -26,14 +28,14 @@
26
28
  },
27
29
  "dependencies": {
28
30
  "mcp-use": "workspace:*",
29
- "react": "^19.2.4",
30
- "react-dom": "^19.2.4",
31
+ "react": "^19.2.7",
32
+ "react-dom": "^19.2.7",
31
33
  "zod": "^4.4.3"
32
34
  },
33
35
  "devDependencies": {
34
- "@types/node": "^24.13.2",
36
+ "@types/node": "^22.20.0",
35
37
  "@types/react": "^19.2.17",
36
38
  "@types/react-dom": "^19.2.3",
37
- "typescript": "7.0.1-rc"
39
+ "typescript": "^7.0.2"
38
40
  }
39
41
  }
@@ -9,10 +9,15 @@
9
9
  "esModuleInterop": true,
10
10
  "forceConsistentCasingInFileNames": true,
11
11
  "skipLibCheck": true,
12
- "noEmit": true,
13
- "noUncheckedIndexedAccess": true,
14
- "exactOptionalPropertyTypes": true
12
+ "noEmit": true
15
13
  },
16
- "include": ["index.ts", "tools.d.ts", "resources/**/*"],
14
+ "include": [
15
+ "index.ts",
16
+ "mcp-env.d.ts",
17
+ "src/**/*",
18
+ "views/**/*",
19
+ "server.ts",
20
+ ".mcp-use/**/*.d.ts"
21
+ ],
17
22
  "exclude": ["node_modules", "dist"]
18
23
  }
@@ -0,0 +1,35 @@
1
+ import { useState } from "react";
2
+ import { AccordionItem } from "./AccordionItem.js";
3
+
4
+ export interface AccordionItemData {
5
+ question: string;
6
+ answer: string;
7
+ }
8
+
9
+ interface AccordionProps {
10
+ items: AccordionItemData[];
11
+ }
12
+
13
+ export function Accordion({ items }: AccordionProps) {
14
+ const [openAccordionIndex, setOpenAccordionIndex] = useState<number | null>(
15
+ null
16
+ );
17
+
18
+ return (
19
+ <div className="mt-4 border-t border-neutral-200 p-8 pt-4 dark:border-neutral-700">
20
+ <div className="overflow-hidden rounded-lg border border-neutral-200 dark:border-neutral-700">
21
+ {items.map((item, index) => (
22
+ <AccordionItem
23
+ key={index}
24
+ question={item.question}
25
+ answer={item.answer}
26
+ isOpen={openAccordionIndex === index}
27
+ onToggle={() =>
28
+ setOpenAccordionIndex(openAccordionIndex === index ? null : index)
29
+ }
30
+ />
31
+ ))}
32
+ </div>
33
+ </div>
34
+ );
35
+ }
@@ -0,0 +1,35 @@
1
+ export interface AccordionItemProps {
2
+ question: string;
3
+ answer: string;
4
+ isOpen: boolean;
5
+ onToggle: () => void;
6
+ }
7
+
8
+ export function AccordionItem({
9
+ question,
10
+ answer,
11
+ isOpen,
12
+ onToggle,
13
+ }: AccordionItemProps) {
14
+ return (
15
+ <div className="border-b border-neutral-200 last:border-b-0 dark:border-neutral-700">
16
+ <button
17
+ type="button"
18
+ onClick={onToggle}
19
+ className="flex w-full items-center justify-between p-4 text-left transition-colors hover:bg-neutral-50 dark:hover:bg-neutral-900"
20
+ >
21
+ <span className="font-medium text-neutral-900 dark:text-neutral-100">
22
+ {question}
23
+ </span>
24
+ <span className="text-xl text-neutral-500 transition-transform duration-200 dark:text-neutral-400">
25
+ {isOpen ? "−" : "+"}
26
+ </span>
27
+ </button>
28
+ {isOpen && (
29
+ <div className="px-4 pb-4 text-neutral-600 dark:text-neutral-400">
30
+ {answer}
31
+ </div>
32
+ )}
33
+ </div>
34
+ );
35
+ }