tabbied-mcp 0.2.2 → 0.2.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.
- package/LICENSE +21 -21
- package/README.md +83 -83
- package/dist/index.js.map +1 -1
- package/dist/info.d.ts +1 -1
- package/dist/info.js +10 -9
- package/dist/info.js.map +1 -1
- package/dist/node/render.js.map +1 -1
- package/dist/node/resources.js.map +1 -1
- package/dist/server.js.map +1 -1
- package/dist/stdio.js.map +1 -1
- package/dist/templates.js.map +1 -1
- package/dist/tools.js.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +56 -55
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Sy Hong and Ye Joo Park
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sy Hong and Ye Joo Park
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
# tabbied-mcp
|
|
2
|
-
|
|
3
|
-
An [MCP](https://modelcontextprotocol.io) server for
|
|
4
|
-
[Tabbied](https://tabbied.com): search 338 generative pattern designs, look at
|
|
5
|
-
them, and render them to SVG or PNG - from Claude Code, Claude Desktop, Cursor,
|
|
6
|
-
or any other MCP client.
|
|
7
|
-
|
|
8
|
-
## Use it without installing anything
|
|
9
|
-
|
|
10
|
-
The same server runs at `https://tabbied.com/mcp`:
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
claude mcp add --transport http tabbied https://tabbied.com/mcp
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
```jsonc
|
|
17
|
-
{
|
|
18
|
-
"mcpServers": {
|
|
19
|
-
"tabbied": { "url": "https://tabbied.com/mcp" }
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Or run it locally, and render real files
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
claude mcp add tabbied -- npx -y tabbied-mcp
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
```jsonc
|
|
31
|
-
{
|
|
32
|
-
"mcpServers": {
|
|
33
|
-
"tabbied": { "command": "npx", "args": ["-y", "tabbied-mcp"] }
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
The local server adds `render_design`, which the remote one cannot offer -
|
|
39
|
-
rendering a css-doodle pattern needs a real browser. Install a Playwright
|
|
40
|
-
alongside it (`npm i -D playwright`) or point `TABBIED_CHROMIUM` at a Chromium
|
|
41
|
-
binary.
|
|
42
|
-
|
|
43
|
-
## Tools
|
|
44
|
-
|
|
45
|
-
| Tool | What it does |
|
|
46
|
-
| --- | --- |
|
|
47
|
-
| `search_designs` | Filter by motif, mood, density, intended use, free text, or SVG-export support. |
|
|
48
|
-
| `get_design` | The full record for one slug, plus ready-to-paste snippets. |
|
|
49
|
-
| `preview_design` | The rendered preview image for up to six designs, so the model can *look*. |
|
|
50
|
-
| `get_docs` | The complete API reference (`llms-full.txt`). |
|
|
51
|
-
| `render_design` | SVG or PNG at any size, seed, palette, and option set. **Local only.** |
|
|
52
|
-
|
|
53
|
-
Slugs are opaque - `cleat`, `karst`, `radius` - so the intended flow is
|
|
54
|
-
`search_designs` to narrow, `preview_design` to look, then `get_design` for the
|
|
55
|
-
options. Choosing off tags alone is the main way this goes wrong.
|
|
56
|
-
|
|
57
|
-
## Programmatic use
|
|
58
|
-
|
|
59
|
-
The package's main entry point is runtime-agnostic (no node imports), so it can
|
|
60
|
-
be embedded in a Worker or any Web-standard server. It exposes the tools and an
|
|
61
|
-
`McpServer` factory; the transport is the MCP SDK's:
|
|
62
|
-
|
|
63
|
-
```ts
|
|
64
|
-
import { createMcpHandler } from '@modelcontextprotocol/server';
|
|
65
|
-
import { buildServer, catalogTools } from 'tabbied-mcp';
|
|
66
|
-
|
|
67
|
-
const tools = catalogTools({ catalog, fetchPreview, fetchDocs });
|
|
68
|
-
|
|
69
|
-
export default {
|
|
70
|
-
fetch: createMcpHandler(() => buildServer(tools)).fetch,
|
|
71
|
-
};
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Pass the *factory*, not a built server: MCP v2 is stateless and the handler
|
|
75
|
-
constructs one server per request.
|
|
76
|
-
|
|
77
|
-
Built on [`@modelcontextprotocol/server`](https://www.npmjs.com/package/@modelcontextprotocol/server)
|
|
78
|
-
v2, so it speaks the stateless `2026-07-28` revision and still serves 2025-era
|
|
79
|
-
clients. `docs/mcp-server.md` in the repository has the details.
|
|
80
|
-
|
|
81
|
-
## License
|
|
82
|
-
|
|
83
|
-
MIT
|
|
1
|
+
# tabbied-mcp
|
|
2
|
+
|
|
3
|
+
An [MCP](https://modelcontextprotocol.io) server for
|
|
4
|
+
[Tabbied](https://tabbied.com): search 338 generative pattern designs, look at
|
|
5
|
+
them, and render them to SVG or PNG - from Claude Code, Claude Desktop, Cursor,
|
|
6
|
+
or any other MCP client.
|
|
7
|
+
|
|
8
|
+
## Use it without installing anything
|
|
9
|
+
|
|
10
|
+
The same server runs at `https://tabbied.com/mcp`:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
claude mcp add --transport http tabbied https://tabbied.com/mcp
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```jsonc
|
|
17
|
+
{
|
|
18
|
+
"mcpServers": {
|
|
19
|
+
"tabbied": { "url": "https://tabbied.com/mcp" }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Or run it locally, and render real files
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
claude mcp add tabbied -- npx -y tabbied-mcp
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```jsonc
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"tabbied": { "command": "npx", "args": ["-y", "tabbied-mcp"] }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The local server adds `render_design`, which the remote one cannot offer -
|
|
39
|
+
rendering a css-doodle pattern needs a real browser. Install a Playwright
|
|
40
|
+
alongside it (`npm i -D playwright`) or point `TABBIED_CHROMIUM` at a Chromium
|
|
41
|
+
binary.
|
|
42
|
+
|
|
43
|
+
## Tools
|
|
44
|
+
|
|
45
|
+
| Tool | What it does |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `search_designs` | Filter by motif, mood, density, intended use, free text, or SVG-export support. |
|
|
48
|
+
| `get_design` | The full record for one slug, plus ready-to-paste snippets. |
|
|
49
|
+
| `preview_design` | The rendered preview image for up to six designs, so the model can *look*. |
|
|
50
|
+
| `get_docs` | The complete API reference (`llms-full.txt`). |
|
|
51
|
+
| `render_design` | SVG or PNG at any size, seed, palette, and option set. **Local only.** |
|
|
52
|
+
|
|
53
|
+
Slugs are opaque - `cleat`, `karst`, `radius` - so the intended flow is
|
|
54
|
+
`search_designs` to narrow, `preview_design` to look, then `get_design` for the
|
|
55
|
+
options. Choosing off tags alone is the main way this goes wrong.
|
|
56
|
+
|
|
57
|
+
## Programmatic use
|
|
58
|
+
|
|
59
|
+
The package's main entry point is runtime-agnostic (no node imports), so it can
|
|
60
|
+
be embedded in a Worker or any Web-standard server. It exposes the tools and an
|
|
61
|
+
`McpServer` factory; the transport is the MCP SDK's:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { createMcpHandler } from '@modelcontextprotocol/server';
|
|
65
|
+
import { buildServer, catalogTools } from 'tabbied-mcp';
|
|
66
|
+
|
|
67
|
+
const tools = catalogTools({ catalog, fetchPreview, fetchDocs });
|
|
68
|
+
|
|
69
|
+
export default {
|
|
70
|
+
fetch: createMcpHandler(() => buildServer(tools)).fetch,
|
|
71
|
+
};
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Pass the *factory*, not a built server: MCP v2 is stateless and the handler
|
|
75
|
+
constructs one server per request.
|
|
76
|
+
|
|
77
|
+
Built on [`@modelcontextprotocol/server`](https://www.npmjs.com/package/@modelcontextprotocol/server)
|
|
78
|
+
v2, so it speaks the stateless `2026-07-28` revision and still serves 2025-era
|
|
79
|
+
clients. `docs/mcp-server.md` in the repository has the details.
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
|
|
83
|
+
MIT
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,4EAA4E;AAC5E,4EAA4E;AAC5E,0EAA0E;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAgB,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC","sourcesContent":["// The runtime-agnostic half of the server: the tool definitions and the\
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,4EAA4E;AAC5E,4EAA4E;AAC5E,0EAA0E;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAgB,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC","sourcesContent":["// The runtime-agnostic half of the server: the tool definitions and the\n// `McpServer` factory. Nothing reachable from here may import node, because\n// this entry point is what the Cloudflare Worker bundles; the local catalog\n// reader and `render_design` live behind the bin. See docs/mcp-server.md.\nexport { buildServer } from './server.js';\nexport { catalogTools, createToolset, type Toolset } from './tools.js';\nexport { templateTools } from './templates.js';\nexport { INSTRUCTIONS, SERVER_NAME, VERSION } from './info.js';\nexport type {\n Catalog,\n CatalogDesign,\n CatalogOption,\n TemplateCatalog,\n TemplateCatalogEntry,\n TemplateSpec,\n Tool,\n ToolContent,\n ToolContext,\n ToolDefinition,\n ToolResult,\n} from './types.js';\n"]}
|
package/dist/info.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const SERVER_NAME = "tabbied";
|
|
2
|
-
export declare const VERSION = "0.2.
|
|
2
|
+
export declare const VERSION = "0.2.3";
|
|
3
3
|
/**
|
|
4
4
|
* Shown to the model as a preamble. It carries what no tool description can,
|
|
5
5
|
* because they are properties of the *set* rather than of one call: slugs
|
package/dist/info.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// Server identity and the instructions clients hand to the model.
|
|
2
2
|
//
|
|
3
3
|
// VERSION is a literal rather than a package.json read because this module is
|
|
4
|
-
// bundled into a Cloudflare Worker, which has no filesystem.
|
|
5
|
-
//
|
|
4
|
+
// bundled into a Cloudflare Worker, which has no filesystem. The release's
|
|
5
|
+
// `version-packages` step rewrites it from package.json
|
|
6
|
+
// (scripts/sync-version.mjs), and test/info.test.mjs pins the two together.
|
|
6
7
|
export const SERVER_NAME = 'tabbied';
|
|
7
|
-
export const VERSION = '0.2.
|
|
8
|
+
export const VERSION = '0.2.3';
|
|
8
9
|
/**
|
|
9
10
|
* Shown to the model as a preamble. It carries what no tool description can,
|
|
10
11
|
* because they are properties of the *set* rather than of one call: slugs
|
|
@@ -12,11 +13,11 @@ export const VERSION = '0.2.2';
|
|
|
12
13
|
* sizing rule is the most common way a correct-looking integration renders as
|
|
13
14
|
* nothing.
|
|
14
15
|
*/
|
|
15
|
-
export const INSTRUCTIONS = `Tabbied is a catalog of generative patterns (css-doodle) usable as backgrounds, textures, posters, and exported SVG/PNG assets.
|
|
16
|
-
|
|
17
|
-
Designs are addressed by slug, and slugs are opaque - "cleat", "karst", "radius" say nothing about what they look like. Never guess one: call search_designs, which filters on a closed vocabulary of motifs, moods, density, and intended use.
|
|
18
|
-
|
|
19
|
-
Metadata narrows the field; it does not settle it. These are pictures, so call preview_design on your shortlist and look before you commit. Choosing off tags alone is the main way this goes wrong.
|
|
20
|
-
|
|
16
|
+
export const INSTRUCTIONS = `Tabbied is a catalog of generative patterns (css-doodle) usable as backgrounds, textures, posters, and exported SVG/PNG assets.
|
|
17
|
+
|
|
18
|
+
Designs are addressed by slug, and slugs are opaque - "cleat", "karst", "radius" say nothing about what they look like. Never guess one: call search_designs, which filters on a closed vocabulary of motifs, moods, density, and intended use.
|
|
19
|
+
|
|
20
|
+
Metadata narrows the field; it does not settle it. These are pictures, so call preview_design on your shortlist and look before you commit. Choosing off tags alone is the main way this goes wrong.
|
|
21
|
+
|
|
21
22
|
When you write integration code, remember a pattern has no intrinsic size: it fills its parent and collapses to nothing in a parent that sizes to content. Pass height or aspectRatio unless the parent is definitely sized. get_docs has the full API contract and recipes.`;
|
|
22
23
|
//# sourceMappingURL=info.js.map
|
package/dist/info.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.js","sourceRoot":"","sources":["../src/info.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,8EAA8E;AAC9E,
|
|
1
|
+
{"version":3,"file":"info.js","sourceRoot":"","sources":["../src/info.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,8EAA8E;AAC9E,2EAA2E;AAC3E,wDAAwD;AACxD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AACrC,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;6QAMiP,CAAC","sourcesContent":["// Server identity and the instructions clients hand to the model.\n//\n// VERSION is a literal rather than a package.json read because this module is\n// bundled into a Cloudflare Worker, which has no filesystem. The release's\n// `version-packages` step rewrites it from package.json\n// (scripts/sync-version.mjs), and test/info.test.mjs pins the two together.\nexport const SERVER_NAME = 'tabbied';\nexport const VERSION = '0.2.3';\n\n/**\n * Shown to the model as a preamble. It carries what no tool description can,\n * because they are properties of the *set* rather than of one call: slugs\n * cannot be guessed, the previews are what a choice should rest on, and the\n * sizing rule is the most common way a correct-looking integration renders as\n * nothing.\n */\nexport const INSTRUCTIONS = `Tabbied is a catalog of generative patterns (css-doodle) usable as backgrounds, textures, posters, and exported SVG/PNG assets.\n\nDesigns are addressed by slug, and slugs are opaque - \"cleat\", \"karst\", \"radius\" say nothing about what they look like. Never guess one: call search_designs, which filters on a closed vocabulary of motifs, moods, density, and intended use.\n\nMetadata narrows the field; it does not settle it. These are pictures, so call preview_design on your shortlist and look before you commit. Choosing off tags alone is the main way this goes wrong.\n\nWhen you write integration code, remember a pattern has no intrinsic size: it fills its parent and collapses to nothing in a parent that sizes to content. Pass height or aspectRatio unless the parent is definitely sized. get_docs has the full API contract and recipes.`;\n"]}
|
package/dist/node/render.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/node/render.ts"],"names":[],"mappings":"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","sourcesContent":["// `render_design`, the one tool that only exists over stdio.\r\n//\r\n// It shells out to the `tabbied` CLI: the only faithful renderer for a\r\n// css-doodle pattern is css-doodle in a real browser (see docs/svg-export.md),\r\n// and the CLI already owns the headless browser, the SVG converter, and the\r\n// option parsing. A Worker has no browser, so it doesn't offer the tool.\r\nimport { execFile } from 'node:child_process';\r\nimport { mkdtemp, readFile, rm, stat } from 'node:fs/promises';\r\nimport { tmpdir } from 'node:os';\r\nimport path from 'node:path';\r\nimport { promisify } from 'node:util';\r\n\r\nimport type { Catalog, Tool, ToolResult } from '../types.js';\r\nimport { tabbiedRoot } from './resources.js';\r\n\r\nconst run = promisify(execFile);\r\n\r\n// Rendering launches a browser and waits for the first arrangement to settle.\r\nconst RENDER_TIMEOUT_MS = 180_000;\r\n\r\n// A PNG returned inline is spent context. Past this the file stays on disk and\r\n// the agent gets the path - better a usable pointer than a truncated image.\r\nconst INLINE_BYTE_BUDGET = 1_500_000;\r\n\r\nconst text = (value: string) => ({ type: 'text' as const, text: value });\r\n\r\nconst toolError = (message: string): ToolResult => ({\r\n content: [text(message)],\r\n isError: true,\r\n});\r\n\r\nexport function renderTool(catalog: Catalog): Tool {\r\n return {\r\n definition: {\r\n name: 'render_design',\r\n title: 'Render a design to a file',\r\n description:\r\n 'Render a design to SVG or PNG with a real browser, at any size, seed, ' +\r\n 'palette, and option set. Use this to produce an actual asset - or to ' +\r\n 'preview a *customized* configuration, which preview_design cannot show ' +\r\n 'you (it only has the stock palette and defaults). Needs Playwright ' +\r\n 'installed alongside this server. Without \"out\" the image comes back ' +\r\n 'inline; with it, the file is written where you ask.',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n slug: { type: 'string', description: 'The design to render.' },\r\n format: {\r\n type: 'string',\r\n enum: ['svg', 'png'],\r\n description:\r\n 'Vector or raster. A few designs cannot be vectorized - check ' +\r\n 'svgExport on the design first.',\r\n },\r\n out: {\r\n type: 'string',\r\n description:\r\n 'Absolute path to write to. Omit to get the image back inline ' +\r\n 'instead of on disk.',\r\n },\r\n seed: {\r\n type: 'string',\r\n description:\r\n 'Fixed seed - the same seed always gives the same image. Random ' +\r\n 'when omitted.',\r\n },\r\n palette: {\r\n type: 'array',\r\n items: { type: 'string' },\r\n description:\r\n \"CSS colors, background first. Omit for the design's authored palette.\",\r\n },\r\n options: {\r\n type: 'object',\r\n description:\r\n 'Option values keyed by option id, e.g. {\"scale\": 3}. Read the ' +\r\n 'ids and ranges off get_design.',\r\n },\r\n width: { type: 'integer', description: 'Pixels wide (default 960).' },\r\n height: { type: 'integer', description: 'Pixels tall (default 960).' },\r\n fit: {\r\n type: 'string',\r\n enum: ['grid', 'cover', 'fixed'],\r\n description: 'Sizing mode (default grid).',\r\n },\r\n scale: {\r\n type: 'integer',\r\n description:\r\n 'PNG device-scale factor. Defaults to 2 when writing a file and ' +\r\n '1 when returning inline, to keep the response small.',\r\n },\r\n },\r\n required: ['slug', 'format'],\r\n additionalProperties: false,\r\n },\r\n },\r\n\r\n async run(args): Promise<ToolResult> {\r\n const slug = typeof args.slug === 'string' ? args.slug : '';\r\n const design = catalog.designs.find((entry) => entry.slug === slug);\r\n if (!design) {\r\n return toolError(\r\n `No design with slug \"${slug}\". Use search_designs to find one.`\r\n );\r\n }\r\n\r\n const format = args.format === 'png' ? 'png' : 'svg';\r\n if (format === 'svg' && !design.svgExport.supported) {\r\n return toolError(\r\n `\"${slug}\" paints effects SVG cannot represent, so it has no vector ` +\r\n 'export. Render it as PNG instead.'\r\n );\r\n }\r\n\r\n const root = tabbiedRoot();\r\n if (!root) {\r\n return toolError(\r\n 'The `tabbied` package is not installed next to this server, so the ' +\r\n 'renderer is unavailable. Run `npm install tabbied`.'\r\n );\r\n }\r\n\r\n const inline = typeof args.out !== 'string' || args.out.length === 0;\r\n // An inline render gets a scratch directory, removed once its bytes\r\n // have been read back.\r\n const scratch = inline ? await mkdtemp(path.join(tmpdir(), 'tabbied-')) : null;\r\n const outPath = scratch ? path.join(scratch, `${slug}.${format}`) : (args.out as string);\r\n const discard = () => (scratch ? rm(scratch, { recursive: true, force: true }) : Promise.resolve());\r\n\r\n const scale =\r\n typeof args.scale === 'number' && Number.isFinite(args.scale)\r\n ? Math.trunc(args.scale)\r\n : inline\r\n ? 1\r\n : 2;\r\n\r\n const argv = [\r\n path.join(root, 'dist', 'cli.js'),\r\n 'render',\r\n slug,\r\n '--out',\r\n outPath,\r\n '--format',\r\n format,\r\n '--scale',\r\n String(scale),\r\n ];\r\n\r\n const push = (flag: string, value: string) => argv.push(flag, value);\r\n\r\n if (typeof args.seed === 'string' && args.seed) push('--seed', args.seed);\r\n if (typeof args.fit === 'string') push('--fit', args.fit);\r\n\r\n const width =\r\n typeof args.width === 'number' ? Math.trunc(args.width) : 960;\r\n const height =\r\n typeof args.height === 'number' ? Math.trunc(args.height) : 960;\r\n push('--size', `${width}x${height}`);\r\n\r\n if (Array.isArray(args.palette) && args.palette.length) {\r\n push('--palette', args.palette.filter(Boolean).join(','));\r\n }\r\n\r\n if (args.options && typeof args.options === 'object') {\r\n const pairs = Object.entries(args.options as Record<string, unknown>)\r\n .map(([id, value]) => `${id}: ${String(value)}`)\r\n .join('; ');\r\n if (pairs) push('--options', pairs);\r\n }\r\n\r\n let stderr = '';\r\n try {\r\n // No shell: argv goes straight to node, so a palette or option value\r\n // can't be read as shell syntax.\r\n ({ stderr } = await run(process.execPath, argv, {\r\n timeout: RENDER_TIMEOUT_MS,\r\n maxBuffer: 8 * 1024 * 1024,\r\n }));\r\n } catch (error) {\r\n const detail =\r\n error && typeof error === 'object' && 'stderr' in error\r\n ? String((error as { stderr: unknown }).stderr).trim()\r\n : error instanceof Error\r\n ? error.message\r\n : String(error);\r\n return toolError(\r\n `Rendering failed: ${detail || 'the CLI exited non-zero.'}\\n\\n` +\r\n 'If this says a browser is missing, install one alongside the ' +\r\n 'server (`npm i -D playwright`) or point TABBIED_CHROMIUM at a ' +\r\n 'Chromium binary.'\r\n );\r\n }\r\n\r\n // The CLI reports SVG-fidelity caveats on stderr; they matter enough to\r\n // pass through rather than swallow.\r\n const notes = stderr\r\n .split('\\n')\r\n .filter((line) => line.trim().startsWith('note:'))\r\n .join('\\n');\r\n\r\n if (!inline) {\r\n const { size } = await stat(outPath);\r\n return {\r\n content: [\r\n text(\r\n `Rendered ${slug} to ${outPath} (${width}x${height}` +\r\n (format === 'png' ? ` @${scale}x` : '') +\r\n `, ${Math.round(size / 1024)} KB).` +\r\n (notes ? `\\n${notes}` : '')\r\n ),\r\n ],\r\n };\r\n }\r\n\r\n if (format === 'svg') {\r\n const svg = await readFile(outPath, 'utf-8');\r\n await discard();\r\n return {\r\n content: [\r\n text(\r\n `Rendered ${slug} as SVG (${width}x${height}).` +\r\n (notes ? `\\n${notes}` : '')\r\n ),\r\n text(svg),\r\n ],\r\n };\r\n }\r\n\r\n const png = await readFile(outPath);\r\n const data = png.toString('base64');\r\n if (data.length > INLINE_BYTE_BUDGET) {\r\n // Kept: the answer tells the agent to read it from that path.\r\n return {\r\n content: [\r\n text(\r\n `Rendered ${slug} to ${outPath} - ${Math.round(\r\n png.byteLength / 1024\r\n )} KB, too large to return inline. Read it from that path, or ` +\r\n 're-render smaller (lower \"scale\", or a smaller width/height).'\r\n ),\r\n ],\r\n };\r\n }\r\n\r\n await discard();\r\n return {\r\n content: [\r\n text(\r\n `Rendered ${slug} (${width}x${height} @${scale}x).` +\r\n (notes ? `\\n${notes}` : '')\r\n ),\r\n { type: 'image', data, mimeType: 'image/png' },\r\n ],\r\n };\r\n },\r\n };\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/node/render.ts"],"names":[],"mappings":"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","sourcesContent":["// `render_design`, the one tool that only exists over stdio.\n//\n// It shells out to the `tabbied` CLI: the only faithful renderer for a\n// css-doodle pattern is css-doodle in a real browser (see docs/svg-export.md),\n// and the CLI already owns the headless browser, the SVG converter, and the\n// option parsing. A Worker has no browser, so it doesn't offer the tool.\nimport { execFile } from 'node:child_process';\nimport { mkdtemp, readFile, rm, stat } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\n\nimport type { Catalog, Tool, ToolResult } from '../types.js';\nimport { tabbiedRoot } from './resources.js';\n\nconst run = promisify(execFile);\n\n// Rendering launches a browser and waits for the first arrangement to settle.\nconst RENDER_TIMEOUT_MS = 180_000;\n\n// A PNG returned inline is spent context. Past this the file stays on disk and\n// the agent gets the path - better a usable pointer than a truncated image.\nconst INLINE_BYTE_BUDGET = 1_500_000;\n\nconst text = (value: string) => ({ type: 'text' as const, text: value });\n\nconst toolError = (message: string): ToolResult => ({\n content: [text(message)],\n isError: true,\n});\n\nexport function renderTool(catalog: Catalog): Tool {\n return {\n definition: {\n name: 'render_design',\n title: 'Render a design to a file',\n description:\n 'Render a design to SVG or PNG with a real browser, at any size, seed, ' +\n 'palette, and option set. Use this to produce an actual asset - or to ' +\n 'preview a *customized* configuration, which preview_design cannot show ' +\n 'you (it only has the stock palette and defaults). Needs Playwright ' +\n 'installed alongside this server. Without \"out\" the image comes back ' +\n 'inline; with it, the file is written where you ask.',\n inputSchema: {\n type: 'object',\n properties: {\n slug: { type: 'string', description: 'The design to render.' },\n format: {\n type: 'string',\n enum: ['svg', 'png'],\n description:\n 'Vector or raster. A few designs cannot be vectorized - check ' +\n 'svgExport on the design first.',\n },\n out: {\n type: 'string',\n description:\n 'Absolute path to write to. Omit to get the image back inline ' +\n 'instead of on disk.',\n },\n seed: {\n type: 'string',\n description:\n 'Fixed seed - the same seed always gives the same image. Random ' +\n 'when omitted.',\n },\n palette: {\n type: 'array',\n items: { type: 'string' },\n description:\n \"CSS colors, background first. Omit for the design's authored palette.\",\n },\n options: {\n type: 'object',\n description:\n 'Option values keyed by option id, e.g. {\"scale\": 3}. Read the ' +\n 'ids and ranges off get_design.',\n },\n width: { type: 'integer', description: 'Pixels wide (default 960).' },\n height: { type: 'integer', description: 'Pixels tall (default 960).' },\n fit: {\n type: 'string',\n enum: ['grid', 'cover', 'fixed'],\n description: 'Sizing mode (default grid).',\n },\n scale: {\n type: 'integer',\n description:\n 'PNG device-scale factor. Defaults to 2 when writing a file and ' +\n '1 when returning inline, to keep the response small.',\n },\n },\n required: ['slug', 'format'],\n additionalProperties: false,\n },\n },\n\n async run(args): Promise<ToolResult> {\n const slug = typeof args.slug === 'string' ? args.slug : '';\n const design = catalog.designs.find((entry) => entry.slug === slug);\n if (!design) {\n return toolError(\n `No design with slug \"${slug}\". Use search_designs to find one.`\n );\n }\n\n const format = args.format === 'png' ? 'png' : 'svg';\n if (format === 'svg' && !design.svgExport.supported) {\n return toolError(\n `\"${slug}\" paints effects SVG cannot represent, so it has no vector ` +\n 'export. Render it as PNG instead.'\n );\n }\n\n const root = tabbiedRoot();\n if (!root) {\n return toolError(\n 'The `tabbied` package is not installed next to this server, so the ' +\n 'renderer is unavailable. Run `npm install tabbied`.'\n );\n }\n\n const inline = typeof args.out !== 'string' || args.out.length === 0;\n // An inline render gets a scratch directory, removed once its bytes\n // have been read back.\n const scratch = inline ? await mkdtemp(path.join(tmpdir(), 'tabbied-')) : null;\n const outPath = scratch ? path.join(scratch, `${slug}.${format}`) : (args.out as string);\n const discard = () => (scratch ? rm(scratch, { recursive: true, force: true }) : Promise.resolve());\n\n const scale =\n typeof args.scale === 'number' && Number.isFinite(args.scale)\n ? Math.trunc(args.scale)\n : inline\n ? 1\n : 2;\n\n const argv = [\n path.join(root, 'dist', 'cli.js'),\n 'render',\n slug,\n '--out',\n outPath,\n '--format',\n format,\n '--scale',\n String(scale),\n ];\n\n const push = (flag: string, value: string) => argv.push(flag, value);\n\n if (typeof args.seed === 'string' && args.seed) push('--seed', args.seed);\n if (typeof args.fit === 'string') push('--fit', args.fit);\n\n const width =\n typeof args.width === 'number' ? Math.trunc(args.width) : 960;\n const height =\n typeof args.height === 'number' ? Math.trunc(args.height) : 960;\n push('--size', `${width}x${height}`);\n\n if (Array.isArray(args.palette) && args.palette.length) {\n push('--palette', args.palette.filter(Boolean).join(','));\n }\n\n if (args.options && typeof args.options === 'object') {\n const pairs = Object.entries(args.options as Record<string, unknown>)\n .map(([id, value]) => `${id}: ${String(value)}`)\n .join('; ');\n if (pairs) push('--options', pairs);\n }\n\n let stderr = '';\n try {\n // No shell: argv goes straight to node, so a palette or option value\n // can't be read as shell syntax.\n ({ stderr } = await run(process.execPath, argv, {\n timeout: RENDER_TIMEOUT_MS,\n maxBuffer: 8 * 1024 * 1024,\n }));\n } catch (error) {\n const detail =\n error && typeof error === 'object' && 'stderr' in error\n ? String((error as { stderr: unknown }).stderr).trim()\n : error instanceof Error\n ? error.message\n : String(error);\n return toolError(\n `Rendering failed: ${detail || 'the CLI exited non-zero.'}\\n\\n` +\n 'If this says a browser is missing, install one alongside the ' +\n 'server (`npm i -D playwright`) or point TABBIED_CHROMIUM at a ' +\n 'Chromium binary.'\n );\n }\n\n // The CLI reports SVG-fidelity caveats on stderr; they matter enough to\n // pass through rather than swallow.\n const notes = stderr\n .split('\\n')\n .filter((line) => line.trim().startsWith('note:'))\n .join('\\n');\n\n if (!inline) {\n const { size } = await stat(outPath);\n return {\n content: [\n text(\n `Rendered ${slug} to ${outPath} (${width}x${height}` +\n (format === 'png' ? ` @${scale}x` : '') +\n `, ${Math.round(size / 1024)} KB).` +\n (notes ? `\\n${notes}` : '')\n ),\n ],\n };\n }\n\n if (format === 'svg') {\n const svg = await readFile(outPath, 'utf-8');\n await discard();\n return {\n content: [\n text(\n `Rendered ${slug} as SVG (${width}x${height}).` +\n (notes ? `\\n${notes}` : '')\n ),\n text(svg),\n ],\n };\n }\n\n const png = await readFile(outPath);\n const data = png.toString('base64');\n if (data.length > INLINE_BYTE_BUDGET) {\n // Kept: the answer tells the agent to read it from that path.\n return {\n content: [\n text(\n `Rendered ${slug} to ${outPath} - ${Math.round(\n png.byteLength / 1024\n )} KB, too large to return inline. Read it from that path, or ` +\n 're-render smaller (lower \"scale\", or a smaller width/height).'\n ),\n ],\n };\n }\n\n await discard();\n return {\n content: [\n text(\n `Rendered ${slug} (${width}x${height} @${scale}x).` +\n (notes ? `\\n${notes}` : '')\n ),\n { type: 'image', data, mimeType: 'image/png' },\n ],\n };\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/node/resources.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,wEAAwE;AACxE,yDAAyD;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAS7B,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,MAAM,IAAI,GAAG,qBAAqB,CAAC;AAEnC,iFAAiF;AACjF,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAE3B,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CACf,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAC9C,CAAC;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,yEAAyE;YACzE,uEAAuE;YACvE,qDAAqD;YACrD,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACtE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kDAAkD,MAAM,KAAK;gBAC3D,mBAAmB,IAAI,iBAAiB,CAC3C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,eAAe,CAAC,CAAC;IACrD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,wBAAwB,IAAI,0BAA0B,QAAQ,CAAC,MAAM,IAAI;YACvE,0EAA0E,CAC7E,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAY,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAqB;IAErB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,aAAa,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;IACzD,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC/B,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,YAAY;KAC/D,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,IAAI,GAAG,WAAW,EAAE,CAAC;IAC3B,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,mCAAmC;QACrC,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,gBAAgB,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,2BAA2B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,wBAAwB,CAAC,CAAC;IAE9D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,mCAAmC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAoB,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,aAAa,IAAI,OAAO,CAAC,CAAC;IAE9D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,aAAa,IAAI,kBAAkB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAiB,CAAC;AACjD,CAAC","sourcesContent":["// Where the stdio server gets its catalog, previews, and docs.\
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../../src/node/resources.ts"],"names":[],"mappings":"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","sourcesContent":["// Where the stdio server gets its catalog, previews, and docs.\n//\n// The catalog is read from the installed `tabbied` package rather than fetched,\n// so the tools describe exactly the version the caller will `npm install`: a\n// design that only exists on the site would give an import that doesn't\n// resolve. The network is the fallback, not the default.\nimport { createRequire } from 'node:module';\nimport { readFile } from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type {\n Catalog,\n CatalogDesign,\n TemplateCatalog,\n TemplateSpec,\n} from '../types.js';\n\nconst require = createRequire(import.meta.url);\n\nconst SITE = 'https://tabbied.com';\n\n/** Root of the installed `tabbied` package, or null when it isn't resolvable. */\nexport function tabbiedRoot(): string | null {\n try {\n return path.dirname(require.resolve('tabbied/package.json'));\n } catch {\n return null;\n }\n}\n\nexport async function loadCatalog(): Promise<Catalog> {\n const root = tabbiedRoot();\n\n if (root) {\n try {\n return JSON.parse(\n await readFile(path.join(root, 'catalog.json'), 'utf-8')\n ) as Catalog;\n } catch (error) {\n // A resolvable package with no catalog.json means a source checkout that\n // hasn't been built. Say so - the network copy would silently disagree\n // with the local patterns the user is about to edit.\n const reason = error instanceof Error ? error.message : String(error);\n process.stderr.write(\n `tabbied-mcp: could not read the local catalog (${reason}); ` +\n `falling back to ${SITE}/catalog.json\\n`\n );\n }\n }\n\n const response = await fetch(`${SITE}/catalog.json`);\n if (!response.ok) {\n throw new Error(\n `no local catalog and ${SITE}/catalog.json returned ${response.status}. ` +\n 'Install the `tabbied` package (npm i tabbied) or restore network access.'\n );\n }\n return (await response.json()) as Catalog;\n}\n\n/**\n * Preview bytes for one design: the committed @2x renders the site serves, so\n * the agent sees the same image a human browsing the gallery does.\n */\nexport async function fetchPreview(\n design: CatalogDesign\n): Promise<{ data: string; mimeType: string }> {\n const response = await fetch(design.preview);\n if (!response.ok) {\n throw new Error(`${design.preview} returned ${response.status}`);\n }\n const buffer = Buffer.from(await response.arrayBuffer());\n return {\n data: buffer.toString('base64'),\n mimeType: response.headers.get('Content-Type') ?? 'image/webp',\n };\n}\n\n/**\n * The full reference. The package's own llms.txt is the *full* text (in\n * node_modules depth beats brevity), so this works offline too.\n */\nexport async function fetchDocs(): Promise<string> {\n const root = tabbiedRoot();\n if (root) {\n try {\n return await readFile(path.join(root, 'llms.txt'), 'utf-8');\n } catch {\n // fall through to the network copy\n }\n }\n\n const response = await fetch(`${SITE}/llms-full.txt`);\n if (!response.ok) {\n throw new Error(`${SITE}/llms-full.txt returned ${response.status}`);\n }\n return await response.text();\n}\n\n/**\n * The editable-template index and one site's spec. Network only, deliberately:\n * they are *site* artifacts generated from the static export\n * (docs/editable-templates.md), and the `tabbied` package does not contain them.\n */\nexport async function fetchTemplateCatalog(): Promise<TemplateCatalog> {\n const response = await fetch(`${SITE}/editable-catalog.json`);\n\n if (!response.ok) {\n throw new Error(`${SITE}/editable-catalog.json returned ${response.status}`);\n }\n\n return (await response.json()) as TemplateCatalog;\n}\n\nexport async function fetchTemplate(slug: string): Promise<TemplateSpec> {\n const response = await fetch(`${SITE}/editable/${slug}.json`);\n\n if (!response.ok) {\n throw new Error(`${SITE}/editable/${slug}.json returned ${response.status}`);\n }\n\n return (await response.json()) as TemplateSpec;\n}\n"]}
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,6EAA6E;AAC7E,sEAAsE;AACtE,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,qBAAqB;AACrB,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG/D;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,EACvC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE,CAC5D,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,YAAY,CACjB,IAAI,CAAC,UAAU,CAAC,IAAI,EACpB;YACE,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;YAC5B,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW;YACxC,WAAW,EAAE,cAAc,CACzB,IAAI,CAAC,UAAU,CAAC,WAAW,CAC5B;SACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAU,CACtD,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["// Turns the runtime-agnostic toolset into an SDK `McpServer`. The Worker hands\
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,6EAA6E;AAC7E,sEAAsE;AACtE,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,qBAAqB;AACrB,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG/D;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,EACvC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE,CAC5D,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,YAAY,CACjB,IAAI,CAAC,UAAU,CAAC,IAAI,EACpB;YACE,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK;YAC5B,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW;YACxC,WAAW,EAAE,cAAc,CACzB,IAAI,CAAC,UAAU,CAAC,WAAW,CAC5B;SACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAU,CACtD,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["// Turns the runtime-agnostic toolset into an SDK `McpServer`. The Worker hands\n// the factory to `createMcpHandler` and the bin hands it to `serveStdio`, so\n// both transports get the same tools, instructions, and era handling.\n//\n// A *factory*, not an instance: MCP v2 is stateless and the SDK builds one\n// server per request (per connection on stdio). Nothing here may capture\n// per-request state.\nimport { McpServer, fromJsonSchema } from '@modelcontextprotocol/server';\n\nimport { INSTRUCTIONS, SERVER_NAME, VERSION } from './info.js';\nimport type { Tool } from './types.js';\n\n/**\n * Register a toolset onto a fresh `McpServer`.\n *\n * Tool schemas stay plain JSON Schema, adapted by `fromJsonSchema`, because\n * `search_designs`'s enums are derived from the catalog being served and so\n * cannot be static Zod. Registering the schema also makes the SDK validate\n * arguments: a bad enum value comes back as a tool error naming the allowed\n * values instead of silently matching nothing.\n */\nexport function buildServer(tools: Tool[]): McpServer {\n const server = new McpServer(\n { name: SERVER_NAME, version: VERSION },\n { capabilities: { tools: {} }, instructions: INSTRUCTIONS }\n );\n\n for (const tool of tools) {\n server.registerTool(\n tool.definition.name,\n {\n title: tool.definition.title,\n description: tool.definition.description,\n inputSchema: fromJsonSchema<Record<string, unknown>>(\n tool.definition.inputSchema\n ),\n },\n async (args) => (await tool.run(args ?? {})) as never\n );\n }\n\n return server;\n}\n"]}
|
package/dist/stdio.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":";AACA,+EAA+E;AAC/E,+EAA+E;AAC/E,2EAA2E;AAC3E,uCAAuC;AACvC,EAAE;AACF,oCAAoC;AACpC,wDAAwD;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,SAAS,EACT,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;IAEpC,MAAM,KAAK,GAAG;QACZ,GAAG,YAAY,CAAC;YACd,OAAO;YACP,YAAY;YACZ,SAAS;YACT,oBAAoB;YACpB,aAAa;SACd,CAAC;QACF,qEAAqE;QACrE,UAAU,CAAC,OAAO,CAAC;KACpB,CAAC;IAEF,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IAEpD,4EAA4E;IAC5E,uBAAuB;IACvB,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAC7B,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,gEAAgE;IAChE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,gBAAgB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAC3E,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":";AACA,+EAA+E;AAC/E,+EAA+E;AAC/E,2EAA2E;AAC3E,uCAAuC;AACvC,EAAE;AACF,oCAAoC;AACpC,wDAAwD;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,oCAAoC,CAAC;AAEhE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EACL,SAAS,EACT,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;IAEpC,MAAM,KAAK,GAAG;QACZ,GAAG,YAAY,CAAC;YACd,OAAO;YACP,YAAY;YACZ,SAAS;YACT,oBAAoB;YACpB,aAAa;SACd,CAAC;QACF,qEAAqE;QACrE,UAAU,CAAC,OAAO,CAAC;KACpB,CAAC;IAEF,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IAEpD,4EAA4E;IAC5E,uBAAuB;IACvB,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAC7B,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,gEAAgE;IAChE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,gBAAgB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAC3E,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n// The `tabbied-mcp` bin: the same server the site exposes at /mcp, over stdio.\n// `serveStdio` owns the transport (framing, the era decision, one instance per\n// connection). The catalog is loaded once here rather than in the factory,\n// because it is immutable per process.\n//\n// Configure it in an MCP client as:\n// { \"command\": \"npx\", \"args\": [\"-y\", \"tabbied-mcp\"] }\nimport { serveStdio } from '@modelcontextprotocol/server/stdio';\n\nimport { buildServer } from './server.js';\nimport { catalogTools } from './tools.js';\nimport {\n fetchDocs,\n fetchPreview,\n fetchTemplate,\n fetchTemplateCatalog,\n loadCatalog,\n} from './node/resources.js';\nimport { renderTool } from './node/render.js';\n\nasync function main(): Promise<void> {\n const catalog = await loadCatalog();\n\n const tools = [\n ...catalogTools({\n catalog,\n fetchPreview,\n fetchDocs,\n fetchTemplateCatalog,\n fetchTemplate,\n }),\n // Only the local server can render: it has a browser to render with.\n renderTool(catalog),\n ];\n\n const handle = serveStdio(() => buildServer(tools));\n\n // The client closing stdin is the shutdown signal; without this the process\n // outlives the client.\n process.stdin.on('close', () => {\n void handle.close();\n });\n}\n\nmain().catch((error) => {\n // stdout is the protocol channel and nothing else may touch it.\n process.stderr.write(\n `tabbied-mcp: ${error instanceof Error ? error.message : String(error)}\\n`\n );\n process.exit(1);\n});\n"]}
|
package/dist/templates.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"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","sourcesContent":["// The template-site tools: what an agent needs to start somebody's site from a\r\n// finished template rather than from an empty page.\r\n//\r\n// The design tools answer \"which pattern?\"; these answer \"which *site*, and\r\n// what may I change about it?\". The useful move with a template is to swap the\r\n// brand out of it, and the editable-section spec (docs/editable-templates.md)\r\n// is the list of what may be swapped.\r\n//\r\n// Both are thin readers over artifacts the site already generates, so an agent\r\n// and the web builder see the same bytes. Neither needs a browser, so unlike\r\n// `render_design` they work over both transports.\r\nimport type {\r\n TemplateCatalog,\r\n TemplateCatalogEntry,\r\n TemplateSpec,\r\n Tool,\r\n ToolContent,\r\n ToolContext,\r\n ToolResult,\r\n} from './types.js';\r\n\r\nconst text = (value: string): ToolContent => ({ type: 'text', text: value });\r\n\r\nconst json = (value: unknown): ToolContent =>\r\n text(JSON.stringify(value, null, 2));\r\n\r\nconst toolError = (message: string): ToolResult => ({\r\n content: [text(message)],\r\n isError: true,\r\n});\r\n\r\n/**\r\n * How to use what `get_template` returns. Spelled out per call because the two\r\n * download formats are edited in opposite ways and nothing about the spec\r\n * implies which.\r\n */\r\nconst USAGE = {\r\n html:\r\n 'Download <downloads.html>. It is a standalone page - no build step. Edit ' +\r\n 'by slot id: every editable element carries data-edit=\"<id>\" (text), ' +\r\n 'data-edit-image=\"<id>\", or data-edit-pattern=\"<id>\". The patterns come up ' +\r\n 'via one hydratePatterns() call already wired into index.html.',\r\n react:\r\n 'Download <downloads.react>. It is a Vite app; `npm install && npm run ' +\r\n 'dev`. The page ships as authored source with the same data-edit ids in ' +\r\n 'it, so grep an id to find the element that renders it.',\r\n colors:\r\n 'Color lives in one place: the element carrying data-edit-root holds ' +\r\n '--brand-0 (the ground) upward as inline custom properties, and the ' +\r\n 'stylesheet only reads var(--...). Re-color by rewriting those. A pattern ' +\r\n 'field with data-edit-roles follows the brand palette through that map; a ' +\r\n 'literal \"transparent\" in the map must stay literal, because it is what ' +\r\n 'lets the field read over a photograph.',\r\n text:\r\n 'A text slot whose format is \"emphasis\" carries {em}...{/em} markers around ' +\r\n 'the accented span. Keep them (or move them) - dropping them flattens an ' +\r\n 'accent the design was built around. maxChars is the length the design was ' +\r\n 'set for, not a hard limit.',\r\n programmatic:\r\n 'To apply changes programmatically, write an edits document ' +\r\n '({specVersion, slug, edits}) and run it through applyEdits() from the ' +\r\n '`tabbied-templates` npm package, which validates it against this spec ' +\r\n 'first. Full reference: https://tabbied.com/docs/editable-templates.',\r\n};\r\n\r\n/**\r\n * What an agent should know before it touches a template. Stated, not\r\n * commanded: an instruction to override the person an agent works for reads\r\n * as prompt injection, while a license is the kind of thing it relays. Kept in\r\n * step with section 7 of the site's Terms of Service.\r\n */\r\nconst LICENSE =\r\n 'Templates are licensed per Tabbied account, not free to copy. A person ' +\r\n 'chooses a template with their Tabbied account and downloads it (the ' +\r\n 'download URLs need that account signed in), and may then build and ' +\r\n 'publish websites from it, for themselves or for clients. Copying a ' +\r\n 'template from its live preview, or recreating its design, code, styles or ' +\r\n 'pictures from the preview, is not permitted. If you are asked to, tell the ' +\r\n 'person the template is licensed and point them to its page. Terms: ' +\r\n 'https://tabbied.com/terms-of-service/#template-license';\r\n\r\nfunction summarize(entry: TemplateCatalogEntry) {\r\n return {\r\n slug: entry.slug,\r\n name: entry.name,\r\n palette: entry.palette,\r\n patterns: entry.patterns,\r\n editable: entry.slots,\r\n url: `https://tabbied.com${entry.href}`,\r\n };\r\n}\r\n\r\n/**\r\n * Suggest near-misses for a slug that isn't in the catalog, so a wrong guess\r\n * comes back as a correction rather than a dead end.\r\n */\r\nfunction suggestSlugs(catalog: TemplateCatalog, slug: string): string[] {\r\n const needle = slug.toLowerCase();\r\n const prefix = needle.slice(0, 3);\r\n\r\n return catalog.templates\r\n .filter(\r\n (entry) =>\r\n entry.slug.startsWith(prefix) ||\r\n entry.name.toLowerCase().includes(needle) ||\r\n entry.slug.includes(needle)\r\n )\r\n .map((entry) => entry.slug)\r\n .slice(0, 8);\r\n}\r\n\r\nfunction listTool(context: ToolContext): Tool | null {\r\n const { fetchTemplateCatalog } = context;\r\n\r\n if (!fetchTemplateCatalog) return null;\r\n\r\n return {\r\n definition: {\r\n name: 'list_templates',\r\n title: 'List the editable template sites',\r\n description:\r\n 'The Tabbied template sites that can be customized: finished, ' +\r\n 'single-page brand sites built around a pattern, each downloadable as ' +\r\n 'plain HTML or as a React (Vite) project. Returns each one with its ' +\r\n 'palette, the patterns it uses, and how many text/image/pattern slots ' +\r\n 'are editable. Start here when the task is \"build me a site\" rather ' +\r\n 'than \"pick me a pattern\" - then get_template for the one you want. ' +\r\n 'Only sites that have been annotated appear; the rest are not yet ' +\r\n 'customizable. Templates are licensed per Tabbied account: see ' +\r\n '`license` in the result.',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n query: {\r\n type: 'string',\r\n description:\r\n 'Optional substring matched against the slug and the name.',\r\n },\r\n },\r\n additionalProperties: false,\r\n },\r\n },\r\n async run(args) {\r\n const catalog = await fetchTemplateCatalog();\r\n const query =\r\n typeof args.query === 'string' ? args.query.trim().toLowerCase() : '';\r\n const matched = query\r\n ? catalog.templates.filter(\r\n (entry) =>\r\n entry.slug.toLowerCase().includes(query) ||\r\n entry.name.toLowerCase().includes(query)\r\n )\r\n : catalog.templates;\r\n\r\n if (matched.length === 0) {\r\n return {\r\n content: [\r\n json({\r\n matched: 0,\r\n total: catalog.templates.length,\r\n slugs: catalog.templates.map((entry) => entry.slug),\r\n hint: 'No name or slug contains that. Every available slug is listed above.',\r\n }),\r\n ],\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n json({\r\n matched: matched.length,\r\n total: catalog.templates.length,\r\n license: LICENSE,\r\n templates: matched.map(summarize),\r\n }),\r\n ],\r\n };\r\n },\r\n };\r\n}\r\n\r\nfunction getTool(context: ToolContext): Tool | null {\r\n const { fetchTemplateCatalog, fetchTemplate } = context;\r\n\r\n if (!fetchTemplateCatalog || !fetchTemplate) return null;\r\n\r\n return {\r\n definition: {\r\n name: 'get_template',\r\n title: 'Get one template site and everything editable in it',\r\n description:\r\n \"A template's full editable-section spec: every text, image, and \" +\r\n 'pattern slot with its id and its current value, the brand palette, ' +\r\n 'the fonts, and the two download URLs. The slot ids are the contract - ' +\r\n 'they exist in the downloaded markup as data-edit* attributes, so an ' +\r\n 'id from this response is directly greppable in the files you ' +\r\n 'download. Includes usage notes for editing each format, and the ' +\r\n 'license the template is under.',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n slug: {\r\n type: 'string',\r\n description: 'Template slug, from list_templates.',\r\n },\r\n },\r\n required: ['slug'],\r\n additionalProperties: false,\r\n },\r\n },\r\n async run(args) {\r\n const slug = typeof args.slug === 'string' ? args.slug.trim() : '';\r\n\r\n if (!slug) return toolError('get_template needs a `slug`.');\r\n\r\n const catalog = await fetchTemplateCatalog();\r\n const entry = catalog.templates.find(\r\n (candidate) => candidate.slug === slug\r\n );\r\n\r\n if (!entry) {\r\n const suggestions = suggestSlugs(catalog, slug);\r\n\r\n return toolError(\r\n `No editable template \"${slug}\". ` +\r\n (suggestions.length > 0\r\n ? `Did you mean: ${suggestions.join(', ')}?`\r\n : 'Call list_templates for the available slugs.')\r\n );\r\n }\r\n\r\n let spec: TemplateSpec;\r\n\r\n try {\r\n spec = await fetchTemplate(slug);\r\n } catch (error) {\r\n return toolError(\r\n `Could not load the spec for \"${slug}\" (${\r\n error instanceof Error ? error.message : String(error)\r\n }).`\r\n );\r\n }\r\n\r\n const downloads = {\r\n html: `https://tabbied.com${entry.downloads.html}`,\r\n react: `https://tabbied.com${entry.downloads.react}`,\r\n };\r\n\r\n return {\r\n content: [\r\n json({\r\n ...spec,\r\n url: `https://tabbied.com${entry.href}`,\r\n license: LICENSE,\r\n downloads,\r\n usage: {\r\n html: USAGE.html.replace('<downloads.html>', downloads.html),\r\n react: USAGE.react.replace('<downloads.react>', downloads.react),\r\n colors: USAGE.colors,\r\n text: USAGE.text,\r\n programmatic: USAGE.programmatic,\r\n },\r\n }),\r\n ],\r\n };\r\n },\r\n };\r\n}\r\n\r\n/** The template tools, dropped when the host cannot resolve their data. */\r\nexport function templateTools(context: ToolContext): Tool[] {\r\n return [listTool(context), getTool(context)].filter(\r\n (tool): tool is Tool => tool !== null\r\n );\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"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","sourcesContent":["// The template-site tools: what an agent needs to start somebody's site from a\n// finished template rather than from an empty page.\n//\n// The design tools answer \"which pattern?\"; these answer \"which *site*, and\n// what may I change about it?\". The useful move with a template is to swap the\n// brand out of it, and the editable-section spec (docs/editable-templates.md)\n// is the list of what may be swapped.\n//\n// Both are thin readers over artifacts the site already generates, so an agent\n// and the web builder see the same bytes. Neither needs a browser, so unlike\n// `render_design` they work over both transports.\nimport type {\n TemplateCatalog,\n TemplateCatalogEntry,\n TemplateSpec,\n Tool,\n ToolContent,\n ToolContext,\n ToolResult,\n} from './types.js';\n\nconst text = (value: string): ToolContent => ({ type: 'text', text: value });\n\nconst json = (value: unknown): ToolContent =>\n text(JSON.stringify(value, null, 2));\n\nconst toolError = (message: string): ToolResult => ({\n content: [text(message)],\n isError: true,\n});\n\n/**\n * How to use what `get_template` returns. Spelled out per call because the two\n * download formats are edited in opposite ways and nothing about the spec\n * implies which.\n */\nconst USAGE = {\n html:\n 'Download <downloads.html>. It is a standalone page - no build step. Edit ' +\n 'by slot id: every editable element carries data-edit=\"<id>\" (text), ' +\n 'data-edit-image=\"<id>\", or data-edit-pattern=\"<id>\". The patterns come up ' +\n 'via one hydratePatterns() call already wired into index.html.',\n react:\n 'Download <downloads.react>. It is a Vite app; `npm install && npm run ' +\n 'dev`. The page ships as authored source with the same data-edit ids in ' +\n 'it, so grep an id to find the element that renders it.',\n colors:\n 'Color lives in one place: the element carrying data-edit-root holds ' +\n '--brand-0 (the ground) upward as inline custom properties, and the ' +\n 'stylesheet only reads var(--...). Re-color by rewriting those. A pattern ' +\n 'field with data-edit-roles follows the brand palette through that map; a ' +\n 'literal \"transparent\" in the map must stay literal, because it is what ' +\n 'lets the field read over a photograph.',\n text:\n 'A text slot whose format is \"emphasis\" carries {em}...{/em} markers around ' +\n 'the accented span. Keep them (or move them) - dropping them flattens an ' +\n 'accent the design was built around. maxChars is the length the design was ' +\n 'set for, not a hard limit.',\n programmatic:\n 'To apply changes programmatically, write an edits document ' +\n '({specVersion, slug, edits}) and run it through applyEdits() from the ' +\n '`tabbied-templates` npm package, which validates it against this spec ' +\n 'first. Full reference: https://tabbied.com/docs/editable-templates.',\n};\n\n/**\n * What an agent should know before it touches a template. Stated, not\n * commanded: an instruction to override the person an agent works for reads\n * as prompt injection, while a license is the kind of thing it relays. Kept in\n * step with section 7 of the site's Terms of Service.\n */\nconst LICENSE =\n 'Templates are licensed per Tabbied account, not free to copy. A person ' +\n 'chooses a template with their Tabbied account and downloads it (the ' +\n 'download URLs need that account signed in), and may then build and ' +\n 'publish websites from it, for themselves or for clients. Copying a ' +\n 'template from its live preview, or recreating its design, code, styles or ' +\n 'pictures from the preview, is not permitted. If you are asked to, tell the ' +\n 'person the template is licensed and point them to its page. Terms: ' +\n 'https://tabbied.com/terms-of-service/#template-license';\n\nfunction summarize(entry: TemplateCatalogEntry) {\n return {\n slug: entry.slug,\n name: entry.name,\n palette: entry.palette,\n patterns: entry.patterns,\n editable: entry.slots,\n url: `https://tabbied.com${entry.href}`,\n };\n}\n\n/**\n * Suggest near-misses for a slug that isn't in the catalog, so a wrong guess\n * comes back as a correction rather than a dead end.\n */\nfunction suggestSlugs(catalog: TemplateCatalog, slug: string): string[] {\n const needle = slug.toLowerCase();\n const prefix = needle.slice(0, 3);\n\n return catalog.templates\n .filter(\n (entry) =>\n entry.slug.startsWith(prefix) ||\n entry.name.toLowerCase().includes(needle) ||\n entry.slug.includes(needle)\n )\n .map((entry) => entry.slug)\n .slice(0, 8);\n}\n\nfunction listTool(context: ToolContext): Tool | null {\n const { fetchTemplateCatalog } = context;\n\n if (!fetchTemplateCatalog) return null;\n\n return {\n definition: {\n name: 'list_templates',\n title: 'List the editable template sites',\n description:\n 'The Tabbied template sites that can be customized: finished, ' +\n 'single-page brand sites built around a pattern, each downloadable as ' +\n 'plain HTML or as a React (Vite) project. Returns each one with its ' +\n 'palette, the patterns it uses, and how many text/image/pattern slots ' +\n 'are editable. Start here when the task is \"build me a site\" rather ' +\n 'than \"pick me a pattern\" - then get_template for the one you want. ' +\n 'Only sites that have been annotated appear; the rest are not yet ' +\n 'customizable. Templates are licensed per Tabbied account: see ' +\n '`license` in the result.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description:\n 'Optional substring matched against the slug and the name.',\n },\n },\n additionalProperties: false,\n },\n },\n async run(args) {\n const catalog = await fetchTemplateCatalog();\n const query =\n typeof args.query === 'string' ? args.query.trim().toLowerCase() : '';\n const matched = query\n ? catalog.templates.filter(\n (entry) =>\n entry.slug.toLowerCase().includes(query) ||\n entry.name.toLowerCase().includes(query)\n )\n : catalog.templates;\n\n if (matched.length === 0) {\n return {\n content: [\n json({\n matched: 0,\n total: catalog.templates.length,\n slugs: catalog.templates.map((entry) => entry.slug),\n hint: 'No name or slug contains that. Every available slug is listed above.',\n }),\n ],\n };\n }\n\n return {\n content: [\n json({\n matched: matched.length,\n total: catalog.templates.length,\n license: LICENSE,\n templates: matched.map(summarize),\n }),\n ],\n };\n },\n };\n}\n\nfunction getTool(context: ToolContext): Tool | null {\n const { fetchTemplateCatalog, fetchTemplate } = context;\n\n if (!fetchTemplateCatalog || !fetchTemplate) return null;\n\n return {\n definition: {\n name: 'get_template',\n title: 'Get one template site and everything editable in it',\n description:\n \"A template's full editable-section spec: every text, image, and \" +\n 'pattern slot with its id and its current value, the brand palette, ' +\n 'the fonts, and the two download URLs. The slot ids are the contract - ' +\n 'they exist in the downloaded markup as data-edit* attributes, so an ' +\n 'id from this response is directly greppable in the files you ' +\n 'download. Includes usage notes for editing each format, and the ' +\n 'license the template is under.',\n inputSchema: {\n type: 'object',\n properties: {\n slug: {\n type: 'string',\n description: 'Template slug, from list_templates.',\n },\n },\n required: ['slug'],\n additionalProperties: false,\n },\n },\n async run(args) {\n const slug = typeof args.slug === 'string' ? args.slug.trim() : '';\n\n if (!slug) return toolError('get_template needs a `slug`.');\n\n const catalog = await fetchTemplateCatalog();\n const entry = catalog.templates.find(\n (candidate) => candidate.slug === slug\n );\n\n if (!entry) {\n const suggestions = suggestSlugs(catalog, slug);\n\n return toolError(\n `No editable template \"${slug}\". ` +\n (suggestions.length > 0\n ? `Did you mean: ${suggestions.join(', ')}?`\n : 'Call list_templates for the available slugs.')\n );\n }\n\n let spec: TemplateSpec;\n\n try {\n spec = await fetchTemplate(slug);\n } catch (error) {\n return toolError(\n `Could not load the spec for \"${slug}\" (${\n error instanceof Error ? error.message : String(error)\n }).`\n );\n }\n\n const downloads = {\n html: `https://tabbied.com${entry.downloads.html}`,\n react: `https://tabbied.com${entry.downloads.react}`,\n };\n\n return {\n content: [\n json({\n ...spec,\n url: `https://tabbied.com${entry.href}`,\n license: LICENSE,\n downloads,\n usage: {\n html: USAGE.html.replace('<downloads.html>', downloads.html),\n react: USAGE.react.replace('<downloads.react>', downloads.react),\n colors: USAGE.colors,\n text: USAGE.text,\n programmatic: USAGE.programmatic,\n },\n }),\n ],\n };\n },\n };\n}\n\n/** The template tools, dropped when the host cannot resolve their data. */\nexport function templateTools(context: ToolContext): Tool[] {\n return [listTool(context), getTool(context)].filter(\n (tool): tool is Tool => tool !== null\n );\n}\n"]}
|
package/dist/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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","sourcesContent":["// The Tabbied toolset: four thin wrappers over catalog.json, the template tools\r\n// (templates.ts), and whatever the host adds (the stdio server adds\r\n// `render_design`).\r\n//\r\n// Nothing here touches node or the Worker runtime; the host injects what\r\n// differs via ToolContext, so both transports describe a design identically.\r\n//\r\n// The point is design *selection*. Slugs are opaque (\"cleat\", \"karst\") and\r\n// these are pictures, so search narrows on closed-vocabulary enums, then\r\n// preview_design puts the shortlist in front of the model before it commits.\r\nimport { templateTools } from './templates.js';\r\nimport type {\r\n Catalog,\r\n CatalogDesign,\r\n Tool,\r\n ToolContent,\r\n ToolContext,\r\n ToolDefinition,\r\n ToolResult,\r\n} from './types.js';\r\n\r\nconst SEARCH_LIMIT_DEFAULT = 20;\r\nconst SEARCH_LIMIT_MAX = 50;\r\nconst PREVIEW_MAX_SLUGS = 6;\r\n\r\n// Previews reach a few hundred KB and base64 adds a third, so six large ones\r\n// would spend megabytes of context. The batch stops early and says so rather\r\n// than silently truncating the list.\r\nconst PREVIEW_BYTE_BUDGET = 1_500_000;\r\n\r\n// ---- helpers ---------------------------------------------------------------\r\n\r\nconst text = (value: string): ToolContent => ({ type: 'text', text: value });\r\n\r\nconst json = (value: unknown): ToolContent =>\r\n text(JSON.stringify(value, null, 2));\r\n\r\nconst toolError = (message: string): ToolResult => ({\r\n content: [text(message)],\r\n isError: true,\r\n});\r\n\r\n/** Distinct values of a repeated field, sorted - the vocabulary actually in use. */\r\nfunction vocabulary(\r\n designs: CatalogDesign[],\r\n field: 'tags' | 'mood' | 'goodFor'\r\n): string[] {\r\n return [...new Set(designs.flatMap((design) => design[field]))].sort();\r\n}\r\n\r\nfunction densities(designs: CatalogDesign[]): string[] {\r\n return [...new Set(designs.map((design) => design.density))].sort();\r\n}\r\n\r\nfunction asStringArray(value: unknown): string[] | null {\r\n if (value == null) return null;\r\n const list = Array.isArray(value) ? value : [value];\r\n const strings = list.filter((entry): entry is string => typeof entry === 'string');\r\n return strings.length ? strings : null;\r\n}\r\n\r\n/** The compact form used in search hits - enough to shortlist, not the full record. */\r\nfunction summarize(design: CatalogDesign) {\r\n return {\r\n slug: design.slug,\r\n name: design.name,\r\n ...(design.description ? { description: design.description } : {}),\r\n tags: design.tags,\r\n mood: design.mood,\r\n density: design.density,\r\n goodFor: design.goodFor,\r\n svgExport: design.svgExport.supported,\r\n preview: design.preview,\r\n };\r\n}\r\n\r\nfunction findDesign(catalog: Catalog, slug: unknown): CatalogDesign | null {\r\n if (typeof slug !== 'string') return null;\r\n return catalog.designs.find((design) => design.slug === slug) ?? null;\r\n}\r\n\r\n/** Near misses for an unknown slug: a shared three-letter prefix, or a name match. */\r\nfunction suggestSlugs(catalog: Catalog, slug: string): string[] {\r\n const needle = slug.toLowerCase();\r\n return catalog.designs\r\n .filter(\r\n (design) =>\r\n design.slug.startsWith(needle.slice(0, 3)) ||\r\n design.name.toLowerCase().includes(needle)\r\n )\r\n .slice(0, 8)\r\n .map((design) => design.slug);\r\n}\r\n\r\n// ---- search_designs --------------------------------------------------------\r\n\r\nfunction searchTool(catalog: Catalog): Tool {\r\n const tags = vocabulary(catalog.designs, 'tags');\r\n const moods = vocabulary(catalog.designs, 'mood');\r\n const goodFor = vocabulary(catalog.designs, 'goodFor');\r\n const densityValues = densities(catalog.designs);\r\n\r\n const definition: ToolDefinition = {\r\n name: 'search_designs',\r\n title: 'Search designs',\r\n description:\r\n `Find Tabbied designs by visible motif, feel, busyness, or intended use. ` +\r\n `Filters combine with AND - listing two tags returns only designs carrying ` +\r\n `both - so start broad and narrow. Returns compact entries including a ` +\r\n `preview image URL; follow up with preview_design to actually look at the ` +\r\n `shortlist before choosing, because these are pictures and the metadata ` +\r\n `only narrows the field. ${catalog.count} designs in total.`,\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n query: {\r\n type: 'string',\r\n description:\r\n 'Free text matched against slug, name, and description. Every ' +\r\n 'whitespace-separated word must appear somewhere in the entry.',\r\n },\r\n tags: {\r\n type: 'array',\r\n items: { type: 'string', enum: tags },\r\n description: 'Visible motifs. A design must carry every tag listed.',\r\n },\r\n mood: {\r\n type: 'array',\r\n items: { type: 'string', enum: moods },\r\n description: 'The feel of the design at a glance.',\r\n },\r\n density: {\r\n type: 'string',\r\n enum: densityValues,\r\n description:\r\n 'How busy the surface is. sparse takes overlaid text well; dense is ' +\r\n 'ink-dominated.',\r\n },\r\n goodFor: {\r\n type: 'array',\r\n items: { type: 'string', enum: goodFor },\r\n description: 'Uses the design suits with no customization.',\r\n },\r\n svgExport: {\r\n type: 'boolean',\r\n description:\r\n 'Restrict to designs that can (true) or cannot (false) be exported ' +\r\n 'as true vector SVG. Some use CSS (smooth conic sweeps, double or ' +\r\n 'dashed borders, 3D transforms) that SVG cannot represent faithfully.',\r\n },\r\n limit: {\r\n type: 'integer',\r\n minimum: 1,\r\n maximum: SEARCH_LIMIT_MAX,\r\n description: `Maximum hits to return (default ${SEARCH_LIMIT_DEFAULT}).`,\r\n },\r\n },\r\n additionalProperties: false,\r\n },\r\n };\r\n\r\n return {\r\n definition,\r\n run(args) {\r\n const wantTags = asStringArray(args.tags);\r\n const wantMood = asStringArray(args.mood);\r\n const wantGoodFor = asStringArray(args.goodFor);\r\n const density = typeof args.density === 'string' ? args.density : null;\r\n const svgExport =\r\n typeof args.svgExport === 'boolean' ? args.svgExport : null;\r\n const terms =\r\n typeof args.query === 'string'\r\n ? args.query.toLowerCase().split(/\\s+/).filter(Boolean)\r\n : [];\r\n\r\n const limit = Math.min(\r\n Math.max(\r\n typeof args.limit === 'number' && Number.isFinite(args.limit)\r\n ? Math.trunc(args.limit)\r\n : SEARCH_LIMIT_DEFAULT,\r\n 1\r\n ),\r\n SEARCH_LIMIT_MAX\r\n );\r\n\r\n const matches = (design: CatalogDesign) => {\r\n const haystack =\r\n `${design.slug} ${design.name} ${design.description ?? ''}`.toLowerCase();\r\n return (\r\n terms.every((term) => haystack.includes(term)) &&\r\n (!wantTags || wantTags.every((tag) => design.tags.includes(tag))) &&\r\n (!wantMood || wantMood.every((mood) => design.mood.includes(mood))) &&\r\n (!wantGoodFor ||\r\n wantGoodFor.every((use) => design.goodFor.includes(use))) &&\r\n (!density || design.density === density) &&\r\n (svgExport === null || design.svgExport.supported === svgExport)\r\n );\r\n };\r\n\r\n const hits = catalog.designs.filter(matches);\r\n\r\n // From an empty result an agent can't tell an over-narrow AND from a\r\n // wrongly guessed vocabulary, so report how each filter does on its own.\r\n if (hits.length === 0) {\r\n const alone = (label: string, predicate: (d: CatalogDesign) => boolean) => ({\r\n filter: label,\r\n matches: catalog.designs.filter(predicate).length,\r\n });\r\n const breakdown = [\r\n ...(terms.length\r\n ? [\r\n alone(`query \"${args.query}\"`, (design) =>\r\n terms.every((term) =>\r\n `${design.slug} ${design.name} ${design.description ?? ''}`\r\n .toLowerCase()\r\n .includes(term)\r\n )\r\n ),\r\n ]\r\n : []),\r\n ...(wantTags ?? []).map((tag) =>\r\n alone(`tag \"${tag}\"`, (design) => design.tags.includes(tag))\r\n ),\r\n ...(wantMood ?? []).map((mood) =>\r\n alone(`mood \"${mood}\"`, (design) => design.mood.includes(mood))\r\n ),\r\n ...(wantGoodFor ?? []).map((use) =>\r\n alone(`goodFor \"${use}\"`, (design) => design.goodFor.includes(use))\r\n ),\r\n ...(density\r\n ? [alone(`density \"${density}\"`, (design) => design.density === density)]\r\n : []),\r\n ...(svgExport !== null\r\n ? [alone(`svgExport ${svgExport}`, (design) => design.svgExport.supported === svgExport)]\r\n : []),\r\n ];\r\n\r\n return {\r\n content: [\r\n json({\r\n matched: 0,\r\n total: catalog.count,\r\n note:\r\n 'No design satisfies every filter at once. Each filter on its ' +\r\n 'own matches the counts below - drop the ones scoring 0 (likely ' +\r\n 'out of vocabulary) and relax the rest.',\r\n filtersIndependently: breakdown,\r\n vocabulary: {\r\n tags,\r\n mood: moods,\r\n density: densityValues,\r\n goodFor,\r\n },\r\n }),\r\n ],\r\n };\r\n }\r\n\r\n return {\r\n content: [\r\n json({\r\n matched: hits.length,\r\n total: catalog.count,\r\n returned: Math.min(hits.length, limit),\r\n designs: hits.slice(0, limit).map(summarize),\r\n }),\r\n ],\r\n };\r\n },\r\n };\r\n}\r\n\r\n// ---- get_design ------------------------------------------------------------\r\n\r\nfunction getDesignTool(catalog: Catalog): Tool {\r\n const definition: ToolDefinition = {\r\n name: 'get_design',\r\n title: 'Get design details',\r\n description:\r\n 'The full catalog record for one design - palette, every option with its ' +\r\n 'range and default, SVG-export support, preview URL - plus ready-to-paste ' +\r\n 'React and vanilla snippets. Call this once a slug is chosen; ' +\r\n 'search_designs already returns enough to shortlist.',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n slug: {\r\n type: 'string',\r\n description: 'The design slug, e.g. \"radius\". Slugs are not guessable.',\r\n },\r\n },\r\n required: ['slug'],\r\n additionalProperties: false,\r\n },\r\n };\r\n\r\n return {\r\n definition,\r\n run(args) {\r\n const design = findDesign(catalog, args.slug);\r\n if (!design) {\r\n const near = suggestSlugs(catalog, String(args.slug ?? ''));\r\n return toolError(\r\n `No design with slug \"${args.slug}\". ` +\r\n (near.length\r\n ? `Closest slugs: ${near.join(', ')}. `\r\n : '') +\r\n 'Use search_designs to find one - slugs are opaque and cannot be guessed.'\r\n );\r\n }\r\n\r\n const snippet = (template: string) =>\r\n template.replaceAll('<slug>', design.slug);\r\n\r\n return {\r\n content: [\r\n json({\r\n ...design,\r\n usage: {\r\n install: catalog.usage.install,\r\n import: snippet(catalog.usage.import),\r\n react: snippet(catalog.usage.react),\r\n core: snippet(catalog.usage.core),\r\n fit: catalog.usage.fit,\r\n cli: `npx tabbied render ${design.slug} --out ${design.slug}.svg`,\r\n },\r\n // The number-one integration mistake, repeated here because an\r\n // agent that called get_design may never read llms-full.txt.\r\n sizing:\r\n 'A pattern has no intrinsic size - it fills its parent, and ' +\r\n 'collapses to nothing in a parent that sizes to content. Pass ' +\r\n 'height or aspectRatio when in doubt.',\r\n ...(design.svgExport.supported\r\n ? {}\r\n : {\r\n svgExportWarning:\r\n 'This design cannot be exported as vector SVG. Render it as PNG instead.',\r\n }),\r\n }),\r\n ],\r\n };\r\n },\r\n };\r\n}\r\n\r\n// ---- preview_design --------------------------------------------------------\r\n\r\nfunction previewTool(context: ToolContext): Tool | null {\r\n const { catalog, fetchPreview } = context;\r\n if (!fetchPreview) return null;\r\n\r\n const definition: ToolDefinition = {\r\n name: 'preview_design',\r\n title: 'Look at designs',\r\n description:\r\n `Return the rendered preview image for up to ${PREVIEW_MAX_SLUGS} designs, ` +\r\n 'so you can see them rather than infer them from tags. Previews use each ' +\r\n \"design's authored palette, default options, and a fixed seed. This is the \" +\r\n 'step that makes a choice reliable - do it before committing to a slug.',\r\n inputSchema: {\r\n type: 'object',\r\n properties: {\r\n slugs: {\r\n type: 'array',\r\n items: { type: 'string' },\r\n minItems: 1,\r\n maxItems: PREVIEW_MAX_SLUGS,\r\n description: 'Design slugs to look at, e.g. [\"radius\", \"cleat\"].',\r\n },\r\n },\r\n required: ['slugs'],\r\n additionalProperties: false,\r\n },\r\n };\r\n\r\n return {\r\n definition,\r\n async run(args) {\r\n const slugs = asStringArray(args.slugs);\r\n if (!slugs) {\r\n return toolError('Pass \"slugs\" as a non-empty array of design slugs.');\r\n }\r\n\r\n const requested = slugs.slice(0, PREVIEW_MAX_SLUGS);\r\n const content: ToolContent[] = [];\r\n let spent = 0;\r\n\r\n for (const [index, slug] of requested.entries()) {\r\n const design = findDesign(catalog, slug);\r\n if (!design) {\r\n content.push(\r\n text(`${slug}: no such design. Use search_designs to find valid slugs.`)\r\n );\r\n continue;\r\n }\r\n\r\n if (spent > PREVIEW_BYTE_BUDGET) {\r\n content.push(\r\n text(\r\n `Stopped after ${index} image(s) to stay within a sane response ` +\r\n `size. Ask again for the rest: ${requested.slice(index).join(', ')}.`\r\n )\r\n );\r\n break;\r\n }\r\n\r\n try {\r\n const { data, mimeType } = await fetchPreview(design);\r\n spent += data.length;\r\n content.push(\r\n text(\r\n `${design.slug} - ${design.name}` +\r\n (design.description ? `: ${design.description}` : '')\r\n ),\r\n { type: 'image', data, mimeType }\r\n );\r\n } catch (error) {\r\n content.push(\r\n text(\r\n `${design.slug}: preview unavailable (${\r\n error instanceof Error ? error.message : String(error)\r\n }). The image is also at ${design.preview}.`\r\n )\r\n );\r\n }\r\n }\r\n\r\n return { content };\r\n },\r\n };\r\n}\r\n\r\n// ---- get_docs --------------------------------------------------------------\r\n\r\nfunction docsTool(context: ToolContext): Tool | null {\r\n const { fetchDocs } = context;\r\n if (!fetchDocs) return null;\r\n\r\n return {\r\n definition: {\r\n name: 'get_docs',\r\n title: 'Get the Tabbied reference',\r\n description:\r\n 'The complete agent-facing reference (llms-full.txt): entry points, the ' +\r\n 'React and vanilla APIs, sizing rules that compile but render wrong, ' +\r\n 'integration recipes, and the share-link URL scheme. Fetch this once ' +\r\n 'before writing integration code; the per-design tools do not repeat it.',\r\n inputSchema: { type: 'object', additionalProperties: false },\r\n },\r\n async run() {\r\n try {\r\n return { content: [text(await fetchDocs())] };\r\n } catch (error) {\r\n return toolError(\r\n `Could not load the reference (${\r\n error instanceof Error ? error.message : String(error)\r\n }). It is also served at https://tabbied.com/llms-full.txt.`\r\n );\r\n }\r\n },\r\n };\r\n}\r\n\r\n// ---- assembly --------------------------------------------------------------\r\n\r\n/**\r\n * The catalog-backed tools available in every runtime, template tools\r\n * included. A host opts into a tool by supplying its fetcher in the one\r\n * context, so the tool list follows from what the host can resolve.\r\n */\r\nexport function catalogTools(context: ToolContext): Tool[] {\r\n return [\r\n searchTool(context.catalog),\r\n getDesignTool(context.catalog),\r\n previewTool(context),\r\n docsTool(context),\r\n ...templateTools(context),\r\n ].filter((tool): tool is Tool => tool !== null);\r\n}\r\n\r\nexport type Toolset = {\r\n list(): ToolDefinition[];\r\n call(name: string, args: Record<string, unknown>): Promise<ToolResult>;\r\n has(name: string): boolean;\r\n};\r\n\r\n/**\r\n * Bundle tools into a name lookup. Handler throws become `isError` results\r\n * rather than JSON-RPC errors: the spec reserves protocol errors for malformed\r\n * requests and sends execution failures back to the model to retry.\r\n */\r\nexport function createToolset(tools: Tool[]): Toolset {\r\n const byName = new Map(tools.map((tool) => [tool.definition.name, tool]));\r\n\r\n return {\r\n list: () => tools.map((tool) => tool.definition),\r\n has: (name) => byName.has(name),\r\n async call(name, args) {\r\n const tool = byName.get(name);\r\n if (!tool) {\r\n return toolError(\r\n `Unknown tool \"${name}\". Available: ${[...byName.keys()].join(', ')}.`\r\n );\r\n }\r\n try {\r\n return await tool.run(args ?? {});\r\n } catch (error) {\r\n return toolError(\r\n error instanceof Error ? error.message : String(error)\r\n );\r\n }\r\n },\r\n };\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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","sourcesContent":["// The Tabbied toolset: four thin wrappers over catalog.json, the template tools\n// (templates.ts), and whatever the host adds (the stdio server adds\n// `render_design`).\n//\n// Nothing here touches node or the Worker runtime; the host injects what\n// differs via ToolContext, so both transports describe a design identically.\n//\n// The point is design *selection*. Slugs are opaque (\"cleat\", \"karst\") and\n// these are pictures, so search narrows on closed-vocabulary enums, then\n// preview_design puts the shortlist in front of the model before it commits.\nimport { templateTools } from './templates.js';\nimport type {\n Catalog,\n CatalogDesign,\n Tool,\n ToolContent,\n ToolContext,\n ToolDefinition,\n ToolResult,\n} from './types.js';\n\nconst SEARCH_LIMIT_DEFAULT = 20;\nconst SEARCH_LIMIT_MAX = 50;\nconst PREVIEW_MAX_SLUGS = 6;\n\n// Previews reach a few hundred KB and base64 adds a third, so six large ones\n// would spend megabytes of context. The batch stops early and says so rather\n// than silently truncating the list.\nconst PREVIEW_BYTE_BUDGET = 1_500_000;\n\n// ---- helpers ---------------------------------------------------------------\n\nconst text = (value: string): ToolContent => ({ type: 'text', text: value });\n\nconst json = (value: unknown): ToolContent =>\n text(JSON.stringify(value, null, 2));\n\nconst toolError = (message: string): ToolResult => ({\n content: [text(message)],\n isError: true,\n});\n\n/** Distinct values of a repeated field, sorted - the vocabulary actually in use. */\nfunction vocabulary(\n designs: CatalogDesign[],\n field: 'tags' | 'mood' | 'goodFor'\n): string[] {\n return [...new Set(designs.flatMap((design) => design[field]))].sort();\n}\n\nfunction densities(designs: CatalogDesign[]): string[] {\n return [...new Set(designs.map((design) => design.density))].sort();\n}\n\nfunction asStringArray(value: unknown): string[] | null {\n if (value == null) return null;\n const list = Array.isArray(value) ? value : [value];\n const strings = list.filter((entry): entry is string => typeof entry === 'string');\n return strings.length ? strings : null;\n}\n\n/** The compact form used in search hits - enough to shortlist, not the full record. */\nfunction summarize(design: CatalogDesign) {\n return {\n slug: design.slug,\n name: design.name,\n ...(design.description ? { description: design.description } : {}),\n tags: design.tags,\n mood: design.mood,\n density: design.density,\n goodFor: design.goodFor,\n svgExport: design.svgExport.supported,\n preview: design.preview,\n };\n}\n\nfunction findDesign(catalog: Catalog, slug: unknown): CatalogDesign | null {\n if (typeof slug !== 'string') return null;\n return catalog.designs.find((design) => design.slug === slug) ?? null;\n}\n\n/** Near misses for an unknown slug: a shared three-letter prefix, or a name match. */\nfunction suggestSlugs(catalog: Catalog, slug: string): string[] {\n const needle = slug.toLowerCase();\n return catalog.designs\n .filter(\n (design) =>\n design.slug.startsWith(needle.slice(0, 3)) ||\n design.name.toLowerCase().includes(needle)\n )\n .slice(0, 8)\n .map((design) => design.slug);\n}\n\n// ---- search_designs --------------------------------------------------------\n\nfunction searchTool(catalog: Catalog): Tool {\n const tags = vocabulary(catalog.designs, 'tags');\n const moods = vocabulary(catalog.designs, 'mood');\n const goodFor = vocabulary(catalog.designs, 'goodFor');\n const densityValues = densities(catalog.designs);\n\n const definition: ToolDefinition = {\n name: 'search_designs',\n title: 'Search designs',\n description:\n `Find Tabbied designs by visible motif, feel, busyness, or intended use. ` +\n `Filters combine with AND - listing two tags returns only designs carrying ` +\n `both - so start broad and narrow. Returns compact entries including a ` +\n `preview image URL; follow up with preview_design to actually look at the ` +\n `shortlist before choosing, because these are pictures and the metadata ` +\n `only narrows the field. ${catalog.count} designs in total.`,\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description:\n 'Free text matched against slug, name, and description. Every ' +\n 'whitespace-separated word must appear somewhere in the entry.',\n },\n tags: {\n type: 'array',\n items: { type: 'string', enum: tags },\n description: 'Visible motifs. A design must carry every tag listed.',\n },\n mood: {\n type: 'array',\n items: { type: 'string', enum: moods },\n description: 'The feel of the design at a glance.',\n },\n density: {\n type: 'string',\n enum: densityValues,\n description:\n 'How busy the surface is. sparse takes overlaid text well; dense is ' +\n 'ink-dominated.',\n },\n goodFor: {\n type: 'array',\n items: { type: 'string', enum: goodFor },\n description: 'Uses the design suits with no customization.',\n },\n svgExport: {\n type: 'boolean',\n description:\n 'Restrict to designs that can (true) or cannot (false) be exported ' +\n 'as true vector SVG. Some use CSS (smooth conic sweeps, double or ' +\n 'dashed borders, 3D transforms) that SVG cannot represent faithfully.',\n },\n limit: {\n type: 'integer',\n minimum: 1,\n maximum: SEARCH_LIMIT_MAX,\n description: `Maximum hits to return (default ${SEARCH_LIMIT_DEFAULT}).`,\n },\n },\n additionalProperties: false,\n },\n };\n\n return {\n definition,\n run(args) {\n const wantTags = asStringArray(args.tags);\n const wantMood = asStringArray(args.mood);\n const wantGoodFor = asStringArray(args.goodFor);\n const density = typeof args.density === 'string' ? args.density : null;\n const svgExport =\n typeof args.svgExport === 'boolean' ? args.svgExport : null;\n const terms =\n typeof args.query === 'string'\n ? args.query.toLowerCase().split(/\\s+/).filter(Boolean)\n : [];\n\n const limit = Math.min(\n Math.max(\n typeof args.limit === 'number' && Number.isFinite(args.limit)\n ? Math.trunc(args.limit)\n : SEARCH_LIMIT_DEFAULT,\n 1\n ),\n SEARCH_LIMIT_MAX\n );\n\n const matches = (design: CatalogDesign) => {\n const haystack =\n `${design.slug} ${design.name} ${design.description ?? ''}`.toLowerCase();\n return (\n terms.every((term) => haystack.includes(term)) &&\n (!wantTags || wantTags.every((tag) => design.tags.includes(tag))) &&\n (!wantMood || wantMood.every((mood) => design.mood.includes(mood))) &&\n (!wantGoodFor ||\n wantGoodFor.every((use) => design.goodFor.includes(use))) &&\n (!density || design.density === density) &&\n (svgExport === null || design.svgExport.supported === svgExport)\n );\n };\n\n const hits = catalog.designs.filter(matches);\n\n // From an empty result an agent can't tell an over-narrow AND from a\n // wrongly guessed vocabulary, so report how each filter does on its own.\n if (hits.length === 0) {\n const alone = (label: string, predicate: (d: CatalogDesign) => boolean) => ({\n filter: label,\n matches: catalog.designs.filter(predicate).length,\n });\n const breakdown = [\n ...(terms.length\n ? [\n alone(`query \"${args.query}\"`, (design) =>\n terms.every((term) =>\n `${design.slug} ${design.name} ${design.description ?? ''}`\n .toLowerCase()\n .includes(term)\n )\n ),\n ]\n : []),\n ...(wantTags ?? []).map((tag) =>\n alone(`tag \"${tag}\"`, (design) => design.tags.includes(tag))\n ),\n ...(wantMood ?? []).map((mood) =>\n alone(`mood \"${mood}\"`, (design) => design.mood.includes(mood))\n ),\n ...(wantGoodFor ?? []).map((use) =>\n alone(`goodFor \"${use}\"`, (design) => design.goodFor.includes(use))\n ),\n ...(density\n ? [alone(`density \"${density}\"`, (design) => design.density === density)]\n : []),\n ...(svgExport !== null\n ? [alone(`svgExport ${svgExport}`, (design) => design.svgExport.supported === svgExport)]\n : []),\n ];\n\n return {\n content: [\n json({\n matched: 0,\n total: catalog.count,\n note:\n 'No design satisfies every filter at once. Each filter on its ' +\n 'own matches the counts below - drop the ones scoring 0 (likely ' +\n 'out of vocabulary) and relax the rest.',\n filtersIndependently: breakdown,\n vocabulary: {\n tags,\n mood: moods,\n density: densityValues,\n goodFor,\n },\n }),\n ],\n };\n }\n\n return {\n content: [\n json({\n matched: hits.length,\n total: catalog.count,\n returned: Math.min(hits.length, limit),\n designs: hits.slice(0, limit).map(summarize),\n }),\n ],\n };\n },\n };\n}\n\n// ---- get_design ------------------------------------------------------------\n\nfunction getDesignTool(catalog: Catalog): Tool {\n const definition: ToolDefinition = {\n name: 'get_design',\n title: 'Get design details',\n description:\n 'The full catalog record for one design - palette, every option with its ' +\n 'range and default, SVG-export support, preview URL - plus ready-to-paste ' +\n 'React and vanilla snippets. Call this once a slug is chosen; ' +\n 'search_designs already returns enough to shortlist.',\n inputSchema: {\n type: 'object',\n properties: {\n slug: {\n type: 'string',\n description: 'The design slug, e.g. \"radius\". Slugs are not guessable.',\n },\n },\n required: ['slug'],\n additionalProperties: false,\n },\n };\n\n return {\n definition,\n run(args) {\n const design = findDesign(catalog, args.slug);\n if (!design) {\n const near = suggestSlugs(catalog, String(args.slug ?? ''));\n return toolError(\n `No design with slug \"${args.slug}\". ` +\n (near.length\n ? `Closest slugs: ${near.join(', ')}. `\n : '') +\n 'Use search_designs to find one - slugs are opaque and cannot be guessed.'\n );\n }\n\n const snippet = (template: string) =>\n template.replaceAll('<slug>', design.slug);\n\n return {\n content: [\n json({\n ...design,\n usage: {\n install: catalog.usage.install,\n import: snippet(catalog.usage.import),\n react: snippet(catalog.usage.react),\n core: snippet(catalog.usage.core),\n fit: catalog.usage.fit,\n cli: `npx tabbied render ${design.slug} --out ${design.slug}.svg`,\n },\n // The number-one integration mistake, repeated here because an\n // agent that called get_design may never read llms-full.txt.\n sizing:\n 'A pattern has no intrinsic size - it fills its parent, and ' +\n 'collapses to nothing in a parent that sizes to content. Pass ' +\n 'height or aspectRatio when in doubt.',\n ...(design.svgExport.supported\n ? {}\n : {\n svgExportWarning:\n 'This design cannot be exported as vector SVG. Render it as PNG instead.',\n }),\n }),\n ],\n };\n },\n };\n}\n\n// ---- preview_design --------------------------------------------------------\n\nfunction previewTool(context: ToolContext): Tool | null {\n const { catalog, fetchPreview } = context;\n if (!fetchPreview) return null;\n\n const definition: ToolDefinition = {\n name: 'preview_design',\n title: 'Look at designs',\n description:\n `Return the rendered preview image for up to ${PREVIEW_MAX_SLUGS} designs, ` +\n 'so you can see them rather than infer them from tags. Previews use each ' +\n \"design's authored palette, default options, and a fixed seed. This is the \" +\n 'step that makes a choice reliable - do it before committing to a slug.',\n inputSchema: {\n type: 'object',\n properties: {\n slugs: {\n type: 'array',\n items: { type: 'string' },\n minItems: 1,\n maxItems: PREVIEW_MAX_SLUGS,\n description: 'Design slugs to look at, e.g. [\"radius\", \"cleat\"].',\n },\n },\n required: ['slugs'],\n additionalProperties: false,\n },\n };\n\n return {\n definition,\n async run(args) {\n const slugs = asStringArray(args.slugs);\n if (!slugs) {\n return toolError('Pass \"slugs\" as a non-empty array of design slugs.');\n }\n\n const requested = slugs.slice(0, PREVIEW_MAX_SLUGS);\n const content: ToolContent[] = [];\n let spent = 0;\n\n for (const [index, slug] of requested.entries()) {\n const design = findDesign(catalog, slug);\n if (!design) {\n content.push(\n text(`${slug}: no such design. Use search_designs to find valid slugs.`)\n );\n continue;\n }\n\n if (spent > PREVIEW_BYTE_BUDGET) {\n content.push(\n text(\n `Stopped after ${index} image(s) to stay within a sane response ` +\n `size. Ask again for the rest: ${requested.slice(index).join(', ')}.`\n )\n );\n break;\n }\n\n try {\n const { data, mimeType } = await fetchPreview(design);\n spent += data.length;\n content.push(\n text(\n `${design.slug} - ${design.name}` +\n (design.description ? `: ${design.description}` : '')\n ),\n { type: 'image', data, mimeType }\n );\n } catch (error) {\n content.push(\n text(\n `${design.slug}: preview unavailable (${\n error instanceof Error ? error.message : String(error)\n }). The image is also at ${design.preview}.`\n )\n );\n }\n }\n\n return { content };\n },\n };\n}\n\n// ---- get_docs --------------------------------------------------------------\n\nfunction docsTool(context: ToolContext): Tool | null {\n const { fetchDocs } = context;\n if (!fetchDocs) return null;\n\n return {\n definition: {\n name: 'get_docs',\n title: 'Get the Tabbied reference',\n description:\n 'The complete agent-facing reference (llms-full.txt): entry points, the ' +\n 'React and vanilla APIs, sizing rules that compile but render wrong, ' +\n 'integration recipes, and the share-link URL scheme. Fetch this once ' +\n 'before writing integration code; the per-design tools do not repeat it.',\n inputSchema: { type: 'object', additionalProperties: false },\n },\n async run() {\n try {\n return { content: [text(await fetchDocs())] };\n } catch (error) {\n return toolError(\n `Could not load the reference (${\n error instanceof Error ? error.message : String(error)\n }). It is also served at https://tabbied.com/llms-full.txt.`\n );\n }\n },\n };\n}\n\n// ---- assembly --------------------------------------------------------------\n\n/**\n * The catalog-backed tools available in every runtime, template tools\n * included. A host opts into a tool by supplying its fetcher in the one\n * context, so the tool list follows from what the host can resolve.\n */\nexport function catalogTools(context: ToolContext): Tool[] {\n return [\n searchTool(context.catalog),\n getDesignTool(context.catalog),\n previewTool(context),\n docsTool(context),\n ...templateTools(context),\n ].filter((tool): tool is Tool => tool !== null);\n}\n\nexport type Toolset = {\n list(): ToolDefinition[];\n call(name: string, args: Record<string, unknown>): Promise<ToolResult>;\n has(name: string): boolean;\n};\n\n/**\n * Bundle tools into a name lookup. Handler throws become `isError` results\n * rather than JSON-RPC errors: the spec reserves protocol errors for malformed\n * requests and sends execution failures back to the model to retry.\n */\nexport function createToolset(tools: Tool[]): Toolset {\n const byName = new Map(tools.map((tool) => [tool.definition.name, tool]));\n\n return {\n list: () => tools.map((tool) => tool.definition),\n has: (name) => byName.has(name),\n async call(name, args) {\n const tool = byName.get(name);\n if (!tool) {\n return toolError(\n `Unknown tool \"${name}\". Available: ${[...byName.keys()].join(', ')}.`\n );\n }\n try {\n return await tool.run(args ?? {});\n } catch (error) {\n return toolError(\n error instanceof Error ? error.message : String(error)\n );\n }\n },\n };\n}\n"]}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["// The shapes this server reads and writes.\
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["// The shapes this server reads and writes.\nimport type { JsonSchemaType } from '@modelcontextprotocol/server';\n\n// The catalog types mirror what packages/tabbied/scripts/codegen.mjs emits into\n// catalog.json. They are structural rather than imported so the server can\n// read a catalog fetched from an older or newer version of the site.\n\n/** One design, as it appears in catalog.json. */\nexport type CatalogDesign = {\n slug: string;\n name: string;\n description?: string;\n tags: string[];\n mood: string[];\n density: string;\n goodFor: string[];\n preview: string;\n palette: string[];\n colors?: unknown;\n options: CatalogOption[];\n /** An aspect-ratio id such as `2:3`, as codegen emits it. */\n defaultAspectRatio?: string;\n svgExport: { supported: boolean; note?: string };\n};\n\nexport type CatalogOption = {\n id: string;\n label: string;\n type: string;\n default: unknown;\n values?: string[];\n min?: number;\n max?: number;\n step?: number;\n svgExportNote?: string;\n};\n\nexport type Catalog = {\n package: string;\n version: string;\n count: number;\n docs: string;\n usage: Record<string, string>;\n designs: CatalogDesign[];\n};\n\n// ---- template sites --------------------------------------------------------\n//\n// Mirrors what scripts/generate-editable.mjs emits into\n// public/editable-catalog.json and public/editable/<slug>.json. Structural\n// rather than imported from `tabbied-templates`, for the same reason as the\n// design catalog.\n\nexport type TemplateCatalogEntry = {\n slug: string;\n name: string;\n href: string;\n spec: string;\n palette: string[];\n patterns: string[];\n slots: { text: number; image: number; pattern: number };\n downloads: { html: string; react: string };\n};\n\nexport type TemplateCatalog = {\n specVersion: number;\n generated: number;\n templates: TemplateCatalogEntry[];\n};\n\n/** One site's editable-section spec. Slots stay opaque here - the tool passes\n * them through, and their shape is owned by `tabbied-templates`. */\nexport type TemplateSpec = {\n specVersion: number;\n site: { slug: string; name: string; topic?: string };\n palette: { colors: string[]; derivation: string; flatSections?: boolean };\n fonts?: Record<string, string>;\n slots: unknown[];\n};\n\n// ---- tools -----------------------------------------------------------------\n\n/**\n * A content block in a tool result. This is the subset of MCP's content types\n * the Tabbied tools actually produce; the shape is identical in both protocol\n * eras (see docs/mcp-server.md).\n */\nexport type ToolContent =\n | { type: 'text'; text: string }\n | { type: 'image'; data: string; mimeType: string };\n\nexport type ToolResult = {\n content: ToolContent[];\n /**\n * A *tool execution* error (bad slug, unrenderable design), not a JSON-RPC\n * protocol error: the spec asks clients to feed these back to the model so\n * it can self-correct.\n */\n isError?: boolean;\n};\n\nexport type ToolDefinition = {\n name: string;\n title: string;\n description: string;\n /**\n * Plain JSON Schema, not Zod (see server.ts). Typed as the SDK's own type\n * (a type-only import) so a schema the SDK cannot register fails at `tsc`\n * rather than at the first `tools/list`.\n */\n inputSchema: JsonSchemaType;\n};\n\nexport type Tool = {\n definition: ToolDefinition;\n run(args: Record<string, unknown>): ToolResult | Promise<ToolResult>;\n};\n\n/**\n * Everything the catalog tools need from their host. The fetchers are injected\n * rather than imported because they differ per runtime: the Worker reads its\n * own static assets, the stdio server the local package and the network.\n */\nexport type ToolContext = {\n catalog: Catalog;\n /** Resolves a design's preview image to base64. Omit to drop `preview_design`. */\n fetchPreview?: (\n design: CatalogDesign\n ) => Promise<{ data: string; mimeType: string }>;\n /** Resolves the llms-full.txt reference. Omit to drop `get_docs`. */\n fetchDocs?: () => Promise<string>;\n /** Resolves the editable-template index. Omit to drop both template tools. */\n fetchTemplateCatalog?: () => Promise<TemplateCatalog>;\n /** Resolves one template's spec. Omit (with the above) to drop `get_template`. */\n fetchTemplate?: (slug: string) => Promise<TemplateSpec>;\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,55 +1,56 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "tabbied-mcp",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "MCP server for Tabbied: search, look at, and render its generative pattern designs from any MCP client.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"sideEffects": false,
|
|
7
|
-
"license": "MIT",
|
|
8
|
-
"author": "Sy Hong and Ye Joo Park",
|
|
9
|
-
"homepage": "https://tabbied.com",
|
|
10
|
-
"repository": {
|
|
11
|
-
"type": "git",
|
|
12
|
-
"url": "git+https://github.com/tabbied-design/tabbied.git",
|
|
13
|
-
"directory": "packages/tabbied-mcp"
|
|
14
|
-
},
|
|
15
|
-
"keywords": [
|
|
16
|
-
"mcp",
|
|
17
|
-
"model-context-protocol",
|
|
18
|
-
"tabbied",
|
|
19
|
-
"generative-art",
|
|
20
|
-
"pattern",
|
|
21
|
-
"css-doodle"
|
|
22
|
-
],
|
|
23
|
-
"exports": {
|
|
24
|
-
".": {
|
|
25
|
-
"types": "./dist/index.d.ts",
|
|
26
|
-
"import": "./dist/index.js",
|
|
27
|
-
"default": "./dist/index.js"
|
|
28
|
-
},
|
|
29
|
-
"./package.json": "./package.json"
|
|
30
|
-
},
|
|
31
|
-
"main": "./dist/index.js",
|
|
32
|
-
"types": "./dist/index.d.ts",
|
|
33
|
-
"bin": {
|
|
34
|
-
"tabbied-mcp": "dist/stdio.js"
|
|
35
|
-
},
|
|
36
|
-
"files": [
|
|
37
|
-
"dist"
|
|
38
|
-
],
|
|
39
|
-
"scripts": {
|
|
40
|
-
"build": "node -e \"fs.rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",
|
|
41
|
-
"test": "node --test",
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "tabbied-mcp",
|
|
3
|
+
"version": "0.2.3",
|
|
4
|
+
"description": "MCP server for Tabbied: search, look at, and render its generative pattern designs from any MCP client.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "Sy Hong and Ye Joo Park",
|
|
9
|
+
"homepage": "https://tabbied.com",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/tabbied-design/tabbied.git",
|
|
13
|
+
"directory": "packages/tabbied-mcp"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"model-context-protocol",
|
|
18
|
+
"tabbied",
|
|
19
|
+
"generative-art",
|
|
20
|
+
"pattern",
|
|
21
|
+
"css-doodle"
|
|
22
|
+
],
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"import": "./dist/index.js",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./package.json": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/index.js",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"bin": {
|
|
34
|
+
"tabbied-mcp": "dist/stdio.js"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "node -e \"fs.rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.json",
|
|
41
|
+
"test": "node --test",
|
|
42
|
+
"sync-version": "node scripts/sync-version.mjs",
|
|
43
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@modelcontextprotocol/server": "^2.2.0",
|
|
47
|
+
"tabbied": "^0.7.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^26.6.3",
|
|
51
|
+
"typescript": "^7.0.2"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=18"
|
|
55
|
+
}
|
|
56
|
+
}
|