@preply/ds-ai-mcp 11.1.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.
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function createServer(): McpServer;
3
+ //# sourceMappingURL=create-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-server.d.ts","sourceRoot":"","sources":["../src/create-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsCpE,wBAAgB,YAAY,cAW3B"}
@@ -0,0 +1,2 @@
1
+ export * from './create-server';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import { t as createServer } from "./create-server-LzOTK9vc.js";
2
+ export { createServer };
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@preply/ds-ai-mcp",
3
+ "description": "MCP server for the Preply Design System",
4
+ "version": "11.1.0",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "type": "module",
9
+ "bin": "./dist/bin.js",
10
+ "exports": {
11
+ ".": "./dist/index.js"
12
+ },
13
+ "scripts": {
14
+ "clean": "rm -rf dist",
15
+ "check:types": "run --top-level tsc --noEmit",
16
+ "lint": "run --top-level eslint .",
17
+ "build": "vite build",
18
+ "dev": "vite build --watch",
19
+ "dev:inspector": "mcp-inspector tsx src/bin.ts start"
20
+ },
21
+ "devDependencies": {
22
+ "@modelcontextprotocol/inspector": "^0.17.2",
23
+ "@types/node": "^24.12.0",
24
+ "tsx": "^4.20.6",
25
+ "vite": "^8.0.0",
26
+ "vite-plugin-dts": "^4.5.4"
27
+ },
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^1.20.2",
30
+ "@preply/ds-ai-core": "11.1.0",
31
+ "commander": "^14.0.0"
32
+ },
33
+ "gitHead": "a5330f56c6c03a557b29efefcabacb41d67f4b63"
34
+ }
@@ -0,0 +1,60 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { tools } from '@preply/ds-ai-core';
3
+
4
+ vi.mock(import('@preply/ds-ai-core'), async importOriginal => {
5
+ const actual = await importOriginal();
6
+ return {
7
+ ...actual,
8
+ identify: vi.fn(),
9
+ trackToolCall: vi.fn(),
10
+ };
11
+ });
12
+
13
+ import { createServer } from '../create-server';
14
+
15
+ function getRegisteredTools(server: ReturnType<typeof createServer>) {
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ return (server as any)._registeredTools as Record<
18
+ string,
19
+ { description?: string; enabled: boolean; annotations?: Record<string, unknown> }
20
+ >;
21
+ }
22
+
23
+ describe('createServer', () => {
24
+ it('creates a server instance', () => {
25
+ const server = createServer();
26
+ expect(server).toBeDefined();
27
+ });
28
+
29
+ it('registers all tools from ai-core', () => {
30
+ const server = createServer();
31
+ const registered = getRegisteredTools(server);
32
+ const expectedToolNames = Object.values(tools).map(t => t.name);
33
+
34
+ expect(Object.keys(registered)).toEqual(expect.arrayContaining(expectedToolNames));
35
+ expect(Object.keys(registered)).toHaveLength(expectedToolNames.length);
36
+ });
37
+
38
+ it('sets correct annotations on all registered tools', () => {
39
+ const server = createServer();
40
+ const registered = getRegisteredTools(server);
41
+
42
+ for (const tool of Object.values(registered)) {
43
+ expect(tool.annotations).toEqual({
44
+ readOnlyHint: true,
45
+ openWorldHint: false,
46
+ idempotentHint: true,
47
+ destructiveHint: false,
48
+ });
49
+ }
50
+ });
51
+
52
+ it('registers tools as enabled', () => {
53
+ const server = createServer();
54
+ const registered = getRegisteredTools(server);
55
+
56
+ for (const tool of Object.values(registered)) {
57
+ expect(tool.enabled).toBe(true);
58
+ }
59
+ });
60
+ });
package/src/bin.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { program } from 'commander';
2
+ import pkg from '../package.json' with { type: 'json' };
3
+ import { createServer } from './create-server';
4
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
+
6
+ // prettier-ignore
7
+ program
8
+ .name(Object.keys(pkg.bin)[0])
9
+ .description(pkg.description)
10
+ .version(pkg.version, '-v, --version', 'Output the version number')
11
+ .usage('<command>');
12
+
13
+ // prettier-ignore
14
+ program
15
+ .command('start')
16
+ .description('Start the MCP server')
17
+ .action(async () => {
18
+ const transport = new StdioServerTransport();
19
+ const server = createServer();
20
+ await server.connect(transport);
21
+ });
22
+
23
+ program.parse();
@@ -0,0 +1,50 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import pkg from '../package.json' with { type: 'json' };
3
+ import { tools, type Tool, trackToolCall, identify } from '@preply/ds-ai-core';
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
+ function registerTool<T extends Tool<any, any>>(server: McpServer, tool: T) {
7
+ server.registerTool(
8
+ tool.name,
9
+ {
10
+ description: tool.description,
11
+ inputSchema: {
12
+ ...tool.arguments?.shape,
13
+ ...tool.options?.shape,
14
+ },
15
+ annotations: {
16
+ // Hints client that tool is read-only (e.g. clients can use this information to determine if the tool can be used in planning mode)
17
+ readOnlyHint: true,
18
+ // Hints client that tool does not have access to external resources (e.g. internet, files, etc.)
19
+ openWorldHint: false,
20
+ // Hints client that tool is idempotent (can be called multiple times with the same input)
21
+ idempotentHint: true,
22
+ // Hints client that tool is not destructive (cannot change the state of the system)
23
+ destructiveHint: false,
24
+ },
25
+ },
26
+ args => {
27
+ trackToolCall(tool.name, args ?? {}, { invocationMethod: 'mcp' });
28
+
29
+ return {
30
+ content: tool.callback(args).map(text => ({
31
+ type: 'text' as const,
32
+ text,
33
+ })),
34
+ };
35
+ },
36
+ );
37
+ }
38
+
39
+ export function createServer() {
40
+ identify();
41
+
42
+ const server = new McpServer({
43
+ name: 'ds-ai-mcp',
44
+ version: pkg.version,
45
+ });
46
+
47
+ Object.values(tools).forEach(tool => registerTool(server, tool));
48
+
49
+ return server;
50
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './create-server';
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "include": ["src", "package.json", "vite.config.ts"],
4
+ "exclude": ["node_modules", "dist"],
5
+ "compilerOptions": {
6
+ "resolveJsonModule": true,
7
+ "module": "esnext",
8
+ "target": "esnext",
9
+ "types": ["vitest/globals", "node"]
10
+ }
11
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { defineConfig } from 'vite';
2
+ import dts from 'vite-plugin-dts';
3
+
4
+ export default defineConfig({
5
+ plugins: [dts({ exclude: ['vite.config.ts'], entryRoot: 'src' })],
6
+ build: {
7
+ target: 'esnext',
8
+ ssr: true,
9
+ lib: {
10
+ entry: ['src/index.ts', 'src/bin.ts'],
11
+ formats: ['es'],
12
+ },
13
+ rolldownOptions: {
14
+ output: {
15
+ entryFileNames: '[name].js',
16
+ },
17
+ },
18
+ },
19
+ });