@vadenai/mcp-server 0.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,179 @@
1
+ // --- ガイド生成 ---
2
+ /**
3
+ * コンセプト用 LLM ガイドを生成する
4
+ */
5
+ function generateConceptGuide(data) {
6
+ const lines = [];
7
+ lines.push(`# Concept: ${data.serviceName}`);
8
+ lines.push("");
9
+ lines.push(`**Project**: ${data.projectName}`);
10
+ lines.push(`**Domain**: ${data.businessDomain}`);
11
+ lines.push("");
12
+ lines.push("## Brand Identity");
13
+ lines.push("");
14
+ lines.push(`**Personality**: ${data.brandPersonality.join(", ")}`);
15
+ lines.push("");
16
+ lines.push("### Target Users");
17
+ for (const user of data.targetUsers) {
18
+ lines.push(`- ${user}`);
19
+ }
20
+ lines.push("");
21
+ if (data.visualStyle) {
22
+ lines.push("## Visual Direction");
23
+ lines.push("");
24
+ lines.push(`**Aesthetic**: ${data.visualStyle.aesthetic}`);
25
+ lines.push(`**Mood**: ${data.visualStyle.mood}`);
26
+ lines.push(`**Era**: ${data.visualStyle.era}`);
27
+ lines.push("");
28
+ lines.push("### Inspiration");
29
+ for (const item of data.visualStyle.inspiration) {
30
+ lines.push(`- ${item}`);
31
+ }
32
+ lines.push("");
33
+ }
34
+ if (data.targetAudience) {
35
+ lines.push("## Target Audience");
36
+ lines.push("");
37
+ lines.push(`**Demographics**: ${data.targetAudience.demographics}`);
38
+ lines.push(`**Psychographics**: ${data.targetAudience.psychographics}`);
39
+ lines.push("");
40
+ lines.push("### Pain Points");
41
+ for (const point of data.targetAudience.painPoints) {
42
+ lines.push(`- ${point}`);
43
+ }
44
+ lines.push("");
45
+ lines.push("### Aspirations");
46
+ for (const aspiration of data.targetAudience.aspirations) {
47
+ lines.push(`- ${aspiration}`);
48
+ }
49
+ lines.push("");
50
+ }
51
+ lines.push("## Design Principles");
52
+ lines.push("");
53
+ for (const principle of data.designPrinciples) {
54
+ lines.push(`- ${principle}`);
55
+ }
56
+ lines.push("");
57
+ lines.push("## Key Features");
58
+ lines.push("");
59
+ for (const feature of data.keyFeatures) {
60
+ lines.push(`- ${feature}`);
61
+ }
62
+ lines.push("");
63
+ lines.push("## User Journeys");
64
+ lines.push("");
65
+ for (const journey of data.userJourneys) {
66
+ lines.push(`- ${journey}`);
67
+ }
68
+ lines.push("");
69
+ lines.push("> Use `get_design_rationale` to understand the reasoning behind design decisions.");
70
+ return lines.join("\n");
71
+ }
72
+ /**
73
+ * デザイン意思決定理由用 LLM ガイドを生成する
74
+ */
75
+ function generateDesignRationaleGuide(data) {
76
+ const lines = [];
77
+ lines.push(`# Design Rationale: ${data.serviceName}`);
78
+ lines.push("");
79
+ lines.push(`**Project**: ${data.projectName}`);
80
+ lines.push("");
81
+ const da = data.designAnalysis;
82
+ if (!da ||
83
+ (!da.philosophy &&
84
+ !da.colorStrategyBase &&
85
+ !da.typographyChoice &&
86
+ (!da.interfaceApproach || da.interfaceApproach.length === 0))) {
87
+ // 最低限のガイド(ヘッダー + Goals のみ)
88
+ lines.push("## Goals");
89
+ lines.push("");
90
+ for (const goal of data.mainGoals) {
91
+ lines.push(`- ${goal}`);
92
+ }
93
+ lines.push("");
94
+ return lines.join("\n");
95
+ }
96
+ lines.push("## Philosophy");
97
+ lines.push("");
98
+ lines.push(da.philosophy);
99
+ lines.push("");
100
+ lines.push("## Interface Approach");
101
+ lines.push("");
102
+ for (const approach of da.interfaceApproach) {
103
+ lines.push(`- ${approach}`);
104
+ }
105
+ lines.push("");
106
+ lines.push("## Color Strategy");
107
+ lines.push("");
108
+ lines.push(`**Base**: ${da.colorStrategyBase}`);
109
+ lines.push(`**Accent Color**: ${da.colorStrategyAccentColor}`);
110
+ lines.push(`**Accent Meaning**: ${da.colorStrategyAccentMeaning}`);
111
+ lines.push("");
112
+ lines.push("## Typography");
113
+ lines.push("");
114
+ lines.push(`**Choice**: ${da.typographyChoice}`);
115
+ lines.push(`**Rationale**: ${da.typographyRationale}`);
116
+ lines.push("");
117
+ lines.push("## UX Principles");
118
+ lines.push("");
119
+ for (const principle of da.uxPrinciples) {
120
+ lines.push(`- ${principle}`);
121
+ }
122
+ lines.push("");
123
+ lines.push("## Success Metrics");
124
+ lines.push("");
125
+ for (const metric of data.successMetrics) {
126
+ lines.push(`- ${metric}`);
127
+ }
128
+ lines.push("");
129
+ lines.push("## Goals");
130
+ lines.push("");
131
+ for (const goal of data.mainGoals) {
132
+ lines.push(`- ${goal}`);
133
+ }
134
+ lines.push("");
135
+ return lines.join("\n");
136
+ }
137
+ // --- ツールハンドラー ---
138
+ /**
139
+ * コンセプト情報を返す
140
+ *
141
+ * @param client - Vaden MCP API クライアント
142
+ * @param projectId - プロジェクトID
143
+ */
144
+ export async function handleGetConcept(client, projectId) {
145
+ const data = await client.get(`/api/projects/${encodeURIComponent(projectId)}/concept`);
146
+ const guide = generateConceptGuide(data);
147
+ const parts = [
148
+ guide,
149
+ "",
150
+ "---",
151
+ "",
152
+ "## Raw Concept (JSON)",
153
+ "```json",
154
+ JSON.stringify(data, null, 2),
155
+ "```",
156
+ ];
157
+ return [{ type: "text", text: parts.join("\n") }];
158
+ }
159
+ /**
160
+ * デザイン意思決定理由を返す
161
+ *
162
+ * @param client - Vaden MCP API クライアント
163
+ * @param projectId - プロジェクトID
164
+ */
165
+ export async function handleGetDesignRationale(client, projectId) {
166
+ const data = await client.get(`/api/projects/${encodeURIComponent(projectId)}/concept`);
167
+ const guide = generateDesignRationaleGuide(data);
168
+ const parts = [
169
+ guide,
170
+ "",
171
+ "---",
172
+ "",
173
+ "## Raw Design Rationale (JSON)",
174
+ "```json",
175
+ JSON.stringify(data.designAnalysis ?? {}, null, 2),
176
+ "```",
177
+ ];
178
+ return [{ type: "text", text: parts.join("\n") }];
179
+ }
@@ -0,0 +1,15 @@
1
+ import type { VadenMcpApiClient } from "../api-client.js";
2
+ /**
3
+ * get_design_tokens ツールハンドラー
4
+ */
5
+ export declare function handleGetDesignTokens(client: VadenMcpApiClient, projectId: string): Promise<{
6
+ type: "text";
7
+ text: string;
8
+ }[]>;
9
+ /**
10
+ * get_theme_css ツールハンドラー
11
+ */
12
+ export declare function handleGetThemeCss(client: VadenMcpApiClient, projectId: string): Promise<{
13
+ type: "text";
14
+ text: string;
15
+ }[]>;
@@ -0,0 +1,115 @@
1
+ /**
2
+ * DesignSystemTokens の構造から LLM 向け使い方ガイドを生成する
3
+ */
4
+ function generateTokenUsageGuide(tokens) {
5
+ const lines = ["# Design Token Usage Guide", ""];
6
+ // カラー
7
+ if (tokens.colors) {
8
+ lines.push("## Colors");
9
+ const mode = tokens.colors.preferredAppearance ?? "light";
10
+ lines.push(`- Preferred appearance: ${mode}`);
11
+ const palette = tokens.colors[mode];
12
+ if (palette?.semantic) {
13
+ const s = palette.semantic;
14
+ if (s.primary) {
15
+ lines.push("- `primary`: Brand color. Use for primary buttons, links, and key interactive elements.");
16
+ }
17
+ if (s.secondary) {
18
+ lines.push("- `secondary`: Supporting color. Use for secondary buttons and accents.");
19
+ }
20
+ if (s.destructive) {
21
+ lines.push("- `destructive`: Error/danger color. Use for delete actions and error states.");
22
+ }
23
+ if (s.base) {
24
+ lines.push("- `background` / `foreground`: Page background and default text color.");
25
+ }
26
+ }
27
+ lines.push("");
28
+ }
29
+ // フォント
30
+ if (tokens.fontFamily) {
31
+ lines.push("## Typography");
32
+ if (tokens.fontFamily.heading) {
33
+ lines.push(`- Heading font: \`${tokens.fontFamily.heading}\` — Use for h1–h6 and display text.`);
34
+ }
35
+ if (tokens.fontFamily.body) {
36
+ lines.push(`- Body font: \`${tokens.fontFamily.body}\` — Use for paragraphs, labels, and UI text.`);
37
+ }
38
+ if (tokens.fontFamily.code) {
39
+ lines.push(`- Code font: \`${tokens.fontFamily.code}\` — Use for code blocks and monospace text.`);
40
+ }
41
+ lines.push("");
42
+ }
43
+ // Spacing
44
+ if (tokens.spacing) {
45
+ lines.push("## Spacing");
46
+ lines.push(`- Base spacing unit: \`${tokens.spacing}\`. Use multiples of this value for consistent layout gaps and padding.`);
47
+ lines.push("");
48
+ }
49
+ // Radius
50
+ if (tokens.radius) {
51
+ lines.push("## Border Radius");
52
+ lines.push(`- Base radius: \`${tokens.radius}\`. Apply via \`--radius\` CSS variable. Do NOT use hardcoded pixel values.`);
53
+ lines.push("");
54
+ }
55
+ // Shadow
56
+ if (tokens.shadowColor ||
57
+ tokens.shadowX != null ||
58
+ tokens.shadowBlur != null) {
59
+ lines.push("## Shadow");
60
+ lines.push("- Shadow color and dimensions are defined by token values. Use the provided shadow tokens rather than custom box-shadow values.");
61
+ if (tokens.shadowX != null || tokens.shadowY != null) {
62
+ lines.push(`- Offset: x=${tokens.shadowX ?? "0"}, y=${tokens.shadowY ?? "0"}, blur=${tokens.shadowBlur ?? "0"}, spread=${tokens.shadowSpread ?? "0"}`);
63
+ }
64
+ lines.push("");
65
+ }
66
+ // Border
67
+ if (tokens.border) {
68
+ lines.push("## Border");
69
+ lines.push("- Border styles are defined by token values. Use border tokens for consistent border styling.");
70
+ lines.push("");
71
+ }
72
+ // Glass / Gradient / Noise (decorative effects)
73
+ const effects = [];
74
+ if (tokens.glass)
75
+ effects.push("glass");
76
+ if (tokens.gradient)
77
+ effects.push("gradient");
78
+ if (tokens.noise)
79
+ effects.push("noise");
80
+ if (effects.length > 0) {
81
+ lines.push("## Decorative Effects");
82
+ lines.push(`- Available effects: ${effects.join(", ")}. Use the token values — do not create custom implementations.`);
83
+ lines.push("");
84
+ }
85
+ lines.push("## Important Rules");
86
+ lines.push("- Always use CSS variables (e.g., `var(--primary)`) instead of raw color values.");
87
+ lines.push("- Do not override token values inline; extend via Tailwind utilities that reference CSS variables.");
88
+ lines.push("- For dark mode, wrap overrides in the `.dark` class — the theme CSS handles this automatically.");
89
+ return lines.join("\n");
90
+ }
91
+ /**
92
+ * get_design_tokens ツールハンドラー
93
+ */
94
+ export async function handleGetDesignTokens(client, projectId) {
95
+ const data = await client.get(`/api/projects/${projectId}/design-system/tokens`);
96
+ const usageGuide = generateTokenUsageGuide(data.tokens);
97
+ const output = [
98
+ usageGuide,
99
+ "",
100
+ "---",
101
+ "",
102
+ "## Raw Tokens (JSON)",
103
+ "```json",
104
+ JSON.stringify(data.tokens, null, 2),
105
+ "```",
106
+ ].join("\n");
107
+ return [{ type: "text", text: output }];
108
+ }
109
+ /**
110
+ * get_theme_css ツールハンドラー
111
+ */
112
+ export async function handleGetThemeCss(client, projectId) {
113
+ const data = await client.get(`/api/projects/${projectId}/design-system/theme-css`);
114
+ return [{ type: "text", text: data.css }];
115
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * ワイヤーフレーム関連 MCP ツールハンドラー
3
+ *
4
+ * ワイヤーフレーム一覧 API: GET /api/projects/{projectId}/wireframe
5
+ * 画面詳細 API: GET /api/projects/{projectId}/wireframe/{screenId}
6
+ */
7
+ import type { VadenMcpApiClient } from "../api-client.js";
8
+ /**
9
+ * ワイヤーフレーム一覧を返す
10
+ *
11
+ * @param client - Vaden MCP API クライアント
12
+ * @param projectId - プロジェクトID
13
+ */
14
+ export declare function handleGetWireframes(client: VadenMcpApiClient, projectId: string): Promise<{
15
+ type: "text";
16
+ text: string;
17
+ }[]>;
18
+ /**
19
+ * 特定画面の詳細を返す
20
+ *
21
+ * @param client - Vaden MCP API クライアント
22
+ * @param projectId - プロジェクトID
23
+ * @param screenId - 画面ID
24
+ */
25
+ export declare function handleGetWireframeDetail(client: VadenMcpApiClient, projectId: string, screenId: string): Promise<{
26
+ type: "text";
27
+ text: string;
28
+ }[]>;
@@ -0,0 +1,214 @@
1
+ // --- ガイド生成 ---
2
+ /**
3
+ * ワイヤーフレーム一覧用 LLM ガイドを生成する
4
+ */
5
+ function generateWireframesGuide(data) {
6
+ const { screens, transitions, metadata } = data;
7
+ const lines = [];
8
+ lines.push("# Wireframe Overview");
9
+ lines.push("");
10
+ lines.push(`Total screens: ${metadata.totalScreens}${metadata.generatedAt ? ` (generated: ${metadata.generatedAt})` : ""}`);
11
+ lines.push("");
12
+ // Screen Map(画面一覧テーブル)
13
+ lines.push("## Screen Map");
14
+ lines.push("");
15
+ lines.push("| ID | Name | Purpose | Group | Journey Stage | Components |");
16
+ lines.push("|-----|------|---------|-------|--------------|------------|");
17
+ for (const screen of screens) {
18
+ lines.push(`| \`${screen.id}\` | ${screen.name} | ${screen.purpose} | ${screen.group ?? "—"} | ${screen.journeyStage ?? "—"} | ${screen.componentCount} |`);
19
+ }
20
+ lines.push("");
21
+ // Screen Groups(グループ別の画面リスト)
22
+ const groups = new Map();
23
+ for (const screen of screens) {
24
+ const group = screen.group ?? "(ungrouped)";
25
+ const existing = groups.get(group);
26
+ if (existing) {
27
+ existing.push(screen);
28
+ }
29
+ else {
30
+ groups.set(group, [screen]);
31
+ }
32
+ }
33
+ lines.push("## Screen Groups");
34
+ lines.push("");
35
+ for (const [group, groupScreens] of groups.entries()) {
36
+ lines.push(`### ${group}`);
37
+ for (const s of groupScreens) {
38
+ lines.push(`- \`${s.id}\` — **${s.name}**: ${s.purpose}`);
39
+ }
40
+ lines.push("");
41
+ }
42
+ // Navigation Flow(遷移をアスキーアートで表現)
43
+ lines.push("## Navigation Flow");
44
+ lines.push("");
45
+ if (transitions.length === 0) {
46
+ lines.push("_(no transitions defined)_");
47
+ }
48
+ else {
49
+ // 画面名を素早く引けるマップ
50
+ const screenNameMap = new Map(screens.map((s) => [s.id, s.name]));
51
+ for (const t of transitions) {
52
+ const fromName = screenNameMap.get(t.fromScreenId) ?? t.fromScreenId;
53
+ const toName = screenNameMap.get(t.toScreenId) ?? t.toScreenId;
54
+ const action = t.triggerAction ? `[${t.triggerAction}]` : "";
55
+ const label = t.label ? ` "${t.label}"` : "";
56
+ lines.push(`${fromName} --${action}${label}--> ${toName}`);
57
+ }
58
+ }
59
+ lines.push("");
60
+ lines.push("> Use `get_wireframe_detail` with a screen ID to get full component details.");
61
+ return lines.join("\n");
62
+ }
63
+ /**
64
+ * 画面詳細用 LLM ガイドを生成する
65
+ */
66
+ function generateWireframeDetailGuide(screen) {
67
+ const lines = [];
68
+ lines.push(`# Screen: ${screen.name}`);
69
+ lines.push("");
70
+ lines.push(`**ID**: \`${screen.id}\``);
71
+ lines.push(`**Purpose**: ${screen.purpose}`);
72
+ if (screen.layoutPattern) {
73
+ lines.push(`**Layout Pattern**: ${screen.layoutPattern}`);
74
+ }
75
+ if (screen.journeyStage) {
76
+ lines.push(`**Journey Stage**: ${screen.journeyStage}`);
77
+ }
78
+ if (screen.group) {
79
+ lines.push(`**Group**: ${screen.group}`);
80
+ }
81
+ lines.push("");
82
+ // コンポーネント一覧テーブル
83
+ lines.push("## Components");
84
+ lines.push("");
85
+ if (screen.components.length === 0) {
86
+ lines.push("_(no components)_");
87
+ }
88
+ else {
89
+ lines.push("| ID | Type | Label | DataKey | Position (x,y) | Size (w×h) |");
90
+ lines.push("|----|------|-------|---------|----------------|------------|");
91
+ for (const comp of screen.components) {
92
+ const pos = comp.x !== undefined && comp.y !== undefined
93
+ ? `${comp.x},${comp.y}`
94
+ : "—";
95
+ const size = comp.width !== undefined && comp.height !== undefined
96
+ ? `${comp.width}×${comp.height}`
97
+ : "—";
98
+ lines.push(`| \`${comp.id}\` | ${comp.type} | ${comp.label} | ${comp.dataKey ?? "—"} | ${pos} | ${size} |`);
99
+ }
100
+ }
101
+ lines.push("");
102
+ // UI States(状態一覧)
103
+ if (screen.designSpec?.states && screen.designSpec.states.length > 0) {
104
+ lines.push("## UI States");
105
+ lines.push("");
106
+ for (const state of screen.designSpec.states) {
107
+ lines.push(`### ${state.name}`);
108
+ lines.push(`- **Condition**: ${state.condition}`);
109
+ lines.push(`- **Display**: ${state.display}`);
110
+ if (state.behavior) {
111
+ lines.push(`- **Behavior**: ${state.behavior}`);
112
+ }
113
+ lines.push("");
114
+ }
115
+ }
116
+ // Behaviors(アクション→結果)
117
+ if (screen.designSpec?.behaviors && screen.designSpec.behaviors.length > 0) {
118
+ lines.push("## Behaviors");
119
+ lines.push("");
120
+ lines.push("| Action | Result | On Error |");
121
+ lines.push("|--------|--------|----------|");
122
+ for (const b of screen.designSpec.behaviors) {
123
+ lines.push(`| ${b.action} | ${b.result} | ${b.onError ?? "—"} |`);
124
+ }
125
+ lines.push("");
126
+ }
127
+ // Design Rules
128
+ if (screen.designSpec?.rules && screen.designSpec.rules.length > 0) {
129
+ lines.push("## Design Rules");
130
+ lines.push("");
131
+ for (const rule of screen.designSpec.rules) {
132
+ lines.push(`- ${rule}`);
133
+ }
134
+ lines.push("");
135
+ }
136
+ // 遷移先画面一覧
137
+ if (screen.relatedScreens.length > 0) {
138
+ lines.push("## Related Screens");
139
+ lines.push("");
140
+ for (const related of screen.relatedScreens) {
141
+ lines.push(`- \`${related.id}\` — **${related.name}**: ${related.purpose}`);
142
+ }
143
+ lines.push("");
144
+ }
145
+ // Mock Data の概要
146
+ if (screen.mockData && Object.keys(screen.mockData).length > 0) {
147
+ lines.push("## Mock Data Keys");
148
+ lines.push("");
149
+ for (const key of Object.keys(screen.mockData)) {
150
+ const val = screen.mockData[key];
151
+ const preview = Array.isArray(val)
152
+ ? `Array(${val.length})`
153
+ : typeof val === "object" && val !== null
154
+ ? `Object(${Object.keys(val).join(", ")})`
155
+ : String(val);
156
+ lines.push(`- \`${key}\`: ${preview}`);
157
+ }
158
+ lines.push("");
159
+ }
160
+ // Notes
161
+ if (screen.designSpec?.notes && screen.designSpec.notes.length > 0) {
162
+ lines.push("## Notes");
163
+ lines.push("");
164
+ for (const note of screen.designSpec.notes) {
165
+ lines.push(`- ${note}`);
166
+ }
167
+ lines.push("");
168
+ }
169
+ return lines.join("\n");
170
+ }
171
+ // --- ツールハンドラー ---
172
+ /**
173
+ * ワイヤーフレーム一覧を返す
174
+ *
175
+ * @param client - Vaden MCP API クライアント
176
+ * @param projectId - プロジェクトID
177
+ */
178
+ export async function handleGetWireframes(client, projectId) {
179
+ const data = await client.get(`/api/projects/${encodeURIComponent(projectId)}/wireframe`);
180
+ const guide = generateWireframesGuide(data);
181
+ const parts = [
182
+ guide,
183
+ "",
184
+ "---",
185
+ "",
186
+ "## Raw Wireframe (JSON)",
187
+ "```json",
188
+ JSON.stringify(data, null, 2),
189
+ "```",
190
+ ];
191
+ return [{ type: "text", text: parts.join("\n") }];
192
+ }
193
+ /**
194
+ * 特定画面の詳細を返す
195
+ *
196
+ * @param client - Vaden MCP API クライアント
197
+ * @param projectId - プロジェクトID
198
+ * @param screenId - 画面ID
199
+ */
200
+ export async function handleGetWireframeDetail(client, projectId, screenId) {
201
+ const data = await client.get(`/api/projects/${encodeURIComponent(projectId)}/wireframe/${encodeURIComponent(screenId)}`);
202
+ const guide = generateWireframeDetailGuide(data);
203
+ const parts = [
204
+ guide,
205
+ "",
206
+ "---",
207
+ "",
208
+ "## Raw Screen (JSON)",
209
+ "```json",
210
+ JSON.stringify(data, null, 2),
211
+ "```",
212
+ ];
213
+ return [{ type: "text", text: parts.join("\n") }];
214
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@vadenai/mcp-server",
3
+ "description": "Vaden MCP Server — Provide design tokens, component specs, and wireframes to coding agents via MCP",
4
+ "keywords": [
5
+ "design-system",
6
+ "design-tokens",
7
+ "mcp",
8
+ "mcp-server",
9
+ "vaden"
10
+ ],
11
+ "homepage": "https://vaden.ai",
12
+ "license": "MIT",
13
+ "version": "0.1.0",
14
+ "type": "module",
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "bin": {
19
+ "vaden-mcp-server": "dist/index.js"
20
+ },
21
+ "dependencies": {
22
+ "@modelcontextprotocol/sdk": "1.26.0"
23
+ },
24
+ "devDependencies": {
25
+ "@supabase/supabase-js": "2.98.0",
26
+ "jose": "6.1.3",
27
+ "tsx": "4.19.4",
28
+ "typescript": "5.9.3",
29
+ "vitest": "4.0.6"
30
+ },
31
+ "scripts": {
32
+ "build": "tsc",
33
+ "generate-token": "tsx scripts/generate-dev-token.ts",
34
+ "postbuild": "node scripts/postbuild.js",
35
+ "prepack": "npm run build",
36
+ "test": "vitest run",
37
+ "typecheck": "tsc --noEmit"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "README.md",
42
+ "LICENSE"
43
+ ],
44
+ "author": "ROUTE06, Inc.",
45
+ "engines": {
46
+ "node": ">=18.18"
47
+ },
48
+ "types": "dist/index.d.ts"
49
+ }