@igstack/app-catalog-frontend-core 1.0.0 → 1.0.1-alpha-20260914185229
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.
|
@@ -38,7 +38,7 @@ function McpPage() {
|
|
|
38
38
|
2
|
|
39
39
|
);
|
|
40
40
|
const cliCommand = `claude mcp add --transport http ${serverName} ${endpoint}`;
|
|
41
|
-
return /* @__PURE__ */ jsx("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8 max-w-3xl pb-8", children: [
|
|
41
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8 w-full max-w-3xl mx-auto pb-8", children: [
|
|
42
42
|
/* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-2", children: [
|
|
43
43
|
/* @__PURE__ */ jsx(
|
|
44
44
|
"h1",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpPage.js","sources":["../../../../../../src/modules/appCatalog/ui/pages/McpPage.tsx"],"sourcesContent":["import { Check, Copy, TriangleAlert } from 'lucide-react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { Button } from '~/ui/button'\nimport { Spinner } from '~/ui/spinner'\nimport type { McpTool } from '../../utils/fetchMcpTools'\nimport { MCP_ENDPOINT_PATH, fetchMcpTools } from '../../utils/fetchMcpTools'\n\n/**\n * MCP docs page: how to point an AI agent at this catalog.\n *\n * Every snippet is built from `window.location.origin`, so production, a\n * preview host and localhost each show a config that actually works — nothing\n * is hardcoded.\n *\n * The tool reference is fetched from the live registry (`tools/list`) rather\n * than written out by hand, so it cannot rot when the server's tools change.\n */\nexport function McpPage() {\n const origin = typeof window === 'undefined' ? '' : window.location.origin\n const endpoint = `${origin}${MCP_ENDPOINT_PATH}`\n const serverName = 'app-catalog'\n\n const [tools, setTools] = useState<McpTool[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [reloadKey, setReloadKey] = useState(0)\n const headingRef = useRef<HTMLHeadingElement>(null)\n\n // New view: land keyboard and screen-reader users in the content rather than\n // leaving focus on whatever nav element was clicked.\n useEffect(() => {\n headingRef.current?.focus()\n }, [])\n\n useEffect(() => {\n const controller = new AbortController()\n setTools(null)\n setError(null)\n fetchMcpTools(origin, controller.signal)\n .then(setTools)\n .catch((err: unknown) => {\n if (controller.signal.aborted) return\n setError(\n err instanceof Error\n ? err.message\n : 'Could not reach the MCP endpoint.',\n )\n })\n return () => controller.abort()\n }, [origin, reloadKey])\n\n const mcpJson = JSON.stringify(\n {\n mcpServers: {\n [serverName]: { type: 'http', url: endpoint },\n },\n },\n null,\n 2,\n )\n const cliCommand = `claude mcp add --transport http ${serverName} ${endpoint}`\n\n return (\n <div className=\"flex flex-col flex-1 min-h-0 overflow-y-auto\">\n <div className=\"flex flex-col gap-8 max-w-3xl pb-8\">\n <section className=\"flex flex-col gap-2\">\n <h1\n ref={headingRef}\n tabIndex={-1}\n className=\"text-xl font-semibold outline-none\"\n >\n MCP server\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n This catalog exposes a{' '}\n <a\n href=\"https://modelcontextprotocol.io\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n >\n Model Context Protocol\n </a>{' '}\n server, so an AI agent can search the catalog and read an entry the\n same way you can — what exists, who owns it, and how to request\n access. Point your agent at the endpoint below and it gains those\n tools; no key or account is needed.\n </p>\n <p className=\"text-sm text-muted-foreground\">\n It speaks MCP over Streamable HTTP (JSON-RPC over{' '}\n <code className=\"text-xs\">POST</code>), and it is read-only.\n </p>\n </section>\n\n <Snippet\n title=\"Endpoint\"\n description=\"The URL an MCP client connects to.\"\n value={endpoint}\n />\n\n <Snippet\n title=\"Add it with the CLI\"\n description=\"One command, if your agent ships a CLI that manages MCP servers.\"\n value={cliCommand}\n />\n\n <Snippet\n title=\"Or add it to .mcp.json\"\n description=\"Commit this in a project so everyone working on it gets the same tools.\"\n value={mcpJson}\n language=\"json\"\n />\n\n <section\n className=\"flex flex-col gap-3\"\n aria-busy={tools === null && error === null}\n >\n <div className=\"flex flex-col gap-1\">\n <h2 className=\"text-base font-semibold\">Tools</h2>\n <p className=\"text-xs text-muted-foreground\">\n Read live from the server, so this list is always what your agent\n will actually see.\n </p>\n </div>\n\n {error !== null ? (\n <div\n role=\"alert\"\n className=\"flex flex-col items-start gap-3 rounded-md border border-destructive/40 bg-destructive/5 p-4\"\n >\n <p className=\"flex items-start gap-2 text-sm\">\n <TriangleAlert className=\"size-4 shrink-0 mt-0.5 text-destructive\" />\n <span>\n Could not read the tool list. {error} The setup instructions\n above are still correct.\n </span>\n </p>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setReloadKey((k) => k + 1)}\n >\n Try again\n </Button>\n </div>\n ) : tools === null ? (\n <p className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner className=\"size-4\" />\n Reading the tool list…\n </p>\n ) : tools.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n The server reported no tools.\n </p>\n ) : (\n <ul className=\"flex flex-col gap-4 list-none p-0 m-0\">\n {tools.map((tool) => (\n <li\n key={tool.name}\n className=\"rounded-md border p-4 flex flex-col gap-2\"\n >\n <code className=\"text-sm font-semibold\">{tool.name}</code>\n {tool.description && (\n <p className=\"text-sm text-muted-foreground\">\n {tool.description}\n </p>\n )}\n {tool.parameters.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n No parameters.\n </p>\n ) : (\n <dl className=\"flex flex-col gap-2 m-0\">\n {tool.parameters.map((param) => (\n <div key={param.name} className=\"flex flex-col gap-0.5\">\n <dt className=\"text-xs\">\n <code className=\"font-medium\">{param.name}</code>\n {param.type && (\n <span className=\"text-muted-foreground\">\n {' '}\n {param.type}\n </span>\n )}\n <span className=\"text-muted-foreground\">\n {' '}\n — {param.required ? 'required' : 'optional'}\n </span>\n </dt>\n {param.description && (\n <dd className=\"text-xs text-muted-foreground m-0\">\n {param.description}\n </dd>\n )}\n {param.enumValues && (\n <dd className=\"text-xs text-muted-foreground m-0\">\n One of: {param.enumValues.join(', ')}\n </dd>\n )}\n </div>\n ))}\n </dl>\n )}\n </li>\n ))}\n </ul>\n )}\n </section>\n </div>\n </div>\n )\n}\n\nfunction Snippet({\n title,\n description,\n value,\n language,\n}: {\n title: string\n description: string\n value: string\n language?: string\n}) {\n return (\n <section className=\"flex flex-col gap-2\">\n <h2 className=\"text-base font-semibold\">{title}</h2>\n <p className=\"text-xs text-muted-foreground\">{description}</p>\n <div className=\"relative\">\n <pre\n className=\"overflow-x-auto rounded-md border bg-muted/40 p-3 pr-12 text-xs\"\n data-language={language}\n >\n <code>{value}</code>\n </pre>\n <CopyButton value={value} label={title} />\n </div>\n </section>\n )\n}\n\nfunction CopyButton({ value, label }: { value: string; label: string }) {\n const [copied, setCopied] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n useEffect(\n () => () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n },\n [],\n )\n\n const copy = useCallback(() => {\n void navigator.clipboard.writeText(value)\n setCopied(true)\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n timeoutRef.current = setTimeout(() => setCopied(false), 2000)\n }, [value])\n\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={copy}\n aria-label={copied ? `${label} copied` : `Copy ${label}`}\n title={copied ? 'Copied' : 'Copy'}\n className=\"absolute right-1.5 top-1.5\"\n >\n {copied ? (\n <Check className=\"size-4 text-primary\" />\n ) : (\n <Copy className=\"size-4\" />\n )}\n </Button>\n )\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"McpPage.js","sources":["../../../../../../src/modules/appCatalog/ui/pages/McpPage.tsx"],"sourcesContent":["import { Check, Copy, TriangleAlert } from 'lucide-react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\nimport { Button } from '~/ui/button'\nimport { Spinner } from '~/ui/spinner'\nimport type { McpTool } from '../../utils/fetchMcpTools'\nimport { MCP_ENDPOINT_PATH, fetchMcpTools } from '../../utils/fetchMcpTools'\n\n/**\n * MCP docs page: how to point an AI agent at this catalog.\n *\n * Every snippet is built from `window.location.origin`, so production, a\n * preview host and localhost each show a config that actually works — nothing\n * is hardcoded.\n *\n * The tool reference is fetched from the live registry (`tools/list`) rather\n * than written out by hand, so it cannot rot when the server's tools change.\n */\nexport function McpPage() {\n const origin = typeof window === 'undefined' ? '' : window.location.origin\n const endpoint = `${origin}${MCP_ENDPOINT_PATH}`\n const serverName = 'app-catalog'\n\n const [tools, setTools] = useState<McpTool[] | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [reloadKey, setReloadKey] = useState(0)\n const headingRef = useRef<HTMLHeadingElement>(null)\n\n // New view: land keyboard and screen-reader users in the content rather than\n // leaving focus on whatever nav element was clicked.\n useEffect(() => {\n headingRef.current?.focus()\n }, [])\n\n useEffect(() => {\n const controller = new AbortController()\n setTools(null)\n setError(null)\n fetchMcpTools(origin, controller.signal)\n .then(setTools)\n .catch((err: unknown) => {\n if (controller.signal.aborted) return\n setError(\n err instanceof Error\n ? err.message\n : 'Could not reach the MCP endpoint.',\n )\n })\n return () => controller.abort()\n }, [origin, reloadKey])\n\n const mcpJson = JSON.stringify(\n {\n mcpServers: {\n [serverName]: { type: 'http', url: endpoint },\n },\n },\n null,\n 2,\n )\n const cliCommand = `claude mcp add --transport http ${serverName} ${endpoint}`\n\n return (\n <div className=\"flex flex-col flex-1 min-h-0 overflow-y-auto\">\n <div className=\"flex flex-col gap-8 w-full max-w-3xl mx-auto pb-8\">\n <section className=\"flex flex-col gap-2\">\n <h1\n ref={headingRef}\n tabIndex={-1}\n className=\"text-xl font-semibold outline-none\"\n >\n MCP server\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n This catalog exposes a{' '}\n <a\n href=\"https://modelcontextprotocol.io\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-primary hover:underline\"\n >\n Model Context Protocol\n </a>{' '}\n server, so an AI agent can search the catalog and read an entry the\n same way you can — what exists, who owns it, and how to request\n access. Point your agent at the endpoint below and it gains those\n tools; no key or account is needed.\n </p>\n <p className=\"text-sm text-muted-foreground\">\n It speaks MCP over Streamable HTTP (JSON-RPC over{' '}\n <code className=\"text-xs\">POST</code>), and it is read-only.\n </p>\n </section>\n\n <Snippet\n title=\"Endpoint\"\n description=\"The URL an MCP client connects to.\"\n value={endpoint}\n />\n\n <Snippet\n title=\"Add it with the CLI\"\n description=\"One command, if your agent ships a CLI that manages MCP servers.\"\n value={cliCommand}\n />\n\n <Snippet\n title=\"Or add it to .mcp.json\"\n description=\"Commit this in a project so everyone working on it gets the same tools.\"\n value={mcpJson}\n language=\"json\"\n />\n\n <section\n className=\"flex flex-col gap-3\"\n aria-busy={tools === null && error === null}\n >\n <div className=\"flex flex-col gap-1\">\n <h2 className=\"text-base font-semibold\">Tools</h2>\n <p className=\"text-xs text-muted-foreground\">\n Read live from the server, so this list is always what your agent\n will actually see.\n </p>\n </div>\n\n {error !== null ? (\n <div\n role=\"alert\"\n className=\"flex flex-col items-start gap-3 rounded-md border border-destructive/40 bg-destructive/5 p-4\"\n >\n <p className=\"flex items-start gap-2 text-sm\">\n <TriangleAlert className=\"size-4 shrink-0 mt-0.5 text-destructive\" />\n <span>\n Could not read the tool list. {error} The setup instructions\n above are still correct.\n </span>\n </p>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setReloadKey((k) => k + 1)}\n >\n Try again\n </Button>\n </div>\n ) : tools === null ? (\n <p className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner className=\"size-4\" />\n Reading the tool list…\n </p>\n ) : tools.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n The server reported no tools.\n </p>\n ) : (\n <ul className=\"flex flex-col gap-4 list-none p-0 m-0\">\n {tools.map((tool) => (\n <li\n key={tool.name}\n className=\"rounded-md border p-4 flex flex-col gap-2\"\n >\n <code className=\"text-sm font-semibold\">{tool.name}</code>\n {tool.description && (\n <p className=\"text-sm text-muted-foreground\">\n {tool.description}\n </p>\n )}\n {tool.parameters.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n No parameters.\n </p>\n ) : (\n <dl className=\"flex flex-col gap-2 m-0\">\n {tool.parameters.map((param) => (\n <div key={param.name} className=\"flex flex-col gap-0.5\">\n <dt className=\"text-xs\">\n <code className=\"font-medium\">{param.name}</code>\n {param.type && (\n <span className=\"text-muted-foreground\">\n {' '}\n {param.type}\n </span>\n )}\n <span className=\"text-muted-foreground\">\n {' '}\n — {param.required ? 'required' : 'optional'}\n </span>\n </dt>\n {param.description && (\n <dd className=\"text-xs text-muted-foreground m-0\">\n {param.description}\n </dd>\n )}\n {param.enumValues && (\n <dd className=\"text-xs text-muted-foreground m-0\">\n One of: {param.enumValues.join(', ')}\n </dd>\n )}\n </div>\n ))}\n </dl>\n )}\n </li>\n ))}\n </ul>\n )}\n </section>\n </div>\n </div>\n )\n}\n\nfunction Snippet({\n title,\n description,\n value,\n language,\n}: {\n title: string\n description: string\n value: string\n language?: string\n}) {\n return (\n <section className=\"flex flex-col gap-2\">\n <h2 className=\"text-base font-semibold\">{title}</h2>\n <p className=\"text-xs text-muted-foreground\">{description}</p>\n <div className=\"relative\">\n <pre\n className=\"overflow-x-auto rounded-md border bg-muted/40 p-3 pr-12 text-xs\"\n data-language={language}\n >\n <code>{value}</code>\n </pre>\n <CopyButton value={value} label={title} />\n </div>\n </section>\n )\n}\n\nfunction CopyButton({ value, label }: { value: string; label: string }) {\n const [copied, setCopied] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n useEffect(\n () => () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n },\n [],\n )\n\n const copy = useCallback(() => {\n void navigator.clipboard.writeText(value)\n setCopied(true)\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n timeoutRef.current = setTimeout(() => setCopied(false), 2000)\n }, [value])\n\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={copy}\n aria-label={copied ? `${label} copied` : `Copy ${label}`}\n title={copied ? 'Copied' : 'Copy'}\n className=\"absolute right-1.5 top-1.5\"\n >\n {copied ? (\n <Check className=\"size-4 text-primary\" />\n ) : (\n <Copy className=\"size-4\" />\n )}\n </Button>\n )\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@igstack/app-catalog-frontend-core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1-alpha-20260914185229",
|
|
4
4
|
"description": "Frontend core library for App Catalog",
|
|
5
5
|
"homepage": "https://github.com/lislon/app-catalog",
|
|
6
6
|
"repository": {
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"tailwindcss": "^4.1.7",
|
|
114
114
|
"tiptap-markdown": "^0.8.0",
|
|
115
115
|
"tslib": "^2.3.0",
|
|
116
|
-
"@igstack/app-catalog-shared-core": "1.0.
|
|
116
|
+
"@igstack/app-catalog-shared-core": "1.0.1-alpha-20260914185229"
|
|
117
117
|
},
|
|
118
118
|
"devDependencies": {
|
|
119
119
|
"@tailwindcss/vite": "^4.0.5",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
"vite-plugin-static-copy": "^3.1.4",
|
|
141
141
|
"vite-plugin-svgr": "^4.2.0",
|
|
142
142
|
"vitest": "^4.1.2",
|
|
143
|
-
"@igstack/app-catalog-backend-core": "1.0.
|
|
143
|
+
"@igstack/app-catalog-backend-core": "1.0.1-alpha-20260914185229"
|
|
144
144
|
},
|
|
145
145
|
"peerDependencies": {
|
|
146
146
|
"react": "19.1.2",
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
"vite": "^6.3.5",
|
|
150
150
|
"vite-plugin-svgr": "^4.2.0"
|
|
151
151
|
},
|
|
152
|
-
"gitHead": "
|
|
152
|
+
"gitHead": "9c6fb866faa7d95ad35d17fe04aaed0218ecbdf5",
|
|
153
153
|
"scripts": {
|
|
154
154
|
"build": "vite build",
|
|
155
155
|
"build:lenient": "vite build --mode lenient",
|
|
@@ -61,7 +61,7 @@ export function McpPage() {
|
|
|
61
61
|
|
|
62
62
|
return (
|
|
63
63
|
<div className="flex flex-col flex-1 min-h-0 overflow-y-auto">
|
|
64
|
-
<div className="flex flex-col gap-8 max-w-3xl pb-8">
|
|
64
|
+
<div className="flex flex-col gap-8 w-full max-w-3xl mx-auto pb-8">
|
|
65
65
|
<section className="flex flex-col gap-2">
|
|
66
66
|
<h1
|
|
67
67
|
ref={headingRef}
|