@nanisoft/prism-mcp-server 0.3.0 → 0.4.0
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/README.md +66 -0
- package/THIRD-PARTY-NOTICES.md +48 -0
- package/dist/descriptions.d.ts +22 -0
- package/dist/descriptions.js +33 -0
- package/dist/generated/built.d.ts +2 -0
- package/dist/generated/built.js +6 -0
- package/dist/generated/server-version.d.ts +1 -0
- package/dist/generated/server-version.js +5 -0
- package/dist/index.d.ts +11 -10
- package/dist/index.js +10 -9
- package/dist/render.d.ts +69 -44
- package/dist/render.js +422 -145
- package/dist/rules.d.ts +12 -0
- package/dist/rules.js +14 -0
- package/dist/schemas.d.ts +104 -0
- package/dist/schemas.js +102 -0
- package/dist/server.d.ts +22 -0
- package/dist/server.js +75 -0
- package/dist/version.d.ts +1 -10
- package/dist/version.js +10 -7
- package/dist/vocab.d.ts +13 -0
- package/dist/vocab.js +19 -0
- package/package.json +32 -23
- package/dist/factory.d.ts +0 -31
- package/dist/factory.d.ts.map +0 -1
- package/dist/factory.js +0 -33
- package/dist/factory.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lookup.d.ts +0 -68
- package/dist/lookup.d.ts.map +0 -1
- package/dist/lookup.js +0 -113
- package/dist/lookup.js.map +0 -1
- package/dist/render.d.ts.map +0 -1
- package/dist/render.js.map +0 -1
- package/dist/search.d.ts +0 -34
- package/dist/search.d.ts.map +0 -1
- package/dist/search.js +0 -68
- package/dist/search.js.map +0 -1
- package/dist/store.d.ts +0 -62
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -80
- package/dist/store.js.map +0 -1
- package/dist/tools.d.ts +0 -22
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js +0 -122
- package/dist/tools.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tool argument schemas, one zod object per tool.
|
|
3
|
+
*
|
|
4
|
+
* Every field carries a `.describe(...)` so a client that reads `tools/list`
|
|
5
|
+
* sees what to pass. The cross-field rule (`category` is Component-only) is a
|
|
6
|
+
* `.refine` on `list_items`, so the protocol answers it as an `isError` result
|
|
7
|
+
* rather than the handler throwing.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
export declare const listItemsSchema: z.ZodObject<{
|
|
11
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
12
|
+
component: "component";
|
|
13
|
+
block: "block";
|
|
14
|
+
page: "page";
|
|
15
|
+
}>>;
|
|
16
|
+
category: z.ZodOptional<z.ZodEnum<{
|
|
17
|
+
"Call to action": "Call to action";
|
|
18
|
+
"Forms and inputs": "Forms and inputs";
|
|
19
|
+
Feedback: "Feedback";
|
|
20
|
+
Layout: "Layout";
|
|
21
|
+
"Data display": "Data display";
|
|
22
|
+
Typography: "Typography";
|
|
23
|
+
Miscellaneous: "Miscellaneous";
|
|
24
|
+
}>>;
|
|
25
|
+
}, z.core.$strip>;
|
|
26
|
+
export declare const getItemDocSchema: z.ZodObject<{
|
|
27
|
+
name: z.ZodString;
|
|
28
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
29
|
+
component: "component";
|
|
30
|
+
block: "block";
|
|
31
|
+
page: "page";
|
|
32
|
+
}>>;
|
|
33
|
+
}, z.core.$strip>;
|
|
34
|
+
export declare const getItemPropsSchema: z.ZodObject<{
|
|
35
|
+
name: z.ZodString;
|
|
36
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
37
|
+
component: "component";
|
|
38
|
+
block: "block";
|
|
39
|
+
page: "page";
|
|
40
|
+
}>>;
|
|
41
|
+
}, z.core.$strip>;
|
|
42
|
+
export declare const getItemSourceSchema: z.ZodObject<{
|
|
43
|
+
name: z.ZodString;
|
|
44
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
45
|
+
component: "component";
|
|
46
|
+
block: "block";
|
|
47
|
+
page: "page";
|
|
48
|
+
}>>;
|
|
49
|
+
}, z.core.$strip>;
|
|
50
|
+
export declare const getThemeDocSchema: z.ZodObject<{
|
|
51
|
+
pack: z.ZodOptional<z.ZodEnum<{
|
|
52
|
+
default: "default";
|
|
53
|
+
blush: "blush";
|
|
54
|
+
mint: "mint";
|
|
55
|
+
lavender: "lavender";
|
|
56
|
+
sky: "sky";
|
|
57
|
+
peach: "peach";
|
|
58
|
+
}>>;
|
|
59
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
60
|
+
light: "light";
|
|
61
|
+
dark: "dark";
|
|
62
|
+
}>>;
|
|
63
|
+
group: z.ZodOptional<z.ZodEnum<{
|
|
64
|
+
motion: "motion";
|
|
65
|
+
typography: "typography";
|
|
66
|
+
spacing: "spacing";
|
|
67
|
+
shadow: "shadow";
|
|
68
|
+
breakpoint: "breakpoint";
|
|
69
|
+
container: "container";
|
|
70
|
+
semantic: "semantic";
|
|
71
|
+
}>>;
|
|
72
|
+
}, z.core.$strip>;
|
|
73
|
+
export declare const listPagesSchema: z.ZodObject<{}, z.core.$strip>;
|
|
74
|
+
export declare const getPageSchema: z.ZodObject<{
|
|
75
|
+
url: z.ZodString;
|
|
76
|
+
}, z.core.$strip>;
|
|
77
|
+
export declare const searchDocsSchema: z.ZodObject<{
|
|
78
|
+
query: z.ZodString;
|
|
79
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
80
|
+
component: "component";
|
|
81
|
+
block: "block";
|
|
82
|
+
page: "page";
|
|
83
|
+
doc: "doc";
|
|
84
|
+
}>>;
|
|
85
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
86
|
+
}, z.core.$strip>;
|
|
87
|
+
/**
|
|
88
|
+
* `get_changelog` takes a package and an optional version, and nothing else.
|
|
89
|
+
*
|
|
90
|
+
* The package is a plain string rather than a closed enum because the set of
|
|
91
|
+
* published packages is the workspace's, discovered at build time, and an enum
|
|
92
|
+
* frozen at compile time would be a second list of them that a newly published
|
|
93
|
+
* package would not be in. The argument accepts the scoped name, the unscoped
|
|
94
|
+
* name and the route segment, because an agent arrives holding whichever it has.
|
|
95
|
+
*
|
|
96
|
+
* `version` is optional rather than defaulted, so one call can return a whole
|
|
97
|
+
* changelog and one call can return a single entry: an agent asking "what broke"
|
|
98
|
+
* for a package it is already on does not need the rest of the history, and an
|
|
99
|
+
* agent asking what a package has done needs all of it.
|
|
100
|
+
*/
|
|
101
|
+
export declare const getChangelogSchema: z.ZodObject<{
|
|
102
|
+
package: z.ZodString;
|
|
103
|
+
version: z.ZodOptional<z.ZodString>;
|
|
104
|
+
}, z.core.$strip>;
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The tool argument schemas, one zod object per tool.
|
|
3
|
+
*
|
|
4
|
+
* Every field carries a `.describe(...)` so a client that reads `tools/list`
|
|
5
|
+
* sees what to pass. The cross-field rule (`category` is Component-only) is a
|
|
6
|
+
* `.refine` on `list_items`, so the protocol answers it as an `isError` result
|
|
7
|
+
* rather than the handler throwing.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { COMPONENT_CATEGORIES, ITEM_KINDS, MODES, PACKS, SEARCH_KINDS, TOKEN_GROUPS } from './vocab.js';
|
|
11
|
+
const kindField = z
|
|
12
|
+
.enum(ITEM_KINDS)
|
|
13
|
+
.optional()
|
|
14
|
+
.describe('One catalogue kind: component, block or page. Omit to search every kind.');
|
|
15
|
+
const nameField = z
|
|
16
|
+
.string()
|
|
17
|
+
.min(1)
|
|
18
|
+
.describe('The item name (for example `Button`) or its slug (for example `button`), case-insensitive.');
|
|
19
|
+
export const listItemsSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
kind: kindField,
|
|
22
|
+
category: z
|
|
23
|
+
.enum(COMPONENT_CATEGORIES)
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('One Component category, for example `Forms and inputs`. Only valid for kind `component`.'),
|
|
26
|
+
})
|
|
27
|
+
.refine((args) => !(args.category && args.kind && args.kind !== 'component'), {
|
|
28
|
+
message: '`category` is a Component-only field; it is not valid for a block or a page.',
|
|
29
|
+
path: ['category'],
|
|
30
|
+
});
|
|
31
|
+
export const getItemDocSchema = z.object({
|
|
32
|
+
name: nameField,
|
|
33
|
+
kind: kindField,
|
|
34
|
+
});
|
|
35
|
+
export const getItemPropsSchema = z.object({
|
|
36
|
+
name: nameField,
|
|
37
|
+
kind: kindField,
|
|
38
|
+
});
|
|
39
|
+
export const getItemSourceSchema = z.object({
|
|
40
|
+
name: nameField,
|
|
41
|
+
kind: kindField,
|
|
42
|
+
});
|
|
43
|
+
export const getThemeDocSchema = z.object({
|
|
44
|
+
pack: z
|
|
45
|
+
.enum(PACKS)
|
|
46
|
+
.optional()
|
|
47
|
+
.describe('The palette id. Defaults to `default`.'),
|
|
48
|
+
mode: z
|
|
49
|
+
.enum(MODES)
|
|
50
|
+
.optional()
|
|
51
|
+
.describe('The mode axis. Defaults to `light`.'),
|
|
52
|
+
group: z
|
|
53
|
+
.enum(TOKEN_GROUPS)
|
|
54
|
+
.optional()
|
|
55
|
+
.describe('One token group: `semantic` for the resolved pack-by-mode set, or a bound scale (motion, typography, spacing, shadow, breakpoint, container). Omit for the semantic set.'),
|
|
56
|
+
});
|
|
57
|
+
export const listPagesSchema = z.object({});
|
|
58
|
+
export const getPageSchema = z.object({
|
|
59
|
+
url: z
|
|
60
|
+
.string()
|
|
61
|
+
.min(1)
|
|
62
|
+
.describe('A non-item page URL or mirror, for example `/overview/quickstart` or `/overview/quickstart.md`.'),
|
|
63
|
+
});
|
|
64
|
+
export const searchDocsSchema = z.object({
|
|
65
|
+
query: z.string().min(1).describe('The substring to match against names, descriptions and page bodies.'),
|
|
66
|
+
kind: z
|
|
67
|
+
.enum(SEARCH_KINDS)
|
|
68
|
+
.optional()
|
|
69
|
+
.describe('Restrict hits to one kind; `doc` means a non-item page. Omit to search the whole corpus.'),
|
|
70
|
+
limit: z
|
|
71
|
+
.number()
|
|
72
|
+
.int()
|
|
73
|
+
.min(1)
|
|
74
|
+
.max(10)
|
|
75
|
+
.optional()
|
|
76
|
+
.describe('Maximum hits to return. Defaults to 5, maximum 10.'),
|
|
77
|
+
});
|
|
78
|
+
/**
|
|
79
|
+
* `get_changelog` takes a package and an optional version, and nothing else.
|
|
80
|
+
*
|
|
81
|
+
* The package is a plain string rather than a closed enum because the set of
|
|
82
|
+
* published packages is the workspace's, discovered at build time, and an enum
|
|
83
|
+
* frozen at compile time would be a second list of them that a newly published
|
|
84
|
+
* package would not be in. The argument accepts the scoped name, the unscoped
|
|
85
|
+
* name and the route segment, because an agent arrives holding whichever it has.
|
|
86
|
+
*
|
|
87
|
+
* `version` is optional rather than defaulted, so one call can return a whole
|
|
88
|
+
* changelog and one call can return a single entry: an agent asking "what broke"
|
|
89
|
+
* for a package it is already on does not need the rest of the history, and an
|
|
90
|
+
* agent asking what a package has done needs all of it.
|
|
91
|
+
*/
|
|
92
|
+
export const getChangelogSchema = z.object({
|
|
93
|
+
package: z
|
|
94
|
+
.string()
|
|
95
|
+
.min(1)
|
|
96
|
+
.describe('A published Prism package, for example `@nanisoft/prism-ui`. The unscoped name and the route segment are accepted too.'),
|
|
97
|
+
version: z
|
|
98
|
+
.string()
|
|
99
|
+
.min(1)
|
|
100
|
+
.optional()
|
|
101
|
+
.describe('One version entry, for example `0.5.0`. Omit to read the whole changelog.'),
|
|
102
|
+
});
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createPrismMcpServer`: the transport-free factory ticket 05 fixed as the one
|
|
3
|
+
* seam. It registers the read-only tools over a validated `PrismDocsStore` and
|
|
4
|
+
* returns an `McpServer` that any transport can connect.
|
|
5
|
+
*
|
|
6
|
+
* The store guard runs at this door, so a raw `data.json` is validated once and
|
|
7
|
+
* every transport inherits the same rejection. The factory holds no I/O: the
|
|
8
|
+
* Worker bundles the store at build time.
|
|
9
|
+
*/
|
|
10
|
+
import { McpServer } from '@modelcontextprotocol/server';
|
|
11
|
+
export interface PrismMcpServerOptions {
|
|
12
|
+
/**
|
|
13
|
+
* The corpus build stamp from the MCP lane's generated module. When omitted
|
|
14
|
+
* or `undefined`, `list_items` omits the `(built ...)` clause.
|
|
15
|
+
*/
|
|
16
|
+
built?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Build a fresh `McpServer` over `raw`, which may be a parsed `PrismDocsStore`
|
|
20
|
+
* or a raw `data.json` payload. The guard is idempotent on a valid store.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createPrismMcpServer(raw: unknown, options?: PrismMcpServerOptions): McpServer;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createPrismMcpServer`: the transport-free factory ticket 05 fixed as the one
|
|
3
|
+
* seam. It registers the read-only tools over a validated `PrismDocsStore` and
|
|
4
|
+
* returns an `McpServer` that any transport can connect.
|
|
5
|
+
*
|
|
6
|
+
* The store guard runs at this door, so a raw `data.json` is validated once and
|
|
7
|
+
* every transport inherits the same rejection. The factory holds no I/O: the
|
|
8
|
+
* Worker bundles the store at build time.
|
|
9
|
+
*/
|
|
10
|
+
import { McpServer } from '@modelcontextprotocol/server';
|
|
11
|
+
import { parsePrismDocsStore } from '@nanisoft/prism-llms';
|
|
12
|
+
import { DESCRIPTIONS } from './descriptions.js';
|
|
13
|
+
import { getChangelogSchema, getItemDocSchema, getItemPropsSchema, getItemSourceSchema, getPageSchema, getThemeDocSchema, listItemsSchema, listPagesSchema, searchDocsSchema, } from './schemas.js';
|
|
14
|
+
import { renderChangelog, renderItemDoc, renderItemProps, renderItemSource, renderListItems, renderListPages, renderPage, renderThemeDoc, searchDocs, } from './render.js';
|
|
15
|
+
import { SERVER_NAME, SERVER_VERSION } from './version.js';
|
|
16
|
+
/**
|
|
17
|
+
* Build a fresh `McpServer` over `raw`, which may be a parsed `PrismDocsStore`
|
|
18
|
+
* or a raw `data.json` payload. The guard is idempotent on a valid store.
|
|
19
|
+
*/
|
|
20
|
+
export function createPrismMcpServer(raw, options = {}) {
|
|
21
|
+
const store = parsePrismDocsStore(raw);
|
|
22
|
+
const built = options.built;
|
|
23
|
+
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION });
|
|
24
|
+
server.registerTool('list_items', {
|
|
25
|
+
title: 'List Prism items',
|
|
26
|
+
description: DESCRIPTIONS.list_items,
|
|
27
|
+
inputSchema: listItemsSchema,
|
|
28
|
+
}, (args) => renderListItems(store, args ?? {}, built));
|
|
29
|
+
server.registerTool('get_item_doc', {
|
|
30
|
+
title: 'Get item documentation',
|
|
31
|
+
description: DESCRIPTIONS.get_item_doc,
|
|
32
|
+
inputSchema: getItemDocSchema,
|
|
33
|
+
}, (args) => renderItemDoc(store, args));
|
|
34
|
+
server.registerTool('get_item_props', {
|
|
35
|
+
title: 'Get item props',
|
|
36
|
+
description: DESCRIPTIONS.get_item_props,
|
|
37
|
+
inputSchema: getItemPropsSchema,
|
|
38
|
+
}, (args) => renderItemProps(store, args));
|
|
39
|
+
server.registerTool('get_item_source', {
|
|
40
|
+
title: 'Get item example source',
|
|
41
|
+
description: DESCRIPTIONS.get_item_source,
|
|
42
|
+
inputSchema: getItemSourceSchema,
|
|
43
|
+
}, (args) => renderItemSource(store, args));
|
|
44
|
+
server.registerTool('get_theme_doc', {
|
|
45
|
+
title: 'Get theme and token contract',
|
|
46
|
+
description: DESCRIPTIONS.get_theme_doc,
|
|
47
|
+
inputSchema: getThemeDocSchema,
|
|
48
|
+
}, (args) => renderThemeDoc(store, args ?? {}));
|
|
49
|
+
server.registerTool('list_pages', {
|
|
50
|
+
title: 'List documentation pages',
|
|
51
|
+
description: DESCRIPTIONS.list_pages,
|
|
52
|
+
inputSchema: listPagesSchema,
|
|
53
|
+
}, () => renderListPages(store));
|
|
54
|
+
server.registerTool('get_page', {
|
|
55
|
+
title: 'Get documentation page',
|
|
56
|
+
description: DESCRIPTIONS.get_page,
|
|
57
|
+
inputSchema: getPageSchema,
|
|
58
|
+
}, (args) => renderPage(store, args));
|
|
59
|
+
server.registerTool('search_docs', {
|
|
60
|
+
title: 'Search the corpus',
|
|
61
|
+
description: DESCRIPTIONS.search_docs,
|
|
62
|
+
inputSchema: searchDocsSchema,
|
|
63
|
+
}, (args) => searchDocs(store, args));
|
|
64
|
+
// Registered last and named `get_changelog` beside the eight rather than
|
|
65
|
+
// replacing one of them. The Changelogs Section reaching the Corpus is a
|
|
66
|
+
// parameter on `list_pages` and `get_page`, which already read the Sections
|
|
67
|
+
// from the Store, plus one tool for the thing the eight cannot express: what
|
|
68
|
+
// a published package changed in a version.
|
|
69
|
+
server.registerTool('get_changelog', {
|
|
70
|
+
title: 'Get a package changelog',
|
|
71
|
+
description: DESCRIPTIONS.get_changelog,
|
|
72
|
+
inputSchema: getChangelogSchema,
|
|
73
|
+
}, (args) => renderChangelog(store, args));
|
|
74
|
+
return server;
|
|
75
|
+
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,11 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The MCP server identity (`serverInfo` in the protocol handshake).
|
|
3
|
-
*
|
|
4
|
-
* Keep in sync with `package.json` — this is a literal because importing the
|
|
5
|
-
* package JSON would drag a file outside `rootDir` into the tsc build. This is
|
|
6
|
-
* *protocol* metadata, not the corpus version: `list_items` echoes the store's
|
|
7
|
-
* own `prismVersion` so agents can detect a corpus/installed-version mismatch.
|
|
8
|
-
*/
|
|
9
1
|
export declare const SERVER_NAME = "prism-mcp-server";
|
|
10
|
-
export declare const SERVER_VERSION
|
|
11
|
-
//# sourceMappingURL=version.d.ts.map
|
|
2
|
+
export declare const SERVER_VERSION: string;
|
package/dist/version.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The protocol identity the MCP lane reports.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The name is the protocol identity and does not move with a release, so it is
|
|
5
|
+
* authored here. The version does move, so it is not authored here: it is
|
|
6
|
+
* stamped from this package's own `package.json` by `scripts/stamp-built.mjs`,
|
|
7
|
+
* which the build, the type-check and the tests all run first. Written by hand
|
|
8
|
+
* it was a second place every release had to remember, and it stayed `0.1.0`
|
|
9
|
+
* through a `0.2.0` release, so the server told every consumer a version it had
|
|
10
|
+
* stopped being.
|
|
8
11
|
*/
|
|
12
|
+
import { SERVER_VERSION as STAMPED_VERSION } from './generated/server-version.js';
|
|
9
13
|
export const SERVER_NAME = 'prism-mcp-server';
|
|
10
|
-
export const SERVER_VERSION =
|
|
11
|
-
//# sourceMappingURL=version.js.map
|
|
14
|
+
export const SERVER_VERSION = STAMPED_VERSION;
|
package/dist/vocab.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const ITEM_KINDS: readonly ["component", "block", "page"];
|
|
2
|
+
export declare const COMPONENT_CATEGORIES: readonly ["Call to action", "Forms and inputs", "Feedback", "Layout", "Data display", "Typography", "Miscellaneous"];
|
|
3
|
+
export declare const PACKS: readonly ["default", "blush", "mint", "lavender", "sky", "peach"];
|
|
4
|
+
export declare const MODES: readonly ["light", "dark"];
|
|
5
|
+
export declare const SCALE_GROUPS: readonly ["motion", "typography", "spacing", "shadow", "breakpoint", "container"];
|
|
6
|
+
/** `'doc'` means a non-item page: a guide, a Foundation or a Content page. */
|
|
7
|
+
export declare const SEARCH_KINDS: readonly ["component", "block", "page", "doc"];
|
|
8
|
+
/** The `get_theme_doc` group: the pack-by-mode semantic set or one bound scale. */
|
|
9
|
+
export declare const TOKEN_GROUPS: readonly ["semantic", "motion", "typography", "spacing", "shadow", "breakpoint", "container"];
|
|
10
|
+
export type ItemKind = (typeof ITEM_KINDS)[number];
|
|
11
|
+
export type ComponentCategory = (typeof COMPONENT_CATEGORIES)[number];
|
|
12
|
+
export type SearchKind = (typeof SEARCH_KINDS)[number];
|
|
13
|
+
export type TokenGroup = (typeof TOKEN_GROUPS)[number];
|
package/dist/vocab.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The closed vocabularies the tool schemas expose.
|
|
3
|
+
*
|
|
4
|
+
* Every list is a projection of a resolved ticket rather than a new list: the
|
|
5
|
+
* item kinds and categories are `prism-llms`' store union (itself the
|
|
6
|
+
* catalogue's closed union), the packs and modes are ticket 07's, and the scale
|
|
7
|
+
* groups are tickets 06 and 18's bound groups. One addition lives here:
|
|
8
|
+
* `SearchKind`, which adds `'doc'` for a non-item page.
|
|
9
|
+
*/
|
|
10
|
+
import { STORE_CATEGORIES, STORE_KINDS, STORE_MODES, STORE_PACKS, STORE_SCALE_GROUPS, } from '@nanisoft/prism-llms';
|
|
11
|
+
export const ITEM_KINDS = STORE_KINDS;
|
|
12
|
+
export const COMPONENT_CATEGORIES = STORE_CATEGORIES;
|
|
13
|
+
export const PACKS = STORE_PACKS;
|
|
14
|
+
export const MODES = STORE_MODES;
|
|
15
|
+
export const SCALE_GROUPS = STORE_SCALE_GROUPS;
|
|
16
|
+
/** `'doc'` means a non-item page: a guide, a Foundation or a Content page. */
|
|
17
|
+
export const SEARCH_KINDS = [...STORE_KINDS, 'doc'];
|
|
18
|
+
/** The `get_theme_doc` group: the pack-by-mode semantic set or one bound scale. */
|
|
19
|
+
export const TOKEN_GROUPS = ['semantic', ...STORE_SCALE_GROUPS];
|
package/package.json
CHANGED
|
@@ -1,42 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nanisoft/prism-mcp-server",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Tool logic for the Prism MCP server — transport-free, fed by prism-llms output. The HTTP transport lives in the apps/site Worker at /mcp.",
|
|
5
|
-
"license": "MIT",
|
|
3
|
+
"version": "0.4.0",
|
|
6
4
|
"type": "module",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
5
|
+
"description": "Prism's read-only MCP tool surface: eight retrieval tools over the bundled PrismDocsStore corpus. Transport-free: one factory serves the site Worker at /mcp.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "NaniSoft",
|
|
8
|
+
"homepage": "https://prism.nanisoft.com",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/NaniSoft/prism.git",
|
|
12
|
+
"directory": "packages/mcp-server"
|
|
10
13
|
},
|
|
14
|
+
"sideEffects": false,
|
|
11
15
|
"exports": {
|
|
12
16
|
".": {
|
|
13
17
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"
|
|
15
|
-
}
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./package.json": "./package.json"
|
|
16
21
|
},
|
|
17
22
|
"files": [
|
|
18
|
-
"dist"
|
|
23
|
+
"dist",
|
|
24
|
+
"THIRD-PARTY-NOTICES.md"
|
|
19
25
|
],
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=22.14.0"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
25
31
|
},
|
|
26
32
|
"dependencies": {
|
|
27
33
|
"@modelcontextprotocol/server": "2.0.0",
|
|
28
|
-
"zod": "^4.
|
|
34
|
+
"zod": "^4.2.0",
|
|
35
|
+
"@nanisoft/prism-llms": "0.5.0"
|
|
29
36
|
},
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"directory": "packages/mcp-server"
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@modelcontextprotocol/client": "2.0.0",
|
|
39
|
+
"@types/node": "^22.0.0",
|
|
40
|
+
"typescript": "^5.7.0",
|
|
41
|
+
"vitest": "^3.2.4"
|
|
36
42
|
},
|
|
37
43
|
"scripts": {
|
|
38
|
-
"
|
|
39
|
-
"
|
|
44
|
+
"prebuild": "node scripts/stamp-built.mjs",
|
|
45
|
+
"build": "tsc -p tsconfig.build.json",
|
|
46
|
+
"pretypecheck": "node scripts/stamp-built.mjs",
|
|
47
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
48
|
+
"pretest": "node scripts/stamp-built.mjs && tsc -p tsconfig.build.json",
|
|
40
49
|
"test": "vitest run"
|
|
41
50
|
}
|
|
42
51
|
}
|
package/dist/factory.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The pure, transport-agnostic factory (ADR-0004): tool logic written once
|
|
3
|
-
* here, served by any transport. The site Worker wires it through
|
|
4
|
-
* `createMcpHandler(factory)`; a stdio-only client bridges with
|
|
5
|
-
* `npx mcp-remote` — there is deliberately no second implementation.
|
|
6
|
-
*
|
|
7
|
-
* The factory runs per request on the Worker lane, so the lookup maps are
|
|
8
|
-
* built inside it (never at isolate scope — ticket 05's startup-limit rule).
|
|
9
|
-
*/
|
|
10
|
-
import { McpServer } from '@modelcontextprotocol/server';
|
|
11
|
-
import { type PrismDocsStore } from './store.js';
|
|
12
|
-
export interface PrismMcpServerOptions {
|
|
13
|
-
/**
|
|
14
|
-
* The corpus build date (`YYYY-MM-DD`) for the `list_items` header.
|
|
15
|
-
*
|
|
16
|
-
* `PrismDocsStore` carries no build date (ADR-0004 §5 fixes the interface and
|
|
17
|
-
* prism-llms emits exactly those fields), so the bundler supplies this when
|
|
18
|
-
* it knows one; when absent the header simply states version + counts rather
|
|
19
|
-
* than inventing a date. If prism-llms grows a `built` field, render it from
|
|
20
|
-
* the store and retire this option.
|
|
21
|
-
*/
|
|
22
|
-
readonly built?: string;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Build an `McpServer` with the eight Prism tools over `docs`. Pure: reads
|
|
26
|
-
* `docs`, touches no I/O, registers no transport. The store guard runs here at
|
|
27
|
-
* the door as well — callers that bypass their own validation get a precise
|
|
28
|
-
* `TypeError` naming the field, not a deep tool failure.
|
|
29
|
-
*/
|
|
30
|
-
export declare function createPrismMcpServer(docs: PrismDocsStore, options?: PrismMcpServerOptions): McpServer;
|
|
31
|
-
//# sourceMappingURL=factory.d.ts.map
|
package/dist/factory.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAIzD,OAAO,EAAuB,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAGtE,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,GAAE,qBAA0B,GAAG,SAAS,CAWzG"}
|
package/dist/factory.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The pure, transport-agnostic factory (ADR-0004): tool logic written once
|
|
3
|
-
* here, served by any transport. The site Worker wires it through
|
|
4
|
-
* `createMcpHandler(factory)`; a stdio-only client bridges with
|
|
5
|
-
* `npx mcp-remote` — there is deliberately no second implementation.
|
|
6
|
-
*
|
|
7
|
-
* The factory runs per request on the Worker lane, so the lookup maps are
|
|
8
|
-
* built inside it (never at isolate scope — ticket 05's startup-limit rule).
|
|
9
|
-
*/
|
|
10
|
-
import { McpServer } from '@modelcontextprotocol/server';
|
|
11
|
-
import { createItemLookup, createPageLookup, createThemeLookup } from './lookup.js';
|
|
12
|
-
import { registerPrismTools } from './tools.js';
|
|
13
|
-
import { parsePrismDocsStore } from './store.js';
|
|
14
|
-
import { SERVER_NAME, SERVER_VERSION } from './version.js';
|
|
15
|
-
/**
|
|
16
|
-
* Build an `McpServer` with the eight Prism tools over `docs`. Pure: reads
|
|
17
|
-
* `docs`, touches no I/O, registers no transport. The store guard runs here at
|
|
18
|
-
* the door as well — callers that bypass their own validation get a precise
|
|
19
|
-
* `TypeError` naming the field, not a deep tool failure.
|
|
20
|
-
*/
|
|
21
|
-
export function createPrismMcpServer(docs, options = {}) {
|
|
22
|
-
const store = parsePrismDocsStore(docs);
|
|
23
|
-
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION });
|
|
24
|
-
registerPrismTools(server, {
|
|
25
|
-
docs: store,
|
|
26
|
-
items: createItemLookup(store.items),
|
|
27
|
-
pages: createPageLookup(store.pages, store.baseUrl),
|
|
28
|
-
themes: createThemeLookup(store.themes),
|
|
29
|
-
built: options.built,
|
|
30
|
-
});
|
|
31
|
-
return server;
|
|
32
|
-
}
|
|
33
|
-
//# sourceMappingURL=factory.js.map
|
package/dist/factory.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAEzD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACpF,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAuB,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAe3D;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAoB,EAAE,OAAO,GAA0B,EAAE;IAC5F,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;IAC7E,kBAAkB,CAAC,MAAM,EAAE;QACzB,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC;QACpC,KAAK,EAAE,gBAAgB,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;QACnD,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC;QACvC,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,oBAAoB,EAA8B,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/lookup.d.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Case-insensitive resolution over the bundled corpus, with did-you-mean
|
|
3
|
-
* suggestions on a miss (ADR-0004 §2: lookups are case-insensitive and a miss
|
|
4
|
-
* returns the closest matches plus a browse pointer — never a throw).
|
|
5
|
-
*
|
|
6
|
-
* Maps are built once per `createPrismMcpServer()` call — per request on the
|
|
7
|
-
* Worker lane, never at isolate scope (ticket 05's startup-limit rule).
|
|
8
|
-
*/
|
|
9
|
-
import type { PrismDocsItem, PrismDocsPage, PrismDocsTheme } from './store.js';
|
|
10
|
-
/** One catalog item kind — the `kind` parameter shared by the item tools. */
|
|
11
|
-
export type ItemKind = PrismDocsItem['kind'];
|
|
12
|
-
/** Order the catalog tools group and count kinds in. */
|
|
13
|
-
export declare const ITEM_KINDS: readonly ItemKind[];
|
|
14
|
-
/** The theme atom a bare `get_theme_doc()` answers with. */
|
|
15
|
-
export declare const DEFAULT_PACK = "blue";
|
|
16
|
-
export declare const DEFAULT_MODE = "light";
|
|
17
|
-
/** Smallest-edit-distance suggestions, closest and shortest first. */
|
|
18
|
-
export declare function didYouMean(query: string, candidates: readonly string[], limit?: number): string[];
|
|
19
|
-
/** What resolving an item name produced. */
|
|
20
|
-
export type ItemMatch = {
|
|
21
|
-
readonly status: 'ok';
|
|
22
|
-
readonly item: PrismDocsItem;
|
|
23
|
-
} | {
|
|
24
|
-
readonly status: 'kind-mismatch';
|
|
25
|
-
readonly item: PrismDocsItem;
|
|
26
|
-
} | {
|
|
27
|
-
readonly status: 'miss';
|
|
28
|
-
readonly suggestions: readonly string[];
|
|
29
|
-
};
|
|
30
|
-
export interface ItemLookup {
|
|
31
|
-
/** Every item name, in corpus order — the suggestion pool and catalog input. */
|
|
32
|
-
readonly names: readonly string[];
|
|
33
|
-
find(name: string, kind?: ItemKind): ItemMatch;
|
|
34
|
-
suggest(name: string): readonly string[];
|
|
35
|
-
}
|
|
36
|
-
export declare function createItemLookup(items: readonly PrismDocsItem[]): ItemLookup;
|
|
37
|
-
export interface PageLookup {
|
|
38
|
-
/** Every page url, in corpus order. */
|
|
39
|
-
readonly urls: readonly string[];
|
|
40
|
-
find(url: string): PrismDocsPage | undefined;
|
|
41
|
-
suggest(url: string): readonly string[];
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Site-pathname lookup (`/docs/theming`), tolerant of case, trailing slashes,
|
|
45
|
-
* and absolute site URLs (`https://prism.nanisoft.com/docs/theming`).
|
|
46
|
-
*/
|
|
47
|
-
export declare function createPageLookup(pages: readonly PrismDocsPage[], baseUrl: string): PageLookup;
|
|
48
|
-
export interface ThemeLookup {
|
|
49
|
-
/** Every theme-atom slug, in corpus order. */
|
|
50
|
-
readonly slugs: readonly string[];
|
|
51
|
-
find(pack: string, mode: string): PrismDocsTheme | undefined;
|
|
52
|
-
suggest(slug: string): readonly string[];
|
|
53
|
-
}
|
|
54
|
-
/** Theme atoms are slugged `<pack>-<mode>` (prism-llms emits four). */
|
|
55
|
-
export declare const themeSlug: (pack: string, mode: string) => string;
|
|
56
|
-
export declare function createThemeLookup(themes: readonly PrismDocsTheme[]): ThemeLookup;
|
|
57
|
-
/** Resolve which example's source `get_item_source` should return. */
|
|
58
|
-
export type ExampleMatch = {
|
|
59
|
-
readonly status: 'ok';
|
|
60
|
-
readonly example: NonNullable<PrismDocsItem['examples']>[number];
|
|
61
|
-
} | {
|
|
62
|
-
readonly status: 'none';
|
|
63
|
-
} | {
|
|
64
|
-
readonly status: 'miss';
|
|
65
|
-
readonly suggestions: readonly string[];
|
|
66
|
-
};
|
|
67
|
-
export declare function resolveExample(item: PrismDocsItem, slug?: string): ExampleMatch;
|
|
68
|
-
//# sourceMappingURL=lookup.d.ts.map
|
package/dist/lookup.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lookup.d.ts","sourceRoot":"","sources":["../src/lookup.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE/E,6EAA6E;AAC7E,MAAM,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;AAE7C,wDAAwD;AACxD,eAAO,MAAM,UAAU,EAAE,SAAS,QAAQ,EAAmC,CAAC;AAE9E,4DAA4D;AAC5D,eAAO,MAAM,YAAY,SAAS,CAAC;AACnC,eAAO,MAAM,YAAY,UAAU,CAAC;AAKpC,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE,CAa5F;AAoBD,4CAA4C;AAC5C,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAA;CAAE,GAClE;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAEzE,MAAM,WAAW,UAAU;IACzB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC/C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,GAAG,UAAU,CAe5E;AAED,MAAM,WAAW,UAAU;IACzB,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;CACzC;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU,CAgB7F;AAED,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAC7D,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,uEAAuE;AACvE,eAAO,MAAM,SAAS,SAAU,MAAM,QAAQ,MAAM,KAAG,MAA2B,CAAC;AAEnF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,WAAW,CAQhF;AAED,sEAAsE;AACtE,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;CAAE,GAC3F;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAEzE,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,CAS/E"}
|